Merged revisions 194557,194685 via svnmerge from
authorDavid Vossel <dvossel@digium.com>
Fri, 15 May 2009 20:52:12 +0000 (20:52 +0000)
committerDavid Vossel <dvossel@digium.com>
Fri, 15 May 2009 20:52:12 +0000 (20:52 +0000)
https://origsvn.digium.com/svn/asterisk/branches/1.4

........
  r194557 | dvossel | 2009-05-14 17:59:43 -0500 (Thu, 14 May 2009) | 10 lines

  IAX2 "Ghost" Channels

  There is a bug tracker issue where people are reporting "Ghost" channels in their 'iax2 show channels' output.  The confusion is caused by channels being listed as "(NONE)" with format "unknown".  These are not channels of coarse.  They are usually just pending registration or poke requests, but it is confusing output.  To help make sense of this I have added two columns to 'iax2 show channels'.  One shows the first message which started the transaction, and the second shows the last message sent by either side of the call.  This helps diagnose why the entry exists and why it may not go away.

  (closes issue #14207)
  Reported by: clive18

  Review: https://reviewboard.asterisk.org/r/246/
........
  r194685 | dvossel | 2009-05-15 10:40:37 -0500 (Fri, 15 May 2009) | 6 lines

  Update to previous IAX2 "Ghost" Channels patch.

  Fixed some comments made on reviewboard for the previous patch.

  (issue #14207)
........

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@194833 65c4cc65-6c06-0410-ace0-fbb531ad65f3

channels/chan_iax2.c
channels/iax2-parser.c
channels/iax2-parser.h
channels/iax2.h

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
 
+/* 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;
@@ -598,6 +601,10 @@ struct chan_iax2_pvt {
        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 */
@@ -5167,6 +5174,13 @@ static int iax2_send(struct chan_iax2_pvt *pvt, struct ast_frame *f, unsigned in
                }
                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;
@@ -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");
                }
-       
+
                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)
 {
-#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;
+       char first_message[10] = { 0, };
+       char last_message[10] = { 0, };
 
        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;
-       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;
-                       
                        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;
                        }
+
+                       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)",
-                               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,
-                               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]);
@@ -5921,14 +5943,18 @@ static int ast_cli_netstats(struct mansession *s, int fd, int limit_fmt)
 {
        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;
-                       
+                       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;
@@ -5946,29 +5972,32 @@ static int ast_cli_netstats(struct mansession *s, int fd, int limit_fmt)
                                localooo = -1;
                        }
                        if (s)
-                               
                                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,
-                                       localjitter, 
+                                       localjitter,
                                        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.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]);
@@ -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;
-       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;
 }
 
-
-
 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);
                        }
-
+                       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 */
index 55c1630..950fc78 100644 (file)
@@ -408,6 +408,135 @@ static void dump_ies(unsigned char *iedata, int len)
        outputf("\n");
 }
 
