[svn-commits] branch oej/sipregister r8836 - /team/oej/sipregister/channels/chan_sip.c

svn-commits at lists.digium.com svn-commits at lists.digium.com
Sat Jan 28 10:44:53 MST 2006


Author: oej
Date: Sat Jan 28 11:44:51 2006
New Revision: 8836

URL: http://svn.digium.com/view/asterisk?rev=8836&view=rev
Log:
First stab at fixing multiple outbound registrations to the same host.
We now send a magic random string to the host as contact. On inbound call,
we recognize the string and replace it with the extension. 

Todo: Add initialization of peer that contained the register= line.
	So we don't match on IP on incoming calls.

Modified:
    team/oej/sipregister/channels/chan_sip.c

Modified: team/oej/sipregister/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/team/oej/sipregister/channels/chan_sip.c?rev=8836&r1=8835&r2=8836&view=diff
==============================================================================
--- team/oej/sipregister/channels/chan_sip.c (original)
+++ team/oej/sipregister/channels/chan_sip.c Sat Jan 28 11:44:51 2006
@@ -133,6 +133,8 @@
 static int max_expiry = DEFAULT_MAX_EXPIRY;	/*!< Maximum accepted registration time */
 static int default_expiry = DEFAULT_DEFAULT_EXPIRY;
 static int expiry = DEFAULT_EXPIRY;
+
+#define REG_MAGICMARKER		"ASTZVXW"	/*!< Magic marker for outbound registrations */
 
 #ifndef MAX
 #define MAX(a,b) ((a) > (b) ? (a) : (b))
@@ -697,7 +699,8 @@
 	struct ast_dsp *vad;			/*!< Voice Activation Detection dsp */
 	
 	struct sip_peer *peerpoke;		/*!< If this dialog is to poke a peer, which one */
-	struct sip_registry *registry;		/*!< If this is a REGISTER dialog, to which registry */
+	struct sip_registry *registry;		/*!< If this is a REGISTER dialog, to which registry
+							If this is an INVITE, to which registry */
 	struct ast_rtp *rtp;			/*!< RTP Session */
 	struct ast_rtp *vrtp;			/*!< Video RTP session */
 	struct sip_pkt *packets;		/*!< Packets scheduled for re-transmission */
@@ -837,7 +840,8 @@
 		AST_STRING_FIELD(hostname);	/*!< Domain or host we register to */
 		AST_STRING_FIELD(secret);	/*!< Password in clear text */	
 		AST_STRING_FIELD(md5secret);	/*!< Password in md5 */
-		AST_STRING_FIELD(contact);	/*!< Contact extension */
+		AST_STRING_FIELD(contact);	/*!< Contact used for this registry entry */
+		AST_STRING_FIELD(extension);	/*!< Extension to place incoming calls to */
 		AST_STRING_FIELD(random);
 	);
 	int portno;			/*!<  Optional port override */
@@ -852,6 +856,7 @@
 	struct sockaddr_in us;		/*!< Who the server thinks we are */
 	int noncecount;			/*!< Nonce-count */
 	char lastmsg[256];		/*!< Last Message sent/received */
+	struct sip_peer *peer;		/*!< If we ahve a known peer for this registry entry, use it for incoming calls */
 };
 
 /* --- Linked lists of various objects --------*/
@@ -950,6 +955,7 @@
 static int sip_poke_peer(struct sip_peer *peer);
 static int __sip_do_register(struct sip_registry *r);
 static int restart_monitor(void);
+static char *generate_random_string(char *buf, size_t size);
 
 /*! \brief Definition of this channel for PBX channel registration */
 static const struct ast_channel_tech sip_tech = {
@@ -3300,9 +3306,10 @@
 {
 	struct sip_registry *reg;
 	char username[256];
-	char *hostname=NULL, *secret=NULL, *authuser=NULL;
-	char *porta=NULL;
-	char *contact=NULL;
+	char randomcontact[33];
+	char *hostname = NULL, *secret = NULL, *authuser = NULL;
+	char *porta = NULL;
+	char *extension = NULL;
 	int portnum = 0;
 
 	if (peer) {	/* build string from peer info */
@@ -3319,7 +3326,7 @@
 		*hostname++ = '\0';
 	if (ast_strlen_zero(username) || ast_strlen_zero(hostname)) {
 		ast_log(LOG_WARNING, "Format for registration is %s at line %d\n",
-			"user[:secret[:authuser]]@host[:port][/contact]",
+			"user[:secret[:authuser]]@host[:port][/extension]",
 			lineno);
 		return -1;
 	}
@@ -3332,11 +3339,11 @@
 			*authuser++ = '\0';
 	}
 	/* split host[:port][/contact] */
-	contact = strchr(hostname, '/');
-	if (contact)
-		*contact++ = '\0';
-	if (ast_strlen_zero(contact))
-		contact = "s";
+	extension = strchr(hostname, '/');
+	if (extension)
+		*extension++ = '\0';
+	if (ast_strlen_zero(extension))
+		extension = "s";
 	porta = strchr(hostname, ':');
 	if (porta) {
 		*porta++ = '\0';
@@ -3351,6 +3358,8 @@
 		ast_log(LOG_ERROR, "Out of memory. Can't allocate SIP registry entry\n");
 		return -1;
 	}
+	if (peer)
+		reg->peer = (struct sip_peer * ) peer;	/* Save SIP peer binding for incoming calls */
 
 	if (ast_string_field_init(reg)) {
 		ast_log(LOG_ERROR, "Out of memory. Can't allocate SIP registry strings\n");
@@ -3360,7 +3369,6 @@
 
 	regobjs++;
 	ASTOBJ_INIT(reg);
-	ast_string_field_set(reg, contact, contact);
 	if (username)
 		ast_string_field_set(reg, username, username);
 	if (hostname)
@@ -3369,13 +3377,20 @@
 		ast_string_field_set(reg, authuser, authuser);
 	if (secret)
 		ast_string_field_set(reg, secret, secret);
+
+	ast_string_field_set(reg, extension, extension);
+
+	/* Build a random contact string for this registration entry */
+	generate_random_string(randomcontact, sizeof(randomcontact));
+	ast_string_field_build(reg, contact, "%s-%s", REG_MAGICMARKER, randomcontact);
+	
 	reg->expire = -1;
 	reg->timeout =  -1;
 	reg->refresh = default_expiry;
 	reg->portno = portnum;
 	reg->callid_valid = 0;
 	reg->ocseq = 101;
-	ASTOBJ_CONTAINER_LINK(&regl, reg);	/* Add the new registry entry to the list */
+	ASTOBJ_CONTAINER_LINK(&regl, reg);		/* Add the new registry entry to the list */
 	ASTOBJ_UNREF(reg,sip_registry_destroy);
 	return 0;
 }
@@ -5406,7 +5421,7 @@
 	} else {
 		r->regstate = REG_STATE_UNREGISTERED;
 		r->timeout = -1;
-		res=transmit_register(r, SIP_REGISTER, NULL, NULL);
+		res = transmit_register(r, SIP_REGISTER, NULL, NULL);
 	}
 	manager_event(EVENT_FLAG_SYSTEM, "Registry", "Channel: SIP\r\nUsername: %s\r\nDomain: %s\r\nStatus: %s\r\n", r->username, r->hostname, regstate2str(r->regstate));
 	ASTOBJ_UNREF(r, sip_registry_destroy);
@@ -5445,7 +5460,7 @@
 			r->callid_valid = 1;
 		}
 		/* Allocate SIP packet for registration */
