diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c index 46d71c1784421f70b017f1e7fd861b780acf22a5..4dabea6849ac83d20ca6306aa3ecbc0932ec3e43 100755 --- a/channels/chan_iax2.c +++ b/channels/chan_iax2.c @@ -2677,114 +2677,107 @@ static void realtime_update_peer(const char *peername, struct sockaddr_in *sin) ast_update_realtime("iaxpeers", "name", peername, "ipaddr", ipaddr, "port", port, "regseconds", regseconds, NULL); } +struct create_addr_info { + int capability; + unsigned int flags; + int maxtime; + int encmethods; + int found; + int sockfd; + char username[80]; + char secret[80]; + char outkey[80]; + char timezone[80]; + char prefs[32]; + char context[AST_MAX_EXTENSION]; + char peercontext[AST_MAX_EXTENSION]; +}; -static int create_addr(struct sockaddr_in *sin, int *capability, int *sendani, - int *maxtime, char *peer, char *context, int *trunk, - int *notransfer, int *usejitterbuf, int *forcejitterbuf, int *encmethods, - char *username, int usernlen, char *secret, int seclen, - int *ofound, char *peercontext, char *timezone, int tzlen, char *pref_str, size_t pref_size, - int *sockfd) +static int create_addr(const char *peername, struct sockaddr_in *sin, struct create_addr_info *cai) { - struct ast_hostent ahp; struct hostent *hp; - struct iax2_peer *p; - int found=0; - if (sendani) - *sendani = 0; - if (maxtime) - *maxtime = 0; - if (trunk) - *trunk = 0; - if (sockfd) - *sockfd = defaultsockfd; + struct ast_hostent ahp; + struct hostent *hp; + struct iax2_peer *peer; + + ast_clear_flag(cai, IAX_SENDANI | IAX_TRUNK); + cai->sockfd = defaultsockfd; + cai->maxtime = 0; sin->sin_family = AF_INET; - p = find_peer(peer, 1); - if (p) { - found++; - if ((p->addr.sin_addr.s_addr || p->defaddr.sin_addr.s_addr) && - (!p->maxms || ((p->lastms > 0) && (p->lastms <= p->maxms)))) { - if(pref_str) { - ast_codec_pref_convert(&p->prefs, pref_str, pref_size, 1); - } - if (sendani) - *sendani = ast_test_flag(p, IAX_SENDANI); /* Whether we transmit ANI */ - if (maxtime) - *maxtime = p->maxms; /* Max time they should take */ - if (context) - ast_copy_string(context, p->context, sizeof(context)); - if (peercontext) - ast_copy_string(peercontext, p->peercontext, sizeof(peercontext)); - if (trunk) - *trunk = ast_test_flag(p, IAX_TRUNK); - if (capability) - *capability = p->capability; - if (encmethods) - *encmethods = p->encmethods; - if (username) - ast_copy_string(username, p->username, usernlen); - if (p->addr.sin_addr.s_addr) { - sin->sin_addr = p->addr.sin_addr; - sin->sin_port = p->addr.sin_port; - } else { - sin->sin_addr = p->defaddr.sin_addr; - sin->sin_port = p->defaddr.sin_port; - } - if (sockfd) - *sockfd = p->sockfd; - if (notransfer) - *notransfer = ast_test_flag(p, IAX_NOTRANSFER); - if (usejitterbuf) - *usejitterbuf = ast_test_flag(p, IAX_USEJITTERBUF); - if (forcejitterbuf) - *forcejitterbuf = ast_test_flag(p, IAX_FORCEJITTERBUF); - if (secret) { - if (!ast_strlen_zero(p->dbsecret)) { - char *family, *key=NULL; - family = ast_strdupa(p->dbsecret); - if (family) { - key = strchr(family, '/'); - if (key) { - *key = '\0'; - key++; - } - } - if (!family || !key || ast_db_get(family, key, secret, seclen)) { - ast_log(LOG_WARNING, "Unable to retrieve database password for family/key '%s'!\n", p->dbsecret); - if (ast_test_flag(p, IAX_TEMPONLY)) - destroy_peer(p); - p = NULL; - } - } else - ast_copy_string(secret, p->secret, seclen); - } - if (timezone) - snprintf(timezone, tzlen-1, "%s", p->zonetag); - } else { - if (ast_test_flag(p, IAX_TEMPONLY)) - destroy_peer(p); - p = NULL; - } - } - if (ofound) - *ofound = found; - if (!p && !found) { - if(pref_str) { /* use global iax prefs for unknown peer/user */ - ast_codec_pref_convert(&prefs, pref_str, pref_size, 1); - } + if (!(peer = find_peer(peername, 1))) { + cai->found = 0; - hp = ast_gethostbyname(peer, &ahp); + hp = ast_gethostbyname(peername, &ahp); if (hp) { memcpy(&sin->sin_addr, hp->h_addr, sizeof(sin->sin_addr)); sin->sin_port = htons(IAX_DEFAULT_PORTNO); + /* use global iax prefs for unknown peer/user */ + ast_codec_pref_convert(&prefs, cai->prefs, sizeof(cai->prefs), 1); return 0; } else { - ast_log(LOG_WARNING, "No such host: %s\n", peer); + ast_log(LOG_WARNING, "No such host: %s\n", peername); return -1; } - } else if (!p) + } + + cai->found = 1; + + /* if the peer has no address (current or default), return failure */ + if (!(peer->addr.sin_addr.s_addr || peer->defaddr.sin_addr.s_addr)) { + if (ast_test_flag(peer, IAX_TEMPONLY)) + destroy_peer(peer); return -1; - if (ast_test_flag(p, IAX_TEMPONLY)) - destroy_peer(p); + } + + /* if the peer is being monitored and is currently unreachable, return failure */ + if (peer->maxms && (peer->lastms > peer->maxms)) { + if (ast_test_flag(peer, IAX_TEMPONLY)) + destroy_peer(peer); + return -1; + } + + ast_copy_flags(cai, peer, IAX_SENDANI | IAX_TRUNK | IAX_NOTRANSFER | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); + cai->maxtime = peer->maxms; + cai->capability = peer->capability; + cai->encmethods = peer->encmethods; + cai->sockfd = peer->sockfd; + ast_codec_pref_convert(&peer->prefs, cai->prefs, sizeof(cai->prefs), 1); + ast_copy_string(cai->context, peer->context, sizeof(cai->context)); + ast_copy_string(cai->peercontext, peer->peercontext, sizeof(cai->peercontext)); + ast_copy_string(cai->username, peer->username, sizeof(cai->username)); + ast_copy_string(cai->timezone, peer->zonetag, sizeof(cai->timezone)); + ast_copy_string(cai->outkey, peer->outkey, sizeof(cai->outkey)); + if (ast_strlen_zero(peer->dbsecret)) { + ast_copy_string(cai->secret, peer->secret, sizeof(cai->secret)); + } else { + char *family; + char *key = NULL; + + family = ast_strdupa(peer->dbsecret); + if (family) { + key = strchr(family, '/'); + if (key) + *key++ = '\0'; + } + if (!family || !key || ast_db_get(family, key, cai->secret, sizeof(cai->secret))) { + ast_log(LOG_WARNING, "Unable to retrieve database password for family/key '%s'!\n", peer->dbsecret); + if (ast_test_flag(peer, IAX_TEMPONLY)) + destroy_peer(peer); + return -1; + } + } + + if (peer->addr.sin_addr.s_addr) { + sin->sin_addr = peer->addr.sin_addr; + sin->sin_port = peer->addr.sin_port; + } else { + sin->sin_addr = peer->defaddr.sin_addr; + sin->sin_port = peer->defaddr.sin_port; + } + + if (ast_test_flag(peer, IAX_TEMPONLY)) + destroy_peer(peer); + return 0; } @@ -2820,148 +2813,189 @@ static unsigned int iax2_datetime(char *tz) return tmp; } +struct parsed_dial_string { + char *username; + char *password; + char *key; + char *peer; + char *port; + char *exten; + char *context; + char *options; +}; + +/*! + * \brief Parses an IAX dial string into its component parts. + * \param data the string to be parsed + * \param pds pointer to a \c struct \c parsed_dial_string to be filled in + * \return nothing + * + * This function parses the string and fills the structure + * with pointers to its component parts. The input string + * will be modified. + * + * \note This function supports both plaintext passwords and RSA + * key names; if the password string is formatted as '[keyname]', + * then the keyname will be placed into the key field, and the + * password field will be set to NULL. + * + * \note The dial string format is: + * [username[:password]@]peer[:port][/exten[@@context]][/options] + */ +static void parse_dial_string(char *data, struct parsed_dial_string *pds) +{ + if (!data || ast_strlen_zero(data)) + return; + + pds->peer = strsep(&data, "/"); + pds->exten = strsep(&data, "/"); + pds->options = data; + + if (pds->exten) { + data = pds->exten; + pds->exten = strsep(&data, "@"); + pds->context = data; + } + + if (strchr(pds->peer, '@')) { + data = pds->peer; + pds->username = strsep(&data, "@"); + pds->peer = data; + } + + if (pds->username) { + data = pds->username; + pds->username = strsep(&data, ":"); + pds->password = data; + } + + data = pds->peer; + pds->peer = strsep(&data, ":"); + pds->port = data; + + /* check for a key name wrapped in [] in the secret position, if found, + move it to the key field instead + */ + if (pds->password && (pds->password[0] == '[')) { + int len = strlen(pds->password); + + if ((len > 2) && (pds->password[len - 1] == ']')) { + pds->key = ++(pds->password); + pds->password[len - 1] = '\0'; + pds->password = NULL; + } + } +} + static int iax2_call(struct ast_channel *c, char *dest, int timeout) { struct sockaddr_in sin; - char host[256]; - char *rdest; - char *rcontext; - char *username; - char *secret = NULL; - char *hname; char *l=NULL, *n=NULL; struct iax_ie_data ied; - char myrdest [5] = "s"; - char context[AST_MAX_EXTENSION] =""; - char peercontext[AST_MAX_EXTENSION] =""; - char *portno = NULL; - char *opts = ""; - int encmethods=iax2_encryption; + char *defaultrdest = "s"; unsigned short callno = PTR_TO_CALLNO(c->tech_pvt); - char *stringp=NULL; - char storedusern[80], storedsecret[80]; - char tz[80] = ""; - char out_prefs[32]; - - memset(out_prefs,0,32); + struct parsed_dial_string pds; + struct create_addr_info cai; if ((c->_state != AST_STATE_DOWN) && (c->_state != AST_STATE_RESERVED)) { - ast_log(LOG_WARNING, "Line is already in use (%s)?\n", c->name); + ast_log(LOG_WARNING, "Channel is already in use (%s)?\n", c->name); return -1; } - ast_copy_string(host, dest, sizeof(host)); - stringp=host; - strsep(&stringp, "/"); - /* If no destination extension specified, use 's' */ - rdest = strsep(&stringp, "/"); - if (!rdest) - rdest = myrdest; - else { - /* Check for trailing options */ - opts = strsep(&stringp, "/"); - if (!opts) - opts = ""; - } - stringp=rdest; - strsep(&stringp, "@"); - rcontext = strsep(&stringp, "@"); - stringp=host; - strsep(&stringp, "@"); - username = strsep(&stringp, "@"); - if (username) { - /* Really the second argument is the host, not the username */ - hname = username; - username = host; - } else { - hname = host; - } - if (username) { - stringp=username; - username = strsep(&stringp, ":"); - secret = strsep(&stringp, ":"); - } - stringp=hname; - if (strsep(&stringp, ":")) { - stringp=hname; - strsep(&stringp, ":"); - portno = strsep(&stringp, ":"); - } - if (create_addr(&sin, NULL, NULL, NULL, hname, context, NULL, NULL, NULL, NULL, &encmethods, storedusern, sizeof(storedusern) - 1, storedsecret, sizeof(storedsecret) - 1, NULL, peercontext, tz, sizeof(tz), out_prefs, sizeof(out_prefs), NULL)) { - ast_log(LOG_WARNING, "No address associated with '%s'\n", hname); + + memset(&cai, 0, sizeof(cai)); + cai.encmethods = iax2_encryption; + + memset(&pds, 0, sizeof(pds)); + parse_dial_string(ast_strdupa(dest), &pds); + + if (!pds.exten) + pds.exten = defaultrdest; + + if (create_addr(pds.peer, &sin, &cai)) { + ast_log(LOG_WARNING, "No address associated with '%s'\n", pds.peer); return -1; } + + if (!pds.username && !ast_strlen_zero(cai.username)) + pds.username = cai.username; + if (!pds.password && !ast_strlen_zero(cai.secret)) + pds.password = cai.secret; + if (!pds.key && !ast_strlen_zero(cai.outkey)) + pds.key = cai.outkey; + if (!pds.context && !ast_strlen_zero(cai.peercontext)) + pds.context = cai.peercontext; + /* Keep track of the context for outgoing calls too */ - ast_copy_string(c->context, context, sizeof(c->context)); - if (portno) { - sin.sin_port = htons(atoi(portno)); - } + ast_copy_string(c->context, cai.context, sizeof(c->context)); + + if (pds.port) + sin.sin_port = htons(atoi(pds.port)); + l = c->cid.cid_num; n = c->cid.cid_name; + /* Now build request */ memset(&ied, 0, sizeof(ied)); + /* On new call, first IE MUST be IAX version of caller */ iax_ie_append_short(&ied, IAX_IE_VERSION, IAX_PROTO_VERSION); - iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, rdest); - if (strchr(opts, 'a')) { + iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, pds.exten); + if (pds.options && strchr(pds.options, 'a')) { /* Request auto answer */ iax_ie_append(&ied, IAX_IE_AUTOANSWER); } - iax_ie_append_str(&ied, IAX_IE_CODEC_PREFS, out_prefs); + + iax_ie_append_str(&ied, IAX_IE_CODEC_PREFS, cai.prefs); if (l) { iax_ie_append_str(&ied, IAX_IE_CALLING_NUMBER, l); iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, c->cid.cid_pres); - } else + } else { iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, AST_PRES_NUMBER_NOT_AVAILABLE); + } + iax_ie_append_byte(&ied, IAX_IE_CALLINGTON, c->cid.cid_ton); iax_ie_append_short(&ied, IAX_IE_CALLINGTNS, c->cid.cid_tns); + if (n) iax_ie_append_str(&ied, IAX_IE_CALLING_NAME, n); - if (ast_test_flag(iaxs[callno], IAX_SENDANI) && c->cid.cid_ani) { + if (ast_test_flag(iaxs[callno], IAX_SENDANI) && c->cid.cid_ani) iax_ie_append_str(&ied, IAX_IE_CALLING_ANI, c->cid.cid_ani); - } + if (c->language && !ast_strlen_zero(c->language)) iax_ie_append_str(&ied, IAX_IE_LANGUAGE, c->language); if (c->cid.cid_dnid && !ast_strlen_zero(c->cid.cid_dnid)) iax_ie_append_str(&ied, IAX_IE_DNID, c->cid.cid_dnid); - if (rcontext) - iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, rcontext); - else if (strlen(peercontext)) - iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, peercontext); - if (!username && !ast_strlen_zero(storedusern)) - username = storedusern; - if (username) - iax_ie_append_str(&ied, IAX_IE_USERNAME, username); - if (encmethods) - iax_ie_append_short(&ied, IAX_IE_ENCRYPTION, encmethods); - if (!secret && !ast_strlen_zero(storedsecret)) - secret = storedsecret; + + if (pds.context) + iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, pds.context); + + if (pds.username) + iax_ie_append_str(&ied, IAX_IE_USERNAME, pds.username); + + if (cai.encmethods) + iax_ie_append_short(&ied, IAX_IE_ENCRYPTION, cai.encmethods); + ast_mutex_lock(&iaxsl[callno]); + if (!ast_strlen_zero(c->context)) ast_copy_string(iaxs[callno]->context, c->context, sizeof(iaxs[callno]->context)); - if (username) - ast_copy_string(iaxs[callno]->username, username, sizeof(iaxs[callno]->username)); - iaxs[callno]->encmethods = encmethods; - if (secret) { - if (secret[0] == '[') { - /* This is an RSA key, not a normal secret */ - ast_copy_string(iaxs[callno]->outkey, secret + 1, sizeof(iaxs[callno]->outkey)); - if (!ast_strlen_zero(iaxs[callno]->outkey)) { - iaxs[callno]->outkey[strlen(iaxs[callno]->outkey) - 1] = '\0'; - } - } else - ast_copy_string(iaxs[callno]->secret, secret, sizeof(iaxs[callno]->secret)); - } + + if (pds.username) + ast_copy_string(iaxs[callno]->username, pds.username, sizeof(iaxs[callno]->username)); + + iaxs[callno]->encmethods = cai.encmethods; + + if (pds.key) + ast_copy_string(iaxs[callno]->outkey, pds.key, sizeof(iaxs[callno]->outkey)); + if (pds.password) + ast_copy_string(iaxs[callno]->secret, pds.password, sizeof(iaxs[callno]->secret)); + iax_ie_append_int(&ied, IAX_IE_FORMAT, c->nativeformats); iax_ie_append_int(&ied, IAX_IE_CAPABILITY, iaxs[callno]->capability); iax_ie_append_short(&ied, IAX_IE_ADSICPE, c->adsicpe); - iax_ie_append_int(&ied, IAX_IE_DATETIME, iax2_datetime(tz)); - /* Transmit the string in a "NEW" request */ -#if 0 - /* XXX We have no equivalent XXX */ - if (option_verbose > 2) - ast_verbose(VERBOSE_PREFIX_3 "Calling using options '%s'\n", requeststr); -#endif + iax_ie_append_int(&ied, IAX_IE_DATETIME, iax2_datetime(cai.timezone)); + if (iaxs[callno]->maxtime) { /* Initialize pingtime and auto-congest time */ iaxs[callno]->pingtime = iaxs[callno]->maxtime / 2; @@ -2970,10 +3004,13 @@ static int iax2_call(struct ast_channel *c, char *dest, int timeout) iaxs[callno]->pingtime = autokill / 2; iaxs[callno]->initid = ast_sched_add(sched, autokill * 2, auto_congest, CALLNO_TO_PTR(callno)); } - send_command(iaxs[callno], AST_FRAME_IAX, - IAX_COMMAND_NEW, 0, ied.buf, ied.pos, -1); + + /* Transmit the string in a "NEW" request */ + send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_NEW, 0, ied.buf, ied.pos, -1); + ast_mutex_unlock(&iaxsl[callno]); ast_setstate(c, AST_STATE_RINGING); + return 0; } @@ -7559,26 +7596,31 @@ static int iax2_provision(struct sockaddr_in *end, char *dest, const char *templ unsigned int sig; struct sockaddr_in sin; int callno; - int sockfd = defaultsockfd; + struct create_addr_info cai; + + memset(&cai, 0, sizeof(cai)); + if (option_debug) ast_log(LOG_DEBUG, "Provisioning '%s' from template '%s'\n", dest, template); + if (iax_provision_build(&provdata, &sig, template, force)) { ast_log(LOG_DEBUG, "No provisioning found for template '%s'\n", template); return 0; } + if (end) memcpy(&sin, end, sizeof(sin)); - else { - if (create_addr(&sin, NULL, NULL, NULL, dest, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, 0, NULL, NULL, NULL, 0, NULL, 0, &sockfd)) - return -1; - } + else if (create_addr(dest, &sin, &cai)) + return -1; + /* Build the rest of the message */ memset(&ied, 0, sizeof(ied)); iax_ie_append_raw(&ied, IAX_IE_PROVISIONING, provdata.buf, provdata.pos); - callno = find_callno(0, 0, &sin, NEW_FORCE, 1, sockfd); + callno = find_callno(0, 0, &sin, NEW_FORCE, 1, cai.sockfd); if (!callno) return -1; + ast_mutex_lock(&iaxsl[callno]); if (iaxs[callno]) { /* Schedule autodestruct in case they don't ever give us anything back */ @@ -7590,6 +7632,7 @@ static int iax2_provision(struct sockaddr_in *end, char *dest, const char *templ send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_PROVISION, 0, ied.buf, ied.pos, -1); } ast_mutex_unlock(&iaxsl[callno]); + return 1; } @@ -7729,72 +7772,50 @@ static struct ast_channel *iax2_request(const char *type, int format, void *data { int callno; int res; - int sendani; - int maxtime; - int found = 0; int fmt, native; struct sockaddr_in sin; - char s[256]; - char *st, *hostname; struct ast_channel *c; - char *stringp=NULL; - char *portno=NULL; int capability = iax2_capability; - int trunk; - int sockfd = defaultsockfd; - int notransfer = ast_test_flag((&globalflags), IAX_NOTRANSFER); - int usejitterbuf = ast_test_flag((&globalflags), IAX_USEJITTERBUF); - int forcejitterbuf = ast_test_flag((&globalflags), IAX_FORCEJITTERBUF); - - ast_copy_string(s, (char *)data, sizeof(s)); - /* FIXME The next two lines seem useless */ - stringp=s; - strsep(&stringp, "/"); - - stringp=s; - strsep(&stringp, "@"); - st = strsep(&stringp, "@"); - - if (!st) - { - st = s; - } - - hostname = strsep(&st, ":"); - - if (st) { - portno = strsep(&st, ":"); - } + struct parsed_dial_string pds; + struct create_addr_info cai; + + memset(&pds, 0, sizeof(pds)); + parse_dial_string(ast_strdupa(data), &pds); + + memset(&cai, 0, sizeof(cai)); + + ast_copy_flags(&cai, &globalflags, IAX_NOTRANSFER | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); /* Populate our address from the given */ - if (create_addr(&sin, &capability, &sendani, &maxtime, hostname, NULL, &trunk, ¬ransfer, &usejitterbuf, &forcejitterbuf, NULL, NULL, 0, NULL, 0, &found, NULL, NULL, 0, NULL, 0, &sockfd)) { + if (create_addr(pds.peer, &sin, &cai)) { *cause = AST_CAUSE_UNREGISTERED; return NULL; } - if (portno) { - sin.sin_port = htons(atoi(portno)); - } - callno = find_callno(0, 0, &sin, NEW_FORCE, 1, sockfd); + + if (pds.port) + sin.sin_port = htons(atoi(pds.port)); + + callno = find_callno(0, 0, &sin, NEW_FORCE, 1, cai.sockfd); if (callno < 1) { ast_log(LOG_WARNING, "Unable to create call\n"); *cause = AST_CAUSE_CONGESTION; return NULL; } + ast_mutex_lock(&iaxsl[callno]); + /* If this is a trunk, update it now */ - ast_set2_flag(iaxs[callno], trunk, IAX_TRUNK); - if (trunk) + ast_copy_flags(iaxs[callno], &cai, IAX_TRUNK | IAX_SENDANI | IAX_NOTRANSFER | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); + if (ast_test_flag(&cai, IAX_TRUNK)) callno = make_trunk(callno, 1); - /* Keep track of sendani flag */ - ast_set2_flag(iaxs[callno], sendani, IAX_SENDANI); - iaxs[callno]->maxtime = maxtime; - ast_set2_flag(iaxs[callno], notransfer, IAX_NOTRANSFER); - ast_set2_flag(iaxs[callno], usejitterbuf, IAX_USEJITTERBUF); - ast_set2_flag(iaxs[callno], forcejitterbuf, IAX_FORCEJITTERBUF); - if (found) - ast_copy_string(iaxs[callno]->host, hostname, sizeof(iaxs[callno]->host)); + iaxs[callno]->maxtime = cai.maxtime; + if (cai.found) + ast_copy_string(iaxs[callno]->host, pds.peer, sizeof(iaxs[callno]->host)); + c = ast_iax2_new(callno, AST_STATE_DOWN, capability); + ast_mutex_unlock(&iaxsl[callno]); + if (c) { /* Choose a format we can live with */ if (c->nativeformats & format) @@ -7804,7 +7825,8 @@ static struct ast_channel *iax2_request(const char *type, int format, void *data fmt = format; res = ast_translator_best_choice(&fmt, &native); if (res < 0) { - ast_log(LOG_WARNING, "Unable to create translator path for %s to %s on %s\n", ast_getformatname(c->nativeformats), ast_getformatname(fmt), c->name); + ast_log(LOG_WARNING, "Unable to create translator path for %s to %s on %s\n", + ast_getformatname(c->nativeformats), ast_getformatname(fmt), c->name); ast_hangup(c); return NULL; } @@ -7813,6 +7835,7 @@ static struct ast_channel *iax2_request(const char *type, int format, void *data c->readformat = ast_best_codec(c->nativeformats); c->writeformat = c->readformat; } + return c; } @@ -8628,82 +8651,65 @@ static int cache_get_callno_locked(const char *data) { struct sockaddr_in sin; int x; - int sockfd = defaultsockfd; - char st[256], *s; - char *host; - char *username=NULL; - char *password=NULL; - char *context=NULL; int callno; struct iax_ie_data ied; - for (x=0;x<IAX_MAX_CALLS; x++) { + struct create_addr_info cai; + struct parsed_dial_string pds; + + for (x=0; x<IAX_MAX_CALLS; x++) { /* Look for an *exact match* call. Once a call is negotiated, it can only look up entries for a single context */ if (!ast_mutex_trylock(&iaxsl[x])) { - if (iaxs[x] && !strcasecmp(data, iaxs[x]->dproot)) { + if (iaxs[x] && !strcasecmp(data, iaxs[x]->dproot)) return x; - } ast_mutex_unlock(&iaxsl[x]); } } - memset(&ied, 0, sizeof(ied)); + /* No match found, we need to create a new one */ - ast_copy_string(st, data, sizeof(st)); - /* Grab the host */ - s = strchr(st, '/'); - if (s) { - *s = '\0'; - s++; - context = s; - } - s = strchr(st, '@'); - if (s) { - /* Get username/password if there is one */ - *s='\0'; - username=st; - password = strchr(username, ':'); - if (password) { - *password = '\0'; - password++; - } - s++; - host = s; - } else { - /* Just a hostname */ - host = st; - } + + memset(&cai, 0, sizeof(cai)); + memset(&ied, 0, sizeof(ied)); + memset(&pds, 0, sizeof(pds)); + + parse_dial_string(ast_strdupa(data), &pds); + /* Populate our address from the given */ - if (create_addr(&sin, NULL, NULL, NULL, host, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, 0, NULL, NULL, NULL, 0, NULL, 0, &sockfd)) { + if (create_addr(pds.peer, &sin, &cai)) return -1; - } - ast_log(LOG_DEBUG, "host: %s, user: %s, password: %s, context: %s\n", host, username, password, context); - callno = find_callno(0, 0, &sin, NEW_FORCE, 1, sockfd); + + ast_log(LOG_DEBUG, "peer: %s, username: %s, password: %s, context: %s\n", + pds.peer, pds.username, pds.password, pds.context); + + callno = find_callno(0, 0, &sin, NEW_FORCE, 1, cai.sockfd); if (callno < 1) { ast_log(LOG_WARNING, "Unable to create call\n"); return -1; } + ast_mutex_lock(&iaxsl[callno]); ast_copy_string(iaxs[callno]->dproot, data, sizeof(iaxs[callno]->dproot)); iaxs[callno]->capability = IAX_CAPABILITY_FULLBANDWIDTH; iax_ie_append_short(&ied, IAX_IE_VERSION, IAX_PROTO_VERSION); iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, "TBD"); - if (context) - iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, context); - if (username) - iax_ie_append_str(&ied, IAX_IE_USERNAME, username); + /* the string format is slightly different from a standard dial string, + because the context appears in the 'exten' position + */ + if (pds.exten) + iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, pds.exten); + if (pds.username) + iax_ie_append_str(&ied, IAX_IE_USERNAME, pds.username); iax_ie_append_int(&ied, IAX_IE_FORMAT, IAX_CAPABILITY_FULLBANDWIDTH); iax_ie_append_int(&ied, IAX_IE_CAPABILITY, IAX_CAPABILITY_FULLBANDWIDTH); /* Keep password handy */ - if (password) - ast_copy_string(iaxs[callno]->secret, password, sizeof(iaxs[callno]->secret)); -#if 0 - /* XXX Need equivalent XXX */ - if (option_verbose > 2) - ast_verbose(VERBOSE_PREFIX_3 "Calling TBD using options '%s'\n", requeststr); -#endif + if (pds.password) + ast_copy_string(iaxs[callno]->secret, pds.password, sizeof(iaxs[callno]->secret)); + if (pds.key) + ast_copy_string(iaxs[callno]->outkey, pds.key, sizeof(iaxs[callno]->outkey)); /* Start the call going */ send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_NEW, 0, ied.buf, ied.pos, -1); + return callno; } diff --git a/contrib/asterisk-ng-doxygen b/contrib/asterisk-ng-doxygen index 8e4a924f3bf3c96875d960bfe9269df8dbcb6411..1874ff22a3a33edb9940bb234a35362b96abde8b 100755 --- a/contrib/asterisk-ng-doxygen +++ b/contrib/asterisk-ng-doxygen @@ -451,7 +451,15 @@ WARN_LOGFILE = # with spaces. INPUT = ./ \ - include/asterisk + include/asterisk \ + channels \ + funcs \ + apps \ + cdr \ + codecs \ + formats \ + pbx \ + res # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp