Index: channels/chan_iax2.c =================================================================== --- channels/chan_iax2.c (revision 288191) +++ channels/chan_iax2.c (working copy) @@ -1237,6 +1237,39 @@ .func_channel_read = acf_channel_read, }; +/*! + * \internal + * \brief Obtain the owner channel lock if the owner exists. + * + * \param callno IAX2 call id. + * + * \note Assumes the iaxsl[callno] lock is already obtained. + * + * \note + * IMPORTANT NOTE!!! Any time this function is used, even if + * iaxs[callno] was valid before calling it, it may no longer be + * valid after calling it. This function may unlock and lock + * the mutex associated with this callno, meaning that another + * thread may grab it and destroy the call. + * + * \return Nothing + */ +static void iax2_lock_owner(int callno) +{ + for (;;) { + if (!iaxs[callno] || !iaxs[callno]->owner) { + /* There is no owner lock to get. */ + break; + } + if (!ast_channel_trylock(iaxs[callno]->owner)) { + /* We got the lock */ + break; + } + /* Avoid deadlock by pausing and trying again */ + DEADLOCK_AVOIDANCE(&iaxsl[callno]); + } +} + static void mwi_event_cb(const struct ast_event *event, void *userdata) { /* The MWI subscriptions exist just so the core knows we care about those @@ -2890,18 +2923,10 @@ */ static int iax2_queue_frame(int callno, struct ast_frame *f) { - for (;;) { - if (iaxs[callno] && iaxs[callno]->owner) { - if (ast_channel_trylock(iaxs[callno]->owner)) { - /* Avoid deadlock by pausing and trying again */ - DEADLOCK_AVOIDANCE(&iaxsl[callno]); - } else { - ast_queue_frame(iaxs[callno]->owner, f); - ast_channel_unlock(iaxs[callno]->owner); - break; - } - } else - break; + iax2_lock_owner(callno); + if (iaxs[callno] && iaxs[callno]->owner) { + ast_queue_frame(iaxs[callno]->owner, f); + ast_channel_unlock(iaxs[callno]->owner); } return 0; } @@ -2921,18 +2946,10 @@ */ static int iax2_queue_hangup(int callno) { - for (;;) { - if (iaxs[callno] && iaxs[callno]->owner) { - if (ast_channel_trylock(iaxs[callno]->owner)) { - /* Avoid deadlock by pausing and trying again */ - DEADLOCK_AVOIDANCE(&iaxsl[callno]); - } else { - ast_queue_hangup(iaxs[callno]->owner); - ast_channel_unlock(iaxs[callno]->owner); - break; - } - } else - break; + iax2_lock_owner(callno); + if (iaxs[callno] && iaxs[callno]->owner) { + ast_queue_hangup(iaxs[callno]->owner); + ast_channel_unlock(iaxs[callno]->owner); } return 0; } @@ -2953,18 +2970,10 @@ static int iax2_queue_control_data(int callno, enum ast_control_frame_type control, const void *data, size_t datalen) { - for (;;) { - if (iaxs[callno] && iaxs[callno]->owner) { - if (ast_channel_trylock(iaxs[callno]->owner)) { - /* Avoid deadlock by pausing and trying again */ - DEADLOCK_AVOIDANCE(&iaxsl[callno]); - } else { - ast_queue_control_data(iaxs[callno]->owner, control, data, datalen); - ast_channel_unlock(iaxs[callno]->owner); - break; - } - } else - break; + iax2_lock_owner(callno); + if (iaxs[callno] && iaxs[callno]->owner) { + ast_queue_control_data(iaxs[callno]->owner, control, data, datalen); + ast_channel_unlock(iaxs[callno]->owner); } return 0; } @@ -4143,6 +4152,12 @@ return -1; } + iax2_lock_owner(fr->callno); + if (!iaxs[fr->callno]) { + /* The call dissappeared so discard this frame that we could not send. */ + iax2_frame_free(fr); + return -1; + } if ((owner = iaxs[fr->callno]->owner)) bridge = ast_bridged_channel(owner); @@ -4151,6 +4166,8 @@ if ( (!ast_test_flag64(iaxs[fr->callno], IAX_FORCEJITTERBUF)) && owner && bridge && (bridge->tech->properties & AST_CHAN_TP_WANTSJITTER) ) { jb_frame frame; + ast_channel_unlock(owner); + /* deliver any frames in the jb */ while (jb_getall(iaxs[fr->callno]->jb, &frame) == JB_OK) { __do_deliver(frame.data); @@ -4169,6 +4186,9 @@ __do_deliver(fr); return -1; } + if (owner) { + ast_channel_unlock(owner); + } /* insert into jitterbuffer */ /* TODO: Perhaps we could act immediately if it's not droppable and late */ @@ -9708,27 +9728,13 @@ static void set_hangup_source_and_cause(int callno, unsigned char causecode) { - int locked = 0; - struct ast_channel *owner=NULL; - - do { - if (ast_channel_trylock(iaxs[callno]->owner)) { - DEADLOCK_AVOIDANCE(&iaxsl[callno]); - } else { - locked = 1; - owner = iaxs[callno]->owner; - } - } - while (!locked && iaxs[callno] && iaxs[callno]->owner); - + iax2_lock_owner(callno); if (iaxs[callno] && iaxs[callno]->owner) { if (causecode) { iaxs[callno]->owner->hangupcause = causecode; } ast_set_hangupsource(iaxs[callno]->owner, iaxs[callno]->owner->name, 0); - ast_channel_unlock(owner); - } else if(locked) { - ast_channel_unlock(owner); + ast_channel_unlock(iaxs[callno]->owner); } } @@ -9845,6 +9851,7 @@ if (f.frametype == AST_FRAME_IAX) { if (iax_parse_ies(&ies, thread->buf + sizeof(struct ast_iax2_full_hdr), f.datalen)) { ast_log(LOG_WARNING, "Undecodable frame received from '%s'\n", ast_inet_ntoa(sin.sin_addr)); + ast_variables_destroy(ies.vars); return 1; } f.data.ptr = NULL; @@ -9864,6 +9871,7 @@ if (!dcallno && iax2_allow_new(f.frametype, f.subclass.integer, 1)) { /* only set NEW_ALLOW if calltoken checks out */ if (handle_call_token(fh, &ies, &sin, fd)) { + ast_variables_destroy(ies.vars); return 1; } @@ -9881,6 +9889,7 @@ /* Don't know anything about it yet */ f.frametype = AST_FRAME_NULL; f.subclass.integer = 0; + memset(&ies, 0, sizeof(ies)); } if (!fr->callno) { @@ -9904,6 +9913,7 @@ } else if (f.frametype == AST_FRAME_IAX && (f.subclass.integer == IAX_COMMAND_REGREQ || f.subclass.integer == IAX_COMMAND_REGREL)) { send_apathetic_reply(1, ntohs(fh->scallno), &sin, IAX_COMMAND_REGREJ, ntohl(fh->ts), fh->iseqno + 1, fd, NULL); } + ast_variables_destroy(ies.vars); return 1; } } @@ -9926,11 +9936,13 @@ } if (fr->callno > 0) ast_mutex_unlock(&iaxsl[fr->callno]); + ast_variables_destroy(ies.vars); return 1; } if (ast_test_flag64(iaxs[fr->callno], IAX_ENCRYPTED) && !decrypted) { if (decrypt_frame(fr->callno, fh, &f, &res)) { ast_log(LOG_NOTICE, "Packet Decrypt Failed!\n"); + ast_variables_destroy(ies.vars); ast_mutex_unlock(&iaxsl[fr->callno]); return 1; } @@ -10020,6 +10032,7 @@ /* Send a VNAK requesting retransmission */ iax2_vnak(fr->callno); } + ast_variables_destroy(ies.vars); ast_mutex_unlock(&iaxsl[fr->callno]); return 1; } @@ -10083,6 +10096,7 @@ iaxs[fr->callno]->rseqno = fr->iseqno; else { /* Stop processing now */ + ast_variables_destroy(ies.vars); ast_mutex_unlock(&iaxsl[fr->callno]); return 1; } @@ -10095,6 +10109,7 @@ ((f.subclass.integer != IAX_COMMAND_TXACC) && (f.subclass.integer != IAX_COMMAND_TXCNT)))) { /* Only messages we accept from a transfer host are TXACC and TXCNT */ + ast_variables_destroy(ies.vars); ast_mutex_unlock(&iaxsl[fr->callno]); return 1; } @@ -10108,6 +10123,7 @@ if (ast_test_flag64(iaxs[fr->callno], IAX_DELAYPBXSTART)) { ast_clear_flag64(iaxs[fr->callno], IAX_DELAYPBXSTART); if (!ast_iax2_new(fr->callno, AST_STATE_RING, iaxs[fr->callno]->chosenformat, NULL)) { + ast_variables_destroy(ies.vars); ast_mutex_unlock(&iaxsl[fr->callno]); return 1; } @@ -10117,6 +10133,13 @@ struct ast_datastore *variablestore = NULL; struct ast_variable *var, *prev = NULL; AST_LIST_HEAD(, ast_var_t) *varlist; + + iax2_lock_owner(fr->callno); + if (!iaxs[fr->callno]) { + ast_variables_destroy(ies.vars); + ast_mutex_unlock(&iaxsl[fr->callno]); + return 1; + } if ((c = iaxs[fr->callno]->owner)) { varlist = ast_calloc(1, sizeof(*varlist)); variablestore = ast_datastore_alloc(&iax2_variable_datastore_info, NULL); @@ -10153,6 +10176,7 @@ ast_free(varlist); } } + ast_channel_unlock(c); } else { /* No channel yet, so transfer the variables directly over to the pvt, * for later inheritance. */ @@ -10182,14 +10206,11 @@ iaxs[fr->callno]->voiceformat = f.subclass.codec; ast_debug(1, "Ooh, voice format changed to '%s'\n", ast_getformatname(f.subclass.codec)); if (iaxs[fr->callno]->owner) { - format_t orignative; -retryowner: - if (ast_channel_trylock(iaxs[fr->callno]->owner)) { - DEADLOCK_AVOIDANCE(&iaxsl[fr->callno]); - if (iaxs[fr->callno] && iaxs[fr->callno]->owner) goto retryowner; - } + iax2_lock_owner(fr->callno); if (iaxs[fr->callno]) { if (iaxs[fr->callno]->owner) { + format_t orignative; + orignative = iaxs[fr->callno]->owner->nativeformats; iaxs[fr->callno]->owner->nativeformats = f.subclass.codec; if (iaxs[fr->callno]->owner->readformat) @@ -10261,22 +10282,32 @@ ast_set_flag64(iaxs[fr->callno], IAX_QUELCH); if (ies.musiconhold) { - if (iaxs[fr->callno]->owner && ast_bridged_channel(iaxs[fr->callno]->owner)) { + iax2_lock_owner(fr->callno); + if (!iaxs[fr->callno] || !iaxs[fr->callno]->owner) { + break; + } + if (ast_bridged_channel(iaxs[fr->callno]->owner)) { const char *moh_suggest = iaxs[fr->callno]->mohsuggest; + + /* + * We already hold the owner lock so we do not + * need to check iaxs[fr->callno] after it returns. + */ iax2_queue_control_data(fr->callno, AST_CONTROL_HOLD, S_OR(moh_suggest, NULL), !ast_strlen_zero(moh_suggest) ? strlen(moh_suggest) + 1 : 0); - if (!iaxs[fr->callno]) { - ast_mutex_unlock(&iaxsl[fr->callno]); - return 1; - } } + ast_channel_unlock(iaxs[fr->callno]->owner); } } break; case IAX_COMMAND_UNQUELCH: if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED)) { - /* Generate Manager Unhold event, if necessary*/ + iax2_lock_owner(fr->callno); + if (!iaxs[fr->callno]) { + break; + } + /* Generate Manager Unhold event, if necessary */ if (iaxs[fr->callno]->owner && ast_test_flag64(iaxs[fr->callno], IAX_QUELCH)) { ast_manager_event(iaxs[fr->callno]->owner, EVENT_FLAG_CALL, "Hold", "Status: Off\r\n" @@ -10287,13 +10318,17 @@ } ast_clear_flag64(iaxs[fr->callno], IAX_QUELCH); - if (iaxs[fr->callno]->owner && ast_bridged_channel(iaxs[fr->callno]->owner)) { + if (!iaxs[fr->callno]->owner) { + break; + } + if (ast_bridged_channel(iaxs[fr->callno]->owner)) { + /* + * We already hold the owner lock so we do not + * need to check iaxs[fr->callno] after it returns. + */ iax2_queue_control_data(fr->callno, AST_CONTROL_UNHOLD, NULL, 0); - if (!iaxs[fr->callno]) { - ast_mutex_unlock(&iaxsl[fr->callno]); - return 1; - } } + ast_channel_unlock(iaxs[fr->callno]->owner); } break; case IAX_COMMAND_TXACC: @@ -10320,8 +10355,7 @@ check_provisioning(&sin, fd, ies.serviceident, ies.provver); ast_mutex_lock(&iaxsl[fr->callno]); if (!iaxs[fr->callno]) { - ast_mutex_unlock(&iaxsl[fr->callno]); - return 1; + break; } } /* If we're in trunk mode, do it now, and update the trunk number in our frame before continuing */ @@ -10358,8 +10392,7 @@ ast_mutex_lock(&iaxsl[fr->callno]); if (!iaxs[fr->callno]) { - ast_mutex_unlock(&iaxsl[fr->callno]); - return 1; + break; } } else exists = 0; @@ -10372,8 +10405,7 @@ iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_NO_ROUTE_DESTINATION); send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); if (!iaxs[fr->callno]) { - ast_mutex_unlock(&iaxsl[fr->callno]); - return 1; + break; } if (authdebug) ast_log(LOG_NOTICE, "Rejected connect attempt from %s, request '%s@%s' does not exist\n", ast_inet_ntoa(sin.sin_addr), iaxs[fr->callno]->exten, iaxs[fr->callno]->context); @@ -10419,8 +10451,7 @@ iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL); send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); if (!iaxs[fr->callno]) { - ast_mutex_unlock(&iaxsl[fr->callno]); - return 1; + break; } if (authdebug) { char tmp[256], tmp2[256], tmp3[256]; @@ -10473,8 +10504,7 @@ ast_log(LOG_ERROR, "No best format in '%s'???\n", ast_getformatname_multiple(tmp, sizeof(tmp), iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability)); send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); if (!iaxs[fr->callno]) { - ast_mutex_unlock(&iaxsl[fr->callno]); - return 1; + break; } if (authdebug) { ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested/capability '%s'/'%s' incompatible with our capability '%s'.\n", @@ -10531,10 +10561,6 @@ iaxs[fr->callno]->encmethods = 0; if (!authenticate_request(fr->callno) && iaxs[fr->callno]) ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_AUTHENTICATED); - if (!iaxs[fr->callno]) { - ast_mutex_unlock(&iaxsl[fr->callno]); - return 1; - } break; case IAX_COMMAND_DPREQ: /* Request status in the dialplan */ @@ -10556,8 +10582,7 @@ if (iaxs[fr->callno]->owner) { set_hangup_source_and_cause(fr->callno, ies.causecode); if (!iaxs[fr->callno]) { - ast_mutex_unlock(&iaxsl[fr->callno]); - return 1; + break; } } @@ -10570,8 +10595,7 @@ if (iaxs[fr->callno]->owner) { set_hangup_source_and_cause(fr->callno, ies.causecode); if (!iaxs[fr->callno]) { - ast_mutex_unlock(&iaxsl[fr->callno]); - return 1; + break; } } @@ -10593,40 +10617,54 @@ case IAX_COMMAND_TRANSFER: { struct ast_channel *bridged_chan; + struct ast_channel *owner; - if (iaxs[fr->callno]->owner && (bridged_chan = ast_bridged_channel(iaxs[fr->callno]->owner)) && ies.called_number) { + iax2_lock_owner(fr->callno); + if (!iaxs[fr->callno]) { + /* Initiating call went away before we could transfer. */ + break; + } + owner = iaxs[fr->callno]->owner; + bridged_chan = owner ? ast_bridged_channel(owner) : NULL; + if (bridged_chan && ies.called_number) { + ast_mutex_unlock(&iaxsl[fr->callno]); + /* Set BLINDTRANSFER channel variables */ + pbx_builtin_setvar_helper(owner, "BLINDTRANSFER", bridged_chan->name); + pbx_builtin_setvar_helper(bridged_chan, "BLINDTRANSFER", owner->name); - ast_mutex_unlock(&iaxsl[fr->callno]); - pbx_builtin_setvar_helper(iaxs[fr->callno]->owner, "BLINDTRANSFER", bridged_chan->name); - ast_mutex_lock(&iaxsl[fr->callno]); - if (!iaxs[fr->callno]) { - ast_mutex_unlock(&iaxsl[fr->callno]); - return 1; - } - - pbx_builtin_setvar_helper(bridged_chan, "BLINDTRANSFER", iaxs[fr->callno]->owner->name); if (ast_parking_ext_valid(ies.called_number, c, iaxs[fr->callno]->context)) { - struct ast_channel *saved_channel = iaxs[fr->callno]->owner; - ast_mutex_unlock(&iaxsl[fr->callno]); - if (iax_park(bridged_chan, saved_channel, ies.called_number)) { - ast_log(LOG_WARNING, "Failed to park call on '%s'\n", bridged_chan->name); - } else { - ast_debug(1, "Parked call on '%s'\n", ast_bridged_channel(iaxs[fr->callno]->owner)->name); + ast_debug(1, "Parking call '%s'\n", bridged_chan->name); + if (iax_park(bridged_chan, owner, ies.called_number)) { + ast_log(LOG_WARNING, "Failed to park call '%s'\n", + bridged_chan->name); } ast_mutex_lock(&iaxsl[fr->callno]); } else { - if (ast_async_goto(bridged_chan, iaxs[fr->callno]->context, ies.called_number, 1)) - ast_log(LOG_WARNING, "Async goto of '%s' to '%s@%s' failed\n", bridged_chan->name, - ies.called_number, iaxs[fr->callno]->context); - else { - ast_debug(1, "Async goto of '%s' to '%s@%s' started\n", bridged_chan->name, - ies.called_number, iaxs[fr->callno]->context); + ast_mutex_lock(&iaxsl[fr->callno]); + + if (iaxs[fr->callno]) { + if (ast_async_goto(bridged_chan, iaxs[fr->callno]->context, + ies.called_number, 1)) { + ast_log(LOG_WARNING, + "Async goto of '%s' to '%s@%s' failed\n", + bridged_chan->name, ies.called_number, + iaxs[fr->callno]->context); + } else { + ast_debug(1, "Async goto of '%s' to '%s@%s' started\n", + bridged_chan->name, ies.called_number, + iaxs[fr->callno]->context); + } + } else { + /* Initiating call went away before we could transfer. */ } } } else { ast_debug(1, "Async goto not applicable on call %d\n", fr->callno); } + if (owner) { + ast_channel_unlock(owner); + } break; } @@ -10655,8 +10693,7 @@ iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL); send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); if (!iaxs[fr->callno]) { - ast_mutex_unlock(&iaxsl[fr->callno]); - return 1; + break; } if (authdebug) { char tmp1[256], tmp2[256]; @@ -10667,24 +10704,18 @@ } } else { ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED); - if (iaxs[fr->callno]->owner) { + iax2_lock_owner(fr->callno); + if (iaxs[fr->callno] && iaxs[fr->callno]->owner) { /* Switch us to use a compatible format */ iaxs[fr->callno]->owner->nativeformats = iaxs[fr->callno]->peerformat; ast_verb(3, "Format for call is %s\n", ast_getformatname(iaxs[fr->callno]->owner->nativeformats)); -retryowner2: - if (ast_channel_trylock(iaxs[fr->callno]->owner)) { - DEADLOCK_AVOIDANCE(&iaxsl[fr->callno]); - if (iaxs[fr->callno] && iaxs[fr->callno]->owner) goto retryowner2; - } - - if (iaxs[fr->callno] && iaxs[fr->callno]->owner) { - /* Setup read/write formats properly. */ - if (iaxs[fr->callno]->owner->writeformat) - ast_set_write_format(iaxs[fr->callno]->owner, iaxs[fr->callno]->owner->writeformat); - if (iaxs[fr->callno]->owner->readformat) - ast_set_read_format(iaxs[fr->callno]->owner, iaxs[fr->callno]->owner->readformat); - ast_channel_unlock(iaxs[fr->callno]->owner); - } + + /* Setup read/write formats properly. */ + if (iaxs[fr->callno]->owner->writeformat) + ast_set_write_format(iaxs[fr->callno]->owner, iaxs[fr->callno]->owner->writeformat); + if (iaxs[fr->callno]->owner->readformat) + ast_set_read_format(iaxs[fr->callno]->owner, iaxs[fr->callno]->owner->readformat); + ast_channel_unlock(iaxs[fr->callno]->owner); } } if (iaxs[fr->callno]) { @@ -10698,10 +10729,6 @@ case IAX_COMMAND_POKE: /* Send back a pong packet with the original timestamp */ send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_PONG, fr->ts, NULL, 0, -1); - if (!iaxs[fr->callno]) { - ast_mutex_unlock(&iaxsl[fr->callno]); - return 1; - } break; case IAX_COMMAND_PING: { @@ -10801,10 +10828,6 @@ ies.username ? ies.username : "", ast_inet_ntoa(iaxs[fr->callno]->addr.sin_addr)); iax2_queue_frame(fr->callno, &hangup_fr); } - if (!iaxs[fr->callno]) { - ast_mutex_unlock(&iaxsl[fr->callno]); - return 1; - } break; case IAX_COMMAND_AUTHREP: /* For security, always ack immediately */ @@ -10835,8 +10858,7 @@ iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_NO_ROUTE_DESTINATION); send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); if (!iaxs[fr->callno]) { - ast_mutex_unlock(&iaxsl[fr->callno]); - return 1; + break; } } else { /* Select an appropriate format */ @@ -10894,8 +10916,7 @@ iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL); send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); if (!iaxs[fr->callno]) { - ast_mutex_unlock(&iaxsl[fr->callno]); - return 1; + break; } } else { /* Pick one... */ @@ -10948,8 +10969,7 @@ iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL); send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); if (!iaxs[fr->callno]) { - ast_mutex_unlock(&iaxsl[fr->callno]); - return 1; + break; } } } @@ -11042,8 +11062,7 @@ iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_NO_ROUTE_DESTINATION); send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); if (!iaxs[fr->callno]) { - ast_mutex_unlock(&iaxsl[fr->callno]); - return 1; + break; } } else { char tmp[256]; @@ -11111,16 +11130,14 @@ send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); if (register_verify(fr->callno, &sin, &ies)) { if (!iaxs[fr->callno]) { - ast_mutex_unlock(&iaxsl[fr->callno]); - return 1; + break; } /* Send delayed failure */ auth_fail(fr->callno, IAX_COMMAND_REGREJ); break; } if (!iaxs[fr->callno]) { - ast_mutex_unlock(&iaxsl[fr->callno]); - return 1; + break; } if ((ast_strlen_zero(iaxs[fr->callno]->secret) && ast_strlen_zero(iaxs[fr->callno]->inkeys)) || ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_AUTHENTICATED)) { @@ -11130,25 +11147,16 @@ if (update_registry(&sin, fr->callno, ies.devicetype, fd, ies.refresh)) ast_log(LOG_WARNING, "Registry error\n"); if (!iaxs[fr->callno]) { - ast_mutex_unlock(&iaxsl[fr->callno]); - return 1; + break; } if (ies.provverpres && ies.serviceident && sin.sin_addr.s_addr) { ast_mutex_unlock(&iaxsl[fr->callno]); check_provisioning(&sin, fd, ies.serviceident, ies.provver); ast_mutex_lock(&iaxsl[fr->callno]); - if (!iaxs[fr->callno]) { - ast_mutex_unlock(&iaxsl[fr->callno]); - return 1; - } } break; } registry_authrequest(fr->callno); - if (!iaxs[fr->callno]) { - ast_mutex_unlock(&iaxsl[fr->callno]); - return 1; - } break; case IAX_COMMAND_REGACK: if (iax2_ack_registry(&ies, &sin, fr->callno)) @@ -11176,10 +11184,6 @@ iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No authority found"); iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_NOT_SUBSCRIBED); send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); - if (!iaxs[fr->callno]) { - ast_mutex_unlock(&iaxsl[fr->callno]); - return 1; - } } break; case IAX_COMMAND_TXREJ: @@ -11301,10 +11305,6 @@ send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_FWDATA, 0, ied0.buf, ied0.pos, -1); else send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_FWDATA, 0, ied0.buf, ied0.pos, -1); - if (!iaxs[fr->callno]) { - ast_mutex_unlock(&iaxsl[fr->callno]); - return 1; - } break; case IAX_COMMAND_CALLTOKEN: { @@ -11350,6 +11350,7 @@ else { ast_log(LOG_WARNING, "Received mini frame before first full video frame\n"); iax2_vnak(fr->callno); + ast_variables_destroy(ies.vars); ast_mutex_unlock(&iaxsl[fr->callno]); return 1; } @@ -11372,12 +11373,14 @@ else { ast_debug(1, "Received mini frame before first full voice frame\n"); iax2_vnak(fr->callno); + ast_variables_destroy(ies.vars); ast_mutex_unlock(&iaxsl[fr->callno]); return 1; } f.datalen = res - sizeof(struct ast_iax2_mini_hdr); if (f.datalen < 0) { ast_log(LOG_WARNING, "Datalen < 0?\n"); + ast_variables_destroy(ies.vars); ast_mutex_unlock(&iaxsl[fr->callno]); return 1; } @@ -11395,6 +11398,7 @@ } /* Don't pass any packets until we're started */ if (!ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED)) { + ast_variables_destroy(ies.vars); ast_mutex_unlock(&iaxsl[fr->callno]); return 1; } @@ -11403,6 +11407,7 @@ struct ast_party_connected_line connected; if (!ast_test_flag64(iaxs[fr->callno], IAX_RECVCONNECTEDLINE)) { + ast_variables_destroy(ies.vars); ast_mutex_unlock(&iaxsl[fr->callno]); return 1; } @@ -11465,6 +11470,7 @@ } /* Always run again */ + ast_variables_destroy(ies.vars); ast_mutex_unlock(&iaxsl[fr->callno]); return 1; }