aboutsummaryrefslogtreecommitdiffstats
path: root/ui/gtk/response_time_delay_table.c
diff options
context:
space:
mode:
authorMichael Mann <mmann78@netscape.net>2015-06-20 12:22:22 -0400
committerAnders Broman <a.broman58@gmail.com>2015-06-22 15:13:39 +0000
commit8f390d497577937dee7311f345b77c840ba42e15 (patch)
treed59679646ab38e4c22d7773cd00003719be028e7 /ui/gtk/response_time_delay_table.c
parent8b230eabddf11becf4ae895fba17f43a3415716e (diff)
Refactor RTD stats.
Very similar to the refactoring of SRT stats, it provides more commonality of the stats for all GUI interfaces. Currently implemented for TShark and GTK. Affected dissectors: MEGACO, MGCP, Radius Change-Id: Icb73a7e603dc3502b39bf696227fcaae37d4ed21 Reviewed-on: https://code.wireshark.org/review/8998 Petri-Dish: Michael Mann <mmann78@netscape.net> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Anders Broman <a.broman58@gmail.com>
Diffstat (limited to 'ui/gtk/response_time_delay_table.c')
-rw-r--r--ui/gtk/response_time_delay_table.c392
1 files changed, 392 insertions, 0 deletions
diff --git a/ui/gtk/response_time_delay_table.c b/ui/gtk/response_time_delay_table.c
new file mode 100644
index 0000000000..e16211414c
--- /dev/null
+++ b/ui/gtk/response_time_delay_table.c
@@ -0,0 +1,392 @@
+/* response_time_delay_table.c
+ *
+ * Based on service_response_time_table.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 <gtk/gtk.h>
+
+#include "epan/packet_info.h"
+#include "epan/proto.h"
+
+#include "ui/simple_dialog.h"
+#include "ui/utf8_entities.h"
+
+#include "ui/gtk/filter_utils.h"
+#include "ui/gtk/gui_stat_util.h"
+#include "ui/gtk/gui_utils.h"
+#include "ui/gtk/dlg_utils.h"
+#include "ui/gtk/response_time_delay_table.h"
+#include "ui/gtk/tap_param_dlg.h"
+#include "ui/gtk/main.h"
+
+enum
+{
+ TYPE_COLUMN,
+ MESSAGES_COLUMN,
+ MIN_SRT_COLUMN,
+ MAX_SRT_COLUMN,
+ AVG_SRT_COLUMN,
+ MIN_FRAME_COLUMN,
+ MAX_FRAME_COLUMN,
+ OPEN_REQUESTS_COLUMN,
+ DISCARDED_RESPONSES_COLUMN,
+ REPEATED_REQUESTS_COLUMN,
+ REPEATED_RESPONSES_COLUMN
+};
+
+static const stat_column titles[]={
+ {G_TYPE_STRING, LEFT, "Type" },
+ {G_TYPE_UINT, RIGHT, "Messages" },
+ {G_TYPE_STRING, RIGHT, "Min SRT" },
+ {G_TYPE_STRING, RIGHT, "Max SRT" },
+ {G_TYPE_STRING, RIGHT, "Avg SRT" },
+ {G_TYPE_UINT, RIGHT, "Min in Frame" },
+ {G_TYPE_UINT, RIGHT, "Max in Frame" }
+};
+
+static const stat_column titles_more[]={
+ {G_TYPE_STRING, LEFT, "Type" },
+ {G_TYPE_UINT, RIGHT, "Messages" },
+ {G_TYPE_STRING, RIGHT, "Min SRT" },
+ {G_TYPE_STRING, RIGHT, "Max SRT" },
+ {G_TYPE_STRING, RIGHT, "Avg SRT" },
+ {G_TYPE_UINT, RIGHT, "Min in Frame" },
+ {G_TYPE_UINT, RIGHT, "Max in Frame" },
+ {G_TYPE_UINT, RIGHT, "Open Requests" },
+ {G_TYPE_UINT, RIGHT, "Discarded Responses" },
+ {G_TYPE_STRING, RIGHT, "Repeated Requests" },
+ {G_TYPE_STRING, RIGHT, "Repeated Responses"}
+};
+
+typedef struct _gtk_rtd_t {
+ GtkWidget *vbox;
+ GtkWidget *win;
+ GtkTreeView *table; /**< Tree view */
+ GtkWidget *scrolled_window; /**< window widget */
+ GtkWidget *menu; /**< context menu */
+ GtkWidget *open_req_label;
+ GtkWidget *dis_rsp_label;
+ GtkWidget *repeat_req_label;
+ GtkWidget *repeat_rsp_label;
+} gtk_rtd_t;
+
+typedef struct _rtd_t {
+ const char *type;
+ const char *filter;
+ gtk_rtd_t gtk_data;
+ register_rtd_t* rtd;
+ rtd_data_t data;
+} rtd_t;
+
+static void
+rtd_set_title(rtd_t *rr)
+{
+ gchar *str;
+
+ str = g_strdup_printf("%s Service Response Time statistics", proto_get_protocol_short_name(find_protocol_by_id(get_rtd_proto_id(rr->rtd))));
+ set_window_title(rr->gtk_data.win, str);
+ g_free(str);
+}
+
+static void
+win_destroy_cb(GtkWindow *win _U_, gpointer data)
+{
+ rtd_t *rr = (rtd_t*)data;
+
+ remove_tap_listener(&rr->data);
+
+ free_rtd_table(rr->rtd, &rr->data.stat_table, NULL, NULL);
+
+ g_free(rr);
+}
+
+static void
+init_gtk_rtd_table(rtd_stat_table* rtd, void* gui_data)
+{
+ gtk_rtd_t* gtk_data = (gtk_rtd_t*)gui_data;
+
+ if (rtd->num_rtds == 1)
+ {
+ gtk_window_set_default_size(GTK_WINDOW(gtk_data->win), RTD_PREFERRED_WIDTH, 300);
+
+ gtk_data->open_req_label = gtk_label_new("Open Requests: 0");
+ gtk_box_pack_start(GTK_BOX(gtk_data->vbox), gtk_data->open_req_label, FALSE, FALSE, 0);
+ gtk_widget_show(gtk_data->open_req_label);
+
+ gtk_data->dis_rsp_label = gtk_label_new("Discarded Responses: 0");
+ gtk_box_pack_start(GTK_BOX(gtk_data->vbox), gtk_data->dis_rsp_label, FALSE, FALSE, 0);
+ gtk_widget_show(gtk_data->dis_rsp_label);
+
+ gtk_data->repeat_req_label = gtk_label_new("Repeated Requests: 0");
+ gtk_box_pack_start(GTK_BOX(gtk_data->vbox), gtk_data->repeat_req_label, FALSE, FALSE, 0);
+ gtk_widget_show(gtk_data->repeat_req_label);
+
+ gtk_data->repeat_rsp_label = gtk_label_new("Repeated Responses: 0");
+ gtk_box_pack_start(GTK_BOX(gtk_data->vbox), gtk_data->repeat_rsp_label, FALSE, FALSE, 0);
+ gtk_widget_show(gtk_data->repeat_rsp_label);
+
+ gtk_data->table = create_stat_table(gtk_data->scrolled_window, gtk_data->vbox, 7, titles);
+ }
+ else
+ {
+ gtk_window_set_default_size(GTK_WINDOW(gtk_data->win), RTD_PREFERRED_WIDTH+100, 200);
+ gtk_data->table = create_stat_table(gtk_data->scrolled_window, gtk_data->vbox, 11, titles_more);
+ }
+}
+
+static void
+rtd_draw(void *arg)
+{
+ GtkListStore *store;
+ rtd_data_t* rtd_data = (rtd_data_t*)arg;
+ rtd_t* rtd = (rtd_t*)rtd_data->user_data;
+ rtd_timestat *ms;
+ GtkTreeIter iter;
+ char str[5][256];
+ gchar* tmp_str;
+ guint i, j;
+ char label_str[256];
+
+ /* clear list before printing */
+ store = GTK_LIST_STORE(gtk_tree_view_get_model(rtd->gtk_data.table));
+ gtk_list_store_clear(store);
+
+ if (rtd_data->stat_table.num_rtds == 1)
+ {
+ ms = &rtd_data->stat_table.time_stats[0];
+
+ g_snprintf(label_str, sizeof(char[256]), "Open Requests: %u", ms->open_req_num);
+ gtk_label_set_text(GTK_LABEL(rtd->gtk_data.open_req_label), label_str);
+ g_snprintf(label_str, sizeof(char[256]), "Discarded Responses: %u", ms->disc_rsp_num);
+ gtk_label_set_text(GTK_LABEL(rtd->gtk_data.dis_rsp_label), label_str);
+ g_snprintf(label_str, sizeof(char[256]), "Repeated Requests: %u", ms->req_dup_num);
+ gtk_label_set_text(GTK_LABEL(rtd->gtk_data.repeat_req_label), label_str);
+ g_snprintf(label_str, sizeof(char[256]), "Repeated Responses: %u", ms->rsp_dup_num);
+ gtk_label_set_text(GTK_LABEL(rtd->gtk_data.repeat_rsp_label), label_str);
+
+ for(i=0;i<ms->num_timestat;i++)
+ {
+ /* nothing seen, nothing to do */
+ if(ms->rtd[i].num==0){
+ continue;
+ }
+
+ g_snprintf(str[0], sizeof(char[256]), "%8.2f msec", nstime_to_msec(&(ms->rtd[i].min)));
+ g_snprintf(str[1], sizeof(char[256]), "%8.2f msec", nstime_to_msec(&(ms->rtd[i].max)));
+ g_snprintf(str[2], sizeof(char[256]), "%8.2f msec", get_average(&(ms->rtd[i].tot), ms->rtd[i].num));
+ tmp_str = val_to_str_wmem(NULL, i, get_rtd_value_string(rtd->rtd), "Other (%d)");
+ gtk_list_store_append(store, &iter);
+ gtk_list_store_set(store, &iter,
+ TYPE_COLUMN, tmp_str,
+ MESSAGES_COLUMN, ms->rtd[i].num,
+ MIN_SRT_COLUMN, str[0],
+ MAX_SRT_COLUMN, str[1],
+ AVG_SRT_COLUMN, str[2],
+ MIN_FRAME_COLUMN, ms->rtd[i].min_num,
+ MAX_FRAME_COLUMN, ms->rtd[i].max_num,
+ -1);
+ wmem_free(NULL, tmp_str);
+ }
+ }
+ else
+ {
+ for (i=0; i<rtd_data->stat_table.num_rtds; i++)
+ {
+ for (j=0; j<rtd_data->stat_table.time_stats[i].num_timestat; j++)
+ {
+
+ /* nothing seen, nothing to do */
+ if(rtd_data->stat_table.time_stats[i].rtd[j].num==0){
+ continue;
+ }
+
+ g_snprintf(str[0], 256, "%8.2f msec", nstime_to_msec(&(rtd_data->stat_table.time_stats[i].rtd[j].min)));
+ g_snprintf(str[1], 256, "%8.2f msec", nstime_to_msec(&(rtd_data->stat_table.time_stats[i].rtd[j].max)));
+ g_snprintf(str[2], 256, "%8.2f msec", get_average(&(rtd_data->stat_table.time_stats[i].rtd[j].tot), rtd_data->stat_table.time_stats[i].rtd[j].num));
+ g_snprintf(str[3], 256, "%4u (%4.2f%%)", rtd_data->stat_table.time_stats[i].req_dup_num,
+ rtd_data->stat_table.time_stats[i].rtd[j].num?((double)rtd_data->stat_table.time_stats[i].req_dup_num*100)/(double)rtd_data->stat_table.time_stats[i].rtd[j].num:0);
+ g_snprintf(str[4], 256, "%4u (%4.2f%%)", rtd_data->stat_table.time_stats[i].rsp_dup_num,
+ rtd_data->stat_table.time_stats[i].rtd[j].num?((double)rtd_data->stat_table.time_stats[i].rsp_dup_num*100)/(double)rtd_data->stat_table.time_stats[i].rtd[j].num:0);
+ tmp_str = val_to_str_wmem(NULL, i, get_rtd_value_string(rtd->rtd), "Other (%d)");
+ gtk_list_store_append(store, &iter);
+ gtk_list_store_set(store, &iter,
+ TYPE_COLUMN, tmp_str,
+ MESSAGES_COLUMN, rtd_data->stat_table.time_stats[i].rtd[j].num,
+ MIN_SRT_COLUMN, str[0],
+ MAX_SRT_COLUMN, str[1],
+ AVG_SRT_COLUMN, str[2],
+ MIN_FRAME_COLUMN, rtd_data->stat_table.time_stats[i].rtd[j].min_num,
+ MAX_FRAME_COLUMN, rtd_data->stat_table.time_stats[i].rtd[j].max_num,
+ OPEN_REQUESTS_COLUMN, rtd_data->stat_table.time_stats[i].open_req_num,
+ DISCARDED_RESPONSES_COLUMN, rtd_data->stat_table.time_stats[i].disc_rsp_num,
+ REPEATED_REQUESTS_COLUMN, str[3],
+ REPEATED_RESPONSES_COLUMN, str[4],
+ -1);
+ wmem_free(NULL, tmp_str);
+ }
+ }
+ }
+}
+
+static void
+reset_table_data(rtd_stat_table* table _U_, void* gui_data)
+{
+ GtkListStore *store;
+ gtk_rtd_t* gtk_data = (gtk_rtd_t*)gui_data;
+
+ store = GTK_LIST_STORE(gtk_tree_view_get_model(gtk_data->table));
+ gtk_list_store_clear(store);
+}
+
+static void
+rtd_reset(void *arg)
+{
+ rtd_data_t *rtd = (rtd_data_t*)arg;
+ rtd_t *rr = (rtd_t *)rtd->user_data;
+
+ reset_rtd_table(&rtd->stat_table, reset_table_data, &rr->gtk_data);
+
+ rtd_set_title(rr);
+}
+
+static void
+init_rtd_tables(register_rtd_t* rtd, const char *filter)
+{
+ rtd_t *rr;
+ gchar *str;
+ GString *error_string;
+ GtkWidget *bbox;
+ GtkWidget *close_bt;
+
+ rr = g_new0(rtd_t, 1);
+
+ str = g_strdup_printf("%s SRT", proto_get_protocol_short_name(find_protocol_by_id(get_rtd_proto_id(rtd))));
+ rr->gtk_data.win=dlg_window_new(str); /* transient_for top_level */
+ g_free(str);
+ gtk_window_set_destroy_with_parent (GTK_WINDOW(rr->gtk_data.win), TRUE);
+
+ rr->gtk_data.vbox=ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 3, FALSE);
+
+ str = g_strdup_printf("%s Service Response Time statistics", proto_get_protocol_short_name(find_protocol_by_id(get_rtd_proto_id(rtd))));
+ init_main_stat_window(rr->gtk_data.win, rr->gtk_data.vbox, str, filter);
+ g_free(str);
+
+ /* init a scrolled window*/
+ rr->gtk_data.scrolled_window = scrolled_window_new(NULL, NULL);
+
+ rr->type = proto_get_protocol_short_name(find_protocol_by_id(get_rtd_proto_id(rtd)));
+ rr->filter = g_strdup(filter);
+ rr->rtd = rtd;
+ rr->data.user_data = rr;
+
+ rtd_table_dissector_init(rtd, &rr->data.stat_table, init_gtk_rtd_table, &rr->gtk_data);
+
+ error_string = register_tap_listener(get_rtd_tap_listener_name(rtd), &rr->data, filter, 0, rtd_reset, get_rtd_packet_func(rtd), rtd_draw);
+ if(error_string){
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", error_string->str);
+ g_string_free(error_string, TRUE);
+ free_rtd_table(rr->rtd, &rr->data.stat_table, NULL, NULL);
+ g_free(rr);
+ return;
+ }
+
+ /* Button row. */
+ bbox = dlg_button_row_new(GTK_STOCK_CLOSE, NULL);
+ gtk_box_pack_end(GTK_BOX(rr->gtk_data.vbox), bbox, FALSE, FALSE, 0);
+
+ close_bt = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CLOSE);
+ window_set_cancel_button(rr->gtk_data.win, close_bt, window_cancel_button_cb);
+
+ g_signal_connect(rr->gtk_data.win, "delete_event", G_CALLBACK(window_delete_event_cb), NULL);
+ g_signal_connect(rr->gtk_data.win, "destroy", G_CALLBACK(win_destroy_cb), rr);
+
+ gtk_widget_show_all(rr->gtk_data.win);
+ window_present(rr->gtk_data.win);
+
+ cf_retap_packets(&cfile);
+ gdk_window_raise(gtk_widget_get_window(rr->gtk_data.win));
+}
+
+static void
+gtk_rtdstat_init(const char *opt_arg, void *userdata _U_)
+{
+ gchar** dissector_name;
+ register_rtd_t *rtd;
+ const char *filter=NULL;
+ char* err;
+
+ /* Use first comma to find dissector name */
+ dissector_name = g_strsplit(opt_arg, ",", -1);
+ g_assert(dissector_name[0]);
+
+ /* Use dissector name to find SRT table */
+ rtd = get_rtd_table_by_name(dissector_name[0]);
+ g_assert(rtd);
+
+ rtd_table_get_filter(rtd, opt_arg, &filter, &err);
+
+ if (err != NULL)
+ {
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err);
+ g_free(err);
+ return;
+ }
+
+ init_rtd_tables(rtd, filter);
+}
+
+static tap_param rtd_stat_params[] = {
+ { PARAM_FILTER, "filter", "Filter", NULL, TRUE }
+};
+
+void register_response_time_delay_tables(gpointer data, gpointer user_data _U_)
+{
+ register_rtd_t* rtd = (register_rtd_t*)data;
+ const char* short_name = proto_get_protocol_short_name(find_protocol_by_id(get_rtd_proto_id(rtd)));
+ tap_param_dlg* rtd_dlg;
+
+ rtd_dlg = g_new(tap_param_dlg, 1);
+
+ rtd_dlg->win_title = g_strdup_printf("%s RTD Statistics", short_name);
+ rtd_dlg->init_string = rtd_table_get_tap_string(rtd);
+ rtd_dlg->tap_init_cb = gtk_rtdstat_init;
+ rtd_dlg->index = -1;
+
+ rtd_dlg->nparams = G_N_ELEMENTS(rtd_stat_params);
+ rtd_dlg->params = rtd_stat_params;
+
+ register_param_stat(rtd_dlg, short_name, REGISTER_STAT_GROUP_RESPONSE_TIME);
+}
+
+/*
+ * Editor modelines - http://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 8
+ * tab-width: 8
+ * indent-tabs-mode: t
+ * End:
+ *
+ * vi: set shiftwidth=8 tabstop=8 noexpandtab:
+ * :indentSize=8:tabSize=8:noTabs=false:
+ */