diff options
Diffstat (limited to 'channels/chan_sip.c')
-rwxr-xr-x | channels/chan_sip.c | 106 |
1 files changed, 64 insertions, 42 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 1cbcf55ed..84911f274 100755 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -901,6 +901,7 @@ static int sip_hangup(struct ast_channel *ast) { struct sip_pvt *p = ast->pvt->pvt; int needcancel = 0; + int needdestroy = 0; if (option_debug) ast_log(LOG_DEBUG, "sip_hangup(%s)\n", ast->name); if (!ast->pvt->pvt) { @@ -924,7 +925,7 @@ static int sip_hangup(struct ast_channel *ast) p->owner = NULL; ast->pvt->pvt = NULL; - p->needdestroy = 1; + needdestroy = 1; /* Start the process if it's not already started */ if (!p->alreadygone && strlen(p->initreq.data)) { if (needcancel) { @@ -932,7 +933,7 @@ static int sip_hangup(struct ast_channel *ast) transmit_request_with_auth(p, "CANCEL", p->ocseq, 1); /* Actually don't destroy us yet, wait for the 487 on our original INVITE, but do set an autodestruct just in case. */ - p->needdestroy = 0; + needdestroy = 0; sip_scheddestroy(p, 15000); } else transmit_response_reliable(p, "403 Forbidden", &p->initreq); @@ -941,11 +942,13 @@ static int sip_hangup(struct ast_channel *ast) /* Send a hangup */ transmit_request_with_auth(p, "BYE", 0, 1); } else { - /* Note we will need a BYE when this all settles out */ + /* Note we will need a BYE when this all settles out + but we can't send one while we have "INVITE" outstanding. */ p->pendingbye = 1; } } } + p->needdestroy = needdestroy; ast_pthread_mutex_unlock(&p->lock); return 0; } @@ -1433,6 +1436,7 @@ static int sip_register(char *value, int lineno) if (secret) strncpy(reg->secret, secret, sizeof(reg->secret)-1); reg->expire = -1; + reg->timeout = -1; reg->refresh = default_expiry; reg->addr.sin_family = AF_INET; memcpy(®->addr.sin_addr, hp->h_addr, sizeof(®->addr.sin_addr)); @@ -2437,8 +2441,9 @@ static int sip_reregister(void *data) { /* if we are here, we know that we need to reregister. */ struct sip_registry *r=(struct sip_registry *)data; - return sip_do_register(r); - + r->expire = -1; + sip_do_register(r); + return 0; } @@ -2455,15 +2460,23 @@ 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=data; + struct sip_pvt *p; int res; ast_pthread_mutex_lock(&r->lock); - ast_log(LOG_NOTICE, "Registration timed out, trying again\n"); + ast_log(LOG_NOTICE, "Registration for '%s@%s' timed out, trying again\n", r->username, inet_ntoa(r->addr.sin_addr)); + if (r->call) { + /* Unlink us, destroy old call. Locking is not relevent here because all this happens + in the single SIP manager thread. */ + p = r->call; + p->registry = NULL; + r->call = NULL; + p->needdestroy = 1; + } r->regstate=REG_STATE_UNREGISTERED; - /* cancel ourselves first!!! */ - /* ast_sched_del(sched,r->timeout); */ + r->timeout = -1; res=transmit_register(r, "REGISTER", NULL); ast_pthread_mutex_unlock(&r->lock); - return res; + return 0; } static int transmit_register(struct sip_registry *r, char *cmd, char *auth) @@ -2481,25 +2494,32 @@ static int transmit_register(struct sip_registry *r, char *cmd, char *auth) return 0; } - - if (!(p=r->call)) { - if (!r->callid_valid) { - build_callid(r->callid, sizeof(r->callid), __ourip); - r->callid_valid=1; - } - p=sip_alloc( r->callid, &r->addr, 0); - p->outgoing = 1; - r->call=p; - p->registry=r; - strncpy(p->peersecret, r->secret, sizeof(p->peersecret)-1); - strncpy(p->peername, r->username, sizeof(p->peername)-1); - strncpy(p->username, r->username, sizeof(p->username)-1); + if (r->call) { + ast_log(LOG_WARNING, "Already have a call??\n"); } + build_callid(r->callid, sizeof(r->callid), __ourip); + p=sip_alloc( r->callid, &r->addr, 0); + if (!p) { + ast_log(LOG_WARNING, "Unable to allocate registration call\n"); + return 0; + } + p->outgoing = 1; + r->call=p; + p->registry=r; + strncpy(p->peersecret, r->secret, sizeof(p->peersecret)-1); + strncpy(p->peername, r->username, sizeof(p->peername)-1); + strncpy(p->username, r->username, sizeof(p->username)-1); + strncpy(p->exten, r->contact, sizeof(p->exten) - 1); + build_contact(p); /* set up a timeout */ - if (auth==NULL && !r->timeout) { + if (auth==NULL) { + if (r->timeout > -1) { + ast_log(LOG_WARNING, "Still have a timeout, %d\n", r->timeout); + ast_sched_del(sched, r->timeout); + } r->timeout = ast_sched_add(sched, 10*1000, sip_reg_timeout, r); - ast_log(LOG_NOTICE, "Scheduled a timeout # %d\n", r->timeout); + ast_log(LOG_DEBUG, "Scheduled a timeout # %d\n", r->timeout); } snprintf(from, sizeof(from), "<sip:%s@%s>;tag=as%08x", r->username, inet_ntoa(r->addr.sin_addr), p->tag); @@ -2516,11 +2536,6 @@ static int transmit_register(struct sip_registry *r, char *cmd, char *auth) add_header(&req, "Via", via); add_header(&req, "From", from); add_header(&req, "To", to); - { - char contact[256]; - snprintf(contact, sizeof(contact), "<sip:%s@%s:%d;transport=udp>", r->contact, inet_ntoa(p->ourip), ourport); - add_header(&req, "Contact", contact); - } add_header(&req, "Call-ID", p->callid); add_header(&req, "CSeq", tmp); add_header(&req, "User-Agent", "Asterisk PBX"); @@ -3816,19 +3831,23 @@ static void handle_response(struct sip_pvt *p, int resp, char *rest, struct sip_ int expires; struct sip_registry *r; r=p->registry; - r->regstate=REG_STATE_REGISTERED; - ast_log(LOG_NOTICE, "Registration successful\n"); - ast_log(LOG_NOTICE, "Cancelling timeout %d\n", r->timeout); - if (r->timeout) - ast_sched_del(sched, r->timeout); - r->timeout=0; - /* set us up for re-registering */ - /* figure out how long we got registered for */ - if (r->expire != -1) - ast_sched_del(sched, r->expire); - expires=atoi(get_header(req, "expires")); - if (!expires) expires=default_expiry; - r->expire=ast_sched_add(sched, (expires-2)*1000, sip_reregister, r); + if (r) { + r->regstate=REG_STATE_REGISTERED; + ast_log(LOG_NOTICE, "Registration successful\n"); + if (r->timeout > -1) { + ast_log(LOG_DEBUG, "Cancelling timeout %d\n", r->timeout); + ast_sched_del(sched, r->timeout); + } + r->timeout=-1; + /* set us up for re-registering */ + /* figure out how long we got registered for */ + if (r->expire > -1) + ast_sched_del(sched, r->expire); + expires=atoi(get_header(req, "expires")); + if (!expires) expires=default_expiry; + r->expire=ast_sched_add(sched, (expires-2)*1000, sip_reregister, r); + } else + ast_log(LOG_WARNING, "Got 200 OK on REGISTER that isn't a register\n"); } break; @@ -4475,10 +4494,13 @@ static void *do_monitor(void *data) restartsearch: sip = iflist; while(sip) { + ast_pthread_mutex_lock(&sip->lock); if (sip->needdestroy && !sip->packets) { + ast_pthread_mutex_unlock(&sip->lock); __sip_destroy(sip, 1); goto restartsearch; } + ast_pthread_mutex_unlock(&sip->lock); sip = sip->next; } ast_pthread_mutex_unlock(&iflock); |