[svn-commits] russell: trunk r180261 - /trunk/channels/chan_sip.c

SVN commits to the Digium repositories svn-commits at lists.digium.com
Wed Mar 4 15:01:10 CST 2009


Author: russell
Date: Wed Mar  4 15:01:05 2009
New Revision: 180261

URL: http://svn.digium.com/svn-view/asterisk?view=rev&rev=180261
Log:
Resolve object matching issues related to the removal of the sip_user object.

Previously, chan_sip had both sip_peer and sip_user objects in memory.  A
patch went in to remove sip_user to simplify the code, since everything
could be done with just sip_peer.  This patch resolves some regressions
found that were introduced by those changes.

This code comes from svn/asterisk/team/group/sip-object-matching/.

Here is a list of the changes that have been made:

1) When doing a match by name with the find_peer() function, make it much
   easier to specify which objects should be matched by having a parameter
   that specifies exactly which object types should be considered.  Also,
   update find_by_name() to handle this parameter.  Finally, update all
   code to use the new option values.

2) When looking up an object for an outbound request by name, consider
   peers only.  (create_addr())

3) Only match peers on an incoming registration request.

4) When doing authentication (except for SUBSCRIBE), look up users
   by name, instead of all objects by name.
   
5) When doing authentication (except for SUBSCRIBE), after looking for
   a user by name, look for a peer by IP address, instead of all objects
   by IP address.

6) When handling the SIP qualify CLI command or manager action, look for
   a peer by name, instead of any object by name.

7) When handling the SIP unregister CLI command, look for a peer by name,
   instead of any object by name.

9) In sip_do_debug_peer(), search for a peer by name, instead of any object
   by name.

9) When handling the SIPPEER() dialplan function, search for a peer by name,
   instead of any object by name.

10) In the following session timer related functions, st_get_se(),
    st_get_refresher(), and st_get_mode(), when looking for an object for a
    given sip_pvt using pvt->peername, look for a peer by name, instead of any
    object by name.

11) Fix build_peer() to properly handle the case where separate type=peer and
    type=user entries were specified in sip.conf.

(closes issue #14505)
Reported by: lmadsen

Review: http://reviewboard.digium.com/r/172/

Modified:
    trunk/channels/chan_sip.c

Modified: trunk/channels/chan_sip.c
URL: http://svn.digium.com/svn-view/asterisk/trunk/channels/chan_sip.c?view=diff&rev=180261&r1=180260&r2=180261
==============================================================================
--- trunk/channels/chan_sip.c (original)
+++ trunk/channels/chan_sip.c Wed Mar  4 15:01:05 2009
@@ -487,8 +487,9 @@
 #endif
 
 /* Arguments for find_peer */
-#define	FINDALLDEVICES	FALSE
-#define FINDONLYUSERS	TRUE
+#define FINDUSERS (1 << 0)
+#define FINDPEERS (1 << 1)
+#define FINDALLDEVICES (FINDUSERS | FINDPEERS)
 
 #define	SIPBUFSIZE		512		/*!< Buffer size for many operations */
 
@@ -1898,7 +1899,6 @@
 	
 	/*XXX Seems like we suddenly have two flags with the same content. Why? To be continued... */
 	enum sip_peer_type type; /*!< Distinguish between "user" and "peer" types. This is used solely for CLI and manager commands */
-	char onlymatchonip;		/*!< Only match on IP for incoming calls (old type=peer) */
 };
 
 
@@ -2438,7 +2438,7 @@
 
 /*--- Device object handling */
 static struct sip_peer *temp_peer(const char *name);
-static struct sip_peer *build_peer(const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime, int ispeer);
+static struct sip_peer *build_peer(const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime);
 static int update_call_counter(struct sip_pvt *fup, int event);
 static void sip_destroy_peer(struct sip_peer *peer);
 static void sip_destroy_peer_fn(void *peer);
@@ -4471,7 +4471,7 @@
 
 
 	/* Peer found in realtime, now build it in memory */
