[asterisk-commits] rizzo: branch rizzo/astobj2 r47336 - /team/rizzo/astobj2/channels/chan_sip.c

asterisk-commits at lists.digium.com asterisk-commits at lists.digium.com
Wed Nov 8 11:27:49 MST 2006


Author: rizzo
Date: Wed Nov  8 12:27:48 2006
New Revision: 47336

URL: http://svn.digium.com/view/asterisk?rev=47336&view=rev
Log:
prepare the conversion of the dialoglist to astobj2.
All the new code is commented out so still works as before.
If you uncomment the #define USE_AO2 line, the code still
compiles but doesn't run because sip_pvt are not yet
allocated correctly.

The goal here is to see how the astobj2 API match with
common usage patterns. Ideally, you should be able to
switch from hand-written lists to astobj2 with minimal
differences in the sources, basically just the for()
loop heading, and the constructor/destructors.

And, if the API is correct, the locking requirements with
astobj2 should be a lot lower because many cases hwere we
currently lock things are handled by keeping a refcount.


Modified:
    team/rizzo/astobj2/channels/chan_sip.c

Modified: team/rizzo/astobj2/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/team/rizzo/astobj2/channels/chan_sip.c?rev=47336&r1=47335&r2=47336&view=diff
==============================================================================
--- team/rizzo/astobj2/channels/chan_sip.c (original)
+++ team/rizzo/astobj2/channels/chan_sip.c Wed Nov  8 12:27:48 2006
@@ -993,6 +993,24 @@
 							you know more) */
 };
 
+//#define	USE_AO2
+#ifdef	USE_AO2	/* astobj2 implementation */
+#include "asterisk/astobj2.h"
+ao2_container *dialoglist;
+
+/* we never need to lock these */
+static void dialoglist_lock(void)
+{
+}
+
+static void dialoglist_unlock(void)
+{
+}
+
+#else	/* normal container */
+#define	CMP_MATCH	1
+#define	CMP_STOP	2
+
 static struct sip_pvt *dialoglist = NULL;
 
 /*! \brief Protect the SIP dialog list (of sip_pvt's) */
@@ -1008,6 +1026,7 @@
 {
 	ast_mutex_unlock(&dialoglock);
 }
+#endif
 
 #define FLAG_RESPONSE (1 << 0)
 #define FLAG_FATAL (1 << 1)
@@ -2997,6 +3016,9 @@
  */
 static void sip_pvt_unlink(struct sip_pvt *p)
 {
+#ifdef USE_AO2
+	ao2_unlink(dialoglist, p);
+#else
 	struct sip_pvt *cur, *prev = NULL;
 
 	dialoglist_lock();
@@ -3009,6 +3031,7 @@
 	dialoglist_unlock();
 	if (!cur)
 		ast_log(LOG_WARNING, "Trying to destroy \"%s\", not found in dialog list?!?! \n", p->callid);
+#endif
 }
 
 /*! \brief Execute destruction of SIP dialog structure, release memory.
@@ -4376,10 +4399,14 @@
 	ast_string_field_set(p, context, default_context);
 
 	/* Add to active dialog list */
+#ifdef USE_AO2
+	ao2_link(dialoglist, p);
+#else
 	dialoglist_lock();
 	p->next = dialoglist;
 	dialoglist = p;
 	dialoglist_unlock();
+#endif
 	if (option_debug)
 		ast_log(LOG_DEBUG, "Allocating new SIP dialog for %s - %s (%s)\n", callid ? callid : "(No Call-ID)", sip_methods[intended_method].text, p->rtp ? "With RTP" : "No RTP");
 	return p;
@@ -4398,8 +4425,10 @@
  * code to determine whether this is the pvt that we are looking for.
  * Return FALSE if not found, true otherwise. p is unlocked.
  */
