Move the APIs for registering and processing "-z" command-line arguments
[obnox/wireshark/wip.git] / gtk / fc_stat.c
1 /* fc_stat.c
2  * fc_stat   2003 Ronnie Sahlberg
3  *
4  * $Id$
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@ethereal.com>
8  * Copyright 1998 Gerald Combs
9  *
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.
14  *
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.
19  *
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.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #ifdef HAVE_SYS_TYPES_H
30 # include <sys/types.h>
31 #endif
32
33 #include <string.h>
34
35 #include <gtk/gtk.h>
36
37 #include <epan/packet_info.h>
38 #include <epan/epan.h>
39 #include <epan/value_string.h>
40
41 #include "../stat.h"
42 #include "stat_menu.h"
43 #include <epan/tap.h>
44 #include <epan/dissectors/packet-fc.h>
45 #include "../register.h"
46 #include "../timestats.h"
47 #include "compat_macros.h"
48 #include "../simple_dialog.h"
49 #include "ui_util.h"
50 #include "dlg_utils.h"
51 #include "../file.h"
52 #include "../globals.h"
53 #include "filter_dlg.h"
54 #include "service_response_time_table.h"
55 #include "gtkglobals.h"
56
57
58 /* used to keep track of the statistics for an entire program interface */
59 typedef struct _fcstat_t {
60         GtkWidget *win;
61         srt_stat_table fc_srt_table;
62 } fcstat_t;
63
64 static void
65 fcstat_set_title(fcstat_t *fc)
66 {
67         char            *title;
68
69         title = g_strdup_printf("Fibre Channel Service Response Time statistics: %s",
70             cf_get_display_name(&cfile));
71         gtk_window_set_title(GTK_WINDOW(fc->win), title);
72         g_free(title);
73 }
74
75 static void
76 fcstat_reset(void *pfc)
77 {
78         fcstat_t *fc=(fcstat_t *)pfc;
79
80         reset_srt_table_data(&fc->fc_srt_table);
81         fcstat_set_title(fc);
82 }
83
84 static int
85 fcstat_packet(void *pfc, packet_info *pinfo, epan_dissect_t *edt _U_, const void *psi)
86 {
87         const fc_hdr *fc=psi;
88         fcstat_t *fs=(fcstat_t *)pfc;
89
90         /* we are only interested in reply packets */
91         if(!(fc->fctl&FC_FCTL_EXCHANGE_RESPONDER)){
92                 return 0;
93         }
94         /* if we havnt seen the request, just ignore it */
95         if( (!fc->fced) || (fc->fced->first_exchange_frame==0) ){
96                 return 0;
97         }
98
99         add_srt_table_data(&fs->fc_srt_table, fc->type, &fc->fced->fc_time, pinfo);
100
101         return 1;
102 }
103
104
105
106 static void
107 fcstat_draw(void *pfc)
108 {
109         fcstat_t *fc=(fcstat_t *)pfc;
110
111         draw_srt_table_data(&fc->fc_srt_table);
112 }
113
114
115 void protect_thread_critical_region(void);
116 void unprotect_thread_critical_region(void);
117 static void
118 win_destroy_cb(GtkWindow *win _U_, gpointer data)
119 {
120         fcstat_t *fc=(fcstat_t *)data;
121
122         protect_thread_critical_region();
123         remove_tap_listener(fc);
124         unprotect_thread_critical_region();
125
126         free_srt_table_data(&fc->fc_srt_table);
127         g_free(fc);
128 }
129
130
131 static void
132 gtk_fcstat_init(const char *optarg)
133 {
134         fcstat_t *fc;
135         const char *filter=NULL;
136         GtkWidget *label;
137         char filter_string[256];
138         GString *error_string;
139         int i;
140         GtkWidget *vbox;
141         GtkWidget *bbox;
142         GtkWidget *close_bt;
143
144         if(!strncmp(optarg,"fc,srt,",7)){
145                 filter=optarg+7;
146         } else {
147                 filter=NULL;
148         }
149
150         fc=g_malloc(sizeof(fcstat_t));
151
152         fc->win=window_new(GTK_WINDOW_TOPLEVEL, "fc-stat");
153         gtk_window_set_default_size(GTK_WINDOW(fc->win), 550, 400);
154         fcstat_set_title(fc);
155
156         vbox=gtk_vbox_new(FALSE, 3);
157         gtk_container_add(GTK_CONTAINER(fc->win), vbox);
158         gtk_container_set_border_width(GTK_CONTAINER(vbox), 12);
159
160         label=gtk_label_new("Fibre Channel Service Response Time statistics");
161         gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
162
163         g_snprintf(filter_string,255,"Filter:%s",filter?filter:"");
164         label=gtk_label_new(filter_string);
165         gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
166
167         label=gtk_label_new("Fibre Channel Types");
168         gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
169
170         /* We must display TOP LEVEL Widget before calling init_srt_table() */
171         gtk_widget_show_all(fc->win);
172
173         init_srt_table(&fc->fc_srt_table, 256, vbox, NULL);
174         for(i=0;i<256;i++){
175                 init_srt_table_row(&fc->fc_srt_table, i, val_to_str(i, fc_fc4_val, "Unknown(0x%02x)"));
176         }
177
178
179         error_string=register_tap_listener("fc", fc, filter, fcstat_reset, fcstat_packet, fcstat_draw);
180         if(error_string){
181                 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, error_string->str);
182                 g_string_free(error_string, TRUE);
183                 g_free(fc);
184                 return;
185         }
186
187         /* Button row. */
188         bbox = dlg_button_row_new(GTK_STOCK_CLOSE, NULL);
189         gtk_box_pack_end(GTK_BOX(vbox), bbox, FALSE, FALSE, 0);
190
191         close_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_CLOSE);
192         window_set_cancel_button(fc->win, close_bt, window_cancel_button_cb);
193
194         SIGNAL_CONNECT(fc->win, "delete_event", window_delete_event_cb, NULL);
195         SIGNAL_CONNECT(fc->win, "destroy", win_destroy_cb, fc);
196
197         gtk_widget_show_all(fc->win);
198         window_present(fc->win);
199
200         cf_retap_packets(&cfile);
201 }
202
203
204
205 static GtkWidget *dlg=NULL;
206 static GtkWidget *filter_entry;
207
208 static void
209 dlg_destroy_cb(void)
210 {
211         dlg=NULL;
212 }
213
214 static void
215 fcstat_start_button_clicked(GtkWidget *item _U_, gpointer data _U_)
216 {
217         GString *str;
218         const char *filter;
219
220         str = g_string_new("fc,srt");
221         filter=gtk_entry_get_text(GTK_ENTRY(filter_entry));
222         if(filter[0]!=0){
223                 g_string_sprintfa(str,",%s", filter);
224         }
225         gtk_fcstat_init(str->str);
226         g_string_free(str, TRUE);
227 }
228
229 static void
230 gtk_fcstat_cb(GtkWidget *w _U_, gpointer d _U_)
231 {
232         GtkWidget *dlg_box;
233         GtkWidget *filter_box, *filter_bt;
234         GtkWidget *bbox, *start_button, *cancel_button;
235         const char *filter;
236         static construct_args_t args = {
237           "Service Response Time Statistics Filter",
238           TRUE,
239           FALSE
240         };
241
242         /* if the window is already open, bring it to front */
243         if(dlg){
244                 gdk_window_raise(dlg->window);
245                 return;
246         }
247
248         dlg=dlg_window_new("Ethereal: Compute Fibre Channel Service Response Time statistics");
249         gtk_window_set_default_size(GTK_WINDOW(dlg), 400, -1);
250
251         dlg_box=gtk_vbox_new(FALSE, 10);
252         gtk_container_border_width(GTK_CONTAINER(dlg_box), 10);
253         gtk_container_add(GTK_CONTAINER(dlg), dlg_box);
254         gtk_widget_show(dlg_box);
255
256         /* Filter box */
257         filter_box=gtk_hbox_new(FALSE, 3);
258
259         /* Filter button */
260         filter_bt=BUTTON_NEW_FROM_STOCK(ETHEREAL_STOCK_DISPLAY_FILTER_ENTRY);
261         SIGNAL_CONNECT(filter_bt, "clicked", display_filter_construct_cb, &args);
262         gtk_box_pack_start(GTK_BOX(filter_box), filter_bt, FALSE, FALSE, 0);
263         gtk_widget_show(filter_bt);
264
265         /* Filter entry */
266         filter_entry=gtk_entry_new();
267     SIGNAL_CONNECT(filter_entry, "changed", filter_te_syntax_check_cb, NULL);
268
269         /* filter prefs dialog */
270         OBJECT_SET_DATA(filter_bt, E_FILT_TE_PTR_KEY, filter_entry);
271         /* filter prefs dialog */
272
273         gtk_box_pack_start(GTK_BOX(filter_box), filter_entry, TRUE, TRUE, 0);
274         filter=gtk_entry_get_text(GTK_ENTRY(main_display_filter_widget));
275         if(filter){
276                 gtk_entry_set_text(GTK_ENTRY(filter_entry), filter);
277         }
278         gtk_widget_show(filter_entry);
279
280         gtk_box_pack_start(GTK_BOX(dlg_box), filter_box, TRUE, TRUE, 0);
281         gtk_widget_show(filter_box);
282
283         /* button box */
284     bbox = dlg_button_row_new(ETHEREAL_STOCK_CREATE_STAT, GTK_STOCK_CANCEL, NULL);
285         gtk_box_pack_start(GTK_BOX(dlg_box), bbox, FALSE, FALSE, 0);
286     gtk_widget_show(bbox);
287
288     start_button = OBJECT_GET_DATA(bbox, ETHEREAL_STOCK_CREATE_STAT);
289     gtk_widget_grab_default(start_button );
290     SIGNAL_CONNECT_OBJECT(start_button, "clicked",
291                               fcstat_start_button_clicked, NULL);
292
293     cancel_button = OBJECT_GET_DATA(bbox, GTK_STOCK_CANCEL);
294     window_set_cancel_button(dlg, cancel_button, window_cancel_button_cb);
295
296         /* Catch the "activate" signal on the filter text entry, so that
297            if the user types Return there, we act as if the "Create Stat"
298            button had been selected, as happens if Return is typed if some
299            widget that *doesn't* handle the Return key has the input
300            focus. */
301         dlg_set_activate(filter_entry, start_button);
302
303         /* Give the initial focus to the "Filter" entry box. */
304         gtk_widget_grab_focus(filter_entry);
305
306     SIGNAL_CONNECT(dlg, "delete_event", window_delete_event_cb, NULL);
307         SIGNAL_CONNECT(dlg, "destroy", dlg_destroy_cb, NULL);
308
309         gtk_widget_show_all(dlg);
310     window_present(dlg);
311 }
312
313 void
314 register_tap_listener_gtkfcstat(void)
315 {
316         register_stat_cmd_arg("fc,srt", gtk_fcstat_init);
317
318         register_stat_menu_item("Fibre Channel...", REGISTER_STAT_GROUP_RESPONSE_TIME,
319             gtk_fcstat_cb, NULL, NULL, NULL);
320 }