From a05dc6e1d7e6b1b7ef096e621f102322f5125623 Mon Sep 17 00:00:00 2001 From: Kaian Date: Thu, 20 Mar 2014 20:20:08 +0100 Subject: [PATCH] Added Message Color by CSeq and cycle through colors using 'C' key --- src/Makefile.in | 2 +- src/group.c | 1 + src/group.h | 1 + src/option.c | 5 +++- src/sip.c | 9 ++++++- src/sip.h | 6 +++++ src/ui_call_flow.c | 62 +++++++++++++++++++++++++++++++++++++++------- src/ui_call_list.c | 2 +- src/ui_call_raw.c | 30 +++++++++++++++++++--- src/ui_manager.c | 14 +++++++++-- 10 files changed, 113 insertions(+), 19 deletions(-) diff --git a/src/Makefile.in b/src/Makefile.in index aa84805..2f4ea07 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -268,7 +268,7 @@ uninstall-binPROGRAMS: clean-binPROGRAMS: -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) -sngrep$(EXEEXT): $(sngrep_OBJECTS) $(sngrep_DEPENDENCIES) $(EXTRA_sngrep_DEPENDENCIES) +sngrep$(EXEEXT): $(sngrep_OBJECTS) $(sngrep_DEPENDENCIES) $(EXTRA_sngrep_DEPENDENCIES) @rm -f sngrep$(EXEEXT) $(AM_V_CCLD)$(LINK) $(sngrep_OBJECTS) $(sngrep_LDADD) $(LIBS) diff --git a/src/group.c b/src/group.c index 5fbfef8..166e774 100644 --- a/src/group.c +++ b/src/group.c @@ -38,6 +38,7 @@ call_group_create() return NULL; } memset(group, 0, sizeof(sip_call_group_t)); + group->color = 0; return group; } diff --git a/src/group.h b/src/group.h index 0fa7f46..e1154d7 100644 --- a/src/group.h +++ b/src/group.h @@ -54,6 +54,7 @@ struct sip_call_group { sip_call_t *calls[1024]; int callcnt; + int color; }; extern sip_call_group_t * diff --git a/src/option.c b/src/option.c index 590b6f3..4f09bb9 100644 --- a/src/option.c +++ b/src/option.c @@ -50,8 +50,11 @@ init_options() // Custom user conf file char userconf[128]; - // Add basic optionurations + // Set default color options set_option_value("color", "on"); + set_option_value("color.request", "on"); + set_option_value("color.callid", "off"); + set_option_value("color.cseq", "off"); // Add Call list column options set_option_value("cl.columns", "6"); diff --git a/src/sip.c b/src/sip.c index 7688421..61eb2a8 100644 --- a/src/sip.c +++ b/src/sip.c @@ -95,6 +95,10 @@ static sip_attr_hdr_t attrs[] = { .id = SIP_ATTR_REQUEST, .name = "request", .desc = "Request" }, + { + .id = SIP_ATTR_CSEQ, + .name = "CSeq", + .desc = "CSeq" }, { .id = SIP_ATTR_SDP, .name = "sdp", @@ -119,6 +123,7 @@ sip_msg_create(const char *header, const char *payload) msg->headerptr = strdup(header); msg->payloadptr = strdup(payload); msg->parsed = 0; + msg->color = -1; return msg; } @@ -129,6 +134,7 @@ sip_call_create(char *callid) sip_call_t *call = malloc(sizeof(sip_call_t)); memset(call, 0, sizeof(sip_call_t)); call->attrs = NULL; + call->color = -1; // Initialize call lock pthread_mutexattr_t attr; @@ -627,12 +633,13 @@ msg_parse_payload(sip_msg_t *msg, const char *payload) } continue; } - if (sscanf(pch, "CSeq: %d %[^\t\n\r]", &irest, value)) { + if (sscanf(pch, "CSeq: %s %[^\t\n\r]", rest, value)) { if (!msg_get_attribute(msg, SIP_ATTR_METHOD)) { // ACK Messages are not considered requests if (strcasecmp(value, "ACK")) msg_set_attribute(msg, SIP_ATTR_REQUEST, "1"); msg_set_attribute(msg, SIP_ATTR_METHOD, value); } + msg_set_attribute(msg, SIP_ATTR_CSEQ, rest); continue; } if (sscanf(pch, "From: %[^:]:%[^\t\n\r>;]", rest, value)) { diff --git a/src/sip.h b/src/sip.h index 1d6425d..9e09f00 100644 --- a/src/sip.h +++ b/src/sip.h @@ -75,6 +75,8 @@ enum sip_attr_id SIP_ATTR_METHOD, //! SIP Message is a request SIP_ATTR_REQUEST, + //! SIP CSeq number + SIP_ATTR_CSEQ, //! SIP Message has sdp SIP_ATTR_SDP, //! SIP Call first message method @@ -148,6 +150,8 @@ struct sip_msg sip_call_t *call; //! Messages linked list sip_msg_t *next; + //! Color for this message (in color.cseq mode) + int color; }; /** @@ -167,6 +171,8 @@ struct sip_call pthread_mutex_t lock; //! Calls double linked list sip_call_t *next, *prev; + //! Last used color (for color.cseq) + int color; }; /** diff --git a/src/ui_call_flow.c b/src/ui_call_flow.c index a962d26..48b651a 100644 --- a/src/ui_call_flow.c +++ b/src/ui_call_flow.c @@ -149,6 +149,7 @@ call_flow_draw(PANEL *panel) sip_msg_t *msg; WINDOW *win; int height, width, cline; + char title[256]; // Get panel information info = call_flow_info(panel); @@ -160,6 +161,24 @@ call_flow_draw(PANEL *panel) wattron(win, COLOR_PAIR(DETAIL_BORDER_COLOR)); title_foot_box(win); wattroff(win, COLOR_PAIR(DETAIL_BORDER_COLOR)); + + // Set title + if (info->group->callcnt == 1) { + sprintf(title, "Call flow for %s", call_get_attribute(*info->group->calls, SIP_ATTR_CALLID)); + } else { + sprintf(title, "Call flow for %d dialogs", info->group->callcnt); + } + + // Print color mode in title + if (is_option_enabled("color")) { + if (is_option_enabled("color.request")) sprintf(title, "%s (%s)", title, "Color by Request/Response"); + if (is_option_enabled("color.callid")) sprintf(title, "%s (%s)", title, "Color by Call-Id"); + if (is_option_enabled("color.cseq")) sprintf(title, "%s (%s)", title, "Color by CSeq"); + } + + mvwprintw(win, 1, (width - strlen(title))/2, "%s", title); + + // Show some keybinding mvwprintw(win, height - 2, 2, "Q/Esc: Quit"); mvwprintw(win, height - 2, 16, "F1: Help"); mvwprintw(win, height - 2, 27, "x: Call-Flow"); @@ -183,7 +202,6 @@ call_flow_draw(PANEL *panel) } // If there are only three columns, then draw the raw message on this panel - //if ((20 + info->columns->colpos * 30 + get_option_int_value("cf.rawminwidth") < width) if (is_option_enabled("cf.forceraw")) { call_flow_draw_raw(panel, info->cur_msg); } @@ -230,6 +248,7 @@ call_flow_draw_message(PANEL *panel, sip_msg_t *msg, int cline) { call_flow_info_t *info; WINDOW *win; + sip_msg_t *prev; const char *msg_time; const char *msg_callid; const char *msg_method; @@ -283,11 +302,11 @@ call_flow_draw_message(PANEL *panel, sip_msg_t *msg, int cline) int endpos = 20 + 30 * column2->colpos; int distance = abs(endpos - startpos) - 3; + // Highlight current message if (msg == info->cur_msg) wattron(win, A_BOLD); - if (is_option_enabled("color.callid")) { - wattron(win, COLOR_PAIR(call_group_color(info->group, msg->call))); - } else { + // Color the message + if (is_option_enabled("color.request")) { // Determine arrow color if (msg_get_attribute(msg, SIP_ATTR_REQUEST)) { wattron(win, COLOR_PAIR(OUTGOING_COLOR)); @@ -295,6 +314,27 @@ call_flow_draw_message(PANEL *panel, sip_msg_t *msg, int cline) wattron(win, COLOR_PAIR(INCOMING_COLOR)); } } + // Color by call-id + if (is_option_enabled("color.callid")) { + wattron(win, COLOR_PAIR(call_group_color(info->group, msg->call))); + } + // Color by CSeq within the same call + if (is_option_enabled("color.cseq")) { + if (msg->call->color == -1) { + msg->call->color = (info->group->color++ % 7) + 1; + } + if (msg->color == -1) { + if ((prev = call_get_prev_msg(msg->call, msg))) { + if (strcmp(msg_get_attribute(msg, SIP_ATTR_CSEQ), + msg_get_attribute(prev, SIP_ATTR_CSEQ))) { + info->group->color = msg->call->color = (info->group->color++ % 7) + 1; + } + } + msg->color = msg->call->color; + } + // Turn on the message color + wattron(win, COLOR_PAIR(msg->color)); + } mvwprintw(win, cline, startpos + 2, "%.*s", distance, ""); mvwprintw(win, cline, startpos + distance / 2 - msglen / 2 + 2, "%.26s", method); @@ -302,12 +342,16 @@ call_flow_draw_message(PANEL *panel, sip_msg_t *msg, int cline) // Write the arrow at the end of the message (two arros if this is a retrans) if (!strcasecmp(msg_src, column1->addr)) { mvwaddch(win, cline + 1, endpos - 2, ACS_RARROW); - if (msg_is_retrans(msg)) + if (msg_is_retrans(msg)) { mvwaddch(win, cline + 1, endpos - 3, ACS_RARROW); + mvwaddch(win, cline + 1, endpos - 4, ACS_RARROW); + } } else { mvwaddch(win, cline + 1, startpos + 2, ACS_LARROW); - if (msg_is_retrans(msg)) - mvwaddch(win, cline + 1, startpos + 2, ACS_LARROW); + if (msg_is_retrans(msg)) { + mvwaddch(win, cline + 1, startpos + 3, ACS_LARROW); + mvwaddch(win, cline + 1, startpos + 4, ACS_LARROW); + } } // Turn off colors @@ -550,9 +594,9 @@ call_flow_help(PANEL *panel) mvwprintw(help_win, 9, 2, "F1 Show this screen."); mvwprintw(help_win, 10, 2, "q/Esc Go back to Call list window."); mvwprintw(help_win, 11, 2, "c Turn on/off window colours."); - mvwprintw(help_win, 12, 2, "C Turn on/off colour by Call-ID."); + mvwprintw(help_win, 12, 2, "C Cycle between available color modes"); mvwprintw(help_win, 13, 2, "Up/Down Move to previous/next message."); - mvwprintw(help_win, 14, 2, "x Show call-flow (Normal) for original call."); + mvwprintw(help_win, 14, 2, "x Show call-flow with X-CID/X-Call-ID dialog"); mvwprintw(help_win, 15, 2, "r Show original call messages in raw mode."); mvwprintw(help_win, 16, 2, "t Toggle raw preview display"); mvwprintw(help_win, 17, 2, "9/0 Increase/Decrease raw preview size"); diff --git a/src/ui_call_list.c b/src/ui_call_list.c index de8ccc7..21e02a6 100644 --- a/src/ui_call_list.c +++ b/src/ui_call_list.c @@ -154,7 +154,7 @@ call_list_draw(PANEL *panel) getmaxyx(win, height, width); // Print in the header if we're actually capturing - mvwprintw(win, 3, 23, "%s", is_option_enabled("sip.capture")?" ":"(Paused)"); + mvwprintw(win, 3, 23, "%s", is_option_enabled("sip.capture")?" ":" (Paused)"); // Get available calls counter (we'll use it here a couple of times) if (!(callcnt = sip_calls_count())) return 0; diff --git a/src/ui_call_raw.c b/src/ui_call_raw.c index e874450..4e030b9 100644 --- a/src/ui_call_raw.c +++ b/src/ui_call_raw.c @@ -90,6 +90,9 @@ call_raw_draw(PANEL *panel) int call_raw_print_msg(PANEL *panel, sip_msg_t *msg) { + // Previous message pointer + sip_msg_t *prev; + // Variables for drawing each message character int raw_line, raw_char, column; @@ -111,10 +114,8 @@ call_raw_print_msg(PANEL *panel, sip_msg_t *msg) info->pad = pad; } - // Determine arrow color - if (info->group && is_option_enabled("color.callid")) { - wattron(pad, COLOR_PAIR(call_group_color(info->group, msg->call))); - } else { + // Color the message + if (is_option_enabled("color.request")) { // Determine arrow color if (msg_get_attribute(msg, SIP_ATTR_REQUEST)) { wattron(pad, COLOR_PAIR(OUTGOING_COLOR)); @@ -122,6 +123,27 @@ call_raw_print_msg(PANEL *panel, sip_msg_t *msg) wattron(pad, COLOR_PAIR(INCOMING_COLOR)); } } + // Color by call-id + if (info->group && is_option_enabled("color.callid")) { + wattron(pad, COLOR_PAIR(call_group_color(info->group, msg->call))); + } + // Color by CSeq within the same call + if (info->group && is_option_enabled("color.cseq")) { + if (msg->call->color == -1) { + msg->call->color = (info->group->color++ % 7) + 1; + } + if (msg->color == -1) { + if ((prev = call_get_prev_msg(msg->call, msg))) { + if (strcmp(msg_get_attribute(msg, SIP_ATTR_CSEQ), + msg_get_attribute(prev, SIP_ATTR_CSEQ))) { + info->group->color = msg->call->color = (info->group->color++ % 7) + 1; + } + } + msg->color = msg->call->color; + } + // Turn on the message color + wattron(pad, COLOR_PAIR(msg->color)); + } // Print msg header wattron(pad, A_BOLD); diff --git a/src/ui_manager.c b/src/ui_manager.c index 513d92c..61d4336 100644 --- a/src/ui_manager.c +++ b/src/ui_manager.c @@ -280,11 +280,20 @@ wait_for_input(ui_t *ui) switch (c) { case 'c': // @todo general application config structure - set_option_value("color", is_option_enabled("color") ? "off" : "on"); + toggle_option("color"); toggle_color(is_option_enabled("color")); break; case 'C': - set_option_value("color.callid", is_option_enabled("color.callid") ? "off" : "on"); + if (is_option_enabled("color.request")) { + toggle_option("color.request"); + toggle_option("color.callid"); + } else if (is_option_enabled("color.callid")) { + toggle_option("color.callid"); + toggle_option("color.cseq"); + } else if (is_option_enabled("color.cseq")) { + toggle_option("color.cseq"); + toggle_option("color.request"); + } break; case 'p': // Toggle capture option @@ -295,6 +304,7 @@ wait_for_input(ui_t *ui) ui_help(ui); break; case 'q': + case 'Q': case 27: /* KEY_ESC */ ui_destroy(ui); return 0;