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]);
}
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]);
}
}
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)