Index: channels/chan_sip.c =================================================================== --- channels/chan_sip.c (revision 262656) +++ channels/chan_sip.c (working copy) @@ -7069,7 +7069,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; @@ -7078,14 +7080,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_CNG)) { - 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 due to CNG detection\n", ast->name); pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten); @@ -7095,11 +7102,9 @@ fr = &ast_null_frame; } else { ast_log(LOG_NOTICE, "FAX CNG 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 262656) +++ include/asterisk/frame.h (working copy) @@ -190,6 +190,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 262656) +++ main/rtp.c (working copy) @@ -1220,7 +1220,7 @@ ast_log(LOG_WARNING, "RTCP Read error: %s. Hanging up.\n", strerror(errno)); return NULL; } - return &ast_null_frame; + return &ast_eagain_frame; } packetwords = res / 4; @@ -1592,16 +1592,19 @@ struct ast_rtp *bridged = NULL; int prev_seqno; struct frame_list frames; - + /* If time is up, kill it */ if (rtp->sending_digit) ast_rtp_senddigit_continuation(rtp); len = sizeof(sock_in); - + /* Cache where the header will go */ res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET, 0, (struct sockaddr *)&sock_in, &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 262656) +++ main/frame.c (working copy) @@ -122,6 +122,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) {