[asterisk-commits] rizzo: branch rizzo/astobj2 r47407 -
/team/rizzo/astobj2/channels/chan_sip.c
asterisk-commits at lists.digium.com
asterisk-commits at lists.digium.com
Thu Nov 9 20:50:53 MST 2006
Author: rizzo
Date: Thu Nov 9 21:50:53 2006
New Revision: 47407
URL: http://svn.digium.com/view/asterisk?view=rev&rev=47407
Log:
rename some pvt pointers to ..._pvt so it is easier to track them.
Note some dubious constructs where the reference is dropped
but the session was not destroyed, possibly causing a memory leak.
The above, unfortunately, applies to trunk/1.4 as well.
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?view=diff&rev=47407&r1=47406&r2=47407
==============================================================================
--- team/rizzo/astobj2/channels/chan_sip.c (original)
+++ team/rizzo/astobj2/channels/chan_sip.c Thu Nov 9 21:50:53 2006
@@ -82,7 +82,7 @@
* the sip_hangup() function
*/
-// #define USE_AO2 // enable to use astobj2
+#define USE_AO2 // enable to use astobj2
#include "asterisk.h"
@@ -862,7 +862,7 @@
char replaces_callid[BUFSIZ]; /*!< Replace info: callid */
char replaces_callid_totag[BUFSIZ/2]; /*!< Replace info: to-tag */
char replaces_callid_fromtag[BUFSIZ/2]; /*!< Replace info: from-tag */
- struct sip_pvt *refer_call; /*!< Call we are referring */
+ struct sip_pvt *refer_pvt; /*!< Call we are referring */
int attendedtransfer; /*!< Attended or blind transfer? */
int localtransfer; /*!< Transfer to local domain? */
enum referstatus status; /*!< REFER status */
@@ -1147,7 +1147,7 @@
struct sockaddr_in addr; /*!< IP address of peer */
/* Qualification */
- struct sip_pvt *peer_call; /*!< Call pointer */
+ struct sip_pvt *peer_pvt; /*!< Call pointer */
int pokeexpire; /*!< When to expire poke (qualify= checking) */
int lastms; /*!< How long last response took (in ms), or -1 for no response */
int maxms; /*!< Max ms we will accept for the host to be up, 0 to not monitor */
@@ -1184,7 +1184,7 @@
int regattempts; /*!< Number of attempts (since the last success) */
int timeout; /*!< sched id of sip_reg_timeout */
int refresh; /*!< How often to refresh */
- struct sip_pvt *call; /*!< create a sip_pvt structure for each outbound "registration dialog" in progress */
+ struct sip_pvt *register_pvt; /*!< create a sip_pvt structure for each outbound "registration dialog" in progress */
enum sipregistrystate regstate; /*!< Registration state (see above) */
time_t regtime; /*!< Last succesful registration time */
int callid_valid; /*!< 0 means we haven't chosen callid for this registry yet. */
@@ -2026,19 +2026,17 @@
if (cur == pkt)
break;
}
- if (cur) {
+ if (!cur)
+ ast_log(LOG_WARNING, "Weird, couldn't find packet owner!\n");
+ else {
if (prev)
prev->next = cur->next;
else
pvt->packets = cur->next;
pkt->pvt = pvt_unref(pvt); /* release the pvt */
- sip_pvt_unlock(pvt);
free(cur);
- pkt = NULL;
- } else
- ast_log(LOG_WARNING, "Weird, couldn't find packet owner!\n");
- if (pkt)
- sip_pvt_unlock(pvt);
+ }
+ sip_pvt_unlock(pvt);
return 0;
}
@@ -2533,8 +2531,8 @@
ast_log(LOG_DEBUG, "Destroying SIP peer %s\n", peer->name);
/* Delete it, it needs to disappear */
- if (peer->peer_call)
- sip_destroy(peer->peer_call);
+ if (peer->peer_pvt)
+ sip_destroy(peer->peer_pvt);
if (peer->mwi_pvt) /* We have an active subscription, delete it */
sip_destroy(peer->mwi_pvt);
@@ -3025,13 +3023,13 @@
if (option_debug > 2)
ast_log(LOG_DEBUG, "Destroying registry entry for %s@%s\n", reg->username, reg->hostname);
- if (reg->call) {
+ if (reg->register_pvt) {
/* Clear registry before destroying to ensure
we don't get reentered trying to grab the registry lock */
- reg->call->registry = NULL;
+ reg->register_pvt->registry = NULL;
if (option_debug > 2)
ast_log(LOG_DEBUG, "Destroying active SIP dialog for registry %s@%s\n", reg->username, reg->hostname);
- sip_destroy(reg->call);
+ sip_destroy(reg->register_pvt);
}
if (reg->expire > -1)
ast_sched_del(sched, reg->expire);
@@ -3109,8 +3107,12 @@
p->route = NULL;
}
if (p->registry) {
- if (p->registry->call == p)
- p->registry->call = NULL;
+ /* XXX why this is only for ourselves ?
+ * in any case, if it is for ourselves, the destructor
+ * would not be called in astobj2
+ */
+ if (p->registry->register_pvt == p)
+ p->registry->register_pvt = pvt_unref(p->registry->register_pvt);
unref_registry(p->registry);
}
@@ -3470,9 +3472,9 @@
sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); /* also cancels previous one if there */
ast_clear_flag(&p->flags[0], SIP_DEFER_BYE_ON_TRANSFER); /* Really hang up next time */
ast_clear_flag(&p->flags[0], SIP_NEEDDESTROY);
+ /* XXX assert(p->owner == ast); */
if (p->owner->tech_pvt) /* i believe that's always */
- pvt_unref(p->owner->tech_pvt);
- p->owner->tech_pvt = NULL;
+ p->owner->tech_pvt = pvt_unref(p->owner->tech_pvt);
p->owner = NULL; /* Owner will be gone after we return, so take it away */
return 0;
}
@@ -3510,7 +3512,8 @@
ast_dsp_free(p->vad);
p->owner = NULL;
- ast->tech_pvt = NULL;
+ if (ast->tech_pvt)
+ ast->tech_pvt = pvt_unref(ast->tech_pvt);
/* Do not destroy this pvt until we have timeout or
get an answer to the BYE or INVITE/CANCEL
@@ -7227,13 +7230,15 @@
{
/* if we are here, we know that we need to reregister. */
struct sip_registry *r= ASTOBJ_REF((struct sip_registry *) data);
+ struct sip_pvt *pvt;
/* if we couldn't get a reference to the registry object, punt */
if (!r)
return 0;
- if (r->call && !ast_test_flag(&r->call->flags[0], SIP_NO_HISTORY))
- append_history(r->call, "RegistryRenew", "Account: %s@%s", r->username, r->hostname);
+ pvt = r->register_pvt; /* XXX do we have a lock on it ? */
+ if (pvt && !ast_test_flag(&pvt->flags[0], SIP_NO_HISTORY))
+ append_history(pvt, "RegistryRenew", "Account: %s@%s", r->username, r->hostname);
/* Since registry's are only added/removed by the the monitor thread, this
may be overkill to reference/dereference at all here */
if (sipdebug)
@@ -7267,17 +7272,18 @@
if (!r)
return 0;
+ p = r->register_pvt;
ast_log(LOG_NOTICE, " -- Registration for '%s@%s' timed out, trying again (Attempt #%d)\n", r->username, r->hostname, r->regattempts);
- if (r->call) {
+ if (p) {
/* Unlink us, destroy old call. Locking is not relevant here because all this happens
in the single SIP manager thread. */
- p = r->call;
if (p->registry)
unref_registry(p->registry);
- r->call = NULL;
ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
/* Pretend to ACK anything just in case */
__sip_pretend_ack(p); /* XXX we need p locked, not sure we have */
+ r->register_pvt = NULL; /* reference goes away down */
+ sip_destroy(p);
}
/* If we have a limit, stop registration and give up */
if (global_regattempts_max && (r->regattempts > global_regattempts_max)) {
@@ -7313,12 +7319,12 @@
return 0;
}
- if (r->call) { /* We have a registration */
+ if (r->register_pvt) { /* We have a registration */
if (!auth) {
ast_log(LOG_WARNING, "Already have a REGISTER going on to %s@%s?? \n", r->username, r->hostname);
return 0;
} else {
- p = pvt_ref(r->call); /* grab a reference */
+ p = pvt_ref(r->register_pvt); /* grab a reference */
make_our_tag(p->tag, sizeof(p->tag)); /* create a new local tag for every register attempt */
ast_string_field_free(p, theirtag); /* forget their old tag, so we don't match tags when getting response */
}
@@ -7358,7 +7364,7 @@
else /* Set registry port to the port set from the peer definition/srv or default */
r->portno = ntohs(p->sa.sin_port);
ast_set_flag(&p->flags[0], SIP_OUTGOING); /* Registration is outgoing call */
- r->call = pvt_ref(p); /* Save pointer to SIP packet */
+ r->register_pvt = pvt_ref(p); /* Save pointer to SIP packet */
p->registry = ASTOBJ_REF(r); /* Add pointer to registry in packet */
if (!ast_strlen_zero(r->secret)) /* Secret (password) */
ast_string_field_set(p, peersecret, r->secret);
@@ -8974,7 +8980,8 @@
ast_copy_string(referdata->refer_to, c, sizeof(referdata->refer_to));
ast_copy_string(referdata->referred_by, "", sizeof(referdata->referred_by));
ast_copy_string(referdata->refer_contact, "", sizeof(referdata->refer_contact));
- referdata->refer_call = NULL;
+ if (referdata->refer_pvt) /* XXX or sip_destroy() ? */
+ referdata->refer_pvt = pvt_unref(referdata->refer_pvt);
/* Set new context */
ast_string_field_set(p, context, transfer_context);
return 0;
@@ -12005,7 +12012,7 @@
break;
}
if (!strcasecmp(bridgepeer->tech->type,"SIP")) {
- bridgepvt = (struct sip_pvt*)(bridgepeer->tech_pvt);
+ bridgepvt = bridgepeer->tech_pvt;
if (bridgepvt->udptl) {
if (p->t38.state == T38_PEER_REINVITE) {
sip_handle_t38_reinvite(bridgepeer, p, 0);
@@ -12173,8 +12180,7 @@
static int handle_response_register(struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int seqno)
{
int expires, expires_ms;
- struct sip_registry *r;
- r=p->registry;
+ struct sip_registry *r = p->registry;
switch (resp) {
case 401: /* Unauthorized */
@@ -12194,8 +12200,10 @@
ast_log(LOG_WARNING, "Got 404 Not found on SIP register to service %s@%s, giving up\n", p->registry->username,p->registry->hostname);
if (global_regattempts_max)
p->registry->regattempts = global_regattempts_max+1;
- ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
- r->call = NULL;
+ ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
+ if (r->register_pvt) /* XXX are we sure about destroy ? */
+ sip_destroy(r->register_pvt);
+ r->register_pvt = NULL;
ast_sched_del(sched, r->timeout);
break;
case 407: /* Proxy auth */
@@ -12209,8 +12217,9 @@
ast_log(LOG_WARNING, "Got 423 Interval too brief for service %s@%s, minimum is %d seconds\n", p->registry->username, p->registry->hostname, r->expiry);
ast_sched_del(sched, r->timeout);
r->timeout = -1;
- if (r->call) {
- r->call = NULL;
+ if (r->register_pvt) { /* XXX are we sure about destroy ? */
+ sip_destroy(r->register_pvt);
+ r->register_pvt = NULL;
ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
}
if (r->expiry > max_expiry) {
@@ -12228,7 +12237,9 @@
if (global_regattempts_max)
p->registry->regattempts = global_regattempts_max+1;
ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
- r->call = NULL;
+ if (r->register_pvt) /* XXX are we sure about destroy ? */
+ sip_destroy(r->register_pvt);
+ r->register_pvt = NULL;
ast_sched_del(sched, r->timeout);
break;
case 200: /* 200 OK */
@@ -12250,7 +12261,9 @@
ast_sched_del(sched, r->timeout);
}
r->timeout=-1;
- r->call = NULL;
+ if (r->register_pvt) /* XXX are we sure about destroy ? */
+ sip_destroy(r->register_pvt);
+ r->register_pvt = NULL;
p->registry = NULL;
/* Let this one hang around until we have all the responses */
sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
@@ -12335,8 +12348,8 @@
peer->lastms = pingtime;
/* XXX do we need to unlink too ? */
- if (peer->peer_call)
- peer->peer_call = pvt_unref(peer->peer_call);
+ if (peer->peer_pvt)
+ peer->peer_pvt = pvt_unref(peer->peer_pvt);
if (statechanged) {
const char *s = is_reachable ? "Reachable" : "Lagged";
@@ -13186,7 +13199,7 @@
int earlyreplace = 0;
int oneleggedreplace = 0; /* Call with no bridge, propably IVR or voice message */
struct ast_channel *c = p->owner; /* Our incoming call */
- struct ast_channel *replacecall = p->refer->refer_call->owner; /* The channel we're about to take over */
+ struct ast_channel *replacecall = p->refer->refer_pvt->owner; /* The channel we're about to take over */
struct ast_channel *targetcall; /* The bridge to the take-over target */
/* Check if we're in ring state */
@@ -13220,16 +13233,17 @@
transmit_response_with_sdp(p, "200 OK", req, XMIT_RELIABLE);
/* Do something more clever here */
ast_channel_unlock(c);
- sip_pvt_unlock(p->refer->refer_call);
+ sip_pvt_unlock(p->refer->refer_pvt);
return 1;
}
+ /* XXX this block is wrong here, we already assumed c != NULL above */
if (!c) {
/* What to do if no channel ??? */
ast_log(LOG_ERROR, "Unable to create new channel. Invite/replace failed.\n");
transmit_response_reliable(p, "503 Service Unavailable", req);
append_history(p, "Xfer", "INVITE/Replace Failed. No new channel.");
sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
- sip_pvt_unlock(p->refer->refer_call);
+ sip_pvt_unlock(p->refer->refer_pvt);
return 1;
}
append_history(p, "Xfer", "INVITE/Replace received");
@@ -13263,10 +13277,10 @@
ast_channel_unlock(c);
/* Unlock PVT */
- sip_pvt_unlock(p->refer->refer_call);
+ sip_pvt_unlock(p->refer->refer_pvt);
/* Make sure that the masq does not free our PVT for the old call */
- ast_set_flag(&p->refer->refer_call->flags[0], SIP_DEFER_BYE_ON_TRANSFER); /* Delay hangup */
+ ast_set_flag(&p->refer->refer_pvt->flags[0], SIP_DEFER_BYE_ON_TRANSFER); /* Delay hangup */
/* Prepare the masquerade - if this does not happen, we will be gone */
if(ast_channel_masquerade(replacecall, c))
@@ -13304,7 +13318,7 @@
}
ast_channel_unlock(replacecall);
}
- sip_pvt_unlock(p->refer->refer_call);
+ sip_pvt_unlock(p->refer->refer_pvt);
ast_setstate(c, AST_STATE_DOWN);
if (option_debug > 3) {
@@ -13329,7 +13343,12 @@
sip_pvt_unlock(p); /* Unlock SIP structure */
/* The call should be down with no ast_channel, so hang it up */
- c->tech_pvt = NULL; /* XXX do we need unref ? */
+ /* XXX not sure if this is a sip tech or something else.
+ * do we need to destroy it or what ?
+ * And why do we reset it before calling hangup ?
+ */
+ if (c->tech_pvt)
+ c->tech_pvt = pvt_unref(c->tech_pvt);
ast_hangup(c);
return 0;
}
@@ -13451,7 +13470,8 @@
/* Try to find call that we are replacing
If we have a Replaces header, we need to cancel that call if we succeed with this call
*/
- if ((p->refer->refer_call = get_sip_pvt_byid_locked(replace_id, totag, fromtag)) == NULL) {
+ /* XXX do we have a previous refer_pvt ? */
+ if ((p->refer->refer_pvt = get_sip_pvt_byid_locked(replace_id, totag, fromtag)) == NULL) {
ast_log(LOG_NOTICE, "Supervised transfer attempted to replace non-existent call id (%s)!\n", replace_id);
transmit_response(p, "481 Call Leg Does Not Exist (Replaces)", req);
error = 1;
@@ -13463,14 +13483,14 @@
We want to bridge the bridged part of the call to the
incoming invite, thus taking over the refered call */
- if (p->refer->refer_call == p) {
+ if (p->refer->refer_pvt == p) {
ast_log(LOG_NOTICE, "INVITE with replaces into it's own call id (%s == %s)!\n", replace_id, p->callid);
- p->refer->refer_call = pvt_unref(p->refer->refer_call);
+ p->refer->refer_pvt = pvt_unref(p->refer->refer_pvt);
transmit_response(p, "400 Bad request", req); /* The best way to not not accept the transfer */
error = 1;
}
- if (!error && !p->refer->refer_call->owner) {
+ if (!error && !p->refer->refer_pvt->owner) {
/* Oops, someting wrong anyway, no owner, no call */
ast_log(LOG_NOTICE, "Supervised transfer attempted to replace non-existing call id (%s)!\n", replace_id);
/* Check for better return code */
@@ -13478,7 +13498,7 @@
error = 1;
}
- if (!error && p->refer->refer_call->owner->_state != AST_STATE_RING && p->refer->refer_call->owner->_state != AST_STATE_UP ) {
+ if (!error && p->refer->refer_pvt->owner->_state != AST_STATE_RING && p->refer->refer_pvt->owner->_state != AST_STATE_UP ) {
ast_log(LOG_NOTICE, "Supervised transfer attempted to replace non-ringing or active call id (%s)!\n", replace_id);
transmit_response(p, "603 Declined (Replaces)", req);
error = 1;
@@ -13488,9 +13508,9 @@
append_history(p, "Xfer", "INVITE/Replace Failed.");
sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
sip_pvt_unlock(p);
- if (p->refer->refer_call) {
- sip_pvt_unlock(p->refer->refer_call);
- ast_channel_unlock(p->refer->refer_call->owner);
+ if (p->refer->refer_pvt) { /* XXX what's the right order here ? */
+ sip_pvt_unlock(p->refer->refer_pvt);
+ ast_channel_unlock(p->refer->refer_pvt->owner);
}
return -1;
}
@@ -13733,7 +13753,7 @@
/* We have a bridge, and this is re-invite to switchover to T38 so we send re-invite with T38 SDP, to other side of bridge*/
/*! XXX: we should also check here does the other side supports t38 at all !!! XXX */
if (!strcasecmp(bridgepeer->tech->type, "SIP")) { /* If we are bridged to SIP channel */
- bridgepvt = (struct sip_pvt*)bridgepeer->tech_pvt;
+ bridgepvt = bridgepeer->tech_pvt;
if (bridgepvt->t38.state == T38_DISABLED) {
if (bridgepvt->udptl) { /* If everything is OK with other side's udptl struct */
/* Send re-invite to the bridged channel */
@@ -13785,7 +13805,7 @@
struct sip_pvt *bridgepvt = NULL;
if ((bridgepeer = ast_bridged_channel(p->owner))) {
if (!strcasecmp(bridgepeer->tech->type, sip_tech.type)) {
- bridgepvt = (struct sip_pvt*)bridgepeer->tech_pvt;
+ bridgepvt = bridgepeer->tech_pvt;
/* Does the bridged peer have T38 ? */
if (bridgepvt->t38.state == T38_ENABLED) {
ast_log(LOG_WARNING, "RTP re-invite after T38 session not handled yet !\n");
@@ -14568,7 +14588,7 @@
if (authpeer->mwi_pvt && authpeer->mwi_pvt != p) /* Destroy old PVT if this is a new one */
/* We only allow one subscription per peer */
sip_destroy(authpeer->mwi_pvt);
- authpeer->mwi_pvt = p; /* Link from peer to pvt */
+ authpeer->mwi_pvt = pvt_ref(p); /* Link from peer to pvt */
p->relatedpeer = authpeer; /* Link from pvt to peer */
/* Do not release authpeer here */
} else { /* At this point, Asterisk does not understand the specified event */
@@ -15320,9 +15340,9 @@
ast_log(LOG_NOTICE, "Peer '%s' is now UNREACHABLE! Last qualify: %d\n", peer->name, peer->lastms);
manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: SIP/%s\r\nPeerStatus: Unreachable\r\nTime: %d\r\n", peer->name, -1);
}
- if (peer->peer_call)
- sip_destroy(peer->peer_call);
- peer->peer_call = NULL;
+ if (peer->peer_pvt)
+ sip_destroy(peer->peer_pvt);
+ peer->peer_pvt = NULL;
peer->lastms = -1;
ast_device_state_changed("SIP/%s", peer->name);
/* Try again quickly */
@@ -15344,16 +15364,16 @@
ast_sched_del(sched, peer->pokeexpire);
peer->lastms = 0;
peer->pokeexpire = -1;
- if (peer->peer_call) /* XXX or sip_destroy() ? */
- peer->peer_call = pvt_unref(peer->peer_call);
+ if (peer->peer_pvt) /* XXX or sip_destroy() ? */
+ peer->peer_pvt = pvt_unref(peer->peer_pvt);
return 0;
}
- if (peer->peer_call) {
+ if (peer->peer_pvt) {
if (sipdebug)
ast_log(LOG_NOTICE, "Still have a QUALIFY dialog active, deleting\n");
- sip_destroy(peer->peer_call);
- }
- if (!(p = peer->peer_call = sip_alloc(NULL, NULL, 0, SIP_OPTIONS)))
+ sip_destroy(peer->peer_pvt);
+ }
+ if (!(p = peer->peer_pvt = sip_alloc(NULL, NULL, 0, SIP_OPTIONS)))
return -1;
p->sa = peer->addr;
@@ -17294,11 +17314,12 @@
/* This is needed, since otherwise active registry entries will not be destroyed */
ASTOBJ_CONTAINER_TRAVERSE(®l, 1, do {
ASTOBJ_RDLOCK(iterator);
- if (iterator->call) {
+ if (iterator->register_pvt) {
if (option_debug > 2)
ast_log(LOG_DEBUG, "Destroying active SIP dialog for registry %s@%s\n", iterator->username, iterator->hostname);
/* This will also remove references to the registry */
- sip_destroy(iterator->call);
+ sip_destroy(iterator->register_pvt);
+ iterator->register_pvt = NULL;
}
ASTOBJ_UNLOCK(iterator);
} while(0));
More information about the asterisk-commits
mailing list