From ef4db783c65899dcb7c034f002e573c34d7570a1 Mon Sep 17 00:00:00 2001 From: Olle Johansson Date: Tue, 23 Jan 2007 15:36:01 +0000 Subject: Issue #8817 - Registry corruption when packet retransmits fail. (tootai, patchy by oej) git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@51659 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- channels/chan_sip.c | 41 ++++++++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 15 deletions(-) (limited to 'channels') diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 71674468f..6d43d36fa 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -1632,11 +1632,21 @@ static void unref_user(struct sip_user *user) ASTOBJ_UNREF(user, sip_destroy_user); } -static void unref_registry(struct sip_registry *reg) +static void registry_unref(struct sip_registry *reg) { + if (option_debug > 2) + ast_log(LOG_DEBUG, "SIP Registry %s: refcount now %d\n", reg->hostname, reg->refcount - 1); ASTOBJ_UNREF(reg, sip_registry_destroy); } +/*! \brief Add object reference to SIP registry */ +static struct sip_registry *registry_addref(struct sip_registry *reg) +{ + if (option_debug > 2) + ast_log(LOG_DEBUG, "SIP Registry %s: refcount now %d\n", reg->hostname, reg->refcount + 1); + return ASTOBJ_REF(reg); /* Add pointer to registry in packet */ +} + /*! \brief Interface structure with callbacks used to connect to UDPTL module*/ static struct ast_udptl_protocol sip_udptl = { type: "SIP", @@ -1969,7 +1979,7 @@ static int retrans_pkt(void *data) /* If no channel owner, destroy now */ /* Let the peerpoke system expire packets when the timer expires for poke_noanswer */ - if (pkt->method != SIP_OPTIONS) + if (pkt->method != SIP_OPTIONS && pkt->method != SIP_REGISTER) ast_set_flag(&pkt->owner->flags[0], SIP_NEEDDESTROY); } } @@ -3036,7 +3046,7 @@ static void __sip_destroy(struct sip_pvt *p, int lockowner, int lockdialoglist) if (p->registry) { if (p->registry->call == p) p->registry->call = NULL; - unref_registry(p->registry); + registry_unref(p->registry); } /* Unlink us from the owner if we have one */ @@ -4607,7 +4617,7 @@ static int sip_register(char *value, int lineno) reg->callid_valid = FALSE; reg->ocseq = INITIAL_CSEQ; ASTOBJ_CONTAINER_LINK(®l, reg); /* Add the new registry entry to the list */ - unref_registry(reg); + registry_unref(reg); return 0; } @@ -7174,7 +7184,7 @@ static char *regstate2str(enum sipregistrystate regstate) static int sip_reregister(void *data) { /* if we are here, we know that we need to reregister. */ - struct sip_registry *r= ASTOBJ_REF((struct sip_registry *) data); + struct sip_registry *r= registry_addref((struct sip_registry *) data); /* if we couldn't get a reference to the registry object, punt */ if (!r) @@ -7189,7 +7199,7 @@ static int sip_reregister(void *data) r->expire = -1; __sip_do_register(r); - unref_registry(r); + registry_unref(r); return 0; } @@ -7207,7 +7217,7 @@ static int sip_reg_timeout(void *data) { /* if we are here, our registration timed out, so we'll just do it over */ - struct sip_registry *r = ASTOBJ_REF((struct sip_registry *) data); + struct sip_registry *r = registry_addref((struct sip_registry *) data); struct sip_pvt *p; int res; @@ -7220,8 +7230,10 @@ static int sip_reg_timeout(void *data) /* 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); + if (p->registry) { + registry_unref(p->registry); + p->registry = NULL; + } r->call = NULL; ast_set_flag(&p->flags[0], SIP_NEEDDESTROY); /* Pretend to ACK anything just in case */ @@ -7240,7 +7252,7 @@ static int sip_reg_timeout(void *data) res=transmit_register(r, SIP_REGISTER, NULL, NULL); } manager_event(EVENT_FLAG_SYSTEM, "Registry", "ChannelDriver: SIP\r\nUsername: %s\r\nDomain: %s\r\nStatus: %s\r\n", r->username, r->hostname, regstate2str(r->regstate)); - unref_registry(r); + registry_unref(r); return 0; } @@ -7306,7 +7318,7 @@ static int transmit_register(struct sip_registry *r, int sipmethod, const char * r->portno = ntohs(p->sa.sin_port); ast_set_flag(&p->flags[0], SIP_OUTGOING); /* Registration is outgoing call */ r->call=p; /* Save pointer to SIP packet */ - p->registry = ASTOBJ_REF(r); /* Add pointer to registry in packet */ + p->registry = registry_addref(r); /* Add pointer to registry in packet */ if (!ast_strlen_zero(r->secret)) /* Secret (password) */ ast_string_field_set(p, peersecret, r->secret); if (!ast_strlen_zero(r->md5secret)) @@ -10409,9 +10421,8 @@ static int sip_show_registry(int fd, int argc, char *argv[]) if (iterator->regtime) { ast_localtime(&iterator->regtime, &tm, NULL); strftime(tmpdat, sizeof(tmpdat), "%a, %d %b %Y %T", &tm); - } else { - tmpdat[0] = 0; - } + } else + tmpdat[0] = '\0'; ast_cli(fd, FORMAT, host, iterator->username, iterator->refresh, regstate2str(iterator->regstate), tmpdat); ASTOBJ_UNLOCK(iterator); } while(0)); @@ -12241,7 +12252,7 @@ static int handle_response_register(struct sip_pvt *p, int resp, char *rest, str /* Schedule re-registration before we expire */ r->expire=ast_sched_add(sched, expires_ms, sip_reregister, r); - unref_registry(r); + registry_unref(r); } return 1; } -- cgit v1.2.3