[Asterisk-cvs] asterisk/channels chan_iax2.c,1.297,1.298

kpfleming at lists.digium.com kpfleming at lists.digium.com
Fri Jun 3 14:44:01 CDT 2005


Update of /usr/cvsroot/asterisk/channels
In directory mongoose.digium.com:/tmp/cvs-serv9801/channels

Modified Files:
	chan_iax2.c 
Log Message:
clean up create_addr, and use a structure instead of a large parameter list
make create_addr return the peer's outkey, so dynamic realtime peers can use keys for calls (bug #4431)
add key support for switch connection strings
use a common dial/switch string parser instead of three copies (none of them identical)
make doxygen docs cover the entire source base


Index: chan_iax2.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channels/chan_iax2.c,v
retrieving revision 1.297
retrieving revision 1.298
diff -u -d -r1.297 -r1.298
--- chan_iax2.c	2 Jun 2005 17:45:38 -0000	1.297
+++ chan_iax2.c	3 Jun 2005 18:46:58 -0000	1.298
@@ -2677,114 +2677,107 @@
 	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 @@
 	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 @@
 		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 @@
 	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 @@
 		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 @@
 {
 	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);
+	struct parsed_dial_string pds;
+	struct create_addr_info cai;
 
-	ast_copy_string(s, (char *)data, sizeof(s));
-	/* FIXME The next two lines seem useless */
-	stringp=s;
-	strsep(&stringp, "/");
+	memset(&pds, 0, sizeof(pds));
+	parse_dial_string(ast_strdupa(data), &pds);
 
-	stringp=s;
-	strsep(&stringp, "@");
-	st = strsep(&stringp, "@");
-	
-	if (!st)
-	{
-		st = s;
-	}
-			
-	hostname = strsep(&st, ":");
-	
-        if (st) {	
-		portno = strsep(&st, ":");
-	}							
+	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, &notransfer, &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 @@
 			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 @@
 		c->readformat = ast_best_codec(c->nativeformats);
 		c->writeformat = c->readformat;
 	}
+
 	return c;
 }
 
@@ -8628,82 +8651,65 @@
 {
 	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;
 }
 




More information about the svn-commits mailing list