Index: channels/chan_sip.c =================================================================== --- channels/chan_sip.c (revision 258776) +++ 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,19 @@ sip_pvt_lock(p); fr = sip_rtp_read(ast, p, &faxdetected); + + if (fr == &ast_eagain_frame) { + /* Don't update the timeout counter, because we haven't actually received a 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 +6180,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: include/asterisk/frame.h =================================================================== --- include/asterisk/frame.h (revision 258776) +++ include/asterisk/frame.h (working copy) @@ -182,6 +182,7 @@ /*! Queueing a null frame is fairly common, so we declare a global null frame object for this purpose instead of having to declare one on the stack */ extern struct ast_frame ast_null_frame; +extern struct ast_frame ast_eagain_frame; /*! \brief Offset into a frame's data buffer. * Index: main/rtp.c =================================================================== --- main/rtp.c (revision 258776) +++ 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_eagain_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) { Index: main/frame.c =================================================================== --- main/frame.c (revision 258776) +++ main/frame.c (working copy) @@ -120,6 +120,7 @@ }; struct ast_frame ast_null_frame = { AST_FRAME_NULL, }; +struct ast_frame ast_eagain_frame = { AST_FRAME_NULL, EAGAIN, }; static int smoother_frame_feed(struct ast_smoother *s, struct ast_frame *f, int swap) {