127fce25f7c06d90d5eee9efc594ef0a9ae0132c
[obnox/wireshark/wip.git] / gtk / ansi_map_stat.c
1 /* ansi_map_stat.c
2  *
3  * Copyright 2003, Michael Lum <mlum [AT] telostech.com>
4  * In association with Telos Technology Inc.
5  *
6  * MUCH code modified from service_response_time_table.c.
7  *
8  * $Id$
9  *
10  * Wireshark - Network traffic analyzer
11  * By Gerald Combs <gerald@wireshark.org>
12  * Copyright 1998 Gerald Combs
13  *
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License
16  * as published by the Free Software Foundation; either version 2
17  * of the License, or (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
27  */
28
29 /*
30  * This TAP provides statistics for ANSI MAP:
31  */
32
33 #ifdef HAVE_CONFIG_H
34 # include "config.h"
35 #endif
36
37 #include <gtk/gtk.h>
38 #include <string.h>
39
40 #include <epan/packet_info.h>
41 #include <epan/epan.h>
42 #include <epan/value_string.h>
43 #include <epan/stat_cmd_args.h>
44 #include <epan/tap.h>
45 #include <epan/dissectors/packet-ansi_map.h>
46
47 #include "../stat_menu.h"
48 #include "../simple_dialog.h"
49 #include "../register.h"
50 #include "../globals.h"
51
52 #include "gtk/gui_stat_menu.h"
53 #include "gtk/dlg_utils.h"
54 #include "gtk/filter_dlg.h"
55 #include "gtk/gui_utils.h"
56
57 enum
58 {
59    OP_CODE_COLUMN,
60    OP_CODE_NAME_COLUMN,
61    COUNT_COLUMN,
62    TOT_BYTES_COLUMN,
63    AVG_BYTES_COLUMN,
64    N_COLUMN /* The number of columns */
65 };
66
67 typedef struct _ansi_map_stat_dlg_t {
68     GtkWidget           *win;
69     GtkWidget           *scrolled_win;
70     GtkWidget           *table;
71 } ansi_map_stat_dlg_t;
72
73 typedef struct _ansi_map_stat_t {
74     int                 message_type[ANSI_MAP_MAX_NUM_MESSAGE_TYPES];
75     double              size[ANSI_MAP_MAX_NUM_MESSAGE_TYPES];
76 } ansi_map_stat_t;
77
78 static ansi_map_stat_dlg_t      dlg;
79 static ansi_map_stat_t          ansi_a_stat;
80
81 /* Create list */
82 static
83 GtkWidget* create_list(void)
84 {
85
86     GtkListStore *list_store;
87     GtkWidget *list;
88     GtkTreeViewColumn *column;
89     GtkCellRenderer *renderer;
90     GtkTreeSortable *sortable;
91         GtkTreeView     *list_view;
92         GtkTreeSelection  *selection;
93
94         /* Create the store */
95     list_store = gtk_list_store_new(N_COLUMN,   /* Total number of columns XXX*/
96                                G_TYPE_UINT,             /* Op Code                      */
97                                G_TYPE_STRING,   /* Operation Name       */
98                                G_TYPE_UINT,             /* Count                        */
99                                G_TYPE_UINT,             /* Total Bytes          */
100                                G_TYPE_FLOAT);   /* Avg Bytes            */
101
102     /* Create a view */
103     list = gtk_tree_view_new_with_model (GTK_TREE_MODEL (list_store));
104
105         list_view = GTK_TREE_VIEW(list);
106         sortable = GTK_TREE_SORTABLE(list_store);
107
108 #if GTK_CHECK_VERSION(2,6,0)
109         /* Speed up the list display */
110         gtk_tree_view_set_fixed_height_mode(list_view, TRUE);
111 #endif
112
113     /* Setup the sortable columns */
114     gtk_tree_sortable_set_sort_column_id(sortable, OP_CODE_COLUMN, GTK_SORT_ASCENDING);
115     gtk_tree_view_set_headers_clickable(list_view, FALSE);
116
117     /* The view now holds a reference.  We can get rid of our own reference */
118     g_object_unref (G_OBJECT (list_store));
119
120     /* 
121          * Create the first column packet, associating the "text" attribute of the
122      * cell_renderer to the first column of the model 
123          */
124         /* 1:st column */
125         renderer = gtk_cell_renderer_text_new ();
126     column = gtk_tree_view_column_new_with_attributes ("Op Code", renderer, 
127                 "text", OP_CODE_COLUMN, 
128                 NULL);
129
130         gtk_tree_view_column_set_cell_data_func(column, renderer, present_as_hex_func, 
131                 GINT_TO_POINTER(OP_CODE_COLUMN), NULL);
132
133         gtk_tree_view_column_set_sort_column_id(column, OP_CODE_COLUMN);
134     gtk_tree_view_column_set_resizable(column, TRUE);
135     gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
136     gtk_tree_view_column_set_min_width(column, 60);
137
138         /* Add the column to the view. */
139     gtk_tree_view_append_column (list_view, column);
140
141     /* 2:nd column... */
142     renderer = gtk_cell_renderer_text_new ();
143     column = gtk_tree_view_column_new_with_attributes ("Operation Name", renderer, 
144                 "text", OP_CODE_NAME_COLUMN,
145                 NULL);
146     gtk_tree_view_column_set_sort_column_id(column, OP_CODE_NAME_COLUMN);
147     gtk_tree_view_column_set_resizable(column, TRUE);
148     gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
149     gtk_tree_view_column_set_min_width(column, 290);
150     gtk_tree_view_append_column (list_view, column);
151
152         /* 3:d column... */
153     renderer = gtk_cell_renderer_text_new ();
154     column = gtk_tree_view_column_new_with_attributes ("Count", renderer, 
155                 "text", COUNT_COLUMN,
156                 NULL);
157     gtk_tree_view_column_set_sort_column_id(column, COUNT_COLUMN);
158     gtk_tree_view_column_set_resizable(column, TRUE);
159     gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
160     gtk_tree_view_column_set_min_width(column, 50);
161     gtk_tree_view_append_column (list_view, column);
162
163     /* 4:th column... */
164     renderer = gtk_cell_renderer_text_new ();
165         column = gtk_tree_view_column_new_with_attributes ("Total Bytes", renderer, 
166                 "text", TOT_BYTES_COLUMN, 
167                 NULL);
168         
169
170     gtk_tree_view_column_set_sort_column_id(column, TOT_BYTES_COLUMN);
171     gtk_tree_view_column_set_resizable(column, TRUE);
172     gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
173     gtk_tree_view_column_set_min_width(column, 100);
174     gtk_tree_view_append_column (list_view, column);
175
176     /* 10:th column.. Avg Bytes. */
177     renderer = gtk_cell_renderer_text_new ();
178         column = gtk_tree_view_column_new_with_attributes ("Avg Bytes", renderer, 
179                 "text", AVG_BYTES_COLUMN, 
180                 NULL);
181         gtk_tree_view_column_set_cell_data_func(column, renderer, float_data_func, 
182                 GINT_TO_POINTER(AVG_BYTES_COLUMN), NULL);
183
184     gtk_tree_view_column_set_sort_column_id(column, AVG_BYTES_COLUMN);
185     gtk_tree_view_column_set_resizable(column, TRUE);
186     gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
187     gtk_tree_view_column_set_min_width(column, 50);
188     gtk_tree_view_append_column (list_view, column);
189
190         /* Now enable the sorting of each column */
191     gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(list_view), TRUE);
192     gtk_tree_view_set_headers_clickable(GTK_TREE_VIEW(list_view), TRUE);
193
194         /* Setup the selection handler */
195         selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(list));
196         gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE);
197
198         return list;
199
200 }
201
202 static void
203 ansi_map_stat_reset(
204     void                *tapdata)
205 {
206     ansi_map_stat_t     *stat_p = tapdata;
207
208     memset(stat_p, 0, sizeof(ansi_map_stat_t));
209 }
210
211
212 static int
213 ansi_map_stat_packet(
214     void                *tapdata,
215     packet_info         *pinfo _U_,
216     epan_dissect_t      *edt _U_,
217     const void          *data)
218 {
219     ansi_map_stat_t     *stat_p = tapdata;
220     const ansi_map_tap_rec_t    *data_p = data;
221
222 #if 0   /* always false because message_type is 8 bit value */
223     if (data_p->message_type >= ANSI_MAP_MAX_NUM_MESSAGE_TYPES)
224     {
225         /*
226          * unknown PDU type !!!
227          */
228         return(0);
229     }
230 #endif
231
232     stat_p->message_type[data_p->message_type]++;
233     stat_p->size[data_p->message_type] += data_p->size;
234
235     return(1);
236 }
237
238
239 static void
240 ansi_map_stat_draw(
241     void                *tapdata)
242 {
243     ansi_map_stat_t     *stat_p = tapdata;
244     int                 i;
245     float               avg;
246     GtkListStore *list_store;
247         GtkTreeIter  iter;
248
249     if (dlg.win && tapdata)
250     {
251                 i = 0;
252                 list_store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW (dlg.table))); /* Get store */
253                 while (ansi_map_opr_code_strings[i].strptr)
254                 {
255                         avg = 0.0f;
256                         if (stat_p->message_type[ansi_map_opr_code_strings[i].value] !=0 ){
257                                 avg = (float)stat_p->size[ansi_map_opr_code_strings[i].value]/(float)stat_p->message_type[ansi_map_opr_code_strings[i].value];
258                         }
259                         /* Creates a new row at position. iter will be changed to point to this new row. 
260                          * If position is larger than the number of rows on the list, then the new row will be appended to the list.
261                          * The row will be filled with the values given to this function.
262                          * :
263                          * should generally be preferred when inserting rows in a sorted list store.
264                          */
265 #if GTK_CHECK_VERSION(2,6,0)
266                         gtk_list_store_insert_with_values( list_store , &iter, G_MAXINT,
267 #else
268                         gtk_list_store_append  (list_store, &iter);
269                         gtk_list_store_set  (list_store, &iter,
270 #endif
271                            OP_CODE_COLUMN, ansi_map_opr_code_strings[i].value,
272                            OP_CODE_NAME_COLUMN, ansi_map_opr_code_strings[i].strptr,
273                            COUNT_COLUMN, (guint)stat_p->message_type[ansi_map_opr_code_strings[i].value],
274                            TOT_BYTES_COLUMN, (guint)stat_p->size[ansi_map_opr_code_strings[i].value],
275                            AVG_BYTES_COLUMN, avg,
276                            -1);
277                         i++;
278                 }
279     }
280 }
281
282
283
284
285 static void
286 ansi_map_stat_gtk_win_destroy_cb(
287     GtkWindow           *win _U_,
288     gpointer            user_data _U_)
289 {
290     memset((void *) user_data, 0, sizeof(ansi_map_stat_dlg_t));
291 }
292
293
294 static void
295 ansi_map_stat_gtk_win_create(
296     ansi_map_stat_dlg_t *dlg_p,
297     const char          *title)
298 {
299     GtkWidget           *vbox;
300     GtkWidget           *bt_close;
301     GtkWidget           *bbox;
302
303
304     dlg_p->win = window_new(GTK_WINDOW_TOPLEVEL, title);
305     gtk_window_set_default_size(GTK_WINDOW(dlg_p->win), 500, 450);
306
307     vbox = gtk_vbox_new(FALSE, 3);
308         gtk_container_add(GTK_CONTAINER(dlg_p->win), vbox);
309     gtk_container_set_border_width(GTK_CONTAINER(vbox), 12);
310
311     dlg_p->scrolled_win = scrolled_window_new(NULL, NULL);
312     gtk_box_pack_start(GTK_BOX(vbox), dlg_p->scrolled_win, TRUE, TRUE, 0);
313
314     dlg_p->table = create_list();
315
316     gtk_container_add(GTK_CONTAINER(dlg_p->scrolled_win), dlg_p->table);
317
318     /* Button row. */
319     bbox = dlg_button_row_new(GTK_STOCK_CLOSE, NULL);
320         gtk_box_pack_start(GTK_BOX(vbox), bbox, FALSE, FALSE, 0);
321
322     bt_close = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CLOSE);
323
324     window_set_cancel_button(dlg_p->win, bt_close, window_cancel_button_cb);
325
326     g_signal_connect(dlg_p->win, "delete_event", G_CALLBACK(window_delete_event_cb), NULL);
327     g_signal_connect(dlg_p->win, "destroy", G_CALLBACK(ansi_map_stat_gtk_win_destroy_cb), dlg_p);
328
329     gtk_widget_show_all(dlg_p->win);
330     window_present(dlg_p->win);
331 }
332
333
334 static void
335 ansi_map_stat_gtk_cb(
336     GtkWidget           *w _U_,
337     gpointer            d _U_)
338 {
339     /*
340      * if the window is already open, bring it to front
341      */
342     if (dlg.win){
343                 gdk_window_raise(dlg.win->window);
344                 return;
345     }
346
347     ansi_map_stat_gtk_win_create(&dlg, "ANSI MAP Operation Statistics");
348     ansi_map_stat_draw(&ansi_a_stat);
349 }
350
351
352 static void
353 ansi_map_stat_gtk_init(
354     const char          *optarg _U_,
355     void* userdata _U_ )
356 {
357     ansi_map_stat_gtk_cb(NULL, NULL);
358 }
359
360
361 void
362 register_tap_listener_gtkansi_map_stat(void)
363 {
364     GString             *err_p;
365
366
367     memset((void *) &ansi_a_stat, 0, sizeof(ansi_map_stat_t));
368
369     err_p =
370         register_tap_listener("ansi_map", &ansi_a_stat, NULL,
371             ansi_map_stat_reset,
372             ansi_map_stat_packet,
373             ansi_map_stat_draw);
374
375     if (err_p != NULL)
376     {
377         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_p->str);
378         g_string_free(err_p, TRUE);
379
380         exit(1);
381     }
382
383     register_stat_menu_item("ANSI/MAP Operation", REGISTER_STAT_GROUP_TELEPHONY,
384         ansi_map_stat_gtk_cb, NULL, NULL, NULL);
385     register_stat_cmd_arg("ansi_map", ansi_map_stat_gtk_init,NULL);
386 }