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