[asterisk-commits] murf: branch murf/bug11210 r89548 - /team/murf/bug11210/channels/chan_sip.c
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Sun Nov 25 00:32:19 CST 2007
Author: murf
Date: Sun Nov 25 00:32:19 2007
New Revision: 89548
URL: http://svn.digium.com/view/asterisk?view=rev&rev=89548
Log:
Good time to checkpoint. compiles, but it needs a ton of work still. Roughed in most traversals and searches. Need to make sure refs are properly incr. and decr.; the right kind of traversals/locks, etc.
Modified:
team/murf/bug11210/channels/chan_sip.c
Modified: team/murf/bug11210/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/team/murf/bug11210/channels/chan_sip.c?view=diff&rev=89548&r1=89547&r2=89548
==============================================================================
--- team/murf/bug11210/channels/chan_sip.c (original)
+++ team/murf/bug11210/channels/chan_sip.c Sun Nov 25 00:32:19 2007
@@ -1127,7 +1127,10 @@
* the container and individual items, and functions to add/remove
* references to the individual items.
*/
-static struct sip_pvt *dialoglist = NULL;
+/* static struct sip_pvt *dialoglist = NULL; */
+
+struct ao2_container *dialogs;
+
/*! \brief Protect the SIP dialog list (of sip_pvt's) */
AST_MUTEX_DEFINE_STATIC(dialoglock);
@@ -1209,6 +1212,7 @@
/* things that don't belong in flags */
char is_realtime; /*!< this is a 'realtime' user */
+ char theMark; /*!< moved out of the ASTOBJ fields; that which bears theMark should be deleted! */
int amaflags; /*!< AMA flags for billing */
int callingpres; /*!< Calling id presentation */
@@ -1280,6 +1284,7 @@
char rt_fromcontact; /*!< P: copy fromcontact from realtime */
char host_dynamic; /*!< P: Dynamic Peers register with Asterisk */
char selfdestruct; /*!< P: Automatic peers need to destruct themselves */
+ char theMark; /*!< moved out of ASTOBJ into struct proper; That with bears theMark should be deleted! */
int expire; /*!< When to expire this peer registration */
int capability; /*!< Codec capability */
@@ -1359,8 +1364,10 @@
#ifdef LOW_MEMORY
#define MAX_PEER_BUCKETS 17
+#define MAX_DIALOG_BUCKETS 17
#else
#define MAX_PEER_BUCKETS 563
+#define MAX_DIALOG_BUCKETS 563
#endif
#define MAX_USER_BUCKETS MAX_PEER_BUCKETS
@@ -1370,6 +1377,7 @@
/*! \brief The peer list: Peers and Friends */
struct ao2_container *peers;
+struct ao2_container *peers_by_ip;
/*! \brief The register list: Other SIP proxies we register with and place calls to */
static struct ast_register_list {
@@ -1404,7 +1412,10 @@
{
const struct sip_peer *peer = obj;
- return ast_str_hash(peer->name);
+ if (ast_test_flag(&peer->flags[0], SIP_INSECURE_PORT))
+ return peer->addr.sin_addr.s_addr;
+ else
+ return peer->addr.sin_addr.s_addr + peer->addr.sin_port;
}
/*!
@@ -1413,8 +1424,17 @@
static int peer_ipcmp_cb(void *obj, void *arg, int flags)
{
struct sip_peer *peer = obj, *peer2 = arg;
-
- return !strcasecmp(peer->name, peer2->name) ? CMP_MATCH : 0;
+
+ if (peer->addr.sin_addr.s_addr != peer2->addr.sin_addr.s_addr)
+ return 0;
+
+ if (!ast_test_flag(&peer->flags[0], SIP_INSECURE_PORT) && !ast_test_flag(&peer2->flags[0], SIP_INSECURE_PORT)) {
+ if (peer->addr.sin_port == peer2->addr.sin_port)
+ return CMP_MATCH;
+ else
+ return 0;
+ }
+ return CMP_MATCH;
}
/*!
@@ -1440,21 +1460,21 @@
/*!
* \note The only member of the user passed here guaranteed to be set is the name field
*/
-static int reg_hash_cb(const void *obj, const int flags)
-{
- const struct sip_registry *reg = obj;
-
- return ast_str_hash(reg->name);
+static int dialog_hash_cb(const void *obj, const int flags)
+{
+ const struct sip_pvt *pvt = obj;
+
+ return ast_str_hash(pvt->callid);
}
/*!
* \note The only member of the user passed here guaranteed to be set is the name field
*/
-static int reg_cmp_cb(void *obj, void *arg, int flags)
-{
- struct sip_registry *reg = obj, *reg2 = arg;
-
- return !strcasecmp(reg->name, reg2->name) ? CMP_MATCH : 0;
+static int dialog_cmp_cb(void *obj, void *arg, int flags)
+{
+ struct sip_registry *pvt = obj, *pvt2 = arg;
+
+ return !strcasecmp(pvt->callid, pvt2->callid) ? CMP_MATCH : 0;
}
static int temp_pvt_init(void *);
@@ -1656,7 +1676,7 @@
static int expire_register(const void *data);
static void *do_monitor(void *data);
static int restart_monitor(void);
-static int sip_addrcmp(char *name, struct sockaddr_in *sin); /* Support for peer matching */
+/* static int sip_addrcmp(char *name, struct sockaddr_in *sin); Support for peer matching */
static int sip_refer_allocate(struct sip_pvt *p);
static void ast_quiet_chan(struct ast_channel *chan);
static int attempt_transfer(struct sip_dual *transferer, struct sip_dual *target);
@@ -1734,7 +1754,9 @@
static struct sip_user *build_user(const char *name, struct ast_variable *v, 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);
static void sip_destroy_user(struct sip_user *user);
+static void sip_destroy_user_fn(void *user);
static int sip_poke_peer(struct sip_peer *peer);
static void set_peer_defaults(struct sip_peer *peer);
static struct sip_peer *temp_peer(const char *name);
@@ -3011,6 +3033,11 @@
while ((mailbox = AST_LIST_REMOVE_HEAD(&peer->mailboxes, entry)))
destroy_mailbox(mailbox);
+}
+
+static void sip_destroy_peer_fn(void *peer)
+{
+ sip_destroy_peer(peer);
}
/*! \brief Destroy peer object from memory */
@@ -3235,6 +3262,7 @@
global_rtautoclear * 1000, expire_register, (void *) peer);
}
ao2_link(peers, peer);
+ ao2_link(peers_by_ip, peer);
} else {
peer->is_realtime = 1;
}
@@ -3248,6 +3276,9 @@
return peer;
}
+
+
+#ifdef NO_MORE
/*! \brief Support routine for find_peer */
static int sip_addrcmp(char *name, struct sockaddr_in *sin)
{
@@ -3257,6 +3288,7 @@
(ast_test_flag(&p->flags[0], SIP_INSECURE_PORT) &&
(p->addr.sin_addr.s_addr == sin->sin_addr.s_addr)));
}
+#endif
/*! \brief Locate peer by name or ip address
* This is used on incoming SIP message to find matching peer on ip
@@ -3267,17 +3299,25 @@
struct sip_peer tmp_peer;
ast_copy_string(tmp_peer.name, peer, sizeof(tmp_peer.name));
+ tmp_peer.addr.sin_addr.s_addr = sin->sin_addr.s_addr;
+ tmp_peer.addr.sin_port = sin->sin_port;
if (peer)
p = ao2_find(peers, &tmp_peer, OBJ_POINTER);
else /* search by addr? */
- p = ASTOBJ_CONTAINER_FIND_FULL(&peerl, sin, name, sip_addr_hashfunc, 1, sip_addrcmp);
+ p = ao2_find(peers_by_ip, &tmp_peer, OBJ_POINTER); /* WAS: p = ASTOBJ_CONTAINER_FIND_FULL(&peerl, sin, name, sip_addr_hashfunc, 1, sip_addrcmp); */
if (!p && realtime)
p = realtime_peer(peer, sin);
return p;
}
+
+static void sip_destroy_user_fn(void *user)
+{
+ sip_destroy_user(user);
+}
+
/*! \brief Remove user object from in-memory storage */
static void sip_destroy_user(struct sip_user *user)
@@ -3348,7 +3388,7 @@
struct sip_user *u;
ast_copy_string(tmp.name, name, sizeof(tmp.name));
- u = ao2_find(users, &tmp_user, OBJ_POINTER);
+ u = ao2_find(users, &tmp, OBJ_POINTER);
if (!u && realtime)
u = realtime_user(name);
@@ -3700,7 +3740,7 @@
/*! \brief Execute destruction of SIP dialog structure, release memory */
static void __sip_destroy(struct sip_pvt *p, int lockowner, int lockdialoglist)
{
- struct sip_pvt *cur, *prev = NULL;
+ struct sip_pvt *cur;
struct sip_pkt *cp;
if (sip_debug_test_pvt(p))
@@ -3771,12 +3811,7 @@
/* Lock dialog list before removing ourselves from the list */
if (lockdialoglist)
dialoglist_lock();
- for (prev = NULL, cur = dialoglist; cur; prev = cur, cur = cur->next) {
- if (cur == p) {
- UNLINK(cur, dialoglist, prev);
- break;
- }
- }
+ cur = ao2_find(dialogs, p, OBJ_POINTER|OBJ_UNLINK);
if (lockdialoglist)
dialoglist_unlock();
if (!cur) {
@@ -3917,6 +3952,12 @@
} else /* u must be set */
unref_user(u);
return 0;
+}
+
+
+static void sip_destroy_fn(void *p)
+{
+ sip_destroy(p);
}
/*! \brief Destroy SIP call structure.
@@ -5072,7 +5113,7 @@
{
struct sip_pvt *p;
- if (!(p = ast_calloc(1, sizeof(*p))))
+ if (!(p = ao2_alloc(sizeof(*p), sip_destroy_fn)))
return NULL;
if (ast_string_field_init(p, 512)) {
@@ -5191,10 +5232,9 @@
ast_string_field_set(p, context, default_context);
/* Add to active dialog list */
- dialoglist_lock();
- p->next = dialoglist;
- dialoglist = dialog_ref(p);
- dialoglist_unlock();
+
+ ao2_link(dialogs, p);
+
ast_debug(1, "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;
}
@@ -5214,6 +5254,7 @@
const char *from = get_header(req, "From");
const char *to = get_header(req, "To");
const char *cseq = get_header(req, "Cseq");
+ struct sip_pvt tmp_dialog, *sip_pvt_ptr;
/* Call-ID, to, from and Cseq are required by RFC 3261. (Max-forwards and via too - ignored now) */
/* get_header always returns non-NULL so we must use ast_strlen_zero() */
@@ -5247,45 +5288,44 @@
return NULL;
}
}
-
+
dialoglist_lock();
- for (p = dialoglist; p; p = p->next) {
- /* In pedantic, we do not want packets with bad syntax to be connected to a PVT */
- int found = FALSE;
- if (ast_strlen_zero(p->callid))
- continue;
- if (req->method == SIP_REGISTER)
- found = (!strcmp(p->callid, callid));
- else
- found = (!strcmp(p->callid, callid) &&
- (!pedanticsipchecking || !tag || ast_strlen_zero(p->theirtag) || !strcmp(p->theirtag, tag))) ;
-
- ast_debug(5, "= %s Their Call ID: %s Their Tag %s Our tag: %s\n", found ? "Found" : "No match", p->callid, p->theirtag, p->tag);
-
- /* If we get a new request within an existing to-tag - check the to tag as well */
- if (pedanticsipchecking && found && req->method != SIP_RESPONSE) { /* SIP Request */
- if (p->tag[0] == '\0' && totag[0]) {
- /* We have no to tag, but they have. Wrong dialog */
- found = FALSE;
- } else if (totag[0]) { /* Both have tags, compare them */
- if (strcmp(totag, p->tag)) {
- found = FALSE; /* This is not our packet */
+ if (!ast_string_field_init(&tmp_dialog, 100)) {
+ ast_string_field_set(&tmp_dialog, callid, callid);
+
+ sip_pvt_ptr = ao2_find(dialogs, &tmp_dialog, OBJ_POINTER);
+ if (sip_pvt_ptr) {
+ if (!(!pedanticsipchecking || !tag || ast_strlen_zero(p->theirtag) || !strcmp(p->theirtag, tag)))
+ {
+ ao2_ref(sip_pvt_ptr,-1); /* basically, if the extra pedanticssipchecking constraints don't pan out,
+ the the match is defeated. There should be no other entry that matches
+ the callid */
+ sip_pvt_ptr = 0;
+ }
+ /* If we get a new request within an existing to-tag - check the to tag as well */
+ if (pedanticsipchecking && sip_pvt_ptr && req->method != SIP_RESPONSE) { /* SIP Request */
+ if (sip_pvt_ptr->tag[0] == '\0' && totag[0]) {
+ /* We have no to tag, but they have. Wrong dialog */
+ sip_pvt_ptr = NULL;
+ } else if (totag[0]) { /* Both have tags, compare them */
+ if (strcmp(totag, sip_pvt_ptr->tag)) {
+ sip_pvt_ptr = NULL; /* This is not our packet */
+ }
}
+ if (!sip_pvt_ptr)
+ ast_debug(5, "= Being pedantic: This is not our match on request: Call ID: %s Ourtag <null> Totag %s Method %s\n", p->callid, totag, sip_methods[req->method].text);
}
- if (!found)
- ast_debug(5, "= Being pedantic: This is not our match on request: Call ID: %s Ourtag <null> Totag %s Method %s\n", p->callid, totag, sip_methods[req->method].text);
- }
-
-
- if (found) {
+ }
+ ast_string_field_free_memory(&tmp_dialog);
+ if (sip_pvt_ptr) {
/* Found the call */
- sip_pvt_lock(p);
+ sip_pvt_lock(sip_pvt_ptr);
dialoglist_unlock();
- return p;
+ return sip_pvt_ptr;
}
}
dialoglist_unlock();
-
+
/* See if the method is capable of creating a dialog */
if (sip_methods[intended_method].can_create == CAN_CREATE_DIALOG) {
if (intended_method == SIP_REFER) {
@@ -5375,7 +5415,7 @@
return -1;
}
}
- if (!(reg = ao2_alloc(sizeof(*reg), sip_registry_destroy))) {
+ if (!(reg = ast_calloc(1,sizeof(*reg)))) {
ast_log(LOG_ERROR, "Out of memory. Can't allocate SIP registry entry\n");
return -1;
}
@@ -5387,6 +5427,7 @@
}
regobjs++;
+ ASTOBJ_INIT(reg);
ast_string_field_set(reg, callback, callback);
if (!ast_strlen_zero(username))
ast_string_field_set(reg, username, username);
@@ -8707,7 +8748,9 @@
if (peer->selfdestruct ||
ast_test_flag(&peer->flags[1], SIP_PAGE2_RTAUTOCLEAR)) {
- peer = ao2_find(peers, peer, OBJ_POINTER|OBJ_UNLINK); /* Remove from peer list */
+ struct sip_peer *peer3;
+ peer3 = ao2_find(peers, peer, OBJ_POINTER|OBJ_UNLINK); /* Remove from peer list */
+ peer3 = ao2_find(peers_by_ip, peer, OBJ_POINTER|OBJ_UNLINK); /* Remove from peer list */
unref_peer(peer); /* Remove from memory */
}
@@ -9748,52 +9791,42 @@
*/
static struct sip_pvt *get_sip_pvt_byid_locked(const char *callid, const char *totag, const char *fromtag)
{
- struct sip_pvt *sip_pvt_ptr;
+ struct sip_pvt *sip_pvt_ptr, tmp_dialog;
if (totag)
ast_debug(4, "Looking for callid %s (fromtag %s totag %s)\n", callid, fromtag ? fromtag : "<no fromtag>", totag ? totag : "<no totag>");
/* Search dialogs and find the match */
- dialoglist_lock();
- for (sip_pvt_ptr = dialoglist; sip_pvt_ptr; sip_pvt_ptr = sip_pvt_ptr->next) {
- if (!strcmp(sip_pvt_ptr->callid, callid)) {
- int match = 1;
+ if (!ast_string_field_init(&tmp_dialog, 100)) {
+ ast_string_field_set(&tmp_dialog, callid, callid);
+
+ sip_pvt_ptr = ao2_find(dialogs, &tmp_dialog, OBJ_POINTER);
+ if (sip_pvt_ptr) {
char *ourtag = sip_pvt_ptr->tag;
-
/* Go ahead and lock it (and its owner) before returning */
sip_pvt_lock(sip_pvt_ptr);
- /* Check if tags match. If not, this is not the call we want
- (With a forking SIP proxy, several call legs share the
- call id, but have different tags)
- */
if (pedanticsipchecking && (strcmp(fromtag, sip_pvt_ptr->theirtag) || (!ast_strlen_zero(totag) && strcmp(totag, ourtag))))
- match = 0;
-
- if (!match) {
+ {
sip_pvt_unlock(sip_pvt_ptr);
- continue;
+ ast_debug(4, "Matched %s call for callid=%s - But the pedantic check rejected the match; their tag is %s Our tag is %s\n",
+ ast_test_flag(&sip_pvt_ptr->flags[0], SIP_OUTGOING) ? "OUTGOING": "INCOMING", sip_pvt_ptr->callid,
+ sip_pvt_ptr->theirtag, sip_pvt_ptr->tag);
+ return 0;
}
-
- if (totag)
+ sip_pvt_unlock(sip_pvt_ptr);
+
+ if (totag)
ast_debug(4, "Matched %s call - their tag is %s Our tag is %s\n",
ast_test_flag(&sip_pvt_ptr->flags[0], SIP_OUTGOING) ? "OUTGOING": "INCOMING",
sip_pvt_ptr->theirtag, sip_pvt_ptr->tag);
-
- /* deadlock avoidance... */
- while (sip_pvt_ptr->owner && ast_channel_trylock(sip_pvt_ptr->owner)) {
- sip_pvt_unlock(sip_pvt_ptr);
- usleep(1);
- sip_pvt_lock(sip_pvt_ptr);
- }
- break;
- }
- }
- dialoglist_unlock();
- if (!sip_pvt_ptr)
- ast_debug(4, "Found no match for callid %s to-tag %s from-tag %s\n", callid, totag, fromtag);
- return sip_pvt_ptr;
+ }
+
+ ast_string_field_free_memory(&tmp_dialog);
+ return sip_pvt_ptr;
+ }
+ return NULL;
}
/*! \brief Call transfer support (the REFER method)
@@ -10816,17 +10849,17 @@
while ((user = ao2_iterator_next(&i))) {
- if (havepattern && regexec(®exbuf, iterator->name, 0, NULL, 0)) {
- ao2_unlock(iterator);
+ if (havepattern && regexec(®exbuf, user->name, 0, NULL, 0)) {
+ ao2_unlock(user);
continue;
}
- ast_cli(a->fd, FORMAT, iterator->name,
- iterator->secret,
- iterator->accountcode,
- iterator->context,
- cli_yesno(iterator->ha != NULL),
- nat2str(ast_test_flag(&iterator->flags[0], SIP_NAT)));
+ ast_cli(a->fd, FORMAT, user->name,
+ user->secret,
+ user->accountcode,
+ user->context,
+ cli_yesno(user->ha != NULL),
+ nat2str(ast_test_flag(&user->flags[0], SIP_NAT)));
}
if (havepattern)
@@ -11072,9 +11105,9 @@
if (a->argc != 3)
return CLI_SHOWUSAGE;
ast_cli(a->fd, "-= User objects: %d static, %d realtime =-\n\n", suserobjs, ruserobjs);
- ao2_callback(users, 0, user_dump_func, &fd);
+ ao2_callback(users, 0, user_dump_func, &a->fd);
ast_cli(a->fd, "-= Peer objects: %d static, %d realtime, %d autocreate =-\n\n", speerobjs, rpeerobjs, apeerobjs);
- ao2_callback(users, 0, peer_dump_func, &fd);
+ ao2_callback(users, 0, peer_dump_func, &a->fd);
ast_cli(a->fd, "-= Registry objects: %d =-\n\n", regobjs);
ASTOBJ_CONTAINER_DUMP(a->fd, tmp, sizeof(tmp), ®l);
return CLI_SUCCESS;
@@ -11147,6 +11180,27 @@
ast_context_destroy(ast_context_find(stalecontext), "SIP");
}
}
+
+static int peer_prune_marked_func(void *userobj, void *arg, int flags)
+{
+ struct sip_peer *peer = userobj;
+ if (peer->theMark) {
+ ao2_unlink(peers,peer);
+ ao2_ref(peer,-1);
+ }
+ return 0;
+}
+
+static int user_prune_marked_func(void *userobj, void *arg, int flags)
+{
+ struct sip_user *user = userobj;
+ if (user->theMark) {
+ ao2_unlink(users,user);
+ ao2_ref(user,-1);
+ }
+ return 0;
+}
+
/*! \brief Remove temporary realtime objects from memory (CLI) */
static char *sip_prune_realtime(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
@@ -11242,12 +11296,12 @@
continue;
};
if (ast_test_flag(&pi->flags[1], SIP_PAGE2_RTCACHEFRIENDS)) {
- ASTOBJ_MARK(pi);
+ pi->theMark = 1;
pruned++;
}
}
if (pruned) {
- ASTOBJ_CONTAINER_PRUNE_MARKED(&peerl, sip_destroy_peer);
+ ao2_callback(peers, 0, peer_prune_marked_func, 0);
ast_cli(a->fd, "%d peers pruned.\n", pruned);
} else
ast_cli(a->fd, "No peers found to prune.\n");
@@ -11263,12 +11317,12 @@
continue;
};
if (ast_test_flag(&ui->flags[1], SIP_PAGE2_RTCACHEFRIENDS)) {
- ASTOBJ_MARK(iterator);
+ ui->theMark = 1;
pruned++;
}
- } while (0) );
+ }
if (pruned) {
- ASTOBJ_CONTAINER_PRUNE_MARKED(&userl, sip_destroy_user);
+ ao2_callback(users, 0, user_prune_marked_func, 0);
ast_cli(a->fd, "%d users pruned.\n", pruned);
} else
ast_cli(a->fd, "No users found to prune.\n");
@@ -11282,6 +11336,7 @@
if (!ast_test_flag(&peer->flags[1], SIP_PAGE2_RTCACHEFRIENDS)) {
ast_cli(a->fd, "Peer '%s' is not a Realtime peer, cannot be pruned.\n", name);
ao2_link(peers, peer);
+ ao2_link(peers_by_ip, peer);
} else
ast_cli(a->fd, "Peer '%s' pruned.\n", name);
unref_peer(peer);
@@ -12053,7 +12108,7 @@
cur->subscribed == MWI_NOTIFICATION ? "<none>" : ast_extension_state2str(cur->laststate),
subscription_type2str(cur->subscribed),
cur->subscribed == MWI_NOTIFICATION ? S_OR(mailbox_str->str, "<none>") : "<none>"
-);
+ );
arg->numchans++;
}
@@ -12067,8 +12122,8 @@
*/
static char *sip_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
- struct sip_pvt *cur;
struct __show_chan_arg arg = { .fd = a->fd, .numchans = 0 };
+
if (cmd == CLI_INIT) {
e->command = "sip show {channels|subscriptions}";
@@ -12090,12 +12145,8 @@
ast_cli(arg.fd, FORMAT3, "Peer", "User", "Call ID", "Extension", "Last state", "Type", "Mailbox");
/* iterate on the container and invoke the callback on each item */
- dialoglist_lock();
- for (cur = dialoglist; cur; cur = cur->next) {
- show_channels_cb(cur, &arg, 0);
- }
- dialoglist_unlock();
-
+ ao2_callback(dialogs, 0, show_channels_cb, 0);
+
/* print summary information */
ast_cli(arg.fd, "%d active SIP %s%s\n", arg.numchans,
(arg.subscriptions ? "subscription" : "dialog"),
@@ -12111,26 +12162,27 @@
* given position. As many functions of this kind, each invokation has
* O(state) time complexity so be careful in using it.
*/
+
+
static char *complete_sipch(const char *line, const char *word, int pos, int state)
{
int which=0;
struct sip_pvt *cur;
char *c = NULL;
int wordlen = strlen(word);
-
- dialoglist_lock();
- for (cur = dialoglist; cur; cur = cur->next) {
+ struct ao2_iterator i;
+
+ i = ao2_iterator_init(dialogs, 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;
}
- }
- dialoglist_unlock();
+ ao2_ref(cur,-1);
+ }
return c;
-}
-
-static int peer_complete_func(void *obj, void *arg, int flags)
-{
}
@@ -12148,7 +12200,7 @@
if (!strncasecmp(word, peer->name, wordlen) &&
(!flags2 || ast_test_flag(&peer->flags[1], flags2)) &&
++which > state)
- result = ast_strdup(iterator->name);
+ result = ast_strdup(peer->name);
if (result)
break;
}
@@ -12161,15 +12213,18 @@
char *result = NULL;
int wordlen = strlen(word);
int which = 0;
-
- ASTOBJ_CONTAINER_TRAVERSE(&peerl, !result, do {
- ASTOBJ_WRLOCK(iterator); /* was WRLOCK */
- if (!strncasecmp(word, iterator->name, wordlen) &&
- (!flags2 || ast_test_flag(&iterator->flags[1], flags2)) &&
- ++which > state && iterator->expire > 0)
- result = ast_strdup(iterator->name);
- ao2_unlock(iterator);
- } while(0) );
+ struct ao2_iterator i;
+ struct sip_peer *peer;
+
+ i = ao2_iterator_init(peers, 0);
+ while ((peer = ao2_iterator_next(&i))) {
+ if (!strncasecmp(word, peer->name, wordlen) &&
+ (!flags2 || ast_test_flag(&peer->flags[1], flags2)) &&
+ ++which > state && peer->expire > 0)
+ result = ast_strdup(peer->name);
+ if (result)
+ break;
+ }
return result;
}
@@ -12206,17 +12261,23 @@
char *result = NULL;
int wordlen = strlen(word);
int which = 0;
-
- ASTOBJ_CONTAINER_TRAVERSE(&userl, !result, do {
+ struct ao2_iterator i;
+ struct sip_user *user;
+
+ i = ao2_iterator_init(users, 0);
+
+ while ((user = ao2_iterator_next(&i))) {
/* locking of the object is not required because only the name and flags are being compared */
- if (!strncasecmp(word, iterator->name, wordlen)) {
- if (flags2 && !ast_test_flag(&iterator->flags[1], flags2))
+ if (!strncasecmp(word, user->name, wordlen)) {
+ if (flags2 && !ast_test_flag(&user->flags[1], flags2))
continue;
if (++which > state) {
- result = ast_strdup(iterator->name);
+ result = ast_strdup(user->name);
}
}
- } while(0) );
+ if (result)
+ break;
+ }
return result;
}
@@ -12265,6 +12326,7 @@
struct sip_pvt *cur;
size_t len;
int found = 0;
+ struct ao2_iterator i;
switch (cmd) {
case CLI_INIT:
@@ -12281,7 +12343,10 @@
return CLI_SHOWUSAGE;
len = strlen(a->argv[3]);
dialoglist_lock();
- for (cur = dialoglist; cur; cur = cur->next) {
+
+ i = ao2_iterator_init(dialogs, 0);
+
+ while ((cur = ao2_iterator_next(&i))) {
if (!strncasecmp(cur->callid, a->argv[3], len)) {
char formatbuf[BUFSIZ/2];
ast_cli(a->fd,"\n");
@@ -12346,6 +12411,7 @@
struct sip_pvt *cur;
size_t len;
int found = 0;
+ struct ao2_iterator i;
switch (cmd) {
case CLI_INIT:
@@ -12364,7 +12430,8 @@
ast_cli(a->fd, "\n***Note: History recording is currently DISABLED. Use 'sip history' to ENABLE.\n");
len = strlen(a->argv[3]);
dialoglist_lock();
- for (cur = dialoglist; cur; cur = cur->next) {
+ i = ao2_iterator_init(dialogs, 0);
+ while ((cur = ao2_iterator_next(&i))) {
if (!strncasecmp(cur->callid, a->argv[3], len)) {
struct sip_history *hist;
int x = 0;
@@ -16086,6 +16153,7 @@
const char *accept = get_header(req, "Accept");
int resubscribe = (p->subscribed != NONE);
char *temp, *event;
+ struct ao2_iterator i;
if (p->initreq.headers) {
/* We already have a dialog */
@@ -16307,7 +16375,7 @@
if (p->subscribed == MWI_NOTIFICATION) {
transmit_response(p, "200 OK", req);
if (p->relatedpeer) { /* Send first notification */
- ASTOBJ_WRLOCK(p->relatedpeer); /* was WRLOCK */
+ ao2_lock(p->relatedpeer); /* was WRLOCK */
sip_send_mwi_to_peer(p->relatedpeer, NULL, 0);
ao2_unlock(p->relatedpeer);
}
@@ -16334,7 +16402,10 @@
ignored (or generate errors)
*/
dialoglist_lock();
- for (p_old = dialoglist; p_old; p_old = p_old->next) {
+
+ i = ao2_iterator_init(dialogs, 0);
+
+ while ((p_old = ao2_iterator_next(&i))) {
if (p_old == p)
continue;
if (p_old->initreq.method != SIP_SUBSCRIBE)
@@ -16887,6 +16958,7 @@
struct sip_pvt *dialog;
time_t t;
int reloading;
+ struct ao2_iterator i;
/* Add an I/O event to our SIP UDP socket */
if (sipsock > -1)
@@ -16913,6 +16985,7 @@
}
/* Check for dialogs needing to be killed */
+
dialoglist_lock();
restartsearch:
t = time(NULL);
@@ -16920,7 +16993,10 @@
of time since the last time we did it (when MWI is being sent, we can
get back to this point every millisecond or less)
*/
- for (dialog = dialoglist; dialog; dialog = dialog->next) {
+
+ i = ao2_iterator_init(dialogs, 0);
+
+ while ((dialog = ao2_iterator_next(&i))) {
sip_pvt_lock(dialog);
/* Check RTP timeouts and kill calls if we have a timeout set and do not get RTP */
check_rtp_timeout(dialog, t);
@@ -17590,7 +17666,7 @@
struct ast_flags mask[2] = {{(0)}};
- if (!(user = ao2_alloc(sizeof(*user), sip_destroy_user)))
+ if (!(user = ao2_alloc(sizeof(*user), sip_destroy_user_fn)))
return NULL;
suserobjs++;
@@ -17739,7 +17815,7 @@
{
struct sip_peer *peer;
- if (!(peer = ao2_alloc(sizeof(*peer), sip_destroy_peer)))
+ if (!(peer = ao2_alloc(sizeof(*peer), sip_destroy_peer_fn)))
return NULL;
apeerobjs++;
@@ -17791,22 +17867,26 @@
struct ast_flags peerflags[2] = {{(0)}};
struct ast_flags mask[2] = {{(0)}};
char callback[256] = "";
-
- if (!realtime)
+ struct sip_peer tmp_peer;
+
+ if (!realtime) {
/* Note we do NOT use find_peer here, to avoid realtime recursion */
/* We also use a case-sensitive comparison (unlike find_peer) so
that case changes made to the peer name will be properly handled
during reload
*/
- peer = ASTOBJ_CONTAINER_FIND_UNLINK_FULL(&peerl, name, name, 0, 0, strcmp);
-
+ strcpy(tmp_peer.name, name);
+ /* peer = ASTOBJ_CONTAINER_FIND_UNLINK_FULL(&peerl, name, name, 0, 0, strcmp); */
+ peer = ao2_find(peers, &tmp_peer, OBJ_POINTER|OBJ_UNLINK);
+ }
+
if (peer) {
/* Already in the list, remove it and it will be added back (or FREE'd) */
found++;
- if (!(peer->objflags & ASTOBJ_FLAG_MARKED))
+ if (!(peer->theMark))
firstpass = 0;
} else {
- if (!(peer = ao2_alloc(sizeof(*peer),sip_destroy_peer)))
+ if (!(peer = ao2_alloc(sizeof(*peer),sip_destroy_peer_fn)))
return NULL;
if (realtime) {
@@ -18046,7 +18126,7 @@
sip_send_mwi_to_peer(peer, NULL, 1);
}
- ASTOBJ_UNMARK(peer);
+ peer->theMark = 0;
ast_free_ha(oldha);
if (!ast_strlen_zero(callback)) { /* build string from peer info */
@@ -18059,6 +18139,13 @@
}
}
return peer;
+}
+
+static int peer_markall_func(void *userobj, void *arg, int flags)
+{
+ struct sip_peer *peer = userobj;
+ peer->theMark = 1;
+ return 0;
}
/*! \brief Re-read SIP.conf config file
@@ -18124,7 +18211,7 @@
ast_debug(4, "--------------- Done destroying user list\n");
ASTOBJ_CONTAINER_DESTROYALL(®l, sip_registry_destroy);
ast_debug(4, "--------------- Done destroying registry list\n");
- ASTOBJ_CONTAINER_MARKALL(&peerl);
+ ao2_callback(peers, 0, peer_markall_func, 0);
}
/* Initialize copy of current global_regcontext for later use in removing stale contexts */
@@ -18525,6 +18612,7 @@
if (peer) {
ast_device_state_changed("SIP/%s", peer->name);
ao2_link(peers, peer);
+ ao2_link(peers_by_ip, peer);
unref_peer(peer);
peer_count++;
}
@@ -18593,6 +18681,7 @@
peer = build_peer(cat, ast_variable_browse(cfg, cat), NULL, 0);
if (peer) {
ao2_link(peers, peer);
+ ao2_link(peers_by_ip, peer);
unref_peer(peer);
peer_count++;
}
@@ -19150,18 +19239,19 @@
static void sip_poke_all_peers(void)
{
int ms = 0;
+ struct ao2_iterator i;
+ struct sip_peer *peer;
+
+ i = ao2_iterator_init(peers, 0);
if (!speerobjs) /* No peers, just give up */
return;
- ASTOBJ_CONTAINER_TRAVERSE(&peerl, 1, do {
- ASTOBJ_WRLOCK(iterator); /* was WRLOCK */
+ while ((peer = ao2_iterator_next(&i))) {
ms += 100;
- iterator->pokeexpire = ast_sched_replace(iterator->pokeexpire,
- sched, ms, sip_poke_peer_s, iterator);
- ao2_unlock(iterator);
- } while (0)
- );
+ peer->pokeexpire = ast_sched_replace(peer->pokeexpire,
+ sched, ms, sip_poke_peer_s, peer);
+ }
}
/*! \brief Send all known registrations */
@@ -19191,7 +19281,8 @@
reload_config(reason);
/* Prune peers who still are supposed to be deleted */
- ASTOBJ_CONTAINER_PRUNE_MARKED(&peerl, sip_destroy_peer);
+ ao2_callback(peers, 0, peer_prune_marked_func, 0);
+
ast_debug(4, "--------------- Done destroying pruned peers\n");
/* Send qualify (OPTIONS) to all peers */
@@ -19272,6 +19363,9 @@
/* if the number of objects gets above MAX_XXX_BUCKETS, things will slow down */
users = ao2_container_alloc(MAX_USER_BUCKETS, user_hash_cb, user_cmp_cb);
peers = ao2_container_alloc(MAX_PEER_BUCKETS, peer_hash_cb, peer_cmp_cb);
+ peers_by_ip = ao2_container_alloc(MAX_PEER_BUCKETS, peer_iphash_cb, peer_ipcmp_cb);
+ dialogs = ao2_container_alloc(MAX_DIALOG_BUCKETS, dialog_hash_cb, dialog_cmp_cb);
+
ASTOBJ_CONTAINER_INIT(®l); /* Registry object list -- not searched for anything */
if (!(sched = sched_context_create())) {
@@ -19342,8 +19436,9 @@
/*! \brief PBX unload module API */
static int unload_module(void)
{
- struct sip_pvt *p, *pl;
+ struct sip_pvt *p;
struct ast_context *con;
+ struct ao2_iterator i;
/* First, take us out of the channel type list */
ast_channel_unregister(&sip_tech);
@@ -19373,7 +19468,8 @@
dialoglist_lock();
/* Hangup all dialogs if they have an owner */
- for (p = dialoglist; p ; p = p->next) {
+ i = ao2_iterator_init(dialogs, 0);
+ while ((p = ao2_iterator_next(&i))) {
if (p->owner)
ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
}
@@ -19390,22 +19486,26 @@
dialoglist_lock();
/* Destroy all the dialogs and free their memory */
- p = dialoglist;
- while (p) {
- pl = p;
- p = p->next;
- __sip_destroy(pl, TRUE, TRUE);
- }
- dialoglist = NULL;
+ i = ao2_iterator_init(dialogs, 0);
+ while ((p = ao2_iterator_next(&i))) {
+ ao2_unlink(dialogs,p);
+ ao2_ref(p,-1);
+ }
dialoglist_unlock();
/* Free memory for local network address mask */
ast_free_ha(localaddr);
+ ao2_ref(peers, -1);
+ ao2_ref(peers_by_ip, -1);
+ ao2_ref(users, -1);
+ ao2_ref(dialogs, -1);
+#ifdef NO_MORE
ASTOBJ_CONTAINER_DESTROYALL(&userl, sip_destroy_user);
ASTOBJ_CONTAINER_DESTROY(&userl);
ASTOBJ_CONTAINER_DESTROYALL(&peerl, sip_destroy_peer);
ASTOBJ_CONTAINER_DESTROY(&peerl);
+#endif
ASTOBJ_CONTAINER_DESTROYALL(®l, sip_registry_destroy);
ASTOBJ_CONTAINER_DESTROY(®l);
More information about the asterisk-commits
mailing list