+void iax_frame_subclass2str(enum iax_frame_subclass subclass, char *str, size_t len)
+{
+       const char *cmd = "Unknown";
+
+       /* if an error occurs here during compile, that means a new iax frame subclass
+        * has been added to the iax_frame_subclass enum.  Add the new subclass to the
+        * switch case and make sure to update it with a new string representation. */
+       switch (subclass) {
+       case IAX_COMMAND_NEW:
+               cmd = "NEW    ";
+               break;
+       case IAX_COMMAND_PING:
+               cmd = "PING   ";
+               break;
+       case IAX_COMMAND_PONG:
+               cmd = "PONG   ";
+               break;
+       case IAX_COMMAND_ACK:
+               cmd = "ACK    ";
+               break;
+       case IAX_COMMAND_HANGUP:
+               cmd = "HANGUP ";
+               break;
+       case IAX_COMMAND_REJECT:
+               cmd = "REJECT ";
+               break;
+       case IAX_COMMAND_ACCEPT:
+               cmd = "ACCEPT ";
+               break;
+       case IAX_COMMAND_AUTHREQ:
+               cmd = "AUTHREQ";
+               break;
+       case IAX_COMMAND_AUTHREP:
+               cmd = "AUTHREP";
+               break;
+       case IAX_COMMAND_INVAL:
+               cmd = "INVAL  ";
+               break;
+       case IAX_COMMAND_LAGRQ:
+               cmd = "LAGRQ  ";
+               break;
+       case IAX_COMMAND_LAGRP:
+               cmd = "LAGRP  ";
+               break;
+       case IAX_COMMAND_REGREQ:
+               cmd = "REGREQ ";
+               break;
+       case IAX_COMMAND_REGAUTH:
+               cmd = "REGAUTH";
+               break;
+       case IAX_COMMAND_REGACK:
+               cmd = "REGACK ";
+               break;
+       case IAX_COMMAND_REGREJ:
+               cmd = "REGREJ ";
+               break;
+       case IAX_COMMAND_REGREL:
+               cmd = "REGREL ";
+               break;
+       case IAX_COMMAND_VNAK:
+               cmd = "VNAK   ";
+               break;
+       case IAX_COMMAND_DPREQ:
+               cmd = "DPREQ  ";
+               break;
+       case IAX_COMMAND_DPREP:
+               cmd = "DPREP  ";
+               break;
+       case IAX_COMMAND_DIAL:
+               cmd = "DIAL   ";
+               break;
+       case IAX_COMMAND_TXREQ:
+               cmd = "TXREQ  ";
+               break;
+       case IAX_COMMAND_TXCNT:
+               cmd = "TXCNT  ";
+               break;
+       case IAX_COMMAND_TXACC:
+               cmd = "TXACC  ";
+               break;
+       case IAX_COMMAND_TXREADY:
+               cmd = "TXREADY";
+               break;
+       case IAX_COMMAND_TXREL:
+               cmd = "TXREL  ";
+               break;
+       case IAX_COMMAND_TXREJ:
+               cmd = "TXREJ  ";
+               break;
+       case IAX_COMMAND_QUELCH:
+               cmd = "QUELCH ";
+               break;
+       case IAX_COMMAND_UNQUELCH:
+               cmd = "UNQULCH";
+               break;
+       case IAX_COMMAND_POKE:
+               cmd = "POKE   ";
+               break;
+       case IAX_COMMAND_PAGE:
+               cmd = "PAGE   ";
+               break;
+       case IAX_COMMAND_MWI:
+               cmd = "MWI    ";
+               break;
+       case IAX_COMMAND_UNSUPPORT:
+               cmd = "UNSPRTD";
+               break;
+       case IAX_COMMAND_TRANSFER:
+               cmd = "TRANSFR";
+               break;
+       case IAX_COMMAND_PROVISION:
+               cmd = "PROVISN";
+               break;
+       case IAX_COMMAND_FWDOWNL:
+               cmd = "FWDWNLD";
+               break;
+       case IAX_COMMAND_FWDATA:
+               cmd = "FWDATA ";
+               break;
+       case IAX_COMMAND_TXMEDIA:
+               cmd = "TXMEDIA";
+               break;
+       case IAX_COMMAND_RTKEY:
+               cmd = "RTKEY  ";
+               break;
+       }
+       ast_copy_string(str, cmd, len);
+}
+
 void iax_showframe(struct iax_frame *f, struct ast_iax2_full_hdr *fhi, int rx, struct sockaddr_in *sin, int datalen)
 {
        const char *framelist[] = {
@@ -425,47 +554,6 @@ void iax_showframe(struct iax_frame *f, struct ast_iax2_full_hdr *fhi, int rx, s
                "MODEM  ",
                "DTMF_B ",
        };
-       const char *iaxs[] = {
-               "(0?)",
-               "NEW    ",
-               "PING   ",
-               "PONG   ",
-               "ACK    ",
-               "HANGUP ",
-               "REJECT ",
-               "ACCEPT ",
-               "AUTHREQ",
-               "AUTHREP",
-               "INVAL  ",
-               "LAGRQ  ",
-               "LAGRP  ",
-               "REGREQ ",
-               "REGAUTH",
-               "REGACK ",
-               "REGREJ ",
-               "REGREL ",
-               "VNAK   ",
-               "DPREQ  ",
-               "DPREP  ",
-               "DIAL   ",
-               "TXREQ  ",
-               "TXCNT  ",
-               "TXACC  ",
-               "TXREADY",
-               "TXREL  ",
-               "TXREJ  ",
-               "QUELCH ",
-               "UNQULCH",
-               "POKE   ",
-               "PAGE   ",
-               "MWI    ",
-               "UNSPRTD",
-               "TRANSFR",
-               "PROVISN",
-               "FWDWNLD",
-               "FWDATA ",
-               "TXMEDIA"
-       };
        const char *cmds[] = {
                "(0?)",
                "HANGUP ",
@@ -533,12 +621,8 @@ void iax_showframe(struct iax_frame *f, struct ast_iax2_full_hdr *fhi, int rx, s
                sprintf(subclass2, "%c", fh->csub);
                subclass = subclass2;
        } else if (fh->type == AST_FRAME_IAX) {
-               if (fh->csub >= ARRAY_LEN(iaxs)) {
-                       snprintf(subclass2, sizeof(subclass2), "(%d?)", fh->csub);
+                       iax_frame_subclass2str((int)fh->csub, subclass2, sizeof(subclass2));
                        subclass = subclass2;
-               } else {
-                       subclass = iaxs[(int)fh->csub];
-               }
        } else if (fh->type == AST_FRAME_CONTROL) {
                if (fh->csub >= ARRAY_LEN(cmds)) {
                        snprintf(subclass2, sizeof(subclass2), "(%d?)", fh->csub);
index e75cd42..9de873b 100644 (file)
@@ -150,6 +150,7 @@ void iax_set_output(void (*output)(const char *data));
 /* Choose a different function for errors */
 void iax_set_error(void (*output)(const char *data));
 void iax_showframe(struct iax_frame *f, struct ast_iax2_full_hdr *fhi, int rx, struct sockaddr_in *sin, int datalen);
+void iax_frame_subclass2str(enum iax_frame_subclass subclass, char *str, size_t len);
 
 const char *iax_ie2str(int ie);
 
index 2b79e91..394eef2 100644 (file)
@@ -44,7 +44,7 @@
 #define IAX_WINDOW                     64
 
 /*! Subclass for AST_FRAME_IAX */
-enum {
+enum iax_frame_subclass {
        IAX_COMMAND_NEW =       1,
        IAX_COMMAND_PING =      2,
        IAX_COMMAND_PONG =      3,
@@ -104,20 +104,20 @@ enum {
        /*! Provision device */
        IAX_COMMAND_PROVISION = 35,
        /*! Download firmware */
-       IAX_COMMAND_FWDOWNL =   36,     
+       IAX_COMMAND_FWDOWNL =   36,
        /*! Firmware Data */
        IAX_COMMAND_FWDATA =    37,
        /*! Transfer media only */
        IAX_COMMAND_TXMEDIA =   38,
        /*! Command to rotate key */
-       IAX_COMMAND_RTKEY =     39,
+       IAX_COMMAND_RTKEY =     39,
 };
 
 /*! By default require re-registration once per minute */
-#define IAX_DEFAULT_REG_EXPIRE  60     
+#define IAX_DEFAULT_REG_EXPIRE  60
 
 /*! How long to wait before closing bridged call */
-#define IAX_LINGER_TIMEOUT             10 
+#define IAX_LINGER_TIMEOUT             10
 
 #define IAX_DEFAULT_PORTNO             4569