2 * wsp_stat 2003 Jean-Michel FAYARD
4 * $Id: wsp_stat.c,v 1.6 2003/12/13 17:10:21 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); */
31 #include "epan/packet_info.h"
32 #include "epan/epan.h"
33 #include "simple_dialog.h"
34 #include "dlg_utils.h"
36 #include "../register.h"
37 #include "../globals.h"
38 #include "compat_macros.h"
39 #include "../packet-wsp.h"
42 /* used to keep track of the stats for a specific PDU type*/
43 typedef struct _wsp_pdu_t {
48 /* used to keep track of the statictics for an entire program interface */
49 typedef struct _wsp_stats_t {
55 GtkWidget *table_pdu_types;
56 GtkWidget *table_status_code;
57 guint index; /* Number of status code to display */
59 /* used to keep track of a single type of status code */
60 typedef struct _wsp_status_code_t {
63 GtkWidget *widget;/* label in which we print the number of packets */
64 wspstat_t *sp; /* entire program interface */
67 static GtkWidget *dlg=NULL;
68 static GtkWidget *filter_entry;
71 wsp_free_hash( gpointer key, gpointer value, gpointer user_data _U_ )
77 wsp_reset_hash(gchar *key _U_ , wsp_status_code_t *data, gpointer ptr _U_ )
82 /* Update the entry corresponding to the number of packets of a special status code
83 * or create it if it don't exist.
86 wsp_draw_statuscode(gchar *key _U_, wsp_status_code_t *data, gchar * string_buff )
88 if ((data==NULL) || (data->packets==0))
90 if (data->widget==NULL){ /* create an entry in the table */
92 int x = 2*((data->sp->index) % 2);
93 int y = (data->sp->index) /2;
96 /* Maybe we should display the hexadecimal value ? */
97 /* sprintf(string_buff, "%s (0X%x)", data->name, *key); */
98 tmp = gtk_label_new( data->name /* string_buff */ );
99 gtk_table_attach_defaults(GTK_TABLE(data->sp->table_status_code), tmp, x, x+1, y, y+1);
100 gtk_label_set_justify(GTK_LABEL(tmp), GTK_JUSTIFY_LEFT);
101 gtk_widget_show(tmp);
103 sprintf( string_buff, "%9d", data->packets );
104 data->widget = gtk_label_new( string_buff );
105 gtk_table_attach_defaults(GTK_TABLE(data->sp->table_status_code), data->widget, x+1, x+2, y, y+1);
106 gtk_label_set_justify(GTK_LABEL(data->widget), GTK_JUSTIFY_LEFT);
107 gtk_widget_show( data->widget );
111 /* Just update the label string */
112 sprintf( string_buff, "%9d", data->packets );
113 gtk_label_set( GTK_LABEL(data->widget), string_buff);
117 wspstat_reset(void *psp)
122 for(i=1;i<=sp->num_pdus;i++)
124 sp->pdu_stats[i].packets=0;
126 g_hash_table_foreach( sp->hash, (GHFunc)wsp_reset_hash, NULL);
129 pdut2index(gint pdut)
131 if (pdut<=0x09) return pdut;
135 } else if (pdut==0x60||pdut==0x61){
142 index2pdut(gint pdut)
154 wspstat_packet(void *psp, packet_info *pinfo _U_, epan_dissect_t *edt _U_, void *pri)
157 wsp_info_value_t *value=pri;
158 gint index = pdut2index(value->pdut);
161 if (value->status_code != 0) {
162 gint *key=g_malloc( sizeof(gint) );
163 wsp_status_code_t *sc;
164 *key=value->status_code ;
165 sc = g_hash_table_lookup(
169 g_warning("%s:%d What's Wrong, doc ?\n", __FILE__, __LINE__);
170 sc = g_malloc( sizeof(wsp_status_code_t) );
188 sp->pdu_stats[ index ].packets++;
198 wspstat_draw(void *psp)
205 for(i=1;i<=sp->num_pdus ; i++)
207 sprintf(str, "%9d", sp->pdu_stats[i ].packets);
208 gtk_label_set( GTK_LABEL(sp->pdu_stats[i].widget), str);
212 g_hash_table_foreach( sp->hash, (GHFunc) wsp_draw_statuscode, str );
213 if (index != sp->index){
214 /* We have inserted a new entry corresponding to a status code ,
215 * let's resize the table */
216 gtk_table_resize ( GTK_TABLE(sp->table_status_code), sp->index % 2 , 4);
223 /* since the gtk2 implementation of tap is multithreaded we must protect
224 * remove_tap_listener() from modifying the list while draw_tap_listener()
225 * is running. the other protected block is in main.c
227 * there should not be any other critical regions in gtk2
229 void protect_thread_critical_region(void);
230 void unprotect_thread_critical_region(void);
232 win_destroy_cb(GtkWindow *win _U_, gpointer data)
234 wspstat_t *sp=(wspstat_t *)data;
236 protect_thread_critical_region();
237 remove_tap_listener(sp);
238 unprotect_thread_critical_region();
240 g_free(sp->pdu_stats);
242 g_hash_table_foreach( sp->hash, (GHFunc)wsp_free_hash, NULL);
243 g_hash_table_destroy( sp->hash);
248 add_table_entry(wspstat_t *sp, char *str, int x, int y, int index)
252 tmp=gtk_label_new( str );
253 gtk_table_attach_defaults(GTK_TABLE(sp->table_pdu_types), tmp, x, x+1, y, y+1);
254 gtk_label_set_justify(GTK_LABEL(tmp), GTK_JUSTIFY_LEFT);
255 gtk_widget_show(tmp);
257 sp->pdu_stats [index] .widget = GTK_LABEL( tmp ) ;
263 wsp_init_table(wspstat_t *sp)
267 /* gchar buffer[51]; */
269 add_table_entry( sp, "PDU Type " , 0, pos, 0);
270 add_table_entry( sp, "packets " , 1, pos, 0);
271 add_table_entry( sp, "PDU Type " , 2, pos, 0);
272 add_table_entry( sp, "packets " , 3, pos, 0);
274 for (i=1 ; i <= sp->num_pdus ; i++ )
277 if (i> (sp->num_pdus+1) /2 ){
280 /* Maybe we should display the hexadecimal value ? */
281 /* snprintf(buffer, 50, "%s (0X%x)", match_strval( index2pdut( i ), vals_pdu_type), index2pdut(i) );*/
283 match_strval(index2pdut(i), vals_pdu_type), /* or buffer, */
288 add_table_entry( sp, "0", x+1, pos
289 , i /* keep a pointer to this widget to update it in _draw() */
292 if (i== (sp->num_pdus+1) /2) {
298 /* When called, this function will create a new instance of gtk2-wspstat.
301 gtk_wspstat_init(char *optarg)
306 GString *error_string;
307 GtkWidget *main_vb, *pdutypes_fr, *statuscode_fr ;
309 wsp_status_code_t *sc;
312 if (!strncmp (optarg, "wsp,stat,", 9)){
318 sp = g_malloc( sizeof(wspstat_t) );
319 sp->hash = g_hash_table_new( g_int_hash, g_int_equal);
320 for (i=0 ; vals_status[i].strptr ; i++ )
323 sc=g_malloc( sizeof(wsp_status_code_t) );
324 key=g_malloc( sizeof(gint) );
325 sc->name=vals_status[i].strptr;
329 *key=vals_status[i].value;
336 sp->pdu_stats=g_malloc( (sp->num_pdus+1) * sizeof( wsp_pdu_t) );
338 sp->filter=g_malloc(strlen(filter)+1);
339 strcpy(sp->filter,filter);
340 title=g_strdup_printf("Ethereal: WSP statistics with filter: %s", filter);
343 title=g_strdup("Ethereal: WSP statistics");
345 for (i=0;i<=sp->num_pdus; i++)
347 sp->pdu_stats[i].packets=0;
350 sp->win = gtk_window_new( GTK_WINDOW_TOPLEVEL);
351 gtk_window_set_title( GTK_WINDOW(sp->win), title );
353 SIGNAL_CONNECT( sp->win, "destroy", win_destroy_cb, sp);
356 /* container for the two frames */
357 main_vb = gtk_vbox_new(FALSE, 10);
358 gtk_container_border_width(GTK_CONTAINER(main_vb), 10);
359 gtk_container_add(GTK_CONTAINER(sp->win), main_vb);
360 gtk_widget_show(main_vb);
362 /* PDU Types frame */
363 pdutypes_fr = gtk_frame_new("Summary of PDU Types (wsp.pdu_type)");
364 gtk_container_add(GTK_CONTAINER(main_vb), pdutypes_fr);
365 gtk_widget_show(pdutypes_fr);
367 sp->table_pdu_types = gtk_table_new( (sp->num_pdus+1) / 2 + 1, 4, FALSE);
368 gtk_container_add( GTK_CONTAINER( pdutypes_fr), sp->table_pdu_types);
369 gtk_container_set_border_width( GTK_CONTAINER(sp->table_pdu_types) , 10);
372 gtk_widget_show( sp->table_pdu_types );
374 /* Status Codes frame */
375 statuscode_fr = gtk_frame_new("Summary of Status Code (wsp.reply.status)");
376 gtk_container_add(GTK_CONTAINER(main_vb), statuscode_fr);
377 gtk_widget_show(statuscode_fr);
379 sp->table_status_code = gtk_table_new( 0, 4, FALSE);
380 gtk_container_add( GTK_CONTAINER( statuscode_fr), sp->table_status_code);
381 gtk_container_set_border_width( GTK_CONTAINER(sp->table_status_code) , 10);
382 sp->index = 0; /* No answers to display yet */
385 error_string = register_tap_listener(
393 /* error, we failed to attach to the tap. clean up */
394 simple_dialog( ESD_TYPE_WARN, NULL, error_string->str );
395 g_free(sp->pdu_stats);
398 g_string_free(error_string, TRUE);
401 gtk_widget_show_all( sp->win );
402 redissect_packets(&cfile);
408 wspstat_start_button_clicked(GtkWidget *item _U_, gpointer data _U_)
413 str = g_string_new("wsp,stat,");
414 filter=(char *)gtk_entry_get_text(GTK_ENTRY(filter_entry));
415 str = g_string_append(str, filter);
416 gtk_wspstat_init(str->str);
417 g_string_free(str, TRUE);
427 dlg_cancel_cb(GtkWidget *cancel_bt _U_, gpointer parent_w)
429 gtk_widget_destroy(GTK_WIDGET(parent_w));
433 gtk_wspstat_cb(GtkWidget *w _U_, gpointer d _U_)
436 GtkWidget *filter_box, *filter_label;
437 GtkWidget *bbox, *start_button, *cancel_button;
439 /* if the window is already open, bring it to front */
441 gdk_window_raise(dlg->window);
445 dlg=dlg_window_new("Ethereal: Compute WSP statistics");
446 SIGNAL_CONNECT(dlg, "destroy", dlg_destroy_cb, NULL);
448 dlg_box=gtk_vbox_new(FALSE, 10);
449 gtk_container_border_width(GTK_CONTAINER(dlg_box), 10);
450 gtk_container_add(GTK_CONTAINER(dlg), dlg_box);
451 gtk_widget_show(dlg_box);
454 filter_box=gtk_hbox_new(FALSE, 3);
457 filter_label=gtk_label_new("Filter:");
458 gtk_box_pack_start(GTK_BOX(filter_box), filter_label, FALSE, FALSE, 0);
459 gtk_widget_show(filter_label);
462 filter_entry=gtk_entry_new();
463 gtk_widget_set_usize(filter_entry, 300, -2);
464 gtk_box_pack_start(GTK_BOX(filter_box), filter_entry, TRUE, TRUE, 0);
465 gtk_widget_show(filter_entry);
467 gtk_box_pack_start(GTK_BOX(dlg_box), filter_box, TRUE, TRUE, 0);
468 gtk_widget_show(filter_box);
471 bbox = gtk_hbutton_box_new();
472 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_DEFAULT_STYLE);
473 gtk_button_box_set_spacing(GTK_BUTTON_BOX(bbox), 5);
474 gtk_box_pack_start(GTK_BOX(dlg_box), bbox, FALSE, FALSE, 0);
475 gtk_widget_show(bbox);
477 /* the start button */
478 start_button=gtk_button_new_with_label("Create Stat");
479 SIGNAL_CONNECT_OBJECT(start_button, "clicked",
480 wspstat_start_button_clicked, NULL);
481 gtk_box_pack_start(GTK_BOX(bbox), start_button, TRUE, TRUE, 0);
482 GTK_WIDGET_SET_FLAGS(start_button, GTK_CAN_DEFAULT);
483 gtk_widget_grab_default(start_button);
484 gtk_widget_show(start_button);
486 #if GTK_MAJOR_VERSION < 2
487 cancel_button=gtk_button_new_with_label("Cancel");
489 cancel_button=gtk_button_new_from_stock(GTK_STOCK_CANCEL);
491 SIGNAL_CONNECT(cancel_button, "clicked", dlg_cancel_cb, dlg);
492 GTK_WIDGET_SET_FLAGS(cancel_button, GTK_CAN_DEFAULT);
493 gtk_box_pack_start(GTK_BOX(bbox), cancel_button, TRUE, TRUE, 0);
494 gtk_widget_show(cancel_button);
496 /* Catch the "activate" signal on the filter text entry, so that
497 if the user types Return there, we act as if the "Create Stat"
498 button had been selected, as happens if Return is typed if
499 some widget that *doesn't* handle the Return key has the input
501 dlg_set_activate(filter_entry, start_button);
503 /* Catch the "key_press_event" signal in the window, so that we can
504 catch the ESC key being pressed and act as if the "Cancel" button
505 had been selected. */
506 dlg_set_cancel(dlg, cancel_button);
508 /* Give the initial focus to the "Filter" entry box. */
509 gtk_widget_grab_focus(filter_entry);
511 gtk_widget_show_all(dlg);
516 register_tap_listener_gtkwspstat(void)
518 register_ethereal_tap("wsp,stat,", gtk_wspstat_init);
522 register_tap_menu_gtkwspstat(void)
524 register_tap_menu_item("Statistics/Watch protocol/WAP-WSP...",
525 gtk_wspstat_cb, NULL, NULL);