-	peer = build_peer(newpeername, var, varregs, TRUE, FALSE);
+	peer = build_peer(newpeername, var, varregs, TRUE);
 	if (!peer) {
 		if(peerlist)
 			ast_config_destroy(peerlist);
@@ -4513,38 +4513,52 @@
 static int find_by_name(void *obj, void *arg, void *data, int flags)
 {
 	struct sip_peer *search = obj, *match = arg;
-	int *forcenamematch = data;
+	int *which_objects = data;
 
 	/* Usernames in SIP uri's are case sensitive. Domains are not */
 	if (strcmp(search->name, match->name)) {
 		return 0;
 	}
 
-	/* If we're only looking for name matches, we should avoid type=peer devices,
-	   since these should not match on any name-based search */
-	if (*forcenamematch && search->onlymatchonip) {
-		return 0;
+	switch (*which_objects) {
+	case FINDUSERS:
+		if (!(search->type & SIP_TYPE_USER)) {
+			return 0;
+		}
+		break;
+	case FINDPEERS:
+		if (!(search->type & SIP_TYPE_PEER)) {
+			return 0;
+		}
+		break;
+	case FINDALLDEVICES:
+		break;
 	}
 
 	return CMP_MATCH | CMP_STOP;
 }
 
-/*! \brief Locate device by name or ip address 
+/*! 
+ * \brief Locate device by name or ip address 
+ *
+ * \param which_objects Define which objects should be matched when doing a lookup
+ *        by name.  Valid options are FINDUSERS, FINDPEERS, or FINDALLDEVICES.
+ *        Note that this option is not used at all when doing a lookup by IP.
+ *
  *	This is used on find matching device on name or ip/port.
-	If the device was declared as type=peer, we don't match on peer name on incoming INVITEs.
-	
-	\note Avoid using this function in new functions if there is a way to avoid it,
-	since it might cause a database lookup.
-
-*/
-static struct sip_peer *find_peer(const char *peer, struct sockaddr_in *sin, int realtime, int forcenamematch, int devstate_only)
+ * If the device was declared as type=peer, we don't match on peer name on incoming INVITEs.
+ *
+ * \note Avoid using this function in new functions if there is a way to avoid it,
+ * since it might cause a database lookup.
+ */
+static struct sip_peer *find_peer(const char *peer, struct sockaddr_in *sin, int realtime, int which_objects, int devstate_only)
 {
 	struct sip_peer *p = NULL;
 	struct sip_peer tmp_peer;
 
 	if (peer) {
 		ast_copy_string(tmp_peer.name, peer, sizeof(tmp_peer.name));
-		p = ao2_t_callback_data(peers, OBJ_POINTER, find_by_name, &tmp_peer, &forcenamematch, "ao2_find in peers table");
+		p = ao2_t_callback_data(peers, OBJ_POINTER, find_by_name, &tmp_peer, &which_objects, "ao2_find in peers table");
 	} else if (sin) { /* search by addr? */
 		tmp_peer.addr.sin_addr.s_addr = sin->sin_addr.s_addr;
 		tmp_peer.addr.sin_port = sin->sin_port;
@@ -4839,7 +4853,7 @@
 	dialog->sa.sin_family = AF_INET;
 	dialog->timer_t1 = global_t1; /* Default SIP retransmission timer T1 (RFC 3261) */
 	dialog->timer_b = global_timer_b; /* Default SIP transaction timer B (RFC 3261) */
-	peer = find_peer(peername, NULL, TRUE, FINDALLDEVICES, FALSE);
+	peer = find_peer(peername, NULL, TRUE, FINDPEERS, FALSE);
 
 	if (peer) {
 		int res;
@@ -11972,7 +11986,7 @@
 
 	ast_string_field_set(p, exten, name);
 	build_contact(p);
-	peer = find_peer(name, NULL, TRUE, FINDALLDEVICES, FALSE);
+	peer = find_peer(name, NULL, TRUE, FINDPEERS, FALSE);
 	if (!(peer && ast_apply_ha(peer->ha, sin))) {
 		/* Peer fails ACL check */
 		if (peer) {
@@ -12884,11 +12898,11 @@
 		peer = find_peer(of, NULL, TRUE, FINDALLDEVICES, FALSE);
 	} else {
 		/* First find devices based on username (avoid all type=peer's) */
-		peer = find_peer(of, NULL, TRUE, FINDONLYUSERS, FALSE);
+		peer = find_peer(of, NULL, TRUE, FINDUSERS, FALSE);
 
 		/* Then find devices based on IP */
 		if (!peer) {
-			peer = find_peer(NULL, &p->recv, TRUE, FINDALLDEVICES, FALSE);
+			peer = find_peer(NULL, &p->recv, TRUE, FINDPEERS, FALSE);
 		}
 	}
 
@@ -14226,7 +14240,7 @@
 		return CLI_SHOWUSAGE;
 
 	load_realtime = (argc == 5 && !strcmp(argv[4], "load")) ? TRUE : FALSE;
-	if ((peer = find_peer(argv[3], NULL, load_realtime, FINDALLDEVICES, FALSE))) {
+	if ((peer = find_peer(argv[3], NULL, load_realtime, FINDPEERS, FALSE))) {
 		sip_poke_peer(peer, 1);
 		unref_peer(peer, "qualify: done with peer");
 	} else if (type == 0) {
@@ -14308,7 +14322,8 @@
 		return CLI_SHOWUSAGE;
 
 	load_realtime = (argc == 5 && !strcmp(argv[4], "load")) ? TRUE : FALSE;
-	peer = find_peer(argv[3], NULL, load_realtime, FINDALLDEVICES, FALSE);
+	peer = find_peer(argv[3], NULL, load_realtime, FINDPEERS, FALSE);
+
 	if (s) { 	/* Manager */
 		if (peer) {
 			const char *id = astman_get_header(m, "ActionID");
@@ -14590,7 +14605,7 @@
 	/* Load from realtime storage? */
 	load_realtime = (a->argc == 5 && !strcmp(a->argv[4], "load")) ? TRUE : FALSE;
 
-	if ((user = find_peer(a->argv[3], NULL, load_realtime, TRUE, FALSE))) {
+	if ((user = find_peer(a->argv[3], NULL, load_realtime, FINDUSERS, FALSE))) {
 		ao2_lock(user);
 		ast_cli(a->fd, "\n\n");
 		ast_cli(a->fd, "  * Name       : %s\n", user->name);
@@ -14748,7 +14763,7 @@
 	if (a->argc != 3)
 		return CLI_SHOWUSAGE;
 	
-	if ((peer = find_peer(a->argv[2], NULL, load_realtime, FINDALLDEVICES, TRUE))) {
+	if ((peer = find_peer(a->argv[2], NULL, load_realtime, FINDPEERS, TRUE))) {
 		if (peer->expire > 0) {
 			expire_register(ref_peer(peer, "ref for expire_register"));
 			ast_cli(a->fd, "Unregistered peer \'%s\'\n\n", a->argv[2]);
@@ -15758,7 +15773,7 @@
 /*! \brief  Turn on SIP debugging for a given peer */
 static char *sip_do_debug_peer(int fd, char *arg)
 {
-	struct sip_peer *peer = find_peer(arg, NULL, TRUE, FINDALLDEVICES, FALSE);
+	struct sip_peer *peer = find_peer(arg, NULL, TRUE, FINDPEERS, FALSE);
 	if (!peer)
 		ast_cli(fd, "No such peer '%s'\n", arg);
 	else if (peer->addr.sin_addr.s_addr == 0)
@@ -16213,7 +16228,7 @@
 	else
 		colname = "ip";
 
-	if (!(peer = find_peer(data, NULL, TRUE, FINDALLDEVICES, FALSE)))
+	if (!(peer = find_peer(data, NULL, TRUE, FINDPEERS, FALSE)))
 		return -1;
 
 	if (!strcasecmp(colname, "ip")) {
@@ -21571,7 +21586,7 @@
 		if (p->stimer->st_cached_max_se) {
 			return p->stimer->st_cached_max_se;
 		} else if (p->peername) {
-			struct sip_peer *pp = find_peer(p->peername, NULL, TRUE, FINDALLDEVICES, FALSE);
+			struct sip_peer *pp = find_peer(p->peername, NULL, TRUE, FINDPEERS, FALSE);
 			if (pp) {
 				p->stimer->st_cached_max_se = pp->stimer.st_max_se;
 				unref_peer(pp, "unref peer pointer from find_peer call in st_get_se");
@@ -21584,7 +21599,7 @@
 		if (p->stimer->st_cached_min_se) {
 			return p->stimer->st_cached_min_se;
 		} else if (p->peername) {
-			struct sip_peer *pp = find_peer(p->peername, NULL, TRUE, FINDALLDEVICES, FALSE);
+			struct sip_peer *pp = find_peer(p->peername, NULL, TRUE, FINDPEERS, FALSE);
 			if (pp) {
 				p->stimer->st_cached_min_se = pp->stimer.st_min_se;
 				unref_peer(pp, "unref peer pointer from find_peer call in st_get_se (2)");
@@ -21606,7 +21621,7 @@
 		return p->stimer->st_cached_ref;
 
 	if (p->peername) {
-		struct sip_peer *pp = find_peer(p->peername, NULL, TRUE, FINDALLDEVICES, FALSE);
+		struct sip_peer *pp = find_peer(p->peername, NULL, TRUE, FINDPEERS, FALSE);
 		if (pp) {
 			p->stimer->st_cached_ref = pp->stimer.st_ref;
 			unref_peer(pp, "unref peer pointer from find_peer call in st_get_refresher");
@@ -21631,7 +21646,7 @@
 		return p->stimer->st_cached_mode;
 
 	if (p->peername) {
-		struct sip_peer *pp = find_peer(p->peername, NULL, TRUE, FINDALLDEVICES, FALSE);
+		struct sip_peer *pp = find_peer(p->peername, NULL, TRUE, FINDPEERS, FALSE);
 		if (pp) {
 			p->stimer->st_cached_mode = pp->stimer.st_mode_oper;
 			unref_peer(pp, "unref peer pointer from find_peer call in st_get_mode");
@@ -22473,7 +22488,7 @@
 }
 
 /*! \brief Build peer from configuration (file or realtime static/dynamic) */
-static struct sip_peer *build_peer(const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime, int ispeer)
+static struct sip_peer *build_peer(const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime)
 {
 	struct sip_peer *peer = NULL;
 	struct ast_ha *oldha = NULL;
@@ -22488,7 +22503,7 @@
 	const char *srvlookup = NULL;
 	static int deprecation_warning = 1;
 	struct ast_str *fullcontact = ast_str_alloca(512);
-	
+
 	if (!realtime || ast_test_flag(&global_flags[1], SIP_PAGE2_RTCACHEFRIENDS)) {
 		/* Note we do NOT use find_peer here, to avoid realtime recursion */
 		/* We also use a case-sensitive comparison (unlike find_peer) so
@@ -22498,13 +22513,13 @@
 		ast_copy_string(tmp_peer.name, name, sizeof(tmp_peer.name));
 		peer = ao2_t_find(peers, &tmp_peer, OBJ_POINTER | OBJ_UNLINK, "find and unlink peer from peers table");
 	}
-	
+
 	if (peer) {
 		/* Already in the list, remove it and it will be added back (or FREE'd)  */
 		found++;
 		if (!(peer->the_mark))
 			firstpass = 0;
- 	} else {
+	} else {
 		if (!(peer = ao2_t_alloc(sizeof(*peer), sip_destroy_peer_fn, "allocate a peer struct")))
 			return NULL;
 
@@ -22519,8 +22534,6 @@
 		} else
 			ast_atomic_fetchadd_int(&speerobjs, 1);
 	}
-
-	peer->onlymatchonip = ispeer;		/* If type=peer, don't match on caller ID for incoming calls */
 
 	/* Note that our peer HAS had its reference count increased */
 	if (firstpass) {
@@ -22528,9 +22541,10 @@
 		oldha = peer->ha;
 		peer->ha = NULL;
 		set_peer_defaults(peer);	/* Set peer defaults */
+		peer->type = 0;
 	}
 	if (!found && name)
-			ast_copy_string(peer->name, name, sizeof(peer->name));
+		ast_copy_string(peer->name, name, sizeof(peer->name));
 
 	/* If we have channel variables, remove them (reload) */
 	if (peer->chanvars) {
@@ -22584,13 +22598,10 @@
 			}
 		} else if (!strcasecmp(v->name, "type")) {
 			if (!strcasecmp(v->value, "peer")) {
-				peer->onlymatchonip = TRUE;		/* For realtime support, add type=peer in the table */
-				peer->type = SIP_TYPE_PEER;
+				peer->type |= SIP_TYPE_PEER;
 			} else if (!strcasecmp(v->value, "user")) {
-				peer->onlymatchonip = FALSE;
-				peer->type = SIP_TYPE_USER;
+				peer->type |= SIP_TYPE_USER;
 			} else if (!strcasecmp(v->value, "friend")) {
-				peer->onlymatchonip = FALSE;
 				peer->type = SIP_TYPE_USER | SIP_TYPE_PEER;
 			}
 		} else if (!strcasecmp(v->name, "remotesecret")) {
@@ -23667,10 +23678,10 @@
 				hassip = ast_variable_retrieve(ucfg, cat, "hassip");
 				registersip = ast_variable_retrieve(ucfg, cat, "registersip");
 				if (ast_true(hassip) || (!hassip && genhassip)) {
-					peer = build_peer(cat, gen, ast_variable_browse(ucfg, cat), 0, FALSE);
+					peer = build_peer(cat, gen, ast_variable_browse(ucfg, cat), 0);
 					if (peer) {
 						ao2_t_link(peers, peer, "link peer into peer table");
-						if (peer->addr.sin_addr.s_addr) {
+						if ((peer->type & SIP_TYPE_PEER) && peer->addr.sin_addr.s_addr) {
 							ao2_t_link(peers_by_ip, peer, "link peer into peers_by_ip table");
 						}
 						
@@ -23719,27 +23730,24 @@
 			ast_log(LOG_WARNING, "Section '%s' lacks type\n", cat);
 			continue;
 		} else {
-			int is_peer = 0;
 			if (!strcasecmp(utype, "user")) {
-				is_peer = 1;
+				;
 			} else if (!strcasecmp(utype, "friend")) {
-				is_peer = 1;
-			} else if (!strcasecmp(utype, "peer"))
-				is_peer = 2;
-			else {
+				;
+			} else if (!strcasecmp(utype, "peer")) {
+				;
+			} else {
 				ast_log(LOG_WARNING, "Unknown type '%s' for '%s' in %s\n", utype, cat, "sip.conf");
 				continue;
 			}
-			if (is_peer) {
-				peer = build_peer(cat, ast_variable_browse(cfg, cat), NULL, 0, is_peer == 2);
-				if (peer) {
-					ao2_t_link(peers, peer, "link peer into peers table");
-					if (peer->addr.sin_addr.s_addr) {
-						ao2_t_link(peers_by_ip, peer, "link peer into peers_by_ip table");
-					}
-					unref_peer(peer, "unref the result of the build_peer call. Now, the links from the tables are the only ones left.");
-					peer_count++;
+			peer = build_peer(cat, ast_variable_browse(cfg, cat), NULL, 0);
+			if (peer) {
+				ao2_t_link(peers, peer, "link peer into peers table");
+				if ((peer->type & SIP_TYPE_PEER) && peer->addr.sin_addr.s_addr) {
+					ao2_t_link(peers_by_ip, peer, "link peer into peers_by_ip table");
 				}
+				unref_peer(peer, "unref the result of the build_peer call. Now, the links from the tables are the only ones left.");
+				peer_count++;
 			}
 		}
 	}




More information about the svn-commits mailing list