Merged revisions 194557,194685 via svnmerge from
[asterisk/asterisk.git] / channels / chan_iax2.c
index 4b55789..a4c0339 100644 (file)
@@ -559,6 +559,9 @@ static AST_LIST_HEAD_STATIC(registrations, iax2_registry);
 /* If consecutive voice frame timestamps jump by more than this many milliseconds, then jitter buffer will resync */
 #define TS_GAP_FOR_JB_RESYNC   5000
 
 /* If consecutive voice frame timestamps jump by more than this many milliseconds, then jitter buffer will resync */
 #define TS_GAP_FOR_JB_RESYNC   5000
 
+/* used for first_iax_message and last_iax_message.  If this bit is set it was TX, else RX */
+#define MARK_IAX_SUBCLASS_TX   0x8000
+
 static int iaxthreadcount = DEFAULT_THREAD_COUNT;
 static int iaxmaxthreadcount = DEFAULT_MAX_THREAD_COUNT;
 static int iaxdynamicthreadcount = 0;
 static int iaxthreadcount = DEFAULT_THREAD_COUNT;
 static int iaxmaxthreadcount = DEFAULT_MAX_THREAD_COUNT;
 static int iaxdynamicthreadcount = 0;
@@ -598,6 +601,10 @@ struct chan_iax2_pvt {
        unsigned int lastvsent;
        /*! Next outgoing timestamp if everything is good */
        unsigned int nextpred;
        unsigned int lastvsent;
        /*! Next outgoing timestamp if everything is good */
        unsigned int nextpred;
+       /*! iax frame subclass that began iax2_pvt entry. 0x8000 bit is set on TX */
+       int first_iax_message;
+       /*! Last iax frame subclass sent or received for a iax2_pvt. 0x8000 bit is set on TX */
+       int last_iax_message;
        /*! True if the last voice we transmitted was not silence/CNG */
        unsigned int notsilenttx:1;
        /*! Ping time */
        /*! True if the last voice we transmitted was not silence/CNG */
        unsigned int notsilenttx:1;
        /*! Ping time */
@@ -5167,6 +5174,13 @@ static int iax2_send(struct chan_iax2_pvt *pvt, struct ast_frame *f, unsigned in
                }
                pvt->lastvsent = fts;
        }
                }
                pvt->lastvsent = fts;
        }
+       if (f->frametype == AST_FRAME_IAX) {
+               /* 0x8000 marks this message as TX:, this bit will be stripped later */
+               pvt->last_iax_message = f->subclass | MARK_IAX_SUBCLASS_TX;
+               if (!pvt->first_iax_message) {
+                       pvt->first_iax_message = pvt->last_iax_message;
+               }
+       }
        /* Allocate an iax_frame */
        if (now) {
                fr = &frb.fr2;
        /* Allocate an iax_frame */
        if (now) {
                fr = &frb.fr2;
@@ -5242,7 +5256,7 @@ static int iax2_send(struct chan_iax2_pvt *pvt, struct ast_frame *f, unsigned in
                        } else
                                ast_log(LOG_WARNING, "Supposed to send packet encrypted, but no key?\n");
                }
                        } else
                                ast_log(LOG_WARNING, "Supposed to send packet encrypted, but no key?\n");
                }
-       
+
                if (now) {
                        res = send_packet(fr);
                } else
                if (now) {
                        res = send_packet(fr);
                } else
