diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c index 2260bb1671cdb1db93499c92459e4e3c143dfa65..f6b040df3589159d834bf88afd199003a4a7dca9 100644 --- a/channels/chan_iax2.c +++ b/channels/chan_iax2.c @@ -1144,12 +1144,19 @@ static int send_ping(const void *data); static void __send_ping(const void *data) { - int callno = (long)data; + int callno = (long) data; + ast_mutex_lock(&iaxsl[callno]); - if (iaxs[callno] && iaxs[callno]->pingid != -1) { + + while (iaxs[callno] && iaxs[callno]->pingid != -1) { + if (!iaxs[callno]->peercallno) { + break; + } send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_PING, 0, NULL, 0, -1); iaxs[callno]->pingid = iax2_sched_add(sched, ping_time * 1000, send_ping, data); + break; } + ast_mutex_unlock(&iaxsl[callno]); } @@ -1178,13 +1185,19 @@ static int send_lagrq(const void *data); static void __send_lagrq(const void *data) { - int callno = (long)data; - /* Ping only if it's real not if it's bridged */ + int callno = (long) data; + ast_mutex_lock(&iaxsl[callno]); - if (iaxs[callno] && iaxs[callno]->lagid > -1) { + + while (iaxs[callno] && iaxs[callno]->lagid > -1) { + if (!iaxs[callno]->peercallno) { + break; + } send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_LAGRQ, 0, NULL, 0, -1); iaxs[callno]->lagid = iax2_sched_add(sched, lagrq_time * 1000, send_lagrq, data); + break; } + ast_mutex_unlock(&iaxsl[callno]); } @@ -7999,8 +8012,25 @@ static int socket_process(struct iax2_thread *thread) } if (!fr->callno) { - fr->callno = find_callno(ntohs(mh->callno) & ~IAX_FLAG_FULL, dcallno, &sin, new, fd, - (ntohs(mh->callno) & IAX_FLAG_FULL) && f.frametype == AST_FRAME_IAX && f.subclass == IAX_COMMAND_ACK); + int check_dcallno = 0; + + /* + * We enforce accurate destination call numbers for all full frames except + * LAGRQ and PING commands. This is because older versions of Asterisk + * schedule these commands to get sent very quickly, and they will sometimes + * be sent before they receive the first frame from the other side. When + * that happens, it doesn't contain the destination call number. However, + * not checking it for these frames is safe. + * + * Discussed in the following thread: + * http://lists.digium.com/pipermail/asterisk-dev/2008-May/033217.html + */ + + if (ntohs(mh->callno) & IAX_FLAG_FULL) { + check_dcallno = f.frametype == AST_FRAME_IAX ? (f.subclass != IAX_COMMAND_PING && f.subclass != IAX_COMMAND_LAGRQ) : 1; + } + + fr->callno = find_callno(ntohs(mh->callno) & ~IAX_FLAG_FULL, dcallno, &sin, new, fd, check_dcallno); } if (fr->callno > 0)