WIDGET_SET_SIZE(-2) is asserted by current GTK2 libs, so don't use it
[obnox/wireshark/wip.git] / gtk / smb_stat.c
1 /* smb_stat.c
2  * smb_stat   2003 Ronnie Sahlberg
3  *
4  * $Id: smb_stat.c,v 1.38 2004/02/22 18:58:35 ulfl Exp $
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 "../tap.h"
43 #include "../smb.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_prefs.h"
53 #include "service_response_time_table.h"
54
55 extern GtkWidget   *main_display_filter_widget;
56
57 /* used to keep track of the statistics for an entire program interface */
58 typedef struct _smbstat_t {
59         GtkWidget *win;
60         srt_stat_table smb_srt_table;
61         srt_stat_table trans2_srt_table;
62         srt_stat_table nt_trans_srt_table;
63 } smbstat_t;
64
65 static void
66 smbstat_set_title(smbstat_t *ss)
67 {
68         char *title;
69
70         title = g_strdup_printf("SMB Service Response Time statistics: %s",
71             cf_get_display_name(&cfile));
72         gtk_window_set_title(GTK_WINDOW(ss->win), title);
73         g_free(title);
74 }
75
76 static void
77 smbstat_reset(void *pss)
78 {
79         smbstat_t *ss=(smbstat_t *)pss;
80
81         reset_srt_table_data(&ss->smb_srt_table);
82         reset_srt_table_data(&ss->trans2_srt_table);
83         reset_srt_table_data(&ss->nt_trans_srt_table);
84         smbstat_set_title(ss);
85 }
86
87 static int
88 smbstat_packet(void *pss, packet_info *pinfo, epan_dissect_t *edt _U_, void *psi)
89 {
90         smbstat_t *ss=(smbstat_t *)pss;
91         smb_info_t *si=psi;
92
93         /* we are only interested in reply packets */
94         if(si->request){
95                 return 0;
96         }
97         /* if we havnt seen the request, just ignore it */
98         if(!si->sip){
99                 return 0;
100         }
101
102         add_srt_table_data(&ss->smb_srt_table, si->cmd, &si->sip->req_time, pinfo);
103
104         if(si->cmd==0xA0){
105                 smb_nt_transact_info_t *sti=(smb_nt_transact_info_t *)si->sip->extra_info;
106
107                 if(sti){
108                         add_srt_table_data(&ss->nt_trans_srt_table, sti->subcmd, &si->sip->req_time, pinfo);
109                 }
110         } else if(si->cmd==0x32){
111                 smb_transact2_info_t *st2i=(smb_transact2_info_t *)si->sip->extra_info;
112
113                 if(st2i){
114                         add_srt_table_data(&ss->trans2_srt_table, st2i->subcmd, &si->sip->req_time, pinfo);
115                 }
116         }
117
118         return 1;
119 }
120
121
122
123 static void
124 smbstat_draw(void *pss)
125 {
126         smbstat_t *ss=(smbstat_t *)pss;
127
128         draw_srt_table_data(&ss->smb_srt_table);
129         draw_srt_table_data(&ss->trans2_srt_table);
130         draw_srt_table_data(&ss->nt_trans_srt_table);
131 }
132
133
134 void protect_thread_critical_region(void);
135 void unprotect_thread_critical_region(void);
136 static void
137 win_destroy_cb(GtkWindow *win _U_, gpointer data)
138 {
139         smbstat_t *ss=(smbstat_t *)data;
140
141         protect_thread_critical_region();
142         remove_tap_listener(ss);
143         unprotect_thread_critical_region();
144
145         free_srt_table_data(&ss->smb_srt_table);
146         free_srt_table_data(&ss->trans2_srt_table);
147         free_srt_table_data(&ss->nt_trans_srt_table);
148         g_free(ss);
149 }
150
151
152 static void
153 gtk_smbstat_init(char *optarg)
154 {
155         smbstat_t *ss;
156         char *filter=NULL;
157         GtkWidget *label;
158         char filter_string[256];
159         GString *error_string;
160         int i;
161         GtkWidget *vbox;
162
163         if(!strncmp(optarg,"smb,srt,",8)){
164                 filter=optarg+8;
165         } else {
166                 filter=NULL;
167         }
168
169         ss=g_malloc(sizeof(smbstat_t));
170
171         ss->win=window_new(GTK_WINDOW_TOPLEVEL, NULL);
172         gtk_window_set_default_size(GTK_WINDOW(ss->win), 550, 600);
173         smbstat_set_title(ss);
174         SIGNAL_CONNECT(ss->win, "destroy", win_destroy_cb, ss);
175
176         vbox=gtk_vbox_new(FALSE, 0);
177         gtk_container_add(GTK_CONTAINER(ss->win), vbox);
178         gtk_container_set_border_width(GTK_CONTAINER(vbox), 10);
179         gtk_widget_show(vbox);
180
181         label=gtk_label_new("SMB Service Response Time statistics");
182         gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
183         gtk_widget_show(label);
184
185         snprintf(filter_string,255,"Filter:%s",filter?filter:"");
186         label=gtk_label_new(filter_string);
187         gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
188         gtk_widget_show(label);
189
190
191         label=gtk_label_new("SMB Commands");
192         gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
193         gtk_widget_show(label);
194
195         /* We must display TOP LEVEL Widget before calling init_srt_table() */
196         gtk_widget_show(ss->win);
197
198         init_srt_table(&ss->smb_srt_table, 256, vbox, "smb.cmd");
199         for(i=0;i<256;i++){
200                 init_srt_table_row(&ss->smb_srt_table, i, val_to_str(i, smb_cmd_vals, "Unknown(0x%02x)"));
201         }
202
203
204         label=gtk_label_new("Transaction2 Sub-Commands");
205         gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
206         gtk_widget_show(label);
207         init_srt_table(&ss->trans2_srt_table, 256, vbox, "smb.trans2.cmd");
208         for(i=0;i<256;i++){
209                 init_srt_table_row(&ss->trans2_srt_table, i, val_to_str(i, trans2_cmd_vals, "Unknown(0x%02x)"));
210         }
211
212
213         label=gtk_label_new("NT Transaction Sub-Commands");
214         gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
215         gtk_widget_show(label);
216         init_srt_table(&ss->nt_trans_srt_table, 256, vbox, "smb.nt.function");
217         for(i=0;i<256;i++){
218                 init_srt_table_row(&ss->nt_trans_srt_table, i, val_to_str(i, nt_cmd_vals, "Unknown(0x%02x)"));
219         }
220
221
222         error_string=register_tap_listener("smb", ss, filter, smbstat_reset, smbstat_packet, smbstat_draw);
223         if(error_string){
224                 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, error_string->str);
225                 g_string_free(error_string, TRUE);
226                 g_free(ss);
227                 return;
228         }
229
230         gtk_widget_show_all(ss->win);
231         retap_packets(&cfile);
232 }
233
234
235
236 static GtkWidget *dlg=NULL;
237 static GtkWidget *filter_entry;
238
239 static void
240 dlg_destroy_cb(void)
241 {
242         dlg=NULL;
243 }
244
245 static void
246 dlg_cancel_cb(GtkWidget *cancel_bt _U_, gpointer parent_w)
247 {
248         gtk_widget_destroy(GTK_WIDGET(parent_w));
249 }
250
251 static void
252 smbstat_start_button_clicked(GtkWidget *item _U_, gpointer data _U_)
253 {
254         GString *str;
255         char *filter;
256
257         str = g_string_new("smb,srt");
258         filter=(char *)gtk_entry_get_text(GTK_ENTRY(filter_entry));
259         if(filter[0]!=0){
260                 g_string_sprintfa(str,",%s", filter);
261         }
262         gtk_smbstat_init(str->str);
263         g_string_free(str, TRUE);
264 }
265
266 static void
267 gtk_smbstat_cb(GtkWidget *w _U_, gpointer d _U_)
268 {
269         GtkWidget *dlg_box;
270         GtkWidget *filter_box, *filter_bt;
271         GtkWidget *bbox, *start_button, *cancel_button;
272         const char *filter;
273         static construct_args_t args = {
274           "Service Response Time Statistics Filter",
275           TRUE,
276           FALSE
277         };
278
279         /* if the window is already open, bring it to front */
280         if(dlg){
281                 gdk_window_raise(dlg->window);
282                 return;
283         }
284
285         dlg=dlg_window_new("Ethereal: Compute SMB SRT statistics");
286         SIGNAL_CONNECT(dlg, "destroy", dlg_destroy_cb, NULL);
287
288         dlg_box=gtk_vbox_new(FALSE, 10);
289         gtk_container_border_width(GTK_CONTAINER(dlg_box), 10);
290         gtk_container_add(GTK_CONTAINER(dlg), dlg_box);
291         gtk_widget_show(dlg_box);
292
293         /* Filter box */
294         filter_box=gtk_hbox_new(FALSE, 3);
295
296         /* Filter button */
297         filter_bt=BUTTON_NEW_FROM_STOCK(ETHEREAL_STOCK_DISPLAY_FILTER_ENTRY);
298         SIGNAL_CONNECT(filter_bt, "clicked", display_filter_construct_cb, &args);
299         gtk_box_pack_start(GTK_BOX(filter_box), filter_bt, FALSE, TRUE, 0);
300         gtk_widget_show(filter_bt);
301
302         /* Filter entry */
303         filter_entry=gtk_entry_new();
304         WIDGET_SET_SIZE(filter_entry, 300, -1);
305
306         /* filter prefs dialog */
307         OBJECT_SET_DATA(filter_bt, E_FILT_TE_PTR_KEY, filter_entry);
308         /* filter prefs dialog */
309
310         gtk_box_pack_start(GTK_BOX(filter_box), filter_entry, TRUE, TRUE, 0);
311         filter=gtk_entry_get_text(GTK_ENTRY(main_display_filter_widget));
312         if(filter){
313                 gtk_entry_set_text(GTK_ENTRY(filter_entry), filter);
314         }
315         gtk_widget_show(filter_entry);
316
317         gtk_box_pack_start(GTK_BOX(dlg_box), filter_box, TRUE, TRUE, 0);
318         gtk_widget_show(filter_box);
319
320         /* button box */
321     bbox = dlg_button_row_new(ETHEREAL_STOCK_CREATE_STAT, GTK_STOCK_CANCEL, NULL);
322         gtk_box_pack_start(GTK_BOX(dlg_box), bbox, FALSE, FALSE, 0);
323     gtk_widget_show(bbox);
324
325     start_button = OBJECT_GET_DATA(bbox, ETHEREAL_STOCK_CREATE_STAT);
326     gtk_widget_grab_default(start_button );
327     SIGNAL_CONNECT_OBJECT(start_button, "clicked",
328                               smbstat_start_button_clicked, NULL);
329
330     cancel_button = OBJECT_GET_DATA(bbox, GTK_STOCK_CANCEL);
331         SIGNAL_CONNECT(cancel_button, "clicked", dlg_cancel_cb, dlg);    
332
333         /* Catch the "activate" signal on the filter text entry, so that
334            if the user types Return there, we act as if the "Create Stat"
335            button had been selected, as happens if Return is typed if some
336            widget that *doesn't* handle the Return key has the input
337            focus. */
338         dlg_set_activate(filter_entry, start_button);
339
340         /* Catch the "key_press_event" signal in the window, so that we can
341            catch the ESC key being pressed and act as if the "Cancel" button
342            had been selected. */
343         dlg_set_cancel(dlg, cancel_button);
344
345         /* Give the initial focus to the "Filter" entry box. */
346         gtk_widget_grab_focus(filter_entry);
347
348         gtk_widget_show_all(dlg);
349 }
350
351 void
352 register_tap_listener_gtksmbstat(void)
353 {
354         register_ethereal_tap("smb,srt", gtk_smbstat_init);
355
356         register_tap_menu_item("SMB (Service Response Time...)", REGISTER_TAP_LAYER_APPLICATION,
357             gtk_smbstat_cb, NULL, NULL, NULL);
358 }