-		p=sip_alloc( r->callid, NULL, 0, SIP_REGISTER);
+		p = sip_alloc( r->callid, NULL, 0, SIP_REGISTER);
 		if (!p) {
 			ast_log(LOG_WARNING, "Unable to allocate registration call\n");
 			return 0;
@@ -5493,7 +5508,8 @@
 		}
 		if (!ast_strlen_zero(r->username))
 			ast_string_field_set(p, username, r->username);
-		/* Save extension in packet */
+
+		/* Save contact in packet */
 		ast_string_field_set(p, exten, r->contact);
 
 		/*
@@ -6617,12 +6633,13 @@
 	return 0;
 }
 
-/*! \brief Find out who the call is for */
+/*! \brief Find out what extension the call is for */
 static int get_destination(struct sip_pvt *p, struct sip_request *oreq)
 {
 	char tmp[256] = "", *uri, *a;
 	char tmpf[256], *from;
 	struct sip_request *req;
+	int localdomain = TRUE;
 	
 	req = oreq;
 	if (!req)
@@ -6674,12 +6691,13 @@
 
 		domain_context[0] = '\0';
 		if (!check_sip_domain(p->domain, domain_context, sizeof(domain_context))) {
+			localdomain = FALSE;
 			if (!allow_external_domains && (req->method == SIP_INVITE || req->method == SIP_REFER)) {
 				ast_log(LOG_DEBUG, "Got SIP %s to non-local domain '%s'; refusing request.\n", sip_methods[req->method].text, p->domain);
 				return -2;
 			}
 		}
-		/* If we have a context defined, overwrite the original context */
+		/* If we have a domain context defined, overwrite the original context */
 		if (!ast_strlen_zero(domain_context))
 			ast_string_field_set(p, context, domain_context);
 	}
@@ -6693,6 +6711,36 @@
 		} else
 			ast_string_field_set(p, fromdomain, from);
 	}
+	
+	/* If the URI starts with our magic marker and has a corresponding
+		entry in the registry, then replace the URI with the extension
+		we want to use */
+	/* We don't have to check this at all if we have no registry entries... */
+	if (localdomain && req->method == SIP_INVITE) {
+		if (option_debug)
+			ast_log(LOG_DEBUG, "Checking %s for magic registry marker \n", uri);
+		/* Check if the incoming URI is a registry entry */
+		/* Need a function in ASTOBJ to check if there are objects
+			in the container at all here to avoid this check 
+			when we have no registry entries */
+		if (!strncmp(uri, REG_MAGICMARKER, strlen(REG_MAGICMARKER))) {
+			if (option_debug)
+				ast_log(LOG_DEBUG, "Checking for %s in registry\n", uri);
+			/* Traverse the registry to find something */
+			int found = FALSE;
+			ASTOBJ_CONTAINER_TRAVERSE(&regl, !found, do {
+				ASTOBJ_RDLOCK(iterator);
+				if (!strcmp(uri, iterator->contact)) {
+					found = TRUE;
+					/* Use the extension of this registry item for the incoming call */
+					uri = (char *) iterator->extension;
+					p->registry = iterator;
+				}
+				ASTOBJ_UNLOCK(iterator);
+			} while(0));
+		}
+	}
+
 	if (sip_debug_test_pvt(p))
 		ast_verbose("Looking for %s in %s (domain %s)\n", uri, p->context, p->domain);
 
@@ -7226,6 +7274,7 @@
 		if (peer) {
 			if (debug)
 				ast_verbose("Found peer '%s'\n", peer->name);
+
 			/* Take the peer */
 			ast_copy_flags(p, peer, SIP_FLAGS_TO_COPY);
 
@@ -10423,6 +10472,7 @@
 		}
 	} else if (debug)
 		ast_verbose("Ignoring this INVITE request\n");
+
 	if (!p->lastinvite && !ignore && !p->owner) {
 
 		/* Handle authentication if this is our first invite */



More information about the svn-commits mailing list