-static int find_call_cb(struct sip_pvt *p, struct find_call_cb_arg *arg)
-{
+static int find_call_cb(void *__p, void *__arg, int flags)
+{
+	struct sip_pvt *p = __p;
+	struct find_call_cb_arg *arg = __arg;
 	/* In pedantic, we do not want packets with bad syntax to be connected to a PVT */
 	int found = FALSE;
 	if (arg->method == SIP_REGISTER)
@@ -4473,9 +4502,16 @@
 	dialoglist_lock();
 	if (profile_id == -1)
 		profile_id = ast_add_profile("find_call", 0);
+#ifdef USE_AO2
+	p = ao2_callback(dialoglist, OBJ_DATA, find_call_cb, &arg);
+	if (p) {
+		sip_pvt_lock(p);
+		return p;
+	}
+#else
 	ast_mark(profile_id, 1 /* start */);
 	for (p = dialoglist; p; p = p->next) {
-		if (find_call_cb(p, &arg)) {
+		if (find_call_cb(p, &arg, 0)) {
 			/* Found the call, lock p before unlocking the container */
 			ast_mark(profile_id, 0 /* stop */);
 			sip_pvt_lock(p);
@@ -4487,6 +4523,7 @@
 	dialoglist_unlock();
 	if (p)
 		return p;
+#endif
 	
 	/* See if the method is capable of creating a dialog */
 	if (sip_methods[intended_method].can_create == CAN_CREATE_DIALOG) {
@@ -8616,8 +8653,11 @@
 	const char *totag;
 };
 
-static int find_pvt_byid_cb(struct sip_pvt *pvt, struct __find_byid_arg *arg)
-{
+static int find_pvt_byid_cb(void *__pvt, void *__arg, int flags)
+{
+	struct sip_pvt *pvt = __pvt;
+	struct __find_byid_arg *arg = __arg;
+
 	if (strcmp(pvt->callid, arg->callid))
 		return 0;	/* not found */
 
@@ -8639,7 +8679,7 @@
 			pvt->theirtag, pvt->tag);
 
 	lock_pvt_and_owner(pvt, 0 /* try forever */); /* safe, dialoglist is locked */
-	return 1;
+	return CMP_MATCH | CMP_STOP;
 }
 
 /*! \brief Lock dialog lock and find matching pvt lock  
@@ -8662,10 +8702,14 @@
 
 	/* Search dialogs and find the match */
 	dialoglist_lock();
+#ifdef USE_AO2
+	sip_pvt_ptr = ao2_callback(dialoglist, OBJ_DATA, find_pvt_byid_cb, &arg);
+#else
 	for (sip_pvt_ptr = dialoglist; sip_pvt_ptr; sip_pvt_ptr = sip_pvt_ptr->next) {
-		if (find_pvt_byid_cb(sip_pvt_ptr, &arg))
+		if (find_pvt_byid_cb(sip_pvt_ptr, &arg, 0))
 			break;
 	}
+#endif
 	dialoglist_unlock();
 	if (option_debug > 3 && !sip_pvt_ptr)
 		ast_log(LOG_DEBUG, "Found no match for callid %s to-tag %s from-tag %s\n", callid, totag, fromtag);
@@ -10540,8 +10584,11 @@
 #define FORMAT3 "%-15.15s  %-10.10s  %-11.11s  %-15.15s  %-13.13s  %-15.15s %-10.10s\n"
 #define FORMAT2 "%-15.15s  %-10.10s  %-11.11s  %-11.11s  %-4.4s  %-7.7s  %-15.15s\n"
 #define FORMAT  "%-15.15s  %-10.10s  %-11.11s  %5.5d/%5.5d  %-4.4s  %-3.3s %-3.3s  %-15.15s %-10.10s\n"
-static int show_chanannels_cb(struct sip_pvt *cur, struct __show_chan_arg *arg)
-{
+static int show_chanannels_cb(void *__cur, void *__arg, int flags)
+{
+	struct sip_pvt *cur = __cur;
+	struct __show_chan_arg *arg = __arg;
+
 	if (cur->subscribed == NONE && !arg->subscriptions) {
 		/* set if SIP transfer in progress */
 		const char *referstatus = cur->refer ? referstatus2str(cur->refer->status) : "";
@@ -10587,9 +10634,14 @@
 	else 
 		ast_cli(fd, FORMAT3, "Peer", "User", "Call ID", "Extension", "Last state", "Type", "Mailbox");
 	dialoglist_lock();
+#ifdef USE_AO2
+	cur = NULL;	/* silence compiler */
+        ao2_callback(dialoglist, 0, show_chanannels_cb, &arg);
+#else
 	for (cur = dialoglist; cur; cur = cur->next) {
-		show_chanannels_cb(cur, &arg);
-	}
+		show_chanannels_cb(cur, &arg, 0);
+	}
+#endif
 	dialoglist_unlock();
 	if (!subscriptions)
 		ast_cli(fd, "%d active SIP channel%s\n", arg.numchans, (arg.numchans != 1) ? "s" : "");
@@ -10609,6 +10661,17 @@
 	char *c = NULL;
 	int wordlen = strlen(word);
 
+#ifdef USE_AO2
+	ao2_iterator i = ao2_iterator_init(dialoglist, 0);
+	while ( (cur = ao2_iterator_next(&i)) ) {
+		if (!strncasecmp(word, cur->callid, wordlen) && ++which > state) {
+			c = ast_strdup(cur->callid);
+			ao2_ref(cur, -1);
+			break;
+		}
+		ao2_ref(cur, -1);
+	}
+#else
 	dialoglist_lock();
 	for (cur = dialoglist; cur; cur = cur->next) {
 		if (!strncasecmp(word, cur->callid, wordlen) && ++which > state) {
@@ -10617,6 +10680,7 @@
 		}
 	}
 	dialoglist_unlock();
+#endif
 	return c;
 }
 
@@ -10747,13 +10811,13 @@
 };
 
 /*! \brief show one channel */
-static int show_channel_cb(const struct sip_pvt *cur, struct pvt_cb_arg *arg)
+static void show_channel_cb(const struct sip_pvt *cur, struct pvt_cb_arg *arg)
 {
 	char formatbuf[BUFSIZ/2];
 	int fd = arg->fd;
 
 	if (strncasecmp(cur->callid, arg->str, arg->len))
-		return 0;
+		return;
 	ast_cli(fd,"\n");
 	if (cur->subscribed != NONE)
 		ast_cli(fd, "  * Subscription (type: %s)\n", subscription_type2str(cur->subscribed));
@@ -10802,7 +10866,6 @@
 		ast_cli(fd, "(none)\n");
 	ast_cli(fd, "\n\n");
 	arg->found++;
-	return 1;	/* found */
 }
 
 /*! \brief Show details of one active dialog */
@@ -10818,23 +10881,33 @@
 	arg.len = strlen(argv[3]);
 	arg.found = 0;
 	dialoglist_lock();
+#ifdef USE_AO2
+    {
+	ao2_iterator i = ao2_iterator_init(dialoglist, 0);
+	while ( (cur = ao2_iterator_next(&i)) ) {
+		show_channel_cb(cur, &arg);
+		ao2_ref(cur, -1);
+	}
+    }
+#else
 	for (cur = dialoglist; cur; cur = cur->next) {
 		show_channel_cb(cur, &arg);
 	}
+#endif
 	dialoglist_unlock();
 	if (arg.found == 0) 
 		ast_cli(fd, "No such SIP Call ID starting with '%s'\n", argv[3]);
 	return RESULT_SUCCESS;
 }
 
-static int show_history_cb(const struct sip_pvt *cur, struct pvt_cb_arg *arg)
+static void show_history_cb(const struct sip_pvt *cur, struct pvt_cb_arg *arg)
 {
 	int fd = arg->fd;
 	struct sip_history *hist;
 	int x = 0;
 
 	if (strncasecmp(cur->callid, arg->str, arg->len))
-		return 0;	/* not found */
+		return;	/* not found */
 
 	ast_cli(fd,"\n");
 	if (cur->subscribed != NONE)
@@ -10847,7 +10920,6 @@
 	if (x == 0)
 		ast_cli(fd, "Call '%s' has no history\n", cur->callid);
 	arg->found++;
-	return 0;
 }
 
 /*! \brief Show history details of one dialog */
@@ -10865,9 +10937,19 @@
 	arg.len = strlen(argv[3]);
 	arg.found = 0;
 	dialoglist_lock();
+#ifdef USE_AO2
+    {
+	ao2_iterator i = ao2_iterator_init(dialoglist, 0);
+	while ( (cur = ao2_iterator_next(&i)) ) {
+		show_history_cb(cur, &arg);
+		ao2_ref(cur, -1);
+	}
+    }
+#else
 	for (cur = dialoglist; cur; cur = cur->next) {
 		show_history_cb(cur, &arg);
 	}
+#endif
 	dialoglist_unlock();
 	if (!arg.found) 
 		ast_cli(fd, "No such SIP Call ID starting with '%s'\n", argv[3]);
@@ -14478,8 +14560,6 @@
 				ASTOBJ_UNLOCK(p->relatedpeer);
 			}
 		} else {
-			struct sip_pvt *p_old;
-
 			if ((firststate = ast_extension_state(NULL, p->context, p->exten)) < 0) {
 
 				ast_log(LOG_ERROR, "Got SUBSCRIBE for extension %s@%s from %s, but there is no hint for that extension\n", p->exten, p->context, ast_inet_ntoa(p->sa.sin_addr));
@@ -14500,6 +14580,31 @@
 			ignored (or generate errors)
 			*/
 			dialoglist_lock();
+			{
+			struct sip_pvt *p_old;
+
+#ifdef USE_AO2
+		/* XXX we should really use a callback here */
+			ao2_iterator i = ao2_iterator_init(dialoglist, 0);
+			while ((p_old = ao2_iterator_next(&i))) {
+				if (p_old == p ||
+				    p_old->initreq.method != SIP_SUBSCRIBE ||
+				    p_old->subscribed == NONE) {
+					ao2_ref(p_old, -1);
+					continue;
+				}
+				if (!strcmp(p_old->username, p->username)) {
+					if (!strcmp(p_old->exten, p->exten) &&
+					    !strcmp(p_old->context, p->context)) {
+						ast_set_flag(&p_old->flags[0], SIP_NEEDDESTROY);
+						sip_pvt_unlock(p_old);
+						ao2_ref(p_old, -1);
+						break;
+					}
+				}
+				ao2_ref(p_old, -1);
+			}
+#else
 			for (p_old = dialoglist; p_old; p_old = p_old->next) {
 				if (p_old == p)
 					continue;
@@ -14517,6 +14622,8 @@
 					}
 				}
 				sip_pvt_unlock(p_old);
+			}
+#endif
 			}
 			dialoglist_unlock();
 		}
@@ -15023,9 +15130,27 @@
 		if (!fastrestart) {
 			struct sip_pvt *cur, *prev = NULL;
 			time_t t;
-
 			dialoglist_lock();
 			t = time(NULL);
+#ifdef USE_AO2
+	/* XXX should really use a callback here */
+	{
+			ao2_iterator i = ao2_iterator_init(dialoglist, 0);
+
+			prev = NULL;	/* silence compiler */
+			while ((cur = ao2_iterator_next(&i))) {
+				sip_pvt_lock(cur);
+				check_rtp_timeout(cur, t);
+				if (ast_test_flag(&cur->flags[0], SIP_NEEDDESTROY) && !cur->packets && !cur->owner) {
+					sip_pvt_unlock(cur);
+					ao2_unlink(dialoglist, cur);
+					ao2_ref(cur, -1);
+					__sip_destroy(cur);
+				} else
+					ao2_ref(cur, -1);
+			}
+	}
+#else
 			cur = dialoglist;
         		while (cur) {
 				sip_pvt_lock(cur);
@@ -15049,6 +15174,7 @@
 					cur = cur->next;
 				}
 			}
+#endif
 			dialoglist_unlock();
 		}
 
@@ -17382,6 +17508,16 @@
 	ast_manager_unregister("SIPpeers");
 	ast_manager_unregister("SIPshowpeer");
 
+#ifdef USE_AO2
+	{
+		ao2_iterator i = ao2_iterator_init(dialoglist, 0);
+		while ((p = ao2_iterator_next(&i))) {
+			if (p->owner)
+				ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
+			ao2_ref(p, -1);
+		}
+	}
+#else
 	dialoglist_lock();
 	/* Hangup all dialogs if they have an owner */
 	for (p = dialoglist; p ; p = p->next) {
@@ -17389,6 +17525,7 @@
 			ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
 	}
 	dialoglist_unlock();
+#endif
 
 	ast_mutex_lock(&monlock);
 	if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP)) {
@@ -17399,6 +17536,11 @@
 	monitor_thread = AST_PTHREADT_STOP;
 	ast_mutex_unlock(&monlock);
 
+#ifdef USE_AO2
+	pl = NULL;	/* XXX silence compiler */
+	ao2_ref(dialoglist, -1);
+	dialoglist = NULL;
+#else
 	dialoglist_lock();
 	/* Destroy all the dialogs and free their memory */
 	p = dialoglist;
@@ -17409,7 +17551,7 @@
 	}
 	dialoglist = NULL;
 	dialoglist_unlock();
-
+#endif
 	/* Free memory for local network address mask */
 	ast_free_ha(localaddr);
 



More information about the asterisk-commits mailing list