@@ -5861,11 +5875,13 @@ static int manager_iax2_show_registry(struct mansession *s, const struct message
 
 static char *handle_cli_iax2_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 
 static char *handle_cli_iax2_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-#define FORMAT2 "%-20.20s  %-15.15s  %-10.10s  %-11.11s  %-11.11s  %-7.7s  %-6.6s  %-6.6s  %s\n"
-#define FORMAT  "%-20.20s  %-15.15s  %-10.10s  %5.5d/%5.5d  %5.5d/%5.5d  %-5.5dms  %-4.4dms  %-4.4dms  %-6.6s\n"
+#define FORMAT2 "%-20.20s  %-15.15s  %-10.10s  %-11.11s  %-11.11s  %-7.7s  %-6.6s  %-6.6s  %s  %s  %9s\n"
+#define FORMAT  "%-20.20s  %-15.15s  %-10.10s  %5.5d/%5.5d  %5.5d/%5.5d  %-5.5dms  %-4.4dms  %-4.4dms  %-6.6s  %s%s  %3s%s\n"
 #define FORMATB "%-20.20s  %-15.15s  %-10.10s  %5.5d/%5.5d  %5.5d/%5.5d  [Native Bridged to ID=%5.5d]\n"
        int x;
        int numchans = 0;
 #define FORMATB "%-20.20s  %-15.15s  %-10.10s  %5.5d/%5.5d  %5.5d/%5.5d  [Native Bridged to ID=%5.5d]\n"
        int x;
        int numchans = 0;
+       char first_message[10] = { 0, };
+       char last_message[10] = { 0, };
 
        switch (cmd) {
        case CLI_INIT:
 
        switch (cmd) {
        case CLI_INIT:
@@ -5880,13 +5896,12 @@ static char *handle_cli_iax2_show_channels(struct ast_cli_entry *e, int cmd, str
 
        if (a->argc != 3)
                return CLI_SHOWUSAGE;
 
        if (a->argc != 3)
                return CLI_SHOWUSAGE;
-       ast_cli(a->fd, FORMAT2, "Channel", "Peer", "Username", "ID (Lo/Rem)", "Seq (Tx/Rx)", "Lag", "Jitter", "JitBuf", "Format");
+       ast_cli(a->fd, FORMAT2, "Channel", "Peer", "Username", "ID (Lo/Rem)", "Seq (Tx/Rx)", "Lag", "Jitter", "JitBuf", "Format", "FirstMsg", "LastMsg");
        for (x = 0; x < ARRAY_LEN(iaxs); x++) {
                ast_mutex_lock(&iaxsl[x]);
                if (iaxs[x]) {
                        int lag, jitter, localdelay;
                        jb_info jbinfo;
        for (x = 0; x < ARRAY_LEN(iaxs); x++) {
                ast_mutex_lock(&iaxsl[x]);
                if (iaxs[x]) {
                        int lag, jitter, localdelay;
                        jb_info jbinfo;
-                       
                        if (ast_test_flag(iaxs[x], IAX_USEJITTERBUF)) {
                                jb_getinfo(iaxs[x]->jb, &jbinfo);
                                jitter = jbinfo.jitter;
                        if (ast_test_flag(iaxs[x], IAX_USEJITTERBUF)) {
                                jb_getinfo(iaxs[x]->jb, &jbinfo);
                                jitter = jbinfo.jitter;
@@ -5895,17 +5910,24 @@ static char *handle_cli_iax2_show_channels(struct ast_cli_entry *e, int cmd, str
                                jitter = -1;
                                localdelay = 0;
                        }
                                jitter = -1;
                                localdelay = 0;
                        }
+
+                       iax_frame_subclass2str(iaxs[x]->first_iax_message & ~MARK_IAX_SUBCLASS_TX, first_message, sizeof(first_message));
+                       iax_frame_subclass2str(iaxs[x]->last_iax_message & ~MARK_IAX_SUBCLASS_TX, last_message, sizeof(last_message));
                        lag = iaxs[x]->remote_rr.delay;
                        ast_cli(a->fd, FORMAT,
                                iaxs[x]->owner ? iaxs[x]->owner->name : "(None)",
                        lag = iaxs[x]->remote_rr.delay;
                        ast_cli(a->fd, FORMAT,
                                iaxs[x]->owner ? iaxs[x]->owner->name : "(None)",
-                               ast_inet_ntoa(iaxs[x]->addr.sin_addr), 
+                               ast_inet_ntoa(iaxs[x]->addr.sin_addr),
                                S_OR(iaxs[x]->username, "(None)"),
                                iaxs[x]->callno, iaxs[x]->peercallno,
                                iaxs[x]->oseqno, iaxs[x]->iseqno,
                                lag,
                                jitter,
                                localdelay,
                                S_OR(iaxs[x]->username, "(None)"),
                                iaxs[x]->callno, iaxs[x]->peercallno,
                                iaxs[x]->oseqno, iaxs[x]->iseqno,
                                lag,
                                jitter,
                                localdelay,
-                               ast_getformatname(iaxs[x]->voiceformat) );
+                               ast_getformatname(iaxs[x]->voiceformat),
+                               (iaxs[x]->first_iax_message & MARK_IAX_SUBCLASS_TX) ? "Tx:" : "Rx:",
+                               first_message,
+                               (iaxs[x]->last_iax_message & MARK_IAX_SUBCLASS_TX) ? "Tx:" : "Rx:",
+                               last_message);
                        numchans++;
                }
                ast_mutex_unlock(&iaxsl[x]);
                        numchans++;
                }
                ast_mutex_unlock(&iaxsl[x]);
@@ -5921,14 +5943,18 @@ static int ast_cli_netstats(struct mansession *s, int fd, int limit_fmt)
 {
        int x;
        int numchans = 0;
 {
        int x;
        int numchans = 0;
-#define ACN_FORMAT1 "%-25.25s %4d %4d %4d %5d %3d %5d %4d %6d %4d %4d %5d %3d %5d %4d %6d\n"
-#define ACN_FORMAT2 "%s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n"
+       char first_message[10] = { 0, };
+       char last_message[10] = { 0, };
+#define ACN_FORMAT1 "%-20.25s %4d %4d %4d %5d %3d %5d %4d %6d %4d %4d %5d %3d %5d %4d %6d %s%s %4s%s\n"
+#define ACN_FORMAT2 "%s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %s%s %s%s\n"
        for (x = 0; x < ARRAY_LEN(iaxs); x++) {
                ast_mutex_lock(&iaxsl[x]);
                if (iaxs[x]) {
                        int localjitter, localdelay, locallost, locallosspct, localdropped, localooo;
                        jb_info jbinfo;
        for (x = 0; x < ARRAY_LEN(iaxs); x++) {
                ast_mutex_lock(&iaxsl[x]);
                if (iaxs[x]) {
                        int localjitter, localdelay, locallost, locallosspct, localdropped, localooo;
                        jb_info jbinfo;
-                       
+                       iax_frame_subclass2str(iaxs[x]->first_iax_message & ~MARK_IAX_SUBCLASS_TX, first_message, sizeof(first_message));
+                       iax_frame_subclass2str(iaxs[x]->last_iax_message & ~MARK_IAX_SUBCLASS_TX, last_message, sizeof(last_message));
+
                        if(ast_test_flag(iaxs[x], IAX_USEJITTERBUF)) {
                                jb_getinfo(iaxs[x]->jb, &jbinfo);
                                localjitter = jbinfo.jitter;
                        if(ast_test_flag(iaxs[x], IAX_USEJITTERBUF)) {
                                jb_getinfo(iaxs[x]->jb, &jbinfo);
                                localjitter = jbinfo.jitter;
@@ -5946,29 +5972,32 @@ static int ast_cli_netstats(struct mansession *s, int fd, int limit_fmt)
                                localooo = -1;
                        }
                        if (s)
                                localooo = -1;
                        }
                        if (s)
-                               
                                astman_append(s, limit_fmt ? ACN_FORMAT1 : ACN_FORMAT2,
                                astman_append(s, limit_fmt ? ACN_FORMAT1 : ACN_FORMAT2,
-                                             iaxs[x]->owner ? iaxs[x]->owner->name : "(None)",
-                                             iaxs[x]->pingtime,
-                                             localjitter, 
-                                             localdelay,
-                                             locallost,
-                                             locallosspct,
-                                             localdropped,
-                                             localooo,
-                                             iaxs[x]->frames_received/1000,
-                                             iaxs[x]->remote_rr.jitter,
-                                             iaxs[x]->remote_rr.delay,
-                                             iaxs[x]->remote_rr.losscnt,
-                                             iaxs[x]->remote_rr.losspct,
-                                             iaxs[x]->remote_rr.dropped,
-                                             iaxs[x]->remote_rr.ooo,
-                                             iaxs[x]->remote_rr.packets/1000);
+                                       iaxs[x]->owner ? iaxs[x]->owner->name : "(None)",
+                                       iaxs[x]->pingtime,
+                                       localjitter,
+                                       localdelay,
+                                       locallost,
+                                       locallosspct,
+                                       localdropped,
+                                       localooo,
+                                       iaxs[x]->frames_received/1000,
+                                       iaxs[x]->remote_rr.jitter,
+                                       iaxs[x]->remote_rr.delay,
+                                       iaxs[x]->remote_rr.losscnt,
+                                       iaxs[x]->remote_rr.losspct,
+                                       iaxs[x]->remote_rr.dropped,
+                                       iaxs[x]->remote_rr.ooo,
+                                       iaxs[x]->remote_rr.packets/1000,
+                                       (iaxs[x]->first_iax_message & MARK_IAX_SUBCLASS_TX) ? "Tx:" : "Rx:",
+                                       first_message,
+                                       (iaxs[x]->last_iax_message & MARK_IAX_SUBCLASS_TX) ? "Tx:" : "Rx:",
+                                       last_message);
                        else
                                ast_cli(fd, limit_fmt ? ACN_FORMAT1 : ACN_FORMAT2,
                                        iaxs[x]->owner ? iaxs[x]->owner->name : "(None)",
                                        iaxs[x]->pingtime,
                        else
                                ast_cli(fd, limit_fmt ? ACN_FORMAT1 : ACN_FORMAT2,
                                        iaxs[x]->owner ? iaxs[x]->owner->name : "(None)",
                                        iaxs[x]->pingtime,
-                                       localjitter, 
+                                       localjitter,
                                        localdelay,
                                        locallost,
                                        locallosspct,
                                        localdelay,
                                        locallost,
                                        locallosspct,
@@ -5981,8 +6010,11 @@ static int ast_cli_netstats(struct mansession *s, int fd, int limit_fmt)
                                        iaxs[x]->remote_rr.losspct,
                                        iaxs[x]->remote_rr.dropped,
                                        iaxs[x]->remote_rr.ooo,
                                        iaxs[x]->remote_rr.losspct,
                                        iaxs[x]->remote_rr.dropped,
                                        iaxs[x]->remote_rr.ooo,
-                                       iaxs[x]->remote_rr.packets/1000
-                                       );
+                                       iaxs[x]->remote_rr.packets/1000,
+                                       (iaxs[x]->first_iax_message & MARK_IAX_SUBCLASS_TX) ? "Tx:" : "Rx:",
+                                       first_message,
+                                       (iaxs[x]->last_iax_message & MARK_IAX_SUBCLASS_TX) ? "Tx:" : "Rx:",
+                                       last_message);
                        numchans++;
                }
                ast_mutex_unlock(&iaxsl[x]);
                        numchans++;
                }
                ast_mutex_unlock(&iaxsl[x]);
@@ -6007,15 +6039,13 @@ static char *handle_cli_iax2_show_netstats(struct ast_cli_entry *e, int cmd, str
        }
        if (a->argc != 3)
                return CLI_SHOWUSAGE;
        }
        if (a->argc != 3)
                return CLI_SHOWUSAGE;
-       ast_cli(a->fd, "                                -------- LOCAL ---------------------  -------- REMOTE --------------------\n");
-       ast_cli(a->fd, "Channel                    RTT  Jit  Del  Lost   %%  Drop  OOO  Kpkts  Jit  Del  Lost   %%  Drop  OOO  Kpkts\n");
+       ast_cli(a->fd, "                           -------- LOCAL ---------------------  -------- REMOTE --------------------\n");
+       ast_cli(a->fd, "Channel               RTT  Jit  Del  Lost   %%  Drop  OOO  Kpkts  Jit  Del  Lost   %%  Drop  OOO  Kpkts FirstMsg    LastMsg\n");
        numchans = ast_cli_netstats(NULL, a->fd, 1);
        ast_cli(a->fd, "%d active IAX channel%s\n", numchans, (numchans != 1) ? "s" : "");
        return CLI_SUCCESS;
 }
 
        numchans = ast_cli_netstats(NULL, a->fd, 1);
        ast_cli(a->fd, "%d active IAX channel%s\n", numchans, (numchans != 1) ? "s" : "");
        return CLI_SUCCESS;
 }
 
-
-
 static char *handle_cli_iax2_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
        switch (cmd) {
 static char *handle_cli_iax2_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
        switch (cmd) {
@@ -8877,7 +8907,10 @@ retryowner:
                                if (iaxdebug)
                                        ast_debug(1, "For call=%d, set last=%d\n", fr->callno, fr->ts);
                        }
                                if (iaxdebug)
                                        ast_debug(1, "For call=%d, set last=%d\n", fr->callno, fr->ts);
                        }
-
+                       iaxs[fr->callno]->last_iax_message = f.subclass;
+                       if (!iaxs[fr->callno]->first_iax_message) {
+                               iaxs[fr->callno]->first_iax_message = f.subclass;
+                       }
                        switch(f.subclass) {
                        case IAX_COMMAND_ACK:
                                /* Do nothing */
                        switch(f.subclass) {
                        case IAX_COMMAND_ACK:
                                /* Do nothing */