diff options
-rw-r--r-- | channels/chan_iax2.c | 77 | ||||
-rw-r--r-- | channels/iax2-parser.c | 53 | ||||
-rw-r--r-- | channels/iax2-parser.h | 1 |
3 files changed, 110 insertions, 21 deletions
diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c index 3f2dd4cb1..7ded98d5f 100644 --- a/channels/chan_iax2.c +++ b/channels/chan_iax2.c @@ -482,6 +482,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 */ int notsilenttx; /*! Ping time */ @@ -4566,6 +4570,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 | 0x8000; + if (!pvt->first_iax_message) { + pvt->first_iax_message = pvt->last_iax_message; + } + } /* Allocate an iax_frame */ if (now) { fr = &frb.fr2; @@ -4643,7 +4654,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 @@ -5033,21 +5044,22 @@ static int iax2_show_registry(int fd, int argc, char *argv[]) static int iax2_show_channels(int fd, int argc, char *argv[]) { -#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, }; if (argc != 3) return RESULT_SHOWUSAGE; - ast_cli(fd, FORMAT2, "Channel", "Peer", "Username", "ID (Lo/Rem)", "Seq (Tx/Rx)", "Lag", "Jitter", "JitBuf", "Format"); + ast_cli(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; @@ -5056,17 +5068,24 @@ static int iax2_show_channels(int fd, int argc, char *argv[]) jitter = -1; localdelay = 0; } + + iax_frame_subclass2str(iaxs[x]->first_iax_message & ~0x8000, first_message, sizeof(first_message)); + iax_frame_subclass2str(iaxs[x]->last_iax_message & ~0x8000, last_message, sizeof(last_message)); lag = iaxs[x]->remote_rr.delay; ast_cli(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 & 0x8000) ? "Tx:" : "Rx:", + first_message, + (iaxs[x]->last_iax_message & 0x8000) ? "Tx:" : "Rx:", + last_message); numchans++; } ast_mutex_unlock(&iaxsl[x]); @@ -5082,13 +5101,15 @@ static int ast_cli_netstats(struct mansession *s, int fd, int limit_fmt) { int x; int numchans = 0; + char first_message[10] = { 0, }; + char last_message[10] = { 0, }; for (x = 0; x < ARRAY_LEN(iaxs); x++) { ast_mutex_lock(&iaxsl[x]); if (iaxs[x]) { int localjitter, localdelay, locallost, locallosspct, localdropped, localooo; char *fmt; jb_info jbinfo; - + if(ast_test_flag(iaxs[x], IAX_USEJITTERBUF)) { jb_getinfo(iaxs[x]->jb, &jbinfo); localjitter = jbinfo.jitter; @@ -5105,16 +5126,18 @@ static int ast_cli_netstats(struct mansession *s, int fd, int limit_fmt) localdropped = 0; localooo = -1; } + iax_frame_subclass2str(iaxs[x]->first_iax_message & ~0x8000, first_message, sizeof(first_message)); + iax_frame_subclass2str(iaxs[x]->last_iax_message & ~0x8000, last_message, sizeof(last_message)); if (limit_fmt) - fmt = "%-25.25s %4d %4d %4d %5d %3d %5d %4d %6d %4d %4d %5d %3d %5d %4d %6d\n"; + fmt = "%-20.25s %4d %4d %4d %5d %3d %5d %4d %6d %4d %4d %5d %3d %5d %4d %6d %s%s %4s%s\n"; else - fmt = "%s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n"; + fmt = "%s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %s%s %s%s\n"; if (s) - + astman_append(s, fmt, iaxs[x]->owner ? iaxs[x]->owner->name : "(None)", iaxs[x]->pingtime, - localjitter, + localjitter, localdelay, locallost, locallosspct, @@ -5127,12 +5150,16 @@ 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 & 0x8000) ? "Tx:" : "Rx:", + first_message, + (iaxs[x]->last_iax_message & 0x8000) ? "Tx:" : "Rx:", + last_message); else ast_cli(fd, fmt, iaxs[x]->owner ? iaxs[x]->owner->name : "(None)", iaxs[x]->pingtime, - localjitter, + localjitter, localdelay, locallost, locallosspct, @@ -5145,8 +5172,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 & 0x8000) ? "Tx:" : "Rx:", + first_message, + (iaxs[x]->last_iax_message & 0x8000) ? "Tx:" : "Rx:", + last_message); numchans++; } ast_mutex_unlock(&iaxsl[x]); @@ -5159,8 +5189,8 @@ static int iax2_show_netstats(int fd, int argc, char *argv[]) int numchans = 0; if (argc != 3) return RESULT_SHOWUSAGE; - ast_cli(fd, " -------- LOCAL --------------------- -------- REMOTE --------------------\n"); - ast_cli(fd, "Channel RTT Jit Del Lost %% Drop OOO Kpkts Jit Del Lost %% Drop OOO Kpkts\n"); + ast_cli(fd, " -------- LOCAL --------------------- -------- REMOTE --------------------\n"); + ast_cli(fd, "Channel RTT Jit Del Lost %% Drop OOO Kpkts Jit Del Lost %% Drop OOO Kpkts FirstMsg LastMsg\n"); numchans = ast_cli_netstats(NULL, fd, 1); ast_cli(fd, "%d active IAX channel%s\n", numchans, (numchans != 1) ? "s" : ""); return RESULT_SUCCESS; @@ -7718,8 +7748,9 @@ retryowner: if (f.frametype == AST_FRAME_IAX) { AST_SCHED_DEL(sched, iaxs[fr->callno]->initid); /* Handle the IAX pseudo frame itself */ - if (option_debug && iaxdebug) + if (option_debug && iaxdebug) { ast_log(LOG_DEBUG, "IAX subclass %d received\n", f.subclass); + } /* Update last ts unless the frame's timestamp originated with us. */ if (iaxs[fr->callno]->last < fr->ts && @@ -7727,10 +7758,14 @@ retryowner: f.subclass != IAX_COMMAND_PONG && f.subclass != IAX_COMMAND_LAGRP) { iaxs[fr->callno]->last = fr->ts; - if (option_debug && iaxdebug) + if (option_debug && iaxdebug) { ast_log(LOG_DEBUG, "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 */ diff --git a/channels/iax2-parser.c b/channels/iax2-parser.c index 67bffa897..4cf2c1812 100644 --- a/channels/iax2-parser.c +++ b/channels/iax2-parser.c @@ -400,6 +400,59 @@ static void dump_ies(unsigned char *iedata, int len) outputf("\n"); } +void iax_frame_subclass2str(int subclass, char *str, size_t len) +{ + int copylen = 8; + 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" + }; + if ((copylen > len) || !subclass) { + str[0] = '\0'; + } else if (subclass < ARRAY_LEN(iaxs)) { + memcpy(str, iaxs[subclass], len); + } else { + memcpy(str, "Unknown", len); + } +} + void iax_showframe(struct iax_frame *f, struct ast_iax2_full_hdr *fhi, int rx, struct sockaddr_in *sin, int datalen) { const char *frames[] = { diff --git a/channels/iax2-parser.h b/channels/iax2-parser.h index 91da2e427..e6c5ece99 100644 --- a/channels/iax2-parser.h +++ b/channels/iax2-parser.h @@ -147,6 +147,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(int subclass, char *str, size_t len); const char *iax_ie2str(int ie); |