Rename epan/stat.[ch] to epan/stat_cmd_args.[ch] - it only deals with
[obnox/wireshark/wip.git] / gtk / ansi_a_stat.c
1 /* ansi_a_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  * Ethereal - Network traffic analyzer
11  * By Gerald Combs <gerald@ethereal.com>
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 the ANSI A-Interface:
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 "stat_menu.h"
45 #include "image/clist_ascend.xpm"
46 #include "image/clist_descend.xpm"
47 #include "simple_dialog.h"
48 #include "dlg_utils.h"
49 #include <epan/tap.h>
50 #include "../register.h"
51 #include <epan/dissectors/packet-bssap.h>
52 #include <epan/dissectors/packet-ansi_a.h>
53 #include "../globals.h"
54 #include "filter_dlg.h"
55 #include "compat_macros.h"
56 #include "gui_utils.h"
57
58
59 typedef struct column_arrows {
60     GtkWidget           *table;
61     GtkWidget           *ascend_pm;
62     GtkWidget           *descend_pm;
63 } column_arrows;
64
65 typedef struct _ansi_a_stat_dlg_t {
66     GtkWidget           *win;
67     GtkWidget           *scrolled_win;
68     GtkWidget           *table;
69     char                *entries[3];
70 } ansi_a_stat_dlg_t;
71
72 typedef struct _ansi_a_stat_t {
73     int                 bsmap_message_type[0xff];
74     int                 dtap_message_type[0xff];
75 } ansi_a_stat_t;
76
77
78 static ansi_a_stat_dlg_t        dlg_bsmap;
79 static ansi_a_stat_dlg_t        dlg_dtap;
80 static ansi_a_stat_t            stat;
81
82
83 static void
84 ansi_a_stat_reset(
85     void                *tapdata)
86 {
87     ansi_a_stat_t       *stat_p = tapdata;
88
89     memset(stat_p, 0, sizeof(ansi_a_stat_t));
90 }
91
92
93 static int
94 ansi_a_stat_packet(
95     void                *tapdata,
96     packet_info         *pinfo _U_,
97     epan_dissect_t      *edt _U_,
98     const void          *data)
99 {
100     ansi_a_stat_t       *stat_p = tapdata;
101     const ansi_a_tap_rec_t      *data_p = data;
102
103     switch (data_p->pdu_type)
104     {
105     case BSSAP_PDU_TYPE_BSMAP:
106         stat_p->bsmap_message_type[data_p->message_type]++;
107         break;
108
109     case BSSAP_PDU_TYPE_DTAP:
110         stat_p->dtap_message_type[data_p->message_type]++;
111         break;
112
113     default:
114         /*
115          * unknown PDU type !!!
116          */
117         return(0);
118     }
119
120     return(1);
121 }
122
123
124 static void
125 ansi_a_stat_draw(
126     void                *tapdata)
127 {
128     ansi_a_stat_t       *stat_p = tapdata;
129     int                 i, j;
130     char                *strp;
131
132     if (dlg_bsmap.win && tapdata)
133     {
134         i = 0;
135
136         while (ansi_a_ios401_bsmap_strings[i].strptr)
137         {
138             j = gtk_clist_find_row_from_data(GTK_CLIST(dlg_bsmap.table), (gpointer) i);
139
140             strp = g_strdup_printf("%d",
141                     stat_p->bsmap_message_type[ansi_a_ios401_bsmap_strings[i].value]);
142             gtk_clist_set_text(GTK_CLIST(dlg_bsmap.table), j, 2, strp);
143             g_free(strp);
144
145             i++;
146         }
147
148         gtk_clist_sort(GTK_CLIST(dlg_bsmap.table));
149     }
150
151     if (dlg_dtap.win && tapdata)
152     {
153         i = 0;
154
155         while (ansi_a_ios401_dtap_strings[i].strptr)
156         {
157             j = gtk_clist_find_row_from_data(GTK_CLIST(dlg_dtap.table), (gpointer) i);
158
159             strp = g_strdup_printf("%d",
160                     stat_p->dtap_message_type[ansi_a_ios401_dtap_strings[i].value]);
161             gtk_clist_set_text(GTK_CLIST(dlg_dtap.table), j, 2, strp);
162             g_free(strp);
163
164             i++;
165         }
166
167         gtk_clist_sort(GTK_CLIST(dlg_dtap.table));
168     }
169 }
170
171
172 static void
173 ansi_a_stat_gtk_click_column_cb(
174     GtkCList            *clist,
175     gint                column,
176     gpointer            data)
177 {
178     column_arrows       *col_arrows = (column_arrows *) data;
179     int                 i;
180
181
182     gtk_clist_freeze(clist);
183
184     for (i=0; i < 3; i++)
185     {
186         gtk_widget_hide(col_arrows[i].ascend_pm);
187         gtk_widget_hide(col_arrows[i].descend_pm);
188     }
189
190     if (column == clist->sort_column)
191     {
192         if (clist->sort_type == GTK_SORT_ASCENDING)
193         {
194             clist->sort_type = GTK_SORT_DESCENDING;
195             gtk_widget_show(col_arrows[column].descend_pm);
196         }
197         else
198         {
199             clist->sort_type = GTK_SORT_ASCENDING;
200             gtk_widget_show(col_arrows[column].ascend_pm);
201         }
202     }
203     else
204     {
205         /*
206          * Columns 0-1 sorted in descending order by default
207          * Columns 2 sorted in ascending order by default
208          */
209         if (column <= 1)
210         {
211             clist->sort_type = GTK_SORT_ASCENDING;
212             gtk_widget_show(col_arrows[column].ascend_pm);
213         }
214         else
215         {
216             clist->sort_type = GTK_SORT_DESCENDING;
217             gtk_widget_show(col_arrows[column].descend_pm);
218         }
219
220         gtk_clist_set_sort_column(clist, column);
221     }
222
223     gtk_clist_thaw(clist);
224     gtk_clist_sort(clist);
225 }
226
227
228 static gint
229 ansi_a_stat_gtk_sort_column(
230     GtkCList            *clist,
231     gconstpointer       ptr1,
232     gconstpointer       ptr2)
233 {
234     const GtkCListRow   *row1 = ptr1;
235     const GtkCListRow   *row2 = ptr2;
236     char                *text1 = NULL;
237     char                *text2 = NULL;
238     int                 i1, i2;
239
240     text1 = GTK_CELL_TEXT(row1->cell[clist->sort_column])->text;
241     text2 = GTK_CELL_TEXT(row2->cell[clist->sort_column])->text;
242
243     switch (clist->sort_column)
244     {
245     case 0:
246         /* FALLTHRU */
247
248     case 2:
249         i1 = strtol(text1, NULL, 0);
250         i2 = strtol(text2, NULL, 0);
251         return(i1 - i2);
252
253     case 1:
254         return(strcmp(text1, text2));
255     }
256
257     g_assert_not_reached();
258
259     return(0);
260 }
261
262
263 static void
264 ansi_a_stat_gtk_win_destroy_cb(
265     GtkWindow           *win _U_,
266     gpointer            user_data _U_)
267 {
268     memset((void *) user_data, 0, sizeof(ansi_a_stat_dlg_t));
269 }
270
271
272 static void
273 ansi_a_stat_gtk_win_create(
274     ansi_a_stat_dlg_t   *dlg_p,
275     const char          *title)
276 {
277 #define INIT_TABLE_NUM_COLUMNS  3
278     const char          *default_titles[] = { "IEI", "Message Name", "Count" };
279     int                 i;
280     column_arrows       *col_arrows;
281     GtkWidget           *column_lb;
282     GtkWidget           *vbox;
283     GtkWidget           *bt_close;
284     GtkWidget           *bbox;
285
286
287     dlg_p->win = window_new(GTK_WINDOW_TOPLEVEL, title);
288     gtk_window_set_default_size(GTK_WINDOW(dlg_p->win), 480, 450);
289
290         vbox=gtk_vbox_new(FALSE, 3);
291         gtk_container_add(GTK_CONTAINER(dlg_p->win), vbox);
292         gtk_container_set_border_width(GTK_CONTAINER(vbox), 12);
293
294     dlg_p->scrolled_win = scrolled_window_new(NULL, NULL);
295     gtk_box_pack_start(GTK_BOX(vbox), dlg_p->scrolled_win, TRUE, TRUE, 0);
296
297     dlg_p->table = gtk_clist_new(INIT_TABLE_NUM_COLUMNS);
298
299     col_arrows =
300         (column_arrows *) g_malloc(sizeof(column_arrows) * INIT_TABLE_NUM_COLUMNS);
301
302     for (i = 0; i < INIT_TABLE_NUM_COLUMNS; i++)
303     {
304         col_arrows[i].table = gtk_table_new(2, 2, FALSE);
305
306         gtk_table_set_col_spacings(GTK_TABLE(col_arrows[i].table), 5);
307
308         column_lb = gtk_label_new(default_titles[i]);
309
310         gtk_table_attach(GTK_TABLE(col_arrows[i].table), column_lb,
311         0, 1, 0, 2, GTK_SHRINK, GTK_SHRINK, 0, 0);
312
313         gtk_widget_show(column_lb);
314
315         col_arrows[i].ascend_pm = xpm_to_widget(clist_ascend_xpm);
316
317         gtk_table_attach(GTK_TABLE(col_arrows[i].table), col_arrows[i].ascend_pm,
318         1, 2, 1, 2, GTK_SHRINK, GTK_SHRINK, 0, 0);
319
320         col_arrows[i].descend_pm = xpm_to_widget(clist_descend_xpm);
321
322         gtk_table_attach(GTK_TABLE(col_arrows[i].table), col_arrows[i].descend_pm,
323         1, 2, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0);
324
325         if (i == 0)
326         {
327             /* default column sorting */
328             gtk_widget_show(col_arrows[i].ascend_pm);
329         }
330
331         gtk_clist_set_column_widget(GTK_CLIST(dlg_p->table), i, col_arrows[i].table);
332         gtk_widget_show(col_arrows[i].table);
333     }
334     gtk_clist_column_titles_show(GTK_CLIST(dlg_p->table));
335
336     gtk_clist_set_compare_func(GTK_CLIST(dlg_p->table), ansi_a_stat_gtk_sort_column);
337     gtk_clist_set_sort_column(GTK_CLIST(dlg_p->table), 0);
338     gtk_clist_set_sort_type(GTK_CLIST(dlg_p->table), GTK_SORT_ASCENDING);
339
340     gtk_clist_set_column_width(GTK_CLIST(dlg_p->table), 0, 50);
341     gtk_clist_set_column_width(GTK_CLIST(dlg_p->table), 1, 280);
342     gtk_clist_set_column_width(GTK_CLIST(dlg_p->table), 2, 50);
343
344     gtk_clist_set_shadow_type(GTK_CLIST(dlg_p->table), GTK_SHADOW_IN);
345     gtk_clist_column_titles_show(GTK_CLIST(dlg_p->table));
346     gtk_container_add(GTK_CONTAINER(dlg_p->scrolled_win), dlg_p->table);
347
348     SIGNAL_CONNECT(dlg_p->table, "click-column", ansi_a_stat_gtk_click_column_cb, col_arrows);
349
350         /* Button row. */
351     bbox = dlg_button_row_new(GTK_STOCK_CLOSE, NULL);
352         gtk_box_pack_start(GTK_BOX(vbox), bbox, FALSE, FALSE, 0);
353
354     bt_close = OBJECT_GET_DATA(bbox, GTK_STOCK_CLOSE);
355     window_set_cancel_button(dlg_p->win, bt_close, window_cancel_button_cb);
356
357     SIGNAL_CONNECT(dlg_p->win, "delete_event", window_delete_event_cb, NULL);
358     SIGNAL_CONNECT(dlg_p->win, "destroy", ansi_a_stat_gtk_win_destroy_cb, dlg_p);
359
360     gtk_widget_show_all(dlg_p->win);
361     window_present(dlg_p->win);
362 }
363
364
365 /*
366  * Never gets called ?
367  */
368 static void
369 ansi_a_stat_gtk_init(
370     const char          *optarg _U_)
371 {
372     /* does not appear to be called */
373 }
374
375
376 static void
377 ansi_a_stat_gtk_bsmap_cb(
378     GtkWidget           *w _U_,
379     gpointer            d _U_)
380 {
381     int                 i;
382     char                str[100];
383
384
385     /*
386      * if the window is already open, bring it to front
387      */
388     if (dlg_bsmap.win)
389     {
390         gdk_window_raise(dlg_bsmap.win->window);
391         return;
392     }
393
394     ansi_a_stat_gtk_win_create(&dlg_bsmap, "ANSI A-I/F BSMAP Statistics");
395
396     i = 0;
397     while (ansi_a_ios401_bsmap_strings[i].strptr)
398     {
399         g_snprintf(str, 100, "0x%02x", ansi_a_ios401_bsmap_strings[i].value);
400         dlg_bsmap.entries[0] = g_strdup(str);
401
402         dlg_bsmap.entries[1] = g_strdup(ansi_a_ios401_bsmap_strings[i].strptr);
403
404         dlg_bsmap.entries[2] = g_strdup("0");
405
406         gtk_clist_insert(GTK_CLIST(dlg_bsmap.table), i, dlg_bsmap.entries);
407         gtk_clist_set_row_data(GTK_CLIST(dlg_bsmap.table), i, (gpointer) i);
408
409         i++;
410     }
411
412     ansi_a_stat_draw(&stat);
413 }
414
415
416 static void
417 ansi_a_stat_gtk_dtap_cb(
418     GtkWidget           *w _U_,
419     gpointer            d _U_)
420 {
421     int                 i;
422     char                str[100];
423
424
425     /*
426      * if the window is already open, bring it to front
427      */
428     if (dlg_dtap.win)
429     {
430         gdk_window_raise(dlg_dtap.win->window);
431         return;
432     }
433
434     ansi_a_stat_gtk_win_create(&dlg_dtap, "ANSI A-I/F DTAP Statistics");
435
436     i = 0;
437     while (ansi_a_ios401_dtap_strings[i].strptr)
438     {
439         g_snprintf(str, 100, "0x%02x", ansi_a_ios401_dtap_strings[i].value);
440         dlg_dtap.entries[0] = g_strdup(str);
441
442         dlg_dtap.entries[1] = g_strdup(ansi_a_ios401_dtap_strings[i].strptr);
443
444         dlg_dtap.entries[2] = g_strdup("0");
445
446         gtk_clist_insert(GTK_CLIST(dlg_dtap.table), i, dlg_dtap.entries);
447         gtk_clist_set_row_data(GTK_CLIST(dlg_dtap.table), i, (gpointer) i);
448
449         i++;
450     }
451
452     ansi_a_stat_draw(&stat);
453 }
454
455
456 void
457 register_tap_listener_gtkansi_a_stat(void)
458 {
459     GString             *err_p;
460
461
462     register_stat_cmd_arg("ansi_a,", ansi_a_stat_gtk_init);
463
464     memset((void *) &stat, 0, sizeof(ansi_a_stat_t));
465
466     err_p =
467         register_tap_listener("ansi_a", &stat, NULL,
468             ansi_a_stat_reset,
469             ansi_a_stat_packet,
470             ansi_a_stat_draw);
471
472     if (err_p != NULL)
473     {
474         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, err_p->str);
475         g_string_free(err_p, TRUE);
476
477         exit(1);
478     }
479
480     register_stat_menu_item("ANSI/A-Interface BSMAP", REGISTER_STAT_GROUP_TELEPHONY, 
481         ansi_a_stat_gtk_bsmap_cb, NULL, NULL ,NULL);
482     register_stat_menu_item("ANSI/A-Interface DTAP", REGISTER_STAT_GROUP_TELEPHONY,
483         ansi_a_stat_gtk_dtap_cb, NULL, NULL ,NULL);
484 }