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