[asterisk-commits] murf: branch murf/bug11210 r90797 - in /team/murf/bug11210: channels/ configs/
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Mon Dec 3 22:38:23 CST 2007
Author: murf
Date: Mon Dec 3 22:38:23 2007
New Revision: 90797
URL: http://svn.digium.com/view/asterisk?view=rev&rev=90797
Log:
Another pass over the code. Finishing up the config file additions for hash tab sizes. Tons of debug. A Start at getting the ref counts right.
Modified:
team/murf/bug11210/channels/chan_sip.c
team/murf/bug11210/configs/sip.conf.sample
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=90797&r1=90796&r2=90797
==============================================================================
--- team/murf/bug11210/channels/chan_sip.c (original)
+++ team/murf/bug11210/channels/chan_sip.c Mon Dec 3 22:38:23 2007
@@ -1204,11 +1204,13 @@
*/
static struct sip_pvt *dialog_ref(struct sip_pvt *p)
{
+ ao2_ref(p,1);
return p;
}
static struct sip_pvt *dialog_unref(struct sip_pvt *p)
{
+ ao2_ref(p,-1);
return NULL;
}
@@ -1610,6 +1612,7 @@
in coming releases */
/*--- PBX interface functions */
+static void check_rtp_timeout(struct sip_pvt *dialog, time_t t);
static struct ast_channel *sip_request_call(const char *type, int format, void *data, int *cause);
static int sip_devicestate(void *data);
static int sip_sendtext(struct ast_channel *ast, const char *text);
@@ -1666,7 +1669,9 @@
static void sip_scheddestroy(struct sip_pvt *p, int ms);
static void sip_cancel_destroy(struct sip_pvt *p);
static struct sip_pvt *sip_destroy(struct sip_pvt *p);
-static void __sip_destroy(struct sip_pvt *p, int lockowner, int lockdialoglist);
+static void *dialog_unlink_all(struct sip_pvt *dialog, int lockowner, int lockdialoglist);
+static void *registry_unref(struct sip_registry *reg);
+static void __sip_destroy(struct sip_pvt *p);
static void __sip_ack(struct sip_pvt *p, int seqno, int resp, int sipmethod);
static void __sip_pretend_ack(struct sip_pvt *p);
static int __sip_semi_ack(struct sip_pvt *p, int seqno, int resp, int sipmethod);
@@ -2022,12 +2027,40 @@
*/
static void unref_peer(struct sip_peer *peer)
{
- ao2_ref(peer,-1);
+ int rc = ao2_ref(peer,-1);
+ ast_log(LOG_NOTICE,"Unref peer %s prev refcount=%d\n", peer->name, rc);
}
static void unref_user(struct sip_user *user)
{
- ao2_ref(user,-1);
+ int rc = ao2_ref(user,-1);
+ ast_log(LOG_NOTICE,"Unref user %s prev refcount=%d\n", user->name, rc);
+}
+
+static void *dialog_unlink_all(struct sip_pvt *dialog, int lockowner, int lockdialoglist)
+{
+ struct sip_pvt *x;
+ int rc = ao2_ref(dialog,0);
+ ast_log(LOG_NOTICE,"Unlink dialog %s prev refcount=%d\n", dialog->callid, rc);
+ /* Remove link from peer to subscription of MWI */
+ if (dialog->relatedpeer && dialog->relatedpeer->mwipvt)
+ dialog->relatedpeer->mwipvt = dialog_unref(dialog->relatedpeer->mwipvt);
+ if (dialog->registry) {
+ if (dialog->registry->call == dialog)
+ dialog->registry->call = NULL;
+ dialog->registry = registry_unref(dialog->registry);
+ }
+ /* Unlink us from the owner if we have one */
+ if (dialog->owner) {
+ if (lockowner)
+ ast_channel_lock(dialog->owner);
+ ast_debug(1, "Detaching from %s\n", dialog->owner->name);
+ dialog->owner->tech_pvt = NULL;
+ if (lockowner)
+ ast_channel_unlock(dialog->owner);
+ }
+ x = ao2_find(dialogs, dialog, OBJ_POINTER|OBJ_UNLINK);
+ return NULL;
}
static void *registry_unref(struct sip_registry *reg)
@@ -2596,7 +2629,10 @@
} else {
append_history(p, "AutoDestroy", "%s", p->callid);
ast_debug(3, "Auto destroying SIP dialog '%s'\n", p->callid);
- sip_destroy(p); /* Go ahead and destroy dialog. All attempts to recover is done */
+ ast_log(LOG_NOTICE,"AutoDestroy dialog %s\n", p->callid);
+ dialog_unlink_all(p, TRUE, TRUE); /* once it's unlinked and unrefd everywhere, it'll be freed automagically */
+
+ /* sip_destroy(p); */ /* Go ahead and destroy dialog. All attempts to recover is done */
/* sip_destroy also absorbs the reference */
}
return 0;
@@ -3098,12 +3134,19 @@
peer->outboundproxy = NULL;
/* Delete it, it needs to disappear */
- if (peer->call)
- peer->call = sip_destroy(peer->call);
-
- if (peer->mwipvt) /* We have an active subscription, delete it */
- peer->mwipvt = sip_destroy(peer->mwipvt);
-
+ if (peer->call) {
+ ast_log(LOG_NOTICE,"Calling Sip_Destroy() from peer for %s....\n", peer->call->callid);
+ dialog_unlink_all(peer->call, TRUE, TRUE);
+ /* peer->call = sip_destroy(peer->call); */
+ }
+
+
+ if (peer->mwipvt) { /* We have an active subscription, delete it */
+ ast_log(LOG_NOTICE,"Calling Sip_Destroy() from mwipvt for %s....\n", peer->mwipvt->callid);
+ peer->mwipvt = dialog_unlink_all(peer->mwipvt, TRUE, TRUE);
+ /* peer->mwipvt = sip_destroy(peer->mwipvt); */
+ }
+
if (peer->chanvars) {
ast_variables_destroy(peer->chanvars);
peer->chanvars = NULL;
@@ -3347,18 +3390,16 @@
static struct sip_peer *find_peer(const char *peer, struct sockaddr_in *sin, int realtime)
{
struct sip_peer *p = NULL;
+ int rc;
struct sip_peer tmp_peer;
- ast_copy_string(tmp_peer.name, peer, sizeof(tmp_peer.name));
- if (sin) {
+ if (peer)
+ {
+ ast_copy_string(tmp_peer.name, peer, sizeof(tmp_peer.name));
+ p = ao2_find(peers, &tmp_peer, OBJ_POINTER);
+ } 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;
- }
-
-
- if (peer)
- p = ao2_find(peers, &tmp_peer, OBJ_POINTER);
- else if (sin) { /* search by addr? */
ast_log(LOG_NOTICE,"Searching for peer %s by IP addr/port = %d/%d\n", peer, sin->sin_addr.s_addr, sin->sin_port);
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); */
}
@@ -3372,9 +3413,10 @@
else if (!p)
ast_log(LOG_NOTICE,"Did not find peer %s / addr=%d port=%d\n", peer, sin->sin_addr.s_addr, sin->sin_port);
- if (p)
- ast_log(LOG_NOTICE,"FOUND peer %s\n", peer);
-
+ if (p) {
+ rc = ao2_ref(p,0);
+ ast_log(LOG_NOTICE,"FOUND peer %s refcount = %d\n", peer, rc);
+ }
return p;
}
@@ -3796,7 +3838,9 @@
we don't get reentered trying to grab the registry lock */
reg->call->registry = NULL;
ast_debug(3, "Destroying active SIP dialog for registry %s@%s\n", reg->username, reg->hostname);
- reg->call = sip_destroy(reg->call);
+ ast_log(LOG_NOTICE,"Calling Sip_Destroy() from registry for %s....\n", reg->call->callid);
+ reg->call = dialog_unlink_all(reg->call, TRUE, TRUE);
+ /* reg->call = sip_destroy(reg->call); */
}
if (reg->expire > -1)
ast_sched_del(sched, reg->expire);
@@ -3808,12 +3852,13 @@
}
-/*! \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;
+/*! \brief Execute destruction of SIP dialog structure, release memory:
+ should be unlinked before destruction */
+static void __sip_destroy(struct sip_pvt *p)
+{
struct sip_pkt *cp;
+ ast_log(LOG_NOTICE,"Destroying the empty shell of dialog %s\n", p->callid);
if (sip_debug_test_pvt(p))
ast_verbose("Really destroying SIP dialog '%s' Method: %s\n", p->callid, sip_methods[p->method].text);
@@ -3821,10 +3866,6 @@
update_call_counter(p, DEC_CALL_LIMIT);
ast_debug(2, "This call did not properly clean up call limits. Call ID %s\n", p->callid);
}
-
- /* Remove link from peer to subscription of MWI */
- if (p->relatedpeer && p->relatedpeer->mwipvt)
- p->relatedpeer->mwipvt = dialog_unref(p->relatedpeer->mwipvt);
if (dumphistory)
sip_dump_history(p);
@@ -3853,21 +3894,7 @@
free_old_route(p->route);
p->route = NULL;
}
- if (p->registry) {
- if (p->registry->call == p)
- p->registry->call = NULL;
- p->registry = registry_unref(p->registry);
- }
-
- /* Unlink us from the owner if we have one */
- if (p->owner) {
- if (lockowner)
- ast_channel_lock(p->owner);
- ast_debug(1, "Detaching from %s\n", p->owner->name);
- p->owner->tech_pvt = NULL;
- if (lockowner)
- ast_channel_unlock(p->owner);
- }
+
/* Clear history */
if (p->history) {
struct sip_history *hist;
@@ -3878,18 +3905,6 @@
ast_free(p->history);
p->history = NULL;
}
-
- /* Lock dialog list before removing ourselves from the list */
- if (lockdialoglist)
- dialoglist_lock();
- cur = ao2_find(dialogs, p, OBJ_POINTER|OBJ_UNLINK);
- ast_log(LOG_NOTICE,"Searched for dialog %s, to UNLINK. got %p\n", p->callid, cur);
- if (lockdialoglist)
- dialoglist_unlock();
- if (!cur) {
- ast_log(LOG_WARNING, "Trying to destroy \"%s\", not found in dialog list?!?! \n", p->callid);
- return;
- }
/* remove all current packets in this dialog */
while((cp = p->packets)) {
@@ -3906,7 +3921,9 @@
ast_mutex_destroy(&p->pvt_lock);
ast_string_field_free_memory(p);
-
+
+ ast_log(LOG_NOTICE,"Destroying dialog;\n");
+
ast_free(p);
}
@@ -4029,6 +4046,7 @@
static void sip_destroy_fn(void *p)
{
+ ast_log(LOG_NOTICE,"sip_destroy_fn called\n");
sip_destroy(p);
}
@@ -4040,7 +4058,7 @@
static struct sip_pvt * sip_destroy(struct sip_pvt *p)
{
ast_debug(3, "Destroying SIP dialog %s\n", p->callid);
- __sip_destroy(p, TRUE, TRUE);
+ __sip_destroy(p);
return NULL;
}
@@ -5186,7 +5204,10 @@
int useglobal_nat, const int intended_method)
{
struct sip_pvt *p;
-
+ struct sip_pvt *p2;
+ int rc;
+
+ ast_log(LOG_NOTICE,"allocating PVT for %s\n", callid);
if (!(p = ao2_alloc(sizeof(*p), sip_destroy_fn)))
return NULL;
@@ -5306,9 +5327,16 @@
ast_string_field_set(p, context, default_context);
/* Add to active dialog list */
+
+ ast_log(LOG_NOTICE,"***About to Search for dialog %s\n", p->callid);
+ p2 = ao2_find(dialogs, p, OBJ_POINTER);
+ if (p2) {
+ ast_log(LOG_NOTICE, "ABOUT TO LINK %s, but it is already in the dialog table!\n", p2->callid);
+ ao2_ref(p2,-1);
+ }
ao2_link(dialogs, p);
- ast_log(LOG_NOTICE,"Linked in dialog %s\n", p->callid);
+ rc = ao2_ref(p, 0);
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;
@@ -5366,12 +5394,14 @@
dialoglist_lock();
if (!ast_string_field_init(&tmp_dialog, 100)) {
+ int rc;
ast_string_field_set(&tmp_dialog, callid, callid);
sip_pvt_ptr = ao2_find(dialogs, &tmp_dialog, OBJ_POINTER);
if (sip_pvt_ptr) {
- ast_log(LOG_NOTICE,"Found dialog %s\n", tmp_dialog.callid);
- if (!(!pedanticsipchecking || !tag || ast_strlen_zero(p->theirtag) || !strcmp(p->theirtag, tag)))
+ rc = ao2_ref(sip_pvt_ptr,0);
+ ast_log(LOG_NOTICE,"Found CALL dialog %s, refcount = %d\n", tmp_dialog.callid, rc);
+ if (!(!pedanticsipchecking || !tag || ast_strlen_zero(sip_pvt_ptr->theirtag) || !strcmp(sip_pvt_ptr->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
@@ -5382,16 +5412,19 @@
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 */
+ ao2_ref(sip_pvt_ptr,-1);
sip_pvt_ptr = NULL;
} else if (totag[0]) { /* Both have tags, compare them */
if (strcmp(totag, sip_pvt_ptr->tag)) {
+ ao2_ref(sip_pvt_ptr,-1);
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);
+ ast_debug(5, "= Being pedantic: This is not our match on request: Call ID: %s Ourtag <null> Totag %s Method %s\n", sip_pvt_ptr->callid, totag, sip_methods[req->method].text);
}
}
+
ast_string_field_free_memory(&tmp_dialog);
if (sip_pvt_ptr) {
/* Found the call */
@@ -5414,6 +5447,9 @@
} else {
/* Ok, time to create a new SIP dialog object, a pvt */
if ((p = sip_alloc(callid, sin, 1, intended_method))) {
+ int rc = ao2_ref(p,0);
+ ast_log(LOG_NOTICE,"Couldn't find call %s, so CREATED dialog, refcount = %d\n",
+ callid, rc);
/* Ok, we've created a dialog, let's go and process it */
sip_pvt_lock(p);
} else {
@@ -5491,7 +5527,7 @@
return -1;
}
}
- if (!(reg = ast_calloc(1,sizeof(*reg)))) {
+ if (!(reg = ast_calloc(1, sizeof(*reg)))) {
ast_log(LOG_ERROR, "Out of memory. Can't allocate SIP registry entry\n");
return -1;
}
@@ -5520,8 +5556,8 @@
reg->portno = portnum;
reg->callid_valid = FALSE;
reg->ocseq = INITIAL_CSEQ;
- ASTOBJ_CONTAINER_LINK(®l, reg);/* Add the new registry entry to the list */
- registry_unref(reg); /* release the reference. The container has another reference */
+ ASTOBJ_CONTAINER_LINK(®l, reg); /* Add the new registry entry to the list */
+ registry_unref(reg); /* release the reference given by ASTOBJ_INIT. The container has another reference */
return 0;
}
@@ -8473,7 +8509,9 @@
if (create_addr(p, r->hostname)) {
/* we have what we hope is a temporary network error,
* probably DNS. We need to reschedule a registration try */
- sip_destroy(p);
+ ast_log(LOG_NOTICE,"Calling Sip_Destroy() from registry building for %s....\n", p->callid);
+ dialog_unlink_all(p, TRUE, TRUE);
+ /* sip_destroy(p); */
if (r->timeout > -1) {
r->timeout = ast_sched_replace(r->timeout, sched,
global_reg_timeout * 1000, sip_reg_timeout, r);
@@ -8842,8 +8880,28 @@
ast_test_flag(&peer->flags[1], SIP_PAGE2_RTAUTOCLEAR)) {
struct sip_peer *peer3;
peer3 = ao2_find(peers, peer, OBJ_POINTER|OBJ_UNLINK); /* Remove from peer list */
+ if (peer3) {
+ int rc = ao2_ref(peer3,0);
+ ast_log(LOG_NOTICE,"Peer %s removed from the name hash. Refc=%d\n", peer->name, rc);
+ if (peer3 != peer)
+ ast_log(LOG_WARNING,"Peer (%p) not equal to peer3 (%p); %s != %s;\n",
+ peer, peer3, peer->name, peer3->name);
+ unref_peer(peer); /* Remove from memory */
+ } else {
+ ast_log(LOG_NOTICE,"Peer %s NOT found in the name hash table!\n", peer->name);
+ }
+
peer3 = ao2_find(peers_by_ip, peer, OBJ_POINTER|OBJ_UNLINK); /* Remove from peer list */
- unref_peer(peer); /* Remove from memory */
+ if (peer3) {
+ int rc = ao2_ref(peer3,0);
+ ast_log(LOG_NOTICE,"Peer %s removed from the IP hash. Refc=%d\n", peer->name, rc);
+ if (peer3 != peer)
+ ast_log(LOG_WARNING,"IP Peer (%p) not equal to peer3 (%p); %s != %s;\n",
+ peer, peer3, peer->name, peer3->name);
+ unref_peer(peer); /* Remove from memory */
+ } else {
+ ast_log(LOG_NOTICE,"Peer %s NOT found in the IP hash table!\n", peer->name);
+ }
}
return 0;
@@ -9412,7 +9470,8 @@
/* Request device state update */
ast_device_state_changed("SIP/%s", peer->name);
-
+ unref_peer(peer);
+
return;
}
@@ -9896,7 +9955,8 @@
sip_pvt_ptr = ao2_find(dialogs, &tmp_dialog, OBJ_POINTER);
if (sip_pvt_ptr) {
char *ourtag = sip_pvt_ptr->tag;
- ast_log(LOG_NOTICE,"Found dialog %s\n", sip_pvt_ptr->callid);
+ int rc = ao2_ref(sip_pvt_ptr,0);
+ ast_log(LOG_NOTICE,"Found dialog %s refcount=%d\n", sip_pvt_ptr->callid, rc);
/* Go ahead and lock it (and its owner) before returning */
sip_pvt_lock(sip_pvt_ptr);
@@ -11199,9 +11259,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, &a->fd);
+ ao2_callback(users, OBJ_NODATA, 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, &a->fd);
+ ao2_callback(users, OBJ_NODATA, 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;
@@ -11275,26 +11335,49 @@
}
}
-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);
+/* this func is used with ao2_callback to unlink/delete all dialogs that
+ are marked needdestroy. It will return CMP_MATCH for candidates, and they
+ will be unlinked */
+
+static int dialog_needdestroy(void *dialogobj, void *arg, int flags)
+{
+ struct sip_pvt *dialog = dialogobj;
+ time_t *t = arg;
+
+ /* Check RTP timeouts and kill calls if we have a timeout set and do not get RTP */
+ check_rtp_timeout(dialog, *t);
+
+ if (dialog->needdestroy && !dialog->packets && !dialog->owner) {
+ ast_log(LOG_NOTICE, "Dialog %s should be destroyed\n", dialog->callid);
+ return CMP_MATCH;
}
return 0;
}
-static int user_prune_marked_func(void *userobj, void *arg, int flags)
+/* this func is used with ao2_callback to unlink/delete all marked
+ peers */
+static int peer_is_marked(void *peerobj, void *arg, int flags)
+{
+ struct sip_peer *peer = peerobj;
+ if (peer->theMark)
+ {
+ return CMP_MATCH;
+ } else {
+ return 0;
+ }
+}
+
+/* this func is used with ao2_callback to unlink/delete all marked
+ users */
+static int user_is_marked(void *userobj, void *arg, int flags)
{
struct sip_user *user = userobj;
if (user->theMark) {
- ao2_unlink(users,user);
- ao2_ref(user,-1);
- }
- return 0;
-}
-
+ return CMP_MATCH;
+ } else {
+ 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)
@@ -11395,7 +11478,8 @@
}
}
if (pruned) {
- ao2_callback(peers, 0, peer_prune_marked_func, 0);
+ ast_log(LOG_NOTICE,"Callback to PRUNE PEERS\n");
+ ao2_callback(peers, OBJ_NODATA|OBJ_UNLINK, peer_is_marked, 0);
ast_cli(a->fd, "%d peers pruned.\n", pruned);
} else
ast_cli(a->fd, "No peers found to prune.\n");
@@ -11416,7 +11500,8 @@
}
}
if (pruned) {
- ao2_callback(users, 0, user_prune_marked_func, 0);
+ ast_log(LOG_NOTICE,"Callback to PRUNE USERS\n");
+ ao2_callback(users, OBJ_NODATA|OBJ_UNLINK, user_is_marked, 0);
ast_cli(a->fd, "%d users pruned.\n", pruned);
} else
ast_cli(a->fd, "No users found to prune.\n");
@@ -11942,6 +12027,7 @@
} else {
ast_cli(a->fd, "Peer %s not registered\n", a->argv[2]);
}
+ unref_peer(peer);
} else {
ast_cli(a->fd, "Peer unknown: \'%s\'. Not unregistered.\n", a->argv[2]);
}
@@ -12173,14 +12259,14 @@
struct sip_pvt *cur = __cur;
struct __show_chan_arg *arg = __arg;
const struct sockaddr_in *dst = sip_real_dst(cur);
-
- /* XXX indentation preserved to reduce diff. Will be fixed later */
- if (cur->subscribed == NONE && !arg->subscriptions) {
- /* set if SIP transfer in progress */
- const char *referstatus = cur->refer ? referstatus2str(cur->refer->status) : "";
- char formatbuf[BUFSIZ/2];
-
- ast_cli(arg->fd, FORMAT, ast_inet_ntoa(dst->sin_addr),
+
+ /* XXX indentation preserved to reduce diff. Will be fixed later */
+ if (cur->subscribed == NONE && !arg->subscriptions) {
+ /* set if SIP transfer in progress */
+ const char *referstatus = cur->refer ? referstatus2str(cur->refer->status) : "";
+ char formatbuf[BUFSIZ/2];
+
+ ast_cli(arg->fd, FORMAT, ast_inet_ntoa(dst->sin_addr),
S_OR(cur->username, S_OR(cur->cid_num, "(None)")),
cur->callid,
cur->ocseq, cur->icseq,
@@ -12190,13 +12276,13 @@
cur->lastmsg ,
referstatus
);
- arg->numchans++;
- }
- if (cur->subscribed != NONE && arg->subscriptions) {
- struct ast_str *mailbox_str = ast_str_alloca(512);
- if (cur->subscribed == MWI_NOTIFICATION && cur->relatedpeer)
- peer_mailboxes_to_str(&mailbox_str, cur->relatedpeer);
- ast_cli(arg->fd, FORMAT3, ast_inet_ntoa(dst->sin_addr),
+ arg->numchans++;
+ }
+ if (cur->subscribed != NONE && arg->subscriptions) {
+ struct ast_str *mailbox_str = ast_str_alloca(512);
+ if (cur->subscribed == MWI_NOTIFICATION && cur->relatedpeer)
+ peer_mailboxes_to_str(&mailbox_str, cur->relatedpeer);
+ ast_cli(arg->fd, FORMAT3, ast_inet_ntoa(dst->sin_addr),
S_OR(cur->username, S_OR(cur->cid_num, "(None)")),
cur->callid,
/* the 'complete' exten/context is hidden in the refer_to field for subscriptions */
@@ -12204,10 +12290,9 @@
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++;
- }
-
+ );
+ arg->numchans++;
+ }
return 0; /* don't care, we scan all channels */
}
@@ -12241,7 +12326,7 @@
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 */
- ao2_callback(dialogs, 0, show_channels_cb, &arg);
+ ao2_callback(dialogs, OBJ_NODATA, show_channels_cb, &arg);
/* print summary information */
ast_cli(arg.fd, "%d active SIP %s%s\n", arg.numchans,
@@ -12905,7 +12990,9 @@
if (create_addr(p, a->argv[i])) {
/* Maybe they're not registered, etc. */
- sip_destroy(p);
+ ast_log(LOG_NOTICE,"Calling Sip_Destroy() from sip_notify for %s....\n", p->callid);
+ dialog_unlink_all(p, TRUE, TRUE);
+ /* sip_destroy(p); */
ast_cli(a->fd, "Could not create address for '%s'\n", a->argv[i]);
continue;
}
@@ -15624,6 +15711,8 @@
transferer->refer->status = REFER_FAILED;
sip_pvt_unlock(targetcall_pvt);
ast_channel_unlock(current->chan1);
+ if (targetcall_pvt)
+ ao2_ref(targetcall_pvt,-1);
return -1;
}
@@ -15684,6 +15773,8 @@
ast_channel_unlock(targetcall_pvt->owner);
}
}
+ if (targetcall_pvt)
+ ao2_ref(targetcall_pvt,-1);
return 1;
}
@@ -16448,11 +16539,14 @@
if (ast_test_flag(&authpeer->flags[1], SIP_PAGE2_SUBSCRIBEMWIONLY)) {
add_peer_mwi_subs(authpeer);
}
- if (authpeer->mwipvt && authpeer->mwipvt != p) /* Destroy old PVT if this is a new one */
+ if (authpeer->mwipvt && authpeer->mwipvt != p) { /* Destroy old PVT if this is a new one */
/* We only allow one subscription per peer */
- sip_destroy(authpeer->mwipvt);
- authpeer->mwipvt = p; /* Link from peer to pvt */
- p->relatedpeer = authpeer; /* Link from pvt to peer */
+ ast_log(LOG_NOTICE,"Calling Sip_Destroy() from subscribe request for %s....\n", authpeer->mwipvt->callid);
+ dialog_unlink_all(authpeer->mwipvt, TRUE, TRUE);
+ /* sip_destroy(authpeer->mwipvt); */
+ }
+ authpeer->mwipvt = p; /* Link from peer to pvt UH- should this be dialog_ref()? */
+ p->relatedpeer = authpeer; /* Link from pvt to peer UH- should this be dialog_ref()? */
/* Do not release authpeer here */
} else { /* At this point, Asterisk does not understand the specified event */
transmit_response(p, "489 Bad Event", req);
@@ -16884,6 +16978,8 @@
break; /* locking succeeded */
ast_debug(1, "Failed to grab owner channel lock, trying again. (SIP call %s)\n", p->callid);
sip_pvt_unlock(p);
+ if (lockretry != 1)
+ ao2_ref(p,-1); /* we'll look for it again, but p is dead now */
ast_mutex_unlock(&netlock);
/* Sleep for a very short amount of time */
usleep(1);
@@ -16901,6 +16997,7 @@
transmit_response(p, "503 Server error", &req); /* We must respond according to RFC 3261 sec 12.2 */
/* XXX We could add retry-after to make sure they come back */
append_history(p, "LockFail", "Owner lock failed, transaction failed.");
+ ao2_ref(p, -1); /* p is gone after the return */
return 1;
}
nounlock = 0;
@@ -16915,7 +17012,7 @@
ast_mutex_unlock(&netlock);
if (recount)
ast_update_use_count();
-
+ ao2_ref(p, -1); /* p is gone after the return */
return 1;
}
@@ -16982,7 +17079,9 @@
return -1;
if (create_addr_from_peer(p, peer)) {
/* Maybe they're not registered, etc. */
- sip_destroy(p);
+ ast_log(LOG_NOTICE,"Calling Sip_Destroy() from peer mwi for %s....\n", p->callid);
+ dialog_unlink_all(p, TRUE, TRUE);
+ /* sip_destroy(p); */
return 0;
}
/* Recalculate our side, and recalculate Call ID */
@@ -17075,10 +17174,8 @@
static void *do_monitor(void *data)
{
int res;
- 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)
@@ -17106,31 +17203,13 @@
/* Check for dialogs needing to be killed */
- dialoglist_lock();
-restartsearch:
t = time(NULL);
/* don't scan the dialogs list if it hasn't been a reasonable period
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)
*/
- 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);
- /* If we have sessions that needs to be destroyed, do it now */
- /* Check if we have outstanding requests not responsed to or an active call
- - if that's the case, wait with destruction */
- if (dialog->needdestroy && !dialog->packets && !dialog->owner) {
- sip_pvt_unlock(dialog);
- __sip_destroy(dialog, TRUE, FALSE);
- goto restartsearch;
- }
- sip_pvt_unlock(dialog);
- }
- dialoglist_unlock();
+ ao2_callback(dialogs, OBJ_UNLINK|OBJ_NODATA, dialog_needdestroy, &t);
pthread_testcancel();
/* Wait for sched or io */
@@ -17192,8 +17271,12 @@
if (global_regextenonqualify)
register_peer_exten(peer, FALSE);
}
- if (peer->call)
- peer->call = sip_destroy(peer->call);
+ if (peer->call) {
+ ast_log(LOG_NOTICE,"Calling Sip_Destroy() from peer call poke for %s....\n", peer->call->callid);
+ peer->call = dialog_unlink_all(peer->call, TRUE, TRUE);
+ /* peer->call = sip_destroy(peer->call);*/
+ }
+
peer->lastms = -1;
ast_device_state_changed("SIP/%s", peer->name);
/* Try again quickly */
@@ -17223,7 +17306,9 @@
if (peer->call) {
if (sipdebug)
ast_log(LOG_NOTICE, "Still have a QUALIFY dialog active, deleting\n");
- peer->call = sip_destroy(peer->call);
+ ast_log(LOG_NOTICE,"Calling Sip_Destroy() from peer poking for %s....\n", peer->call->callid);
+ peer->call = dialog_unlink_all(peer->call, TRUE, TRUE);
+ /* peer->call = sip_destroy(peer->call); */
}
if (!(p = peer->call = sip_alloc(NULL, NULL, 0, SIP_OPTIONS)))
return -1;
@@ -17406,7 +17491,9 @@
p->outgoing_call = TRUE;
if (!(p->options = ast_calloc(1, sizeof(*p->options)))) {
- sip_destroy(p);
+ ast_log(LOG_NOTICE,"Calling Sip_Destroy() from call request for %s....\n", p->callid);
+ dialog_unlink_all(p, TRUE, TRUE);
+ /* sip_destroy(p); */
ast_log(LOG_ERROR, "Unable to build option SIP data structure - Out of memory\n");
*cause = AST_CAUSE_SWITCH_CONGESTION;
return NULL;
@@ -17427,7 +17514,9 @@
if (create_addr(p, host)) {
*cause = AST_CAUSE_UNREGISTERED;
ast_debug(3, "Cant create SIP call - target device not registred\n");
- sip_destroy(p);
+ ast_log(LOG_NOTICE,"Calling Sip_Destroy() from call request 2 for %s....\n", p->callid);
+ dialog_unlink_all(p, TRUE, TRUE);
+ /* sip_destroy(p); */
return NULL;
}
if (ast_strlen_zero(p->peername) && ext)
@@ -17457,8 +17546,12 @@
"Channel: %s\r\nChanneltype: %s\r\nSIPcallid: %s\r\nSIPfullcontact: %s\r\nPeername: %s\r\n",
p->owner? p->owner->name : "", "SIP", p->callid, p->fullcontact, p->peername);
sip_pvt_unlock(p);
- if (!tmpc)
- sip_destroy(p);
+ if (!tmpc) {
+ ast_log(LOG_NOTICE,"Calling Sip_Destroy() from call request 3 for %s....\n", p->callid);
+ dialog_unlink_all(p, TRUE, TRUE);
+ /* sip_destroy(p); */
+ }
+
ast_update_use_count();
restart_monitor();
return tmpc;
@@ -17785,7 +17878,8 @@
struct ast_flags userflags[2] = {{(0)}};
struct ast_flags mask[2] = {{(0)}};
-
+ ast_log(LOG_NOTICE,"Allocating USER object for %s\n", name);
+
if (!(user = ao2_alloc(sizeof(*user), sip_destroy_user_fn)))
return NULL;
@@ -17941,6 +18035,7 @@
{
struct sip_peer *peer;
+ ast_log(LOG_NOTICE,"Allocating PEER object for the %s\n", name);
if (!(peer = ao2_alloc(sizeof(*peer), sip_destroy_peer_fn)))
return NULL;
@@ -18003,6 +18098,7 @@
*/
strcpy(tmp_peer.name, name);
/* peer = ASTOBJ_CONTAINER_FIND_UNLINK_FULL(&peerl, name, name, 0, 0, strcmp); */
+ ast_log(LOG_NOTICE,"UNLINK peer %s\n", name);
peer = ao2_find(peers, &tmp_peer, OBJ_POINTER|OBJ_UNLINK);
}
@@ -18012,6 +18108,8 @@
if (!(peer->theMark))
firstpass = 0;
} else {
+ ast_log(LOG_NOTICE,"Allocating PEER object to %s\n", name);
+
if (!(peer = ao2_alloc(sizeof(*peer),sip_destroy_peer_fn)))
return NULL;
@@ -18328,7 +18426,9 @@
if (iterator->call) {
ast_debug(3, "Destroying active SIP dialog for registry %s@%s\n", iterator->username, iterator->hostname);
/* This will also remove references to the registry */
- iterator->call = sip_destroy(iterator->call);
+ ast_log(LOG_NOTICE,"Calling Sip_Destroy() from reload reg for %s....\n", iterator->call->callid);
+ iterator->call = dialog_unlink_all(iterator->call, TRUE, TRUE);
+ /* iterator->call = sip_destroy(iterator->call); */
}
ASTOBJ_UNLOCK(iterator);
@@ -18339,7 +18439,7 @@
ast_debug(4, "--------------- Done destroying user list\n");
ASTOBJ_CONTAINER_DESTROYALL(®l, sip_registry_destroy);
ast_debug(4, "--------------- Done destroying registry list\n");
- ao2_callback(peers, 0, peer_markall_func, 0);
+ ao2_callback(peers, OBJ_NODATA, peer_markall_func, 0);
}
/* Initialize copy of current global_regcontext for later use in removing stale contexts */
@@ -19433,7 +19533,8 @@
reload_config(reason);
/* Prune peers who still are supposed to be deleted */
- ao2_callback(peers, 0, peer_prune_marked_func, 0);
+ ast_log(LOG_NOTICE,"Callback to prune marked peers\n");
+ ao2_callback(peers, OBJ_NODATA|OBJ_UNLINK, peer_is_marked, 0);
ast_debug(4, "--------------- Done destroying pruned peers\n");
Modified: team/murf/bug11210/configs/sip.conf.sample
URL: http://svn.digium.com/view/asterisk/team/murf/bug11210/configs/sip.conf.sample?view=diff&rev=90797&r1=90796&r2=90797
==============================================================================
--- team/murf/bug11210/configs/sip.conf.sample (original)
+++ team/murf/bug11210/configs/sip.conf.sample Mon Dec 3 22:38:23 2007
@@ -38,15 +38,20 @@
;match_auth_username=yes ; if available, match user entry using the
; 'username' field from the authentication line
; instead of the From: field.
+;;
;; hash table sizes. For maximum efficiency, adjust the following
;; values to be slightly larger than the maximum number of users/peers.
;; Too large, and space is wasted. Too small, and things will run slower.
;; 563 is probably way too big for small (home) applications, but it
;; should cover most small/medium sites.
+;; it is recommended to make the sizes be a prime number!
;; This was internally set to 17 for small-memory applications...
-hash_users=563
-hash_peers=563
-hash_dialogs=563
+;; All tables default to 563, except when compiled in LOW_MEMORY mode,
+;; in which case, they default to 17. You can override this by uncommenting
+;; the following, and changing the values.
+;hash_users=563
+;hash_peers=563
+;hash_dialogs=563
allowoverlap=no ; Disable overlap dialing support. (Default is yes)
;allowtransfer=no ; Disable all transfers (unless enabled in peers or users)
More information about the asterisk-commits
mailing list