aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGerald Combs <gerald@zing.org>2015-10-24 17:45:51 -0700
committerGerald Combs <gerald@wireshark.org>2015-10-27 15:21:12 +0000
commit08e44b8b43ad4234a93b8feaa8e8174373188080 (patch)
treef777056da4035b7b3c4ab78a2ab5eba64e467984
parent616dbd78d6afc4f8825ce159de23b19752859605 (diff)
Convert SIP statistics to the stat tap API.
It looks like this one fell through the cracks because it dynamically registered itself via register_tap_listener_gtksipstat and wasn't listed in the "/Telephony/" path in main_menubar.c. Ping-Bug: 11638 Change-Id: I4c82b36d204207c81e82a19efce98b6a091351ca Reviewed-on: https://code.wireshark.org/review/11293 Petri-Dish: Gerald Combs <gerald@wireshark.org> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Gerald Combs <gerald@wireshark.org>
-rw-r--r--epan/dissectors/packet-sip.c318
-rw-r--r--epan/dissectors/packet-sip.h22
-rw-r--r--ui/gtk/CMakeLists.txt1
-rw-r--r--ui/gtk/Makefile.common1
-rw-r--r--ui/gtk/sip_stat.c705
-rw-r--r--ui/qt/main_window.cpp1
-rw-r--r--ui/qt/main_window.ui1
7 files changed, 328 insertions, 721 deletions
diff --git a/epan/dissectors/packet-sip.c b/epan/dissectors/packet-sip.c
index da2e335ba0..6fc80da83b 100644
--- a/epan/dissectors/packet-sip.c
+++ b/epan/dissectors/packet-sip.c
@@ -34,12 +34,14 @@
#include "config.h"
#include <epan/packet.h>
+
#include <epan/exceptions.h>
+#include <epan/exported_pdu.h>
+#include <epan/expert.h>
#include <epan/prefs.h>
#include <epan/req_resp_hdrs.h>
+#include <epan/stat_tap_ui.h>
#include <epan/tap.h>
-#include <epan/exported_pdu.h>
-#include <epan/expert.h>
#include <wsutil/str_util.h>
@@ -4720,6 +4722,297 @@ guint sip_find_invite(packet_info *pinfo,
return result;
}
+/* TAP STAT INFO */
+
+/*
+ * Much of this is from ui/gtk/sip_stat.c:
+ * sip_stat 2004 Martin Mathieson
+ */
+
+/* TODO: extra codes to be added from SIP extensions? */
+static const value_string response_code_vals[] = {
+ { 999, "Unknown response"}, /* Must be first */
+
+ { 100, "Trying"},
+ { 180, "Ringing"},
+ { 181, "Call Is Being Forwarded"},
+ { 182, "Queued"},
+ { 183, "Session Progress"},
+ { 199, "Informational - Others" },
+
+ { 200, "OK"},
+ { 202, "Accepted"},
+ { 204, "No Notification"},
+ { 299, "Success - Others"}, /* used to keep track of other Success packets */
+
+ { 300, "Multiple Choices"},
+ { 301, "Moved Permanently"},
+ { 302, "Moved Temporarily"},
+ { 305, "Use Proxy"},
+ { 380, "Alternative Service"},
+ { 399, "Redirection - Others"},
+
+ { 400, "Bad Request"},
+ { 401, "Unauthorized"},
+ { 402, "Payment Required"},
+ { 403, "Forbidden"},
+ { 404, "Not Found"},
+ { 405, "Method Not Allowed"},
+ { 406, "Not Acceptable"},
+ { 407, "Proxy Authentication Required"},
+ { 408, "Request Timeout"},
+ { 410, "Gone"},
+ { 412, "Conditional Request Failed"},
+ { 413, "Request Entity Too Large"},
+ { 414, "Request-URI Too Long"},
+ { 415, "Unsupported Media Type"},
+ { 416, "Unsupported URI Scheme"},
+ { 420, "Bad Extension"},
+ { 421, "Extension Required"},
+ { 422, "Session Timer Too Small"},
+ { 423, "Interval Too Brief"},
+ { 428, "Use Identity Header"},
+ { 429, "Provide Referrer Identity"},
+ { 430, "Flow Failed"},
+ { 433, "Anonymity Disallowed"},
+ { 436, "Bad Identity-Info"},
+ { 437, "Unsupported Certificate"},
+ { 438, "Invalid Identity Header"},
+ { 439, "First Hop Lacks Outbound Support"},
+ { 440, "Max-Breadth Exceeded"},
+ { 470, "Consent Needed"},
+ { 480, "Temporarily Unavailable"},
+ { 481, "Call/Transaction Does Not Exist"},
+ { 482, "Loop Detected"},
+ { 483, "Too Many Hops"},
+ { 484, "Address Incomplete"},
+ { 485, "Ambiguous"},
+ { 486, "Busy Here"},
+ { 487, "Request Terminated"},
+ { 488, "Not Acceptable Here"},
+ { 489, "Bad Event"},
+ { 491, "Request Pending"},
+ { 493, "Undecipherable"},
+ { 494, "Security Agreement Required"},
+ { 499, "Client Error - Others"},
+
+ { 500, "Server Internal Error"},
+ { 501, "Not Implemented"},
+ { 502, "Bad Gateway"},
+ { 503, "Service Unavailable"},
+ { 504, "Server Time-out"},
+ { 505, "Version Not Supported"},
+ { 513, "Message Too Large"},
+ { 599, "Server Error - Others"},
+
+ { 600, "Busy Everywhere"},
+ { 603, "Decline"},
+ { 604, "Does Not Exist Anywhere"},
+ { 606, "Not Acceptable"},
+ { 699, "Global Failure - Others"},
+
+ { 0, NULL}
+};
+#define RESPONSE_CODE_MIN 100
+#define RESPONSE_CODE_MAX 699
+
+typedef enum
+{
+ REQ_RESP_METHOD_COLUMN,
+ COUNT_COLUMN,
+ RESENT_COLUMN,
+ MIN_SETUP_COLUMN,
+ AVG_SETUP_COLUMN,
+ MAX_SETUP_COLUMN
+} sip_stat_columns;
+
+static stat_tap_table_item sip_stat_fields[] = {
+ {TABLE_ITEM_STRING, TAP_ALIGN_LEFT, "Request Method / Response Code", "%-25s"},
+ {TABLE_ITEM_UINT, TAP_ALIGN_RIGHT, "Count", "%d"},
+ {TABLE_ITEM_UINT, TAP_ALIGN_RIGHT, "Resent", "%d"},
+ {TABLE_ITEM_FLOAT, TAP_ALIGN_RIGHT, "Min Setup (s)", "%8.2f"},
+ {TABLE_ITEM_FLOAT, TAP_ALIGN_RIGHT, "Avg Setup (s)", "%8.2f"},
+ {TABLE_ITEM_FLOAT, TAP_ALIGN_RIGHT, "Max Setup (s)", "%8.2f"},
+};
+
+static void sip_stat_init(new_stat_tap_ui* new_stat, new_stat_tap_gui_init_cb gui_callback, void* gui_data)
+{
+ /* XXX Should we have a single request + response table instead? */
+ int num_fields = sizeof(sip_stat_fields)/sizeof(stat_tap_table_item);
+ new_stat_tap_table *req_table = new_stat_tap_init_table("SIP Requests", num_fields, 0, NULL, gui_callback, gui_data);
+ new_stat_tap_table *resp_table = new_stat_tap_init_table("SIP Responses", num_fields, 0, NULL, gui_callback, gui_data);
+ stat_tap_table_item_type items[sizeof(sip_stat_fields)/sizeof(stat_tap_table_item)];
+ guint i;
+
+ new_stat_tap_add_table(new_stat, req_table);
+ new_stat_tap_add_table(new_stat, resp_table);
+
+ items[REQ_RESP_METHOD_COLUMN].type = TABLE_ITEM_STRING;
+ items[COUNT_COLUMN].type = TABLE_ITEM_UINT;
+ items[COUNT_COLUMN].value.uint_value = 0;
+ items[RESENT_COLUMN].type = TABLE_ITEM_UINT;
+ items[RESENT_COLUMN].value.uint_value = 0;
+ items[MIN_SETUP_COLUMN].type = TABLE_ITEM_FLOAT;
+ items[MIN_SETUP_COLUMN].value.float_value = 0.0f;
+ items[AVG_SETUP_COLUMN].type = TABLE_ITEM_FLOAT;
+ items[AVG_SETUP_COLUMN].value.float_value = 0.0f;
+ items[MAX_SETUP_COLUMN].type = TABLE_ITEM_FLOAT;
+ items[MAX_SETUP_COLUMN].value.float_value = 0.0f;
+
+ for (i = 0; i < array_length(sip_methods); i++) {
+ items[REQ_RESP_METHOD_COLUMN].value.string_value = g_strdup(sip_methods[i]);
+ new_stat_tap_init_table_row(req_table, i, num_fields, items);
+ }
+
+ for (i = 0; response_code_vals[i].strptr; i++) {
+ unsigned response_code = response_code_vals[i].value;
+ items[REQ_RESP_METHOD_COLUMN].value.string_value =
+ g_strdup_printf("%u %s", response_code, response_code_vals[i].strptr);
+ items[REQ_RESP_METHOD_COLUMN].user_data.uint_value = response_code;
+ new_stat_tap_init_table_row(resp_table, i, num_fields, items);
+ }
+}
+
+static gboolean
+sip_stat_packet(void *tapdata, packet_info *pinfo _U_, epan_dissect_t *edt _U_, const void *siv_ptr)
+{
+ new_stat_data_t* stat_data = (new_stat_data_t*) tapdata;
+ const sip_info_value_t *info_value = (const sip_info_value_t *) siv_ptr;
+ new_stat_tap_table *cur_table = NULL;
+ guint cur_row = 0; /* 0 = Unknown for both tables */
+
+ if (info_value->request_method && info_value->response_code < 1) {
+ /* Request table */
+ new_stat_tap_table *req_table = g_array_index(stat_data->new_stat_tap_data->tables, new_stat_tap_table*, 0);
+ stat_tap_table_item_type *item_data;
+ guint element;
+
+ cur_table = req_table;
+ for (element = 0; element < req_table->num_elements; element++) {
+ item_data = new_stat_tap_get_field_data(req_table, element, REQ_RESP_METHOD_COLUMN);
+ if (g_ascii_strcasecmp(info_value->request_method, item_data->value.string_value) == 0) {
+ cur_row = element;
+ break;
+ }
+ }
+
+ } else if (info_value->response_code > 0) {
+ /* Response table */
+ new_stat_tap_table *resp_table = g_array_index(stat_data->new_stat_tap_data->tables, new_stat_tap_table*, 1);
+ guint response_code = info_value->response_code;
+ stat_tap_table_item_type *item_data;
+ guint element;
+
+ cur_table = resp_table;
+ if (response_code < RESPONSE_CODE_MIN || response_code > RESPONSE_CODE_MAX) {
+ response_code = 999;
+ } else if (!try_val_to_str(response_code, response_code_vals)) {
+ response_code = ((response_code / 100) * 100) + 99;
+ }
+
+ for (element = 0; element < resp_table->num_elements; element++) {
+ item_data = new_stat_tap_get_field_data(resp_table, element, REQ_RESP_METHOD_COLUMN);
+ if (item_data->user_data.uint_value == response_code) {
+ cur_row = element;
+ break;
+ }
+ }
+
+ } else {
+ return FALSE;
+ }
+
+ if (cur_table) {
+ stat_tap_table_item_type *item_data;
+
+ item_data = new_stat_tap_get_field_data(cur_table, cur_row, COUNT_COLUMN);
+ item_data->value.uint_value++;
+ new_stat_tap_set_field_data(cur_table, cur_row, COUNT_COLUMN, item_data);
+
+ if (info_value->resend) {
+ item_data = new_stat_tap_get_field_data(cur_table, cur_row, RESENT_COLUMN);
+ item_data->value.uint_value++;
+ new_stat_tap_set_field_data(cur_table, cur_row, RESENT_COLUMN, item_data);
+ }
+
+ if (info_value->setup_time > 0) {
+ stat_tap_table_item_type *min_item_data = new_stat_tap_get_field_data(cur_table, cur_row, MIN_SETUP_COLUMN);
+ stat_tap_table_item_type *avg_item_data = new_stat_tap_get_field_data(cur_table, cur_row, AVG_SETUP_COLUMN);
+ stat_tap_table_item_type *max_item_data = new_stat_tap_get_field_data(cur_table, cur_row, MAX_SETUP_COLUMN);
+ double setup_time = (double) info_value->setup_time / 1000;
+ unsigned count;
+
+ min_item_data->user_data.uint_value++; /* We store the setup count in MIN_SETUP_COLUMN */
+ count = min_item_data->user_data.uint_value;
+ avg_item_data->user_data.float_value += setup_time; /* We store the total setup time in AVG_SETUP_COLUMN */
+
+ if (count <= 1) {
+ min_item_data->value.float_value = setup_time;
+ avg_item_data->value.float_value = setup_time;
+ max_item_data->value.float_value = setup_time;
+ } else {
+ if (setup_time < min_item_data->value.float_value) {
+ min_item_data->value.float_value = setup_time;
+ }
+ avg_item_data->value.float_value = avg_item_data->user_data.float_value / count;
+ if (setup_time > max_item_data->value.float_value) {
+ max_item_data->value.float_value = setup_time;
+ }
+ }
+
+ new_stat_tap_set_field_data(cur_table, cur_row, MIN_SETUP_COLUMN, min_item_data);
+ new_stat_tap_set_field_data(cur_table, cur_row, AVG_SETUP_COLUMN, avg_item_data);
+ new_stat_tap_set_field_data(cur_table, cur_row, MAX_SETUP_COLUMN, max_item_data);
+ }
+ }
+
+ return TRUE;
+}
+
+static void
+sip_stat_reset(new_stat_tap_table* table)
+{
+ guint element;
+ stat_tap_table_item_type* item_data;
+
+ for (element = 0; element < table->num_elements; element++)
+ {
+ item_data = new_stat_tap_get_field_data(table, element, COUNT_COLUMN);
+ item_data->value.uint_value = 0;
+ new_stat_tap_set_field_data(table, element, COUNT_COLUMN, item_data);
+
+ item_data = new_stat_tap_get_field_data(table, element, RESENT_COLUMN);
+ item_data->value.uint_value = 0;
+ new_stat_tap_set_field_data(table, element, RESENT_COLUMN, item_data);
+
+ item_data = new_stat_tap_get_field_data(table, element, RESENT_COLUMN);
+ item_data->value.uint_value = 0;
+ new_stat_tap_set_field_data(table, element, RESENT_COLUMN, item_data);
+
+ item_data = new_stat_tap_get_field_data(table, element, MIN_SETUP_COLUMN);
+ item_data->user_data.uint_value = 0;
+ item_data->value.float_value = 0.0f;
+ new_stat_tap_set_field_data(table, element, MIN_SETUP_COLUMN, item_data);
+
+ item_data = new_stat_tap_get_field_data(table, element, AVG_SETUP_COLUMN);
+ item_data->user_data.float_value = 0;
+ item_data->value.float_value = 0.0f;
+ new_stat_tap_set_field_data(table, element, AVG_SETUP_COLUMN, item_data);
+
+ item_data = new_stat_tap_get_field_data(table, element, MAX_SETUP_COLUMN);
+ item_data->value.float_value = 0.0f;
+ new_stat_tap_set_field_data(table, element, MAX_SETUP_COLUMN, item_data);
+ }
+}
+
+static void
+sip_stat_free_table_item(new_stat_tap_table* table _U_, guint row _U_, guint column, stat_tap_table_item_type* field_data)
+{
+ if (column != REQ_RESP_METHOD_COLUMN) return;
+ g_free((char*)field_data->value.string_value);
+ field_data->value.string_value = NULL;
+}
+
/* Register the protocol with Wireshark */
void proto_register_sip(void)
{
@@ -6003,6 +6296,25 @@ void proto_register_sip(void)
module_t *sip_module;
expert_module_t* expert_sip;
+ static tap_param sip_stat_params[] = {
+ { PARAM_FILTER, "filter", "Filter", NULL, TRUE }
+ };
+
+ static new_stat_tap_ui sip_stat_table = {
+ REGISTER_STAT_GROUP_TELEPHONY,
+ "SIP Statistics",
+ "sip",
+ "sip,stat",
+ sip_stat_init,
+ sip_stat_packet,
+ sip_stat_reset,
+ sip_stat_free_table_item,
+ NULL,
+ sizeof(sip_stat_fields)/sizeof(stat_tap_table_item), sip_stat_fields,
+ sizeof(sip_stat_params)/sizeof(tap_param), sip_stat_params,
+ NULL
+ };
+
/* Register the protocol name and description */
proto_sip = proto_register_protocol("Session Initiation Protocol",
"SIP", "sip");
@@ -6097,6 +6409,8 @@ void proto_register_sip(void)
ext_hdr_subdissector_table = register_dissector_table("sip.hdr", "SIP Extension header", FT_STRING, BASE_NONE);
+ register_new_stat_tap_ui(&sip_stat_table);
+
/* compile patterns */
ws_mempbrk_compile(&pbrk_comma_semi, ",;");
ws_mempbrk_compile(&pbrk_whitespace, " \t\r\n");
diff --git a/epan/dissectors/packet-sip.h b/epan/dissectors/packet-sip.h
index 41177b3a09..11d4c8e149 100644
--- a/epan/dissectors/packet-sip.h
+++ b/epan/dissectors/packet-sip.h
@@ -26,19 +26,19 @@
typedef struct _sip_info_value_t
{
- gchar *request_method;
- guint response_code;
- guchar resend;
- guint32 setup_time;
+ gchar *request_method;
+ guint response_code;
+ gboolean resend;
+ guint32 setup_time;
/* added for VoIP calls analysis, see ui/voip_calls.c*/
- gchar *tap_call_id;
- gchar *tap_from_addr;
- gchar *tap_to_addr;
- guint32 tap_cseq_number;
- gchar *reason_phrase;
+ gchar *tap_call_id;
+ gchar *tap_from_addr;
+ gchar *tap_to_addr;
+ guint32 tap_cseq_number;
+ gchar *reason_phrase;
} sip_info_value_t;
-extern void dfilter_store_sip_from_addr(tvbuff_t *tvb,proto_tree *tree,guint parameter_offset,
- guint parameter_len);
+extern void dfilter_store_sip_from_addr(tvbuff_t *tvb, proto_tree *tree,
+ guint parameter_offset, guint parameter_len);
#endif
diff --git a/ui/gtk/CMakeLists.txt b/ui/gtk/CMakeLists.txt
index 371801ca93..84a0685a7a 100644
--- a/ui/gtk/CMakeLists.txt
+++ b/ui/gtk/CMakeLists.txt
@@ -219,7 +219,6 @@ set(WIRESHARK_TAP_SRC
sctp_chunk_stat.c
sctp_chunk_stat_dlg.c
sctp_stat_dlg.c
- sip_stat.c
stats_tree_stat.c
tcp_graph.c
voip_calls_dlg.c
diff --git a/ui/gtk/Makefile.common b/ui/gtk/Makefile.common
index a46e656caa..1995db6f68 100644
--- a/ui/gtk/Makefile.common
+++ b/ui/gtk/Makefile.common
@@ -170,7 +170,6 @@ WIRESHARK_TAP_SRC = \
sctp_chunk_stat.c \
sctp_chunk_stat_dlg.c \
sctp_stat_dlg.c \
- sip_stat.c \
stats_tree_stat.c \
tcp_graph.c \
voip_calls_dlg.c \
diff --git a/ui/gtk/sip_stat.c b/ui/gtk/sip_stat.c
deleted file mode 100644
index 236eb97e0c..0000000000
--- a/ui/gtk/sip_stat.c
+++ /dev/null
@@ -1,705 +0,0 @@
-/* sip_stat.c
- * sip_stat 2004 Martin Mathieson
- *
- * Copied from http_stat.c
- *
- * Wireshark - Network traffic analyzer
- * By Gerald Combs <gerald@wireshark.org>
- * Copyright 1998 Gerald Combs
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include "config.h"
-#include <string.h>
-
-#include <gtk/gtk.h>
-
-#include <epan/packet_info.h>
-#include <epan/tap.h>
-#include <epan/dissectors/packet-sip.h>
-
-#include "ui/simple_dialog.h"
-
-#include "ui/gtk/gui_utils.h"
-#include "ui/gtk/dlg_utils.h"
-#include "ui/gtk/tap_param_dlg.h"
-#include "ui/gtk/main.h"
-
-
-#define SUM_STR_MAX 1024
-
-/* Info about a grid */
-typedef struct {
- GtkWidget *grid;
- guint row_count;
-} grid_info_t;
-
-/* Used to keep track of the statistics for an entire program interface */
-typedef struct _sip_stats_t {
- char *filter;
- GtkWidget *win;
- GHashTable *hash_responses;
- GHashTable *hash_requests;
- guint32 packets; /* number of sip packets, including continuations */
- guint32 resent_packets;
- guint32 average_setup_time;
- guint32 max_setup_time;
- guint32 min_setup_time;
- guint32 no_of_completed_calls;
- guint64 total_setup_time;
- GtkWidget *packets_label;
- GtkWidget *resent_label;
- GtkWidget *average_setup_time_label;
-
- GtkWidget *request_box; /* container for INVITE, ... */
-
- grid_info_t informational_table_info; /* Status code between 100 and 199 */
- grid_info_t success_table_info; /* 200 and 299 */
- grid_info_t redirection_table_info; /* 300 and 399 */
- grid_info_t client_error_table_info; /* 400 and 499 */
- grid_info_t server_errors_table_info; /* 500 and 599 */
- grid_info_t global_failures_table_info; /* 600 and 699 */
-} sipstat_t;
-
-/* Used to keep track of the stats for a specific response code
- * for example it can be { 3, 404, "Not Found" ,...}
- * which means we captured 3 reply sip/1.1 404 Not Found */
-typedef struct _sip_response_code_t {
- guint32 packets; /* 3 */
- guint response_code; /* 404 */
- const gchar *name; /* "Not Found" */
- GtkWidget *widget; /* Label where we display it */
- grid_info_t *table_info; /* Info about table in which we put it,
- e.g. client_error_table_info */
- sipstat_t *sp; /* Pointer back to main struct */
-} sip_response_code_t;
-
-/* Used to keep track of the stats for a specific request string */
-typedef struct _sip_request_method_t {
- gchar *response; /* eg. : INVITE */
- guint32 packets;
- GtkWidget *widget;
- sipstat_t *sp; /* Pointer back to main struct */
-} sip_request_method_t;
-
-/* TODO: extra codes to be added from SIP extensions? */
-static const value_string vals_status_code[] = {
- { 100, "Trying"},
- { 180, "Ringing"},
- { 181, "Call Is Being Forwarded"},
- { 182, "Queued"},
- { 183, "Session Progress"},
- { 199, "Informational - Others" },
-
- { 200, "OK"},
- { 202, "Accepted"},
- { 204, "No Notification"},
- { 299, "Success - Others"}, /* used to keep track of other Success packets */
-
- { 300, "Multiple Choices"},
- { 301, "Moved Permanently"},
- { 302, "Moved Temporarily"},
- { 305, "Use Proxy"},
- { 380, "Alternative Service"},
- { 399, "Redirection - Others"},
-
- { 400, "Bad Request"},
- { 401, "Unauthorized"},
- { 402, "Payment Required"},
- { 403, "Forbidden"},
- { 404, "Not Found"},
- { 405, "Method Not Allowed"},
- { 406, "Not Acceptable"},
- { 407, "Proxy Authentication Required"},
- { 408, "Request Timeout"},
- { 410, "Gone"},
- { 412, "Conditional Request Failed"},
- { 413, "Request Entity Too Large"},
- { 414, "Request-URI Too Long"},
- { 415, "Unsupported Media Type"},
- { 416, "Unsupported URI Scheme"},
- { 420, "Bad Extension"},
- { 421, "Extension Required"},
- { 422, "Session Timer Too Small"},
- { 423, "Interval Too Brief"},
- { 428, "Use Identity Header"},
- { 429, "Provide Referrer Identity"},
- { 430, "Flow Failed"},
- { 433, "Anonymity Disallowed"},
- { 436, "Bad Identity-Info"},
- { 437, "Unsupported Certificate"},
- { 438, "Invalid Identity Header"},
- { 439, "First Hop Lacks Outbound Support"},
- { 440, "Max-Breadth Exceeded"},
- { 470, "Consent Needed"},
- { 480, "Temporarily Unavailable"},
- { 481, "Call/Transaction Does Not Exist"},
- { 482, "Loop Detected"},
- { 483, "Too Many Hops"},
- { 484, "Address Incomplete"},
- { 485, "Ambiguous"},
- { 486, "Busy Here"},
- { 487, "Request Terminated"},
- { 488, "Not Acceptable Here"},
- { 489, "Bad Event"},
- { 491, "Request Pending"},
- { 493, "Undecipherable"},
- { 494, "Security Agreement Required"},
- { 499, "Client Error - Others"},
-
- { 500, "Server Internal Error"},
- { 501, "Not Implemented"},
- { 502, "Bad Gateway"},
- { 503, "Service Unavailable"},
- { 504, "Server Time-out"},
- { 505, "Version Not Supported"},
- { 513, "Message Too Large"},
- { 599, "Server Error - Others"},
-
- { 600, "Busy Everywhere"},
- { 603, "Decline"},
- { 604, "Does Not Exist Anywhere"},
- { 606, "Not Acceptable"},
- { 699, "Global Failure - Others"},
-
- { 0, NULL}
-};
-
-void register_tap_listener_gtksipstat(void);
-
-
-/* Create tables for responses and requests */
-static void
-sip_init_hash(sipstat_t *sp)
-{
- int i;
-
- /* Create responses table */
- sp->hash_responses = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_free);
-
- /* Add all response codes */
- for (i=0; vals_status_code[i].strptr; i++)
- {
- sip_response_code_t *sc = (sip_response_code_t *)g_malloc(sizeof(sip_response_code_t));
-
- sc->packets = 0;
- sc->response_code = vals_status_code[i].value;
- sc->name = vals_status_code[i].strptr;
- sc->widget = NULL;
- sc->table_info = NULL;
- sc->sp = sp;
- g_hash_table_insert(sc->sp->hash_responses, GUINT_TO_POINTER(vals_status_code[i].value), sc);
- }
-
- /* Create empty requests table */
- sp->hash_requests = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
-}
-
-/* Draw the entry for an individual request message */
-static void
-sip_draw_hash_requests(gchar *key _U_, sip_request_method_t *data, gchar *unused _U_)
-{
- gchar string_buff[SUM_STR_MAX];
-
- g_assert(data != NULL);
-
- if (data->packets == 0)
- {
- return;
- }
-
- /* Build string showing method and count */
- g_snprintf(string_buff, sizeof(string_buff),
- " %-11s : %3d packets", data->response, data->packets);
- if (data->widget == NULL)
- {
- /* Create new label */
- data->widget = gtk_label_new(string_buff);
- gtk_misc_set_alignment(GTK_MISC(data->widget), 0.0f, 0.5f);
- gtk_box_pack_start(GTK_BOX(data->sp->request_box), data->widget, FALSE, FALSE, 0);
- gtk_widget_show(data->widget);
- }
- else
- {
- /* Update existing label */
- gtk_label_set_text(GTK_LABEL(data->widget), string_buff);
- }
-}
-
-/* Draw an individual response entry */
-static void
-sip_draw_hash_responses(gint *key _U_ , sip_response_code_t *data, gchar *unused _U_)
-{
- gchar string_buff[SUM_STR_MAX];
-
- g_assert(data != NULL);
-
- if (data->packets == 0)
- {
- return;
- }
-
- /* Create an entry in the relevant box of the window */
- if (data->widget == NULL)
- {
- guint x;
- GtkWidget *tmp;
- guint i = data->response_code;
-
- /* Out of valid range - ignore */
- if ((i < 100) || (i >= 700))
- {
- return;
- }
-
- /* Find the table matching the code */
- if (i < 200)
- {
- data->table_info = &(data->sp->informational_table_info);
- }
- else if (i < 300)
- {
- data->table_info = &(data->sp->success_table_info);
- }
- else if (i < 400)
- {
- data->table_info = &(data->sp->redirection_table_info);
- }
- else if (i < 500)
- {
- data->table_info = &(data->sp->client_error_table_info);
- }
- else if (i < 600)
- {
- data->table_info = &(data->sp->server_errors_table_info);
- }
- else
- {
- data->table_info = &(data->sp->global_failures_table_info);
- }
-
- /* Get number of rows in table */
- x = data->table_info->row_count;
-
- /* Create a new label with this response, e.g. "SIP 180 Ringing" */
- g_snprintf(string_buff, sizeof(string_buff),
- "SIP %3d %s ", data->response_code, data->name);
- tmp = gtk_label_new(string_buff);
-
- /* Insert the label in the correct place in the table */
- ws_gtk_grid_attach_defaults(GTK_GRID(data->table_info->grid), tmp, 0, x, 1, 1);
- gtk_label_set_justify(GTK_LABEL(tmp), GTK_JUSTIFY_LEFT);
- gtk_widget_show(tmp);
-
- /* Show number of packets */
- g_snprintf(string_buff, sizeof(string_buff), "%9d", data->packets);
- data->widget = gtk_label_new(string_buff);
-
- /* Show this widget in the right place */
- ws_gtk_grid_attach_defaults(GTK_GRID(data->table_info->grid), data->widget, 1, x, 1, 1);
- gtk_label_set_justify(GTK_LABEL(data->widget), GTK_JUSTIFY_RIGHT);
- gtk_widget_show(data->widget);
-
- data->table_info->row_count += 1;
- } else
- {
- /* Just update the existing label string */
- g_snprintf(string_buff, sizeof(string_buff), "%9d", data->packets);
- gtk_label_set_text(GTK_LABEL(data->widget), string_buff);
- }
-}
-
-static void
-sip_reset_hash_responses(gchar *key _U_, sip_response_code_t *data, gpointer ptr _U_)
-{
- data->packets = 0;
-}
-
-static void
-sip_reset_hash_requests(gchar *key _U_ , sip_request_method_t *data, gpointer ptr _U_)
-{
- data->packets = 0;
-}
-
-static void
-sipstat_reset(void *psp)
-{
- sipstat_t *sp = (sipstat_t *)psp;
- if (sp)
- {
- sp->packets = 0;
- sp->resent_packets = 0;
- sp->average_setup_time = 0;
- sp->max_setup_time = 0;
- sp->max_setup_time = 0;
- sp->no_of_completed_calls = 0;
- sp->total_setup_time = 0;
- g_hash_table_foreach(sp->hash_responses, (GHFunc)sip_reset_hash_responses, NULL);
- g_hash_table_foreach(sp->hash_requests, (GHFunc)sip_reset_hash_requests, NULL);
- }
-}
-
-/* Main entry point to SIP tap */
-static int
-sipstat_packet(void *psp, packet_info *pinfo _U_, epan_dissect_t *edt _U_, const void *pri)
-{
- const sip_info_value_t *value = (const sip_info_value_t *)pri;
- sipstat_t *sp = (sipstat_t *)psp;
-
- /* Total number of packets, including continuation packets */
- sp->packets++;
-
- /* Update resent count if flag set */
- if (value->resend)
- {
- sp->resent_packets++;
- }
-
- /* Calculate average setup time */
- if (value->setup_time)
- {
- sp->no_of_completed_calls++;
- /* Check if it's the first value */
- if ( sp->total_setup_time == 0 )
- {
- sp->average_setup_time = value->setup_time;
- sp->total_setup_time = value->setup_time;
- sp->max_setup_time = value->setup_time;
- sp->min_setup_time = value->setup_time;
- } else
- {
- sp->total_setup_time = sp->total_setup_time + value->setup_time;
- if (sp->max_setup_time < value->setup_time)
- {
- sp->max_setup_time = value->setup_time;
- }
- if (sp->min_setup_time > value->setup_time)
- {
- sp->min_setup_time = value->setup_time;
- }
- /* Calculate average */
- sp->average_setup_time = (guint32)(sp->total_setup_time / sp->no_of_completed_calls);
- }
- }
-
- /* Looking at both requests and responses */
- if (value->response_code != 0)
- {
- /* Responses */
- sip_response_code_t *sc;
-
- /* Look up response code in hash table */
- sc = (sip_response_code_t *)g_hash_table_lookup(sp->hash_responses, GUINT_TO_POINTER(value->response_code));
- if (sc == NULL)
- {
- /* Non-standard status code; we classify it as others
- * in the relevant category
- * (Informational, Success, Redirection, Client Error, Server Error, Global Failure)
- */
- guint key;
- guint i = value->response_code;
-
-
- if ((i < 100) || (i >= 700))
- {
- /* Forget about crazy values */
- return 0;
- }
- else if (i < 200)
- {
- key = 199; /* Hopefully, this status code will never be used */
- }
- else if (i < 300)
- {
- key = 299;
- }
- else if (i < 400)
- {
- key = 399;
- }
- else if (i < 500)
- {
- key = 499;
- }
- else if (i < 600)
- {
- key = 599;
- }
- else
- {
- key = 699;
- }
-
- /* Now look up this fallback code to get its text description */
- sc = (sip_response_code_t *)g_hash_table_lookup(sp->hash_responses, GUINT_TO_POINTER(key));
- if (sc == NULL)
- {
- return 0;
- }
- }
- sc->packets++;
- }
- else if (value->request_method)
- {
- /* Requests */
- sip_request_method_t *sc;
-
- /* Look up the request method in the table */
- sc = (sip_request_method_t *)g_hash_table_lookup(sp->hash_requests, value->request_method);
- if (sc == NULL)
- {
- /* First of this type. Create structure and initialise */
- sc = (sip_request_method_t *)g_malloc(sizeof(sip_request_method_t));
- sc->response = g_strdup(value->request_method);
- sc->packets = 1;
- sc->widget = NULL;
- sc->sp = sp;
- /* Insert it into request table */
- g_hash_table_insert(sp->hash_requests, sc->response, sc);
- }
- else
- {
- /* Already existed, just update count for that method */
- sc->packets++;
- }
- /* g_free(value->request_method); */
- }
- else
- {
- /* No request method set. Just ignore */
- return 0;
- }
-
- return 1;
-}
-
-/* Redraw the whole stats window */
-static void
-sipstat_draw(void *psp)
-{
- gchar string_buff[SUM_STR_MAX];
- sipstat_t *sp = (sipstat_t *)psp;
-
- /* Set summary label */
- g_snprintf(string_buff, sizeof(string_buff),
- "SIP stats (%d packets)", sp->packets);
- gtk_label_set_text(GTK_LABEL(sp->packets_label), string_buff);
-
- /* Set resend count label */
- g_snprintf(string_buff, sizeof(string_buff),
- "(%d resent packets)", sp->resent_packets);
- gtk_label_set_text(GTK_LABEL(sp->resent_label), string_buff);
-
- /* Draw responses and requests from their tables */
- g_hash_table_foreach(sp->hash_responses, (GHFunc)sip_draw_hash_responses, NULL);
- g_hash_table_foreach(sp->hash_requests, (GHFunc)sip_draw_hash_requests, NULL);
-
- /* Set resend count label */
- g_snprintf(string_buff, sizeof(string_buff),
- "Average setup time %d ms\n Min %d ms\n Max %d ms",
- sp->average_setup_time, sp->min_setup_time, sp->max_setup_time);
- gtk_label_set_text(GTK_LABEL(sp->average_setup_time_label), string_buff);
-
- gtk_widget_show_all(sp->win);
-}
-
-/* When window is destroyed, clean up */
-
-static void
-win_destroy_cb(GtkWindow *win _U_, gpointer data)
-{
- sipstat_t *sp = (sipstat_t *)data;
-
- remove_tap_listener(sp);
-
- g_hash_table_destroy(sp->hash_responses);
- g_hash_table_destroy(sp->hash_requests);
- g_free(sp->filter);
- g_free(sp);
-}
-
-
-static void
-init_table(GtkWidget *main_vb, const gchar *title, grid_info_t *tbl_info)
-{
- GtkWidget *fr;
-
- fr = gtk_frame_new(title);
- gtk_box_pack_start(GTK_BOX(main_vb), fr, TRUE, TRUE, 0);
-
- /* table (within that frame) */
- (*tbl_info).grid = ws_gtk_grid_new();
- gtk_container_add(GTK_CONTAINER(fr), (*tbl_info).grid);
- (*tbl_info).row_count = 0;
-}
-
-/* Create a new instance of gtk_sipstat. */
-static void
-gtk_sipstat_init(const char *opt_arg, void *userdata _U_)
-{
- sipstat_t *sp;
- const char *filter;
- GString *error_string;
- char *title;
- GtkWidget *main_vb, *separator, *request_fr;
- GtkWidget *bt_close;
- GtkWidget *bbox;
-
-
- if (strncmp(opt_arg, "sip,stat,", 9) == 0)
- {
- /* Skip those characters from filter to display */
- filter = opt_arg + 9;
- }
- else
- {
- /* No filter */
- filter = NULL;
- }
-
- /* Create sip stats window structure */
- sp = (sipstat_t *)g_malloc(sizeof(sipstat_t));
- sp->win = dlg_window_new("sip-stat"); /* transient_for top_level */
- gtk_window_set_destroy_with_parent(GTK_WINDOW(sp->win), TRUE);
-
- /* Set title to include any filter given */
- if (filter)
- {
- sp->filter = g_strdup(filter);
- title = g_strdup_printf("SIP statistics with filter: %s", filter);
- }
- else
- {
- sp->filter = NULL;
- title = g_strdup("SIP statistics");
- }
-
- gtk_window_set_title(GTK_WINDOW(sp->win), title);
- g_free(title);
-
-
- /* Create container for all widgets */
- main_vb = ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 12, FALSE);
- gtk_container_set_border_width(GTK_CONTAINER(main_vb), 12);
- gtk_container_add(GTK_CONTAINER(sp->win), main_vb);
-
- /* Initialise & show number of packets */
- sp->packets = 0;
- sp->packets_label = gtk_label_new("SIP stats (0 SIP packets)");
- gtk_box_pack_start(GTK_BOX(main_vb), sp->packets_label, TRUE, TRUE, 0);
-
- sp->resent_packets = 0;
- sp->resent_label = gtk_label_new("(0 resent packets)");
- gtk_box_pack_start(GTK_BOX(main_vb), sp->resent_label, TRUE, TRUE, 0);
- gtk_widget_show(sp->resent_label);
-
- init_table(main_vb, "Informational SIP 1xx", &(sp->informational_table_info));
- init_table(main_vb, "Success SIP 2xx", &(sp->success_table_info));
- init_table(main_vb, "Redirection SIP 3xx", &(sp->redirection_table_info));
- init_table(main_vb, "Client errors SIP 4xx", &(sp->client_error_table_info));
- init_table(main_vb, "Server errors SIP 5xx", &(sp->server_errors_table_info));
- init_table(main_vb, "Global failures SIP 6xx", &(sp->global_failures_table_info));
-
- /* Separator between requests and responses */
- separator = gtk_separator_new(GTK_ORIENTATION_HORIZONTAL);
- gtk_box_pack_start(GTK_BOX(main_vb), separator, TRUE, TRUE, 0);
-
- /* Request table and frame */
- request_fr = gtk_frame_new("List of request methods");
- gtk_box_pack_start(GTK_BOX(main_vb), request_fr, TRUE, TRUE, 0);
- gtk_container_set_border_width(GTK_CONTAINER(request_fr), 0);
-
- sp->request_box = ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 10, FALSE);
- gtk_container_add(GTK_CONTAINER(request_fr), sp->request_box);
-
- sp->average_setup_time = 0;
- sp->max_setup_time = 0;
- sp->min_setup_time = 0;
- sp->average_setup_time_label = gtk_label_new("(Not calculated)");
- gtk_box_pack_start(GTK_BOX(main_vb), sp->average_setup_time_label, TRUE, TRUE, 0);
- gtk_widget_show(sp->average_setup_time_label);
-
-
- /* Register this tap listener now */
- error_string = register_tap_listener("sip",
- sp,
- filter,
- 0,
- sipstat_reset,
- sipstat_packet,
- sipstat_draw);
- if (error_string)
- {
- /* Error. We failed to attach to the tap. Clean up */
- simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", error_string->str);
- g_free(sp->filter);
- g_free(sp);
- g_string_free(error_string, TRUE);
- return;
- }
-
- /* Button row. */
- bbox = dlg_button_row_new(GTK_STOCK_CLOSE, NULL);
- gtk_box_pack_start(GTK_BOX(main_vb), bbox, FALSE, FALSE, 0);
-
- bt_close = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CLOSE);
- window_set_cancel_button(sp->win, bt_close, window_cancel_button_cb);
-
- g_signal_connect(sp->win, "delete_event", G_CALLBACK(window_delete_event_cb), NULL);
- g_signal_connect(sp->win, "destroy", G_CALLBACK(win_destroy_cb), sp);
-
- /* Display up-to-date contents */
- gtk_widget_show_all(sp->win);
- window_present(sp->win);
-
- sip_init_hash(sp);
- cf_retap_packets(&cfile);
- gdk_window_raise(gtk_widget_get_window(sp->win));
-}
-
-static tap_param sip_stat_params[] = {
- { PARAM_FILTER, "filter", "Filter", NULL, TRUE }
-};
-
-static tap_param_dlg sip_stat_dlg = {
- "SIP Packet Counter",
- "sip,stat",
- gtk_sipstat_init,
- -1,
- G_N_ELEMENTS(sip_stat_params),
- sip_stat_params,
- NULL
-};
-
-/* Register this tap listener and add menu item. */
-void
-register_tap_listener_gtksipstat(void)
-{
- register_param_stat(&sip_stat_dlg, "_SIP", REGISTER_STAT_GROUP_TELEPHONY);
-}
-
-/*
- * Editor modelines - http://www.wireshark.org/tools/modelines.html
- *
- * Local variables:
- * c-basic-offset: 4
- * tab-width: 8
- * indent-tabs-mode: nil
- * End:
- *
- * vi: set shiftwidth=4 tabstop=8 expandtab:
- * :indentSize=4:tabSize=8:noTabs=true:
- */
diff --git a/ui/qt/main_window.cpp b/ui/qt/main_window.cpp
index 4d0c28899a..fb723573d3 100644
--- a/ui/qt/main_window.cpp
+++ b/ui/qt/main_window.cpp
@@ -2160,6 +2160,7 @@ void MainWindow::addDynamicMenus()
wsApp->addDynamicMenuGroupItem(REGISTER_STAT_GROUP_TELEPHONY_LTE, main_ui_->actionTelephonyLteRlcStatistics);
wsApp->addDynamicMenuGroupItem(REGISTER_STAT_GROUP_TELEPHONY_LTE, main_ui_->actionTelephonyLteRlcGraph);
wsApp->addDynamicMenuGroupItem(REGISTER_STAT_GROUP_TELEPHONY_MTP3, main_ui_->actionTelephonyMtp3Summary);
+ wsApp->addDynamicMenuGroupItem(REGISTER_STAT_GROUP_TELEPHONY, main_ui_->actionTelephonySipFlows);
// Fill in each menu
foreach (register_stat_group_t menu_group, menu_groups) {
diff --git a/ui/qt/main_window.ui b/ui/qt/main_window.ui
index 8010411277..761f160cb1 100644
--- a/ui/qt/main_window.ui
+++ b/ui/qt/main_window.ui
@@ -565,7 +565,6 @@
<addaction name="menuTelephonySCTP"/>
<addaction name="actionTelephonySMPPOperations"/>
<addaction name="actionTelephonyUCPMessages"/>
- <addaction name="actionTelephonySipFlows"/>
</widget>
<widget class="QMenu" name="menuEdit">
<property name="title">