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