Index: channels/chan_sip.c =================================================================== --- channels/chan_sip.c (revision 257206) +++ channels/chan_sip.c (working copy) @@ -6147,7 +6147,9 @@ return f; } -/*! \brief Read SIP RTP from channel */ +/*! \brief Read SIP RTP from channel + * Called with ast locked + */ static struct ast_frame *sip_read(struct ast_channel *ast) { struct ast_frame *fr; @@ -6156,14 +6158,18 @@ sip_pvt_lock(p); fr = sip_rtp_read(ast, p, &faxdetected); + + if (fr == &ast_null_frame) { + sip_pvt_unlock(p); + return fr; + } + p->lastrtprx = time(NULL); /* If we detect a CNG tone and fax detection is enabled then send us off to the fax extension */ if (faxdetected && ast_test_flag(&p->flags[1], SIP_PAGE2_FAX_DETECT)) { - ast_channel_lock(ast); if (strcmp(ast->exten, "fax")) { const char *target_context = S_OR(ast->macrocontext, ast->context); - ast_channel_unlock(ast); if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) { ast_verbose(VERBOSE_PREFIX_2 "Redirecting '%s' to fax extension\n", ast->name); pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten); @@ -6173,11 +6179,9 @@ fr = &ast_null_frame; } else { ast_log(LOG_NOTICE, "Fax detected but no fax extension\n"); - } - } else { - ast_channel_unlock(ast); - } - } + } + } + } /* Only allow audio through if they sent progress with SDP, or if the channel is actually answered */ if (fr && fr->frametype == AST_FRAME_VOICE && p->invitestate != INV_EARLY_MEDIA && ast->_state != AST_STATE_UP) { Index: main/rtp.c =================================================================== --- main/rtp.c (revision 257191) +++ main/rtp.c (working copy) @@ -1456,7 +1456,10 @@ /* Cache where the header will go */ res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET, - 0, (struct sockaddr *)&sin, &len); + MSG_DONTWAIT, (struct sockaddr *)&sin, &len); + if (res == -1 && errno == EAGAIN) { + return &ast_null_frame; + } /* If strict RTP protection is enabled see if we need to learn this address or if the packet should be dropped */ if (rtp->strict_rtp_state == STRICT_RTP_LEARN) { @@ -3509,8 +3512,17 @@ oldcodec0 = codec0; } + /* Now that we're in a reinvite bridge, turn off the RTP timeouts, + * because we may (legitimately) not receive any for awhile. */ + ast_rtp_set_rtptimers_onhold(p0); + ast_rtp_set_rtptimers_onhold(p1); + /* Wait for frame to come in on the channels */ if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) { + /* Turn RTP timers back on */ + ast_rtp_set_rtptimers_onhold(p0); + ast_rtp_set_rtptimers_onhold(p1); + if (!timeoutms) { if (pr0->set_rtp_peer(c0, NULL, NULL, NULL, 0, 0)) ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name); @@ -3523,7 +3535,14 @@ break; continue; } + fr = ast_read(who); + + /* Turn RTP timers back on, after the read, so that the timeouts have + * had a chance to be reset. */ + ast_rtp_set_rtptimers_onhold(p0); + ast_rtp_set_rtptimers_onhold(p1); + other = (who == c0) ? c1 : c0; if (!fr || ((fr->frametype == AST_FRAME_DTMF_BEGIN || fr->frametype == AST_FRAME_DTMF_END) && (((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) ||