Convert the MTP3 stats to new "generic stat API".
[metze/wireshark/wip.git] / ui / gtk / wsp_stat.c
1 /* wsp_stat.c
2  * wsp_stat   2003 Jean-Michel FAYARD
3  *
4  * Wireshark - Network traffic analyzer
5  * By Gerald Combs <gerald@wireshark.org>
6  * Copyright 1998 Gerald Combs
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21  */
22
23 /* #define DEBUG        do{ printf("%s:%d  ",__FILE__,__LINE__);} while(0); */
24 #include "config.h"
25 #include <string.h>
26
27 #include <gtk/gtk.h>
28
29 #include <epan/packet.h>
30 #include <epan/tap.h>
31 #include <epan/dissectors/packet-wsp.h>
32
33 #include "ui/simple_dialog.h"
34
35 #include "ui/gtk/gui_utils.h"
36 #include "ui/gtk/dlg_utils.h"
37 #include "ui/gtk/tap_param_dlg.h"
38 #include "ui/gtk/main.h"
39
40
41 void register_tap_listener_gtkwspstat(void);
42
43 /* Used to keep track of the statistics for a specific PDU type */
44 typedef struct _wsp_pdu_t {
45         GtkLabel        *widget;
46         guint32          packets;
47 } wsp_pdu_t;
48
49 /* Used to keep track of the statistics for an entire program interface */
50 typedef struct _wsp_stats_t {
51         char            *filter;
52         wsp_pdu_t       *pdu_stats;
53         guint32          num_pdus;
54         GtkWidget       *win;
55         GHashTable      *hash;
56         GtkWidget       *grid_pdu_types;
57         GtkWidget       *grid_status_code;
58         guint            index; /* Number of status codes to display */
59 } wspstat_t;
60
61 /* Used to keep track of a single type of status code */
62 typedef struct _wsp_status_code_t {
63         const gchar     *name;
64         guint32          packets;
65         GtkWidget       *widget;/* label in which we print the number of packets */
66         wspstat_t       *sp;    /* entire program interface */
67 } wsp_status_code_t;
68
69 static void
70 wsp_reset_hash(gchar *key _U_ , wsp_status_code_t *data, gpointer ptr _U_)
71 {
72         data->packets = 0;
73 }
74
75 /* Update the entry corresponding to the number of packets of a special status code
76  * or create it if it doesn't exist.
77  */
78 static void
79 wsp_draw_statuscode(gchar *key _U_, wsp_status_code_t *data, gchar *unused _U_)
80 {
81         char string_buff[256];
82
83         if ((data == NULL) || (data->packets == 0))
84                 return;
85         if (data->widget == NULL) {     /* create an entry in the table */
86                 GtkWidget *tmp;
87                 int x = 2 * ((data->sp->index) % 2);
88                 int y = (data->sp->index) / 2;
89
90
91                 /* Maybe we should display the hexadecimal value ? */
92                 /* g_snprintf(string_buff, sizeof(string_buff), "%s  (0X%x)", data->name, *key); */
93                 tmp = gtk_label_new(data->name  /* string_buff */ );
94                 ws_gtk_grid_attach_defaults(GTK_GRID(data->sp->grid_status_code), tmp, x, y, 1, 1);
95                 gtk_label_set_justify(GTK_LABEL(tmp), GTK_JUSTIFY_LEFT);
96                 gtk_widget_show(tmp);
97
98                 g_snprintf(string_buff, sizeof(string_buff), "%9d", data->packets);
99                 data->widget = gtk_label_new(string_buff);
100                 ws_gtk_grid_attach_defaults(GTK_GRID(data->sp->grid_status_code), data->widget, x+1, y, 1, 1);
101                 gtk_label_set_justify(GTK_LABEL(data->widget), GTK_JUSTIFY_LEFT);
102                 gtk_widget_show(data->widget);
103
104                 data->sp->index++;
105         } else {
106                 /* Just update the label string */
107                 g_snprintf(string_buff, sizeof(string_buff), "%9d", data->packets);
108                 gtk_label_set_text(GTK_LABEL(data->widget), string_buff);
109         }
110 }
111 static void
112 wspstat_reset(void *psp)
113 {
114         wspstat_t *sp = (wspstat_t *)psp;
115         guint32    i;
116
117         for(i=1; i<=sp->num_pdus; i++)
118         {
119                 sp->pdu_stats[i].packets = 0;
120         }
121         g_hash_table_foreach(sp->hash, (GHFunc)wsp_reset_hash, NULL);
122 }
123
124 /* Fixme: !! Magic !! */
125 /* See wsp_vals_pdu_type in packet-wsp.c */
126 static gint
127 pdut2index(gint pdut)
128 {
129         if (pdut <= 0x09)
130                 return pdut;
131         if (pdut >= 0x40) {
132                 if (pdut <= 0x44) {
133                         return pdut-54;
134                 } else if ((pdut == 0x60) || (pdut == 0x61)) {
135                         return pdut-81;
136                 }
137         }
138         return 0;
139 }
140
141 /* Fixme: !! Magic !! */
142 /* See wsp_vals_pdu_type in packet-wsp.c */
143 static gint
144 index2pdut(gint pdut)
145 {
146         if (pdut <= 9)
147                 return pdut;
148         if (pdut <= 14)
149                 return pdut+54;
150         if (pdut <= 16)
151                 return pdut+81;
152         return 0;
153 }
154
155 static int
156 wspstat_packet(void *psp, packet_info *pinfo _U_, epan_dissect_t *edt _U_, const void *pri)
157 {
158         wspstat_t *sp = (wspstat_t *)psp;
159         const wsp_info_value_t *value = (const wsp_info_value_t *)pri;
160         gint       idx   = pdut2index(value->pdut);
161         gboolean   retour = FALSE;
162
163         if (value->status_code != 0) {
164                 wsp_status_code_t *sc;
165                 sc = (wsp_status_code_t *)g_hash_table_lookup(
166                         sp->hash,
167                         GINT_TO_POINTER(value->status_code));
168                 if (!sc) {
169                         g_warning("%s:%d What's Wrong, doc ?\n", __FILE__, __LINE__);
170                         sc = (wsp_status_code_t *)g_malloc(sizeof(wsp_status_code_t));
171                         sc -> packets = 1;
172                         sc -> name    = NULL;
173                         sc -> widget  = NULL;
174                         sc -> sp      = sp;
175                         g_hash_table_insert(
176                                 sp->hash,
177                                 GINT_TO_POINTER(value->status_code),
178                                 sc);
179                 } else {
180                         sc->packets++;
181                 }
182                 retour = TRUE;
183         }
184
185
186
187         if (idx != 0) {
188                 sp->pdu_stats[idx].packets++;
189                 retour = TRUE;
190         }
191         return retour;
192 }
193
194
195
196 static void
197 wspstat_draw(void *psp)
198 {
199         wspstat_t *sp = (wspstat_t *)psp;
200         guint32    i;
201         char       str[256];
202
203         for(i=1; i<=sp->num_pdus; i++)
204         {
205                 g_snprintf(str, sizeof(str), "%9d",  sp->pdu_stats[i].packets);
206                 gtk_label_set_text(GTK_LABEL(sp->pdu_stats[i].widget), str);
207         }
208
209         g_hash_table_foreach(sp->hash, (GHFunc)wsp_draw_statuscode, NULL);
210 }
211
212 static void
213 win_destroy_cb(GtkWindow *win _U_, gpointer data)
214 {
215         wspstat_t *sp = (wspstat_t *)data;
216
217         remove_tap_listener(sp);
218
219         g_free(sp->pdu_stats);
220         g_free(sp->filter);
221         g_hash_table_destroy(sp->hash);
222         g_free(sp);
223 }
224
225 static void
226 add_table_entry(wspstat_t *sp, const char *str, int x, int y, int idx)
227 {
228         GtkWidget *tmp;
229
230         tmp = gtk_label_new(str);
231         ws_gtk_grid_attach_defaults(GTK_GRID(sp->grid_pdu_types), tmp, x, y, 1, 1);
232         gtk_label_set_justify(GTK_LABEL(tmp), GTK_JUSTIFY_LEFT);
233         gtk_widget_show(tmp);
234         if (idx != 0) {
235                 sp->pdu_stats[idx].widget = GTK_LABEL(tmp);
236         }
237 }
238
239
240 static void
241 wsp_init_table(wspstat_t *sp)
242 {
243         int     pos = 0;
244         guint32 i;
245         /* gchar   buffer[51];  */
246
247         add_table_entry(sp, "PDU Type               ", 0, pos, 0);
248         add_table_entry(sp, "packets  "              , 1, pos, 0);
249         add_table_entry(sp, "PDU Type               ", 2, pos, 0);
250         add_table_entry(sp, "packets  "              , 3, pos, 0);
251         pos++;
252         for (i=1; i<=sp->num_pdus ;i++)
253         {
254                 int x = 0;
255                 if (i > (sp->num_pdus+1) / 2) {
256                         x = 2;
257                 }
258                 /* Maybe we should display the hexadecimal value ? */
259 #if 0
260                 g_snprintf(buffer, sizeof(buffer), "%s  (0X%x)",
261                            try_val_to_str_ext(index2pdut(i), &wsp_vals_pdu_type_ext), index2pdut(i));
262 #endif
263                 add_table_entry(sp,
264                                 try_val_to_str_ext(index2pdut(i), &wsp_vals_pdu_type_ext), /* or buffer, */
265                                 x,
266                                 pos,
267                                 0
268                                 );
269                 add_table_entry(sp,
270                                 "0",
271                                 x+1,
272                                 pos,
273                                 i /* keep a pointer to this widget to update it in _draw() */
274                                 );
275                 pos++;
276                 if (i == (sp->num_pdus+1) / 2) {
277                         pos = 1;
278                 }
279         }
280 }
281
282 /* When called, this function will create a new instance of gtk2-wspstat.
283  */
284 static void
285 gtk_wspstat_init(const char *opt_arg, void *userdata _U_)
286 {
287         wspstat_t  *sp;
288         const char *filter;
289         char       *title;
290         GString    *error_string;
291         GtkWidget  *main_vb, *pdutypes_fr, *statuscode_fr ;
292         GtkWidget  *bt_close;
293         GtkWidget  *bbox;
294         guint32     i;
295         wsp_status_code_t  *sc;
296         const value_string *wsp_vals_status_p;
297
298         if (strncmp(opt_arg, "wsp,stat,", 9) == 0) {
299                 filter = opt_arg+9;
300         } else {
301                 filter = NULL;
302         }
303
304         sp = (wspstat_t *)g_malloc(sizeof(wspstat_t));
305         sp->win = dlg_window_new("wsp-stat");  /* transient_for top_level */
306         gtk_window_set_destroy_with_parent(GTK_WINDOW(sp->win), TRUE);
307
308         sp->hash = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_free);
309         wsp_vals_status_p = VALUE_STRING_EXT_VS_P(&wsp_vals_status_ext);
310         for (i=0; wsp_vals_status_p[i].strptr; i++)
311         {
312                 sc  = (wsp_status_code_t *)g_malloc(sizeof(wsp_status_code_t));
313                 sc->name    = wsp_vals_status_p[i].strptr;
314                 sc->packets = 0;
315                 sc->widget  = NULL;
316                 sc->sp      = sp;
317                 g_hash_table_insert(
318                                 sp->hash,
319                                 GINT_TO_POINTER(wsp_vals_status_p[i].value),
320                                 sc);
321         }
322         sp->num_pdus  = 16;
323         sp->pdu_stats = (wsp_pdu_t *)g_malloc((sp->num_pdus+1) * sizeof(wsp_pdu_t));
324         if (filter) {
325                 sp->filter = g_strdup(filter);
326                 title = g_strdup_printf("Wireshark: WAP-WSP statistics with filter: %s", filter);
327         } else {
328                 sp->filter = NULL;
329                 title = g_strdup("Wireshark: WAP-WSP statistics");
330         }
331         for (i=0; i<=sp->num_pdus; i++)
332         {
333                 sp->pdu_stats[i].packets = 0;
334         }
335
336         gtk_window_set_title(GTK_WINDOW(sp->win), title);
337         g_free(title);
338
339         /* container for the two frames */
340         main_vb = ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 3, FALSE);
341         gtk_container_set_border_width(GTK_CONTAINER(main_vb), 12);
342         gtk_container_add(GTK_CONTAINER(sp->win), main_vb);
343
344         /* PDU Types frame */
345         pdutypes_fr = gtk_frame_new("Summary of PDU Types (wsp.pdu_type)");
346         gtk_box_pack_start(GTK_BOX(main_vb), pdutypes_fr, TRUE, TRUE, 0);
347
348         sp->grid_pdu_types = ws_gtk_grid_new();
349         gtk_container_add(GTK_CONTAINER(pdutypes_fr), sp->grid_pdu_types);
350         gtk_container_set_border_width(GTK_CONTAINER(sp->grid_pdu_types), 10);
351
352         wsp_init_table(sp);
353
354         /* Status Codes frame */
355         statuscode_fr = gtk_frame_new("Summary of Status Code (wsp.reply.status)");
356         gtk_box_pack_start(GTK_BOX(main_vb), statuscode_fr, FALSE, FALSE, 0);
357
358         sp->grid_status_code = ws_gtk_grid_new();
359         gtk_container_add(GTK_CONTAINER(statuscode_fr), sp->grid_status_code);
360         gtk_container_set_border_width(GTK_CONTAINER(sp->grid_status_code), 10);
361         sp->index = 0;          /* No answers to display yet */
362
363         error_string = register_tap_listener(
364                         "wsp",
365                         sp,
366                         filter,
367                         0,
368                         wspstat_reset,
369                         wspstat_packet,
370                         wspstat_draw);
371         if (error_string) {
372                 /* error, we failed to attach to the tap. clean up */
373                 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", error_string->str);
374                 g_free(sp->pdu_stats);
375                 g_free(sp->filter);
376                 g_free(sp);
377                 g_string_free(error_string, TRUE);
378                 return ;
379         }
380
381         /* Button row. */
382         bbox = dlg_button_row_new(GTK_STOCK_CLOSE, NULL);
383         gtk_box_pack_start(GTK_BOX(main_vb), bbox, FALSE, FALSE, 0);
384
385         bt_close = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CLOSE);
386         window_set_cancel_button(sp->win, bt_close, window_cancel_button_cb);
387
388         g_signal_connect(sp->win, "delete_event", G_CALLBACK(window_delete_event_cb), NULL);
389         g_signal_connect(sp->win, "destroy", G_CALLBACK(win_destroy_cb), sp);
390
391         gtk_widget_show_all(sp->win);
392         window_present(sp->win);
393
394         cf_retap_packets(&cfile);
395         gdk_window_raise(gtk_widget_get_window(sp->win));
396 }
397
398 static tap_param wsp_stat_params[] = {
399         { PARAM_FILTER, "filter", "Filter", NULL, TRUE }
400 };
401
402 static tap_param_dlg wsp_stat_dlg = {
403         "WAP-WSP Packet Counter",
404         "wsp,stat",
405         gtk_wspstat_init,
406         -1,
407         G_N_ELEMENTS(wsp_stat_params),
408         wsp_stat_params,
409         NULL
410 };
411
412 void
413 register_tap_listener_gtkwspstat(void)
414 {
415         register_param_stat(&wsp_stat_dlg, "_WAP-WSP",
416             REGISTER_STAT_GROUP_TELEPHONY);
417 }
418
419 /*
420  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
421  *
422  * Local variables:
423  * c-basic-offset: 8
424  * tab-width: 8
425  * indent-tabs-mode: t
426  * End:
427  *
428  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
429  * :indentSize=8:tabSize=8:noTabs=false:
430  */