summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--channels/chan_iax2.c103
-rw-r--r--channels/iax2-parser.c176
-rw-r--r--channels/iax2-parser.h1
-rw-r--r--channels/iax2.h10
4 files changed, 204 insertions, 86 deletions
diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c
index 4b5578934..a4c0339fd 100644
--- a/channels/chan_iax2.c
+++ b/channels/chan_iax2.c
@@ -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 */
diff --git a/channels/iax2-parser.c b/channels/iax2-parser.c
index 55c1630e7..950fc78dd 100644
--- a/channels/iax2-parser.c
+++ b/channels/iax2-parser.c
@@ -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);
diff --git a/channels/iax2-parser.h b/channels/iax2-parser.h
index e75cd4209..9de873b35 100644
--- a/channels/iax2-parser.h
+++ b/channels/iax2-parser.h
@@ -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);
diff --git a/channels/iax2.h b/channels/iax2.h
index 2b79e91d0..394eef2e4 100644
--- a/channels/iax2.h
+++ b/channels/iax2.h
@@ -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