2 * wsp_stat 2003 Jean-Michel FAYARD
4 * $Id: wsp_stat.c,v 1.11 2004/01/10 16:27:43 ulfl Exp $
6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@ethereal.com>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 /* #define DEBUG do{ printf("%s:%d ",__FILE__,__LINE__);} while(0); */
34 #include "epan/packet_info.h"
35 #include "epan/epan.h"
37 #include "simple_dialog.h"
38 #include "dlg_utils.h"
40 #include "../register.h"
41 #include "../globals.h"
42 #include "compat_macros.h"
43 #include "../packet-wsp.h"
45 /* used to keep track of the stats for a specific PDU type*/
46 typedef struct _wsp_pdu_t {
51 /* used to keep track of the statictics for an entire program interface */
52 typedef struct _wsp_stats_t {
58 GtkWidget *table_pdu_types;
59 GtkWidget *table_status_code;
60 guint index; /* Number of status code to display */
62 /* used to keep track of a single type of status code */
63 typedef struct _wsp_status_code_t {
66 GtkWidget *widget;/* label in which we print the number of packets */
67 wspstat_t *sp; /* entire program interface */
70 static GtkWidget *dlg=NULL;
71 static GtkWidget *filter_entry;
74 wsp_free_hash( gpointer key, gpointer value, gpointer user_data _U_ )
80 wsp_reset_hash(gchar *key _U_ , wsp_status_code_t *data, gpointer ptr _U_ )
85 /* Update the entry corresponding to the number of packets of a special status code
86 * or create it if it don't exist.
89 wsp_draw_statuscode(gchar *key _U_, wsp_status_code_t *data, gchar * string_buff )
91 if ((data==NULL) || (data->packets==0))
93 if (data->widget==NULL){ /* create an entry in the table */
95 int x = 2*((data->sp->index) % 2);
96 int y = (data->sp->index) /2;
99 /* Maybe we should display the hexadecimal value ? */
100 /* sprintf(string_buff, "%s (0X%x)", data->name, *key); */
101 tmp = gtk_label_new( data->name /* string_buff */ );
102 gtk_table_attach_defaults(GTK_TABLE(data->sp->table_status_code), tmp, x, x+1, y, y+1);
103 gtk_label_set_justify(GTK_LABEL(tmp), GTK_JUSTIFY_LEFT);
104 gtk_widget_show(tmp);
106 sprintf( string_buff, "%9d", data->packets );
107 data->widget = gtk_label_new( string_buff );
108 gtk_table_attach_defaults(GTK_TABLE(data->sp->table_status_code), data->widget, x+1, x+2, y, y+1);
109 gtk_label_set_justify(GTK_LABEL(data->widget), GTK_JUSTIFY_LEFT);
110 gtk_widget_show( data->widget );
114 /* Just update the label string */
115 sprintf( string_buff, "%9d", data->packets );
116 gtk_label_set( GTK_LABEL(data->widget), string_buff);
120 wspstat_reset(void *psp)
125 for(i=1;i<=sp->num_pdus;i++)
127 sp->pdu_stats[i].packets=0;
129 g_hash_table_foreach( sp->hash, (GHFunc)wsp_reset_hash, NULL);
132 pdut2index(gint pdut)
134 if (pdut<=0x09) return pdut;
138 } else if (pdut==0x60||pdut==0x61){
145 index2pdut(gint pdut)
157 wspstat_packet(void *psp, packet_info *pinfo _U_, epan_dissect_t *edt _U_, void *pri)
160 wsp_info_value_t *value=pri;
161 gint index = pdut2index(value->pdut);
164 if (value->status_code != 0) {
165 gint *key=g_malloc( sizeof(gint) );
166 wsp_status_code_t *sc;
167 *key=value->status_code ;
168 sc = g_hash_table_lookup(
172 g_warning("%s:%d What's Wrong, doc ?\n", __FILE__, __LINE__);
173 sc = g_malloc( sizeof(wsp_status_code_t) );
191 sp->pdu_stats[ index ].packets++;
201 wspstat_draw(void *psp)
208 for(i=1;i<=sp->num_pdus ; i++)
210 sprintf(str, "%9d", sp->pdu_stats[i ].packets);
211 gtk_label_set( GTK_LABEL(sp->pdu_stats[i].widget), str);
215 g_hash_table_foreach( sp->hash, (GHFunc) wsp_draw_statuscode, str );
216 if (index != sp->index){
217 /* We have inserted a new entry corresponding to a status code ,
218 * let's resize the table */
219 gtk_table_resize ( GTK_TABLE(sp->table_status_code), sp->index % 2 , 4);
226 /* since the gtk2 implementation of tap is multithreaded we must protect
227 * remove_tap_listener() from modifying the list while draw_tap_listener()
228 * is running. the other protected block is in main.c
230 * there should not be any other critical regions in gtk2
232 void protect_thread_critical_region(void);
233 void unprotect_thread_critical_region(void);
235 win_destroy_cb(GtkWindow *win _U_, gpointer data)
237 wspstat_t *sp=(wspstat_t *)data;
239 protect_thread_critical_region();
240 remove_tap_listener(sp);
241 unprotect_thread_critical_region();
243 g_free(sp->pdu_stats);
245 g_hash_table_foreach( sp->hash, (GHFunc)wsp_free_hash, NULL);
246 g_hash_table_destroy( sp->hash);
251 add_table_entry(wspstat_t *sp, char *str, int x, int y, int index)
255 tmp=gtk_label_new( str );
256 gtk_table_attach_defaults(GTK_TABLE(sp->table_pdu_types), tmp, x, x+1, y, y+1);
257 gtk_label_set_justify(GTK_LABEL(tmp), GTK_JUSTIFY_LEFT);
258 gtk_widget_show(tmp);
260 sp->pdu_stats [index] .widget = GTK_LABEL( tmp ) ;
266 wsp_init_table(wspstat_t *sp)
270 /* gchar buffer[51]; */
272 add_table_entry( sp, "PDU Type " , 0, pos, 0);
273 add_table_entry( sp, "packets " , 1, pos, 0);
274 add_table_entry( sp, "PDU Type " , 2, pos, 0);
275 add_table_entry( sp, "packets " , 3, pos, 0);
277 for (i=1 ; i <= sp->num_pdus ; i++ )
280 if (i> (sp->num_pdus+1) /2 ){
283 /* Maybe we should display the hexadecimal value ? */
284 /* snprintf(buffer, 50, "%s (0X%x)", match_strval( index2pdut( i ), vals_pdu_type), index2pdut(i) );*/
286 match_strval(index2pdut(i), vals_pdu_type), /* or buffer, */
291 add_table_entry( sp, "0", x+1, pos
292 , i /* keep a pointer to this widget to update it in _draw() */
295 if (i== (sp->num_pdus+1) /2) {
301 /* When called, this function will create a new instance of gtk2-wspstat.
304 gtk_wspstat_init(char *optarg)
309 GString *error_string;
310 GtkWidget *main_vb, *pdutypes_fr, *statuscode_fr ;
312 wsp_status_code_t *sc;
315 if (!strncmp (optarg, "wsp,stat,", 9)){
321 sp = g_malloc( sizeof(wspstat_t) );
322 sp->hash = g_hash_table_new( g_int_hash, g_int_equal);
323 for (i=0 ; vals_status[i].strptr ; i++ )
326 sc=g_malloc( sizeof(wsp_status_code_t) );
327 key=g_malloc( sizeof(gint) );
328 sc->name=vals_status[i].strptr;
332 *key=vals_status[i].value;
339 sp->pdu_stats=g_malloc( (sp->num_pdus+1) * sizeof( wsp_pdu_t) );
341 sp->filter=g_malloc(strlen(filter)+1);
342 strcpy(sp->filter,filter);
343 title=g_strdup_printf("Ethereal: WSP statistics with filter: %s", filter);
346 title=g_strdup("Ethereal: WSP statistics");
348 for (i=0;i<=sp->num_pdus; i++)
350 sp->pdu_stats[i].packets=0;
353 sp->win = gtk_window_new( GTK_WINDOW_TOPLEVEL);
354 gtk_window_set_title( GTK_WINDOW(sp->win), title );
356 SIGNAL_CONNECT( sp->win, "destroy", win_destroy_cb, sp);
359 /* container for the two frames */
360 main_vb = gtk_vbox_new(FALSE, 10);
361 gtk_container_border_width(GTK_CONTAINER(main_vb), 10);
362 gtk_container_add(GTK_CONTAINER(sp->win), main_vb);
363 gtk_widget_show(main_vb);
365 /* PDU Types frame */
366 pdutypes_fr = gtk_frame_new("Summary of PDU Types (wsp.pdu_type)");
367 gtk_container_add(GTK_CONTAINER(main_vb), pdutypes_fr);
368 gtk_widget_show(pdutypes_fr);
370 sp->table_pdu_types = gtk_table_new( (sp->num_pdus+1) / 2 + 1, 4, FALSE);
371 gtk_container_add( GTK_CONTAINER( pdutypes_fr), sp->table_pdu_types);
372 gtk_container_set_border_width( GTK_CONTAINER(sp->table_pdu_types) , 10);
375 gtk_widget_show( sp->table_pdu_types );
377 /* Status Codes frame */
378 statuscode_fr = gtk_frame_new("Summary of Status Code (wsp.reply.status)");
379 gtk_container_add(GTK_CONTAINER(main_vb), statuscode_fr);
380 gtk_widget_show(statuscode_fr);
382 sp->table_status_code = gtk_table_new( 0, 4, FALSE);
383 gtk_container_add( GTK_CONTAINER( statuscode_fr), sp->table_status_code);
384 gtk_container_set_border_width( GTK_CONTAINER(sp->table_status_code) , 10);
385 sp->index = 0; /* No answers to display yet */
388 error_string = register_tap_listener(
396 /* error, we failed to attach to the tap. clean up */
397 simple_dialog( ESD_TYPE_WARN, NULL, error_string->str );
398 g_free(sp->pdu_stats);
401 g_string_free(error_string, TRUE);
404 gtk_widget_show_all( sp->win );
405 redissect_packets(&cfile);
411 wspstat_start_button_clicked(GtkWidget *item _U_, gpointer data _U_)
416 str = g_string_new("wsp,stat,");
417 filter=(char *)gtk_entry_get_text(GTK_ENTRY(filter_entry));
418 str = g_string_append(str, filter);
419 gtk_wspstat_init(str->str);
420 g_string_free(str, TRUE);
430 dlg_cancel_cb(GtkWidget *cancel_bt _U_, gpointer parent_w)
432 gtk_widget_destroy(GTK_WIDGET(parent_w));
436 gtk_wspstat_cb(GtkWidget *w _U_, gpointer d _U_)
439 GtkWidget *filter_box, *filter_label;
440 GtkWidget *bbox, *start_button, *cancel_button;
442 /* if the window is already open, bring it to front */
444 gdk_window_raise(dlg->window);
448 dlg=dlg_window_new("Ethereal: Compute WSP statistics");
449 SIGNAL_CONNECT(dlg, "destroy", dlg_destroy_cb, NULL);
451 dlg_box=gtk_vbox_new(FALSE, 10);
452 gtk_container_border_width(GTK_CONTAINER(dlg_box), 10);
453 gtk_container_add(GTK_CONTAINER(dlg), dlg_box);
454 gtk_widget_show(dlg_box);
457 filter_box=gtk_hbox_new(FALSE, 3);
460 filter_label=gtk_label_new("Filter:");
461 gtk_box_pack_start(GTK_BOX(filter_box), filter_label, FALSE, FALSE, 0);
462 gtk_widget_show(filter_label);
465 filter_entry=gtk_entry_new();
466 WIDGET_SET_SIZE(filter_entry, 300, -2);
467 gtk_box_pack_start(GTK_BOX(filter_box), filter_entry, TRUE, TRUE, 0);
468 gtk_widget_show(filter_entry);
470 gtk_box_pack_start(GTK_BOX(dlg_box), filter_box, TRUE, TRUE, 0);
471 gtk_widget_show(filter_box);
474 bbox = gtk_hbutton_box_new();
475 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_DEFAULT_STYLE);
476 gtk_button_box_set_spacing(GTK_BUTTON_BOX(bbox), 5);
477 gtk_box_pack_start(GTK_BOX(dlg_box), bbox, FALSE, FALSE, 0);
478 gtk_widget_show(bbox);
480 /* the start button */
481 start_button=gtk_button_new_with_label("Create Stat");
482 SIGNAL_CONNECT_OBJECT(start_button, "clicked",
483 wspstat_start_button_clicked, NULL);
484 gtk_box_pack_start(GTK_BOX(bbox), start_button, TRUE, TRUE, 0);
485 GTK_WIDGET_SET_FLAGS(start_button, GTK_CAN_DEFAULT);
486 gtk_widget_grab_default(start_button);
487 gtk_widget_show(start_button);
489 cancel_button=BUTTON_NEW_FROM_STOCK(GTK_STOCK_CANCEL);
490 SIGNAL_CONNECT(cancel_button, "clicked", dlg_cancel_cb, dlg);
491 GTK_WIDGET_SET_FLAGS(cancel_button, GTK_CAN_DEFAULT);
492 gtk_box_pack_start(GTK_BOX(bbox), cancel_button, TRUE, TRUE, 0);
493 gtk_widget_show(cancel_button);
495 /* Catch the "activate" signal on the filter text entry, so that
496 if the user types Return there, we act as if the "Create Stat"
497 button had been selected, as happens if Return is typed if
498 some widget that *doesn't* handle the Return key has the input
500 dlg_set_activate(filter_entry, start_button);
502 /* Catch the "key_press_event" signal in the window, so that we can
503 catch the ESC key being pressed and act as if the "Cancel" button
504 had been selected. */
505 dlg_set_cancel(dlg, cancel_button);
507 /* Give the initial focus to the "Filter" entry box. */
508 gtk_widget_grab_focus(filter_entry);
510 gtk_widget_show_all(dlg);
515 register_tap_listener_gtkwspstat(void)
517 register_ethereal_tap("wsp,stat,", gtk_wspstat_init);
521 register_tap_menu_gtkwspstat(void)
523 register_tap_menu_item("_Statistics/Watch protocol/WAP-WSP...",
524 gtk_wspstat_cb, NULL, NULL, NULL);