[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