aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrussell <russell@f38db490-d61c-443f-a65b-d21fe96a405b>2008-05-30 12:49:39 +0000
committerrussell <russell@f38db490-d61c-443f-a65b-d21fe96a405b>2008-05-30 12:49:39 +0000
commit5213a16f36b848fcf895701cabcffff5f9da9689 (patch)
treefe4595258c5cdb3ac1847c8d0a500d7e9eb7764d
parentbe91a75a1824bdbf5cfcb9b55740a58825cb642d (diff)
- Instead of only enforcing destination call number checking on an ACK, check
all full frames except for PING and LAGRQ, which may be sent by older versions too quickly to contain the destination call number. (As suggested by Tim Panton on the asterisk-dev list) - Merge changes from team/russell/iax2-frame-race, which prevents PING and LAGRQ from being sent before the destination call number is known. git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.2@119237 f38db490-d61c-443f-a65b-d21fe96a405b
-rw-r--r--channels/chan_iax2.c64
1 files changed, 53 insertions, 11 deletions
diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c
index 1e085a89b..09a51a51c 100644
--- a/channels/chan_iax2.c
+++ b/channels/chan_iax2.c
@@ -806,15 +806,27 @@ static const struct ast_channel_tech iax2_tech = {
static int send_ping(void *data)
{
int callno = (long)data;
+ int res = 0;
+
/* Ping only if it's real, not if it's bridged */
- if (iaxs[callno]) {
+
+ ast_mutex_lock(&iaxsl[callno]);
+
+ while (iaxs[callno]) {
+ res = 1;
+ if (!iaxs[callno]->peercallno) {
+ break;
+ }
#ifdef BRIDGE_OPTIMIZATION
if (!iaxs[callno]->bridgecallno)
#endif
send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_PING, 0, NULL, 0, -1);
- return 1;
- } else
- return 0;
+ break;
+ }
+
+ ast_mutex_unlock(&iaxsl[callno]);
+
+ return res;
}
static int get_encrypt_methods(const char *s)
@@ -832,15 +844,27 @@ static int get_encrypt_methods(const char *s)
static int send_lagrq(void *data)
{
int callno = (long)data;
+ int res = 0;
+
/* Ping only if it's real not if it's bridged */
- if (iaxs[callno]) {
+
+ ast_mutex_lock(&iaxsl[callno]);
+
+ while (iaxs[callno]) {
+ res = 1;
+ if (!iaxs[callno]->peercallno) {
+ break;
+ }
#ifdef BRIDGE_OPTIMIZATION
if (!iaxs[callno]->bridgecallno)
#endif
send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_LAGRQ, 0, NULL, 0, -1);
- return 1;
- } else
- return 0;
+ break;
+ }
+
+ ast_mutex_unlock(&iaxsl[callno]);
+
+ return res;
}
static unsigned char compress_subclass(int subclass)
@@ -6814,9 +6838,27 @@ static int socket_read(int *id, int fd, short events, void *cbdata)
f.subclass = 0;
}
- if (!fr->callno)
- fr->callno = find_callno(ntohs(mh->callno) & ~IAX_FLAG_FULL, dcallno, &sin, new, 1, fd,
- (ntohs(mh->callno) & IAX_FLAG_FULL) && f.frametype == AST_FRAME_IAX && f.subclass == IAX_COMMAND_ACK);
+ if (!fr->callno) {
+ 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, 1, fd, check_dcallno);
+ }
if (fr->callno > 0)
ast_mutex_lock(&iaxsl[fr->callno]);