Rename epan/stat.[ch] to epan/stat_cmd_args.[ch] - it only deals with
[obnox/wireshark/wip.git] / gtk / smb_stat.c
1 /* smb_stat.c
2  * smb_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 <epan/stat_cmd_args.h>
42 #include "stat_menu.h"
43 #include <epan/tap.h>
44 #include "../smb.h"
45 #include "../register.h"
46 #include "../timestats.h"
47 #include "compat_macros.h"
48 #include "../simple_dialog.h"
49 #include "gui_utils.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 _smbstat_t {
60         GtkWidget *win;
61         srt_stat_table smb_srt_table;
62         srt_stat_table trans2_srt_table;
63         srt_stat_table nt_trans_srt_table;
64 } smbstat_t;
65
66 static void
67 smbstat_set_title(smbstat_t *ss)
68 {
69         char *title;
70
71         title = g_strdup_printf("SMB Service Response Time statistics: %s",
72             cf_get_display_name(&cfile));
73         gtk_window_set_title(GTK_WINDOW(ss->win), title);
74         g_free(title);
75 }
76
77 static void
78 smbstat_reset(void *pss)
79 {
80         smbstat_t *ss=(smbstat_t *)pss;
81
82         reset_srt_table_data(&ss->smb_srt_table);
83         reset_srt_table_data(&ss->trans2_srt_table);
84         reset_srt_table_data(&ss->nt_trans_srt_table);
85         smbstat_set_title(ss);
86 }
87
88 static int
89 smbstat_packet(void *pss, packet_info *pinfo, epan_dissect_t *edt _U_, const void *psi)
90 {
91         smbstat_t *ss=(smbstat_t *)pss;
92         const smb_info_t *si=psi;
93
94         /* we are only interested in reply packets */
95         if(si->request){
96                 return 0;
97         }
98         /* if we havnt seen the request, just ignore it */
99         if(!si->sip){
100                 return 0;
101         }
102
103         add_srt_table_data(&ss->smb_srt_table, si->cmd, &si->sip->req_time, pinfo);
104
105         if(si->cmd==0xA0 && si->sip->extra_info_type == SMB_EI_NTI){
106                 smb_nt_transact_info_t *sti=(smb_nt_transact_info_t *)si->sip->extra_info;
107
108                 if(sti){
109                         add_srt_table_data(&ss->nt_trans_srt_table, sti->subcmd, &si->sip->req_time, pinfo);
110                 }
111         } else if(si->cmd==0x32 && si->sip->extra_info_type == SMB_EI_T2I){
112                 smb_transact2_info_t *st2i=(smb_transact2_info_t *)si->sip->extra_info;
113
114                 if(st2i){
115                         add_srt_table_data(&ss->trans2_srt_table, st2i->subcmd, &si->sip->req_time, pinfo);
116                 }
117         }
118
119         return 1;
120 }
121
122
123
124 static void
125 smbstat_draw(void *pss)
126 {
127         smbstat_t *ss=(smbstat_t *)pss;
128
129         draw_srt_table_data(&ss->smb_srt_table);
130         draw_srt_table_data(&ss->trans2_srt_table);
131         draw_srt_table_data(&ss->nt_trans_srt_table);
132 }
133
134
135 void protect_thread_critical_region(void);
136 void unprotect_thread_critical_region(void);
137 static void
138 win_destroy_cb(GtkWindow *win _U_, gpointer data)
139 {
140         smbstat_t *ss=(smbstat_t *)data;
141
142         protect_thread_critical_region();
143         remove_tap_listener(ss);
144         unprotect_thread_critical_region();
145
146         free_srt_table_data(&ss->smb_srt_table);
147         free_srt_table_data(&ss->trans2_srt_table);
148         free_srt_table_data(&ss->nt_trans_srt_table);
149         g_free(ss);
150 }
151
152
153 static void
154 gtk_smbstat_init(const char *optarg)
155 {
156         smbstat_t *ss;
157         const char *filter=NULL;
158         GtkWidget *label;
159         char filter_string[256];
160         GString *error_string;
161         int i;
162         GtkWidget *vbox;
163         GtkWidget *bbox;
164         GtkWidget *close_bt;
165
166         if(!strncmp(optarg,"smb,srt,",8)){
167                 filter=optarg+8;
168         } else {
169                 filter=NULL;
170         }
171
172         ss=g_malloc(sizeof(smbstat_t));
173
174         ss->win=window_new(GTK_WINDOW_TOPLEVEL, "smb-stat");
175         gtk_window_set_default_size(GTK_WINDOW(ss->win), 550, 600);
176         smbstat_set_title(ss);
177
178         vbox=gtk_vbox_new(FALSE, 3);
179         gtk_container_add(GTK_CONTAINER(ss->win), vbox);
180         gtk_container_set_border_width(GTK_CONTAINER(vbox), 12);
181
182         label=gtk_label_new("SMB Service Response Time statistics");
183         gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
184
185         g_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
189         label=gtk_label_new("SMB Commands");
190         gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
191
192         /* We must display TOP LEVEL Widget before calling init_srt_table() */
193         gtk_widget_show_all(ss->win);
194
195         init_srt_table(&ss->smb_srt_table, 256, vbox, "smb.cmd");
196         for(i=0;i<256;i++){
197                 init_srt_table_row(&ss->smb_srt_table, i, val_to_str(i, smb_cmd_vals, "Unknown(0x%02x)"));
198         }
199
200
201         label=gtk_label_new("Transaction2 Sub-Commands");
202         gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
203         init_srt_table(&ss->trans2_srt_table, 256, vbox, "smb.trans2.cmd");
204         for(i=0;i<256;i++){
205                 init_srt_table_row(&ss->trans2_srt_table, i, val_to_str(i, trans2_cmd_vals, "Unknown(0x%02x)"));
206         }
207
208
209         label=gtk_label_new("NT Transaction Sub-Commands");
210         gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
211         init_srt_table(&ss->nt_trans_srt_table, 256, vbox, "smb.nt.function");
212         for(i=0;i<256;i++){
213                 init_srt_table_row(&ss->nt_trans_srt_table, i, val_to_str(i, nt_cmd_vals, "Unknown(0x%02x)"));
214         }
215
216
217         error_string=register_tap_listener("smb", ss, filter, smbstat_reset, smbstat_packet, smbstat_draw);
218         if(error_string){
219                 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, error_string->str);
220                 g_string_free(error_string, TRUE);
221                 g_free(ss);
222                 return;
223         }
224
225         /* Button row. */
226         bbox = dlg_button_row_new(GTK_STOCK_CLOSE, NULL);
227         gtk_box_pack_end(GTK_BOX(vbox), bbox, FALSE, FALSE, 0);
228
229         close_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_CLOSE);
230         window_set_cancel_button(ss->win, close_bt, window_cancel_button_cb);
231
232         SIGNAL_CONNECT(ss->win, "delete_event", window_delete_event_cb, NULL);
233         SIGNAL_CONNECT(ss->win, "destroy", win_destroy_cb, ss);
234
235         gtk_widget_show_all(ss->win);
236         window_present(ss->win);
237         
238         cf_retap_packets(&cfile);
239 }
240
241
242
243 static GtkWidget *dlg=NULL;
244 static GtkWidget *filter_entry;
245
246 static void
247 dlg_destroy_cb(void)
248 {
249         dlg=NULL;
250 }
251
252 static void
253 smbstat_start_button_clicked(GtkWidget *item _U_, gpointer data _U_)
254 {
255         GString *str;
256         const char *filter;
257
258         str = g_string_new("smb,srt");
259         filter=gtk_entry_get_text(GTK_ENTRY(filter_entry));
260         if(filter[0]!=0){
261                 g_string_sprintfa(str,",%s", filter);
262         }
263         gtk_smbstat_init(str->str);
264         g_string_free(str, TRUE);
265 }
266
267 static void
268 gtk_smbstat_cb(GtkWidget *w _U_, gpointer d _U_)
269 {
270         GtkWidget *dlg_box;
271         GtkWidget *filter_box, *filter_bt;
272         GtkWidget *bbox, *start_button, *cancel_button;
273         const char *filter;
274         static construct_args_t args = {
275           "Service Response Time Statistics Filter",
276           TRUE,
277           FALSE
278         };
279
280         /* if the window is already open, bring it to front */
281         if(dlg){
282                 gdk_window_raise(dlg->window);
283                 return;
284         }
285
286         dlg=dlg_window_new("Ethereal: Compute SMB SRT statistics");
287         gtk_window_set_default_size(GTK_WINDOW(dlg), 300, -1);
288
289         dlg_box=gtk_vbox_new(FALSE, 10);
290         gtk_container_border_width(GTK_CONTAINER(dlg_box), 10);
291         gtk_container_add(GTK_CONTAINER(dlg), dlg_box);
292         gtk_widget_show(dlg_box);
293
294         /* Filter box */
295         filter_box=gtk_hbox_new(FALSE, 3);
296
297         /* Filter button */
298         filter_bt=BUTTON_NEW_FROM_STOCK(ETHEREAL_STOCK_DISPLAY_FILTER_ENTRY);
299         SIGNAL_CONNECT(filter_bt, "clicked", display_filter_construct_cb, &args);
300         gtk_box_pack_start(GTK_BOX(filter_box), filter_bt, FALSE, TRUE, 0);
301         gtk_widget_show(filter_bt);
302
303         /* Filter entry */
304         filter_entry=gtk_entry_new();
305     SIGNAL_CONNECT(filter_entry, "changed", filter_te_syntax_check_cb, NULL);
306
307         /* filter prefs dialog */
308         OBJECT_SET_DATA(filter_bt, E_FILT_TE_PTR_KEY, filter_entry);
309         /* filter prefs dialog */
310
311         gtk_box_pack_start(GTK_BOX(filter_box), filter_entry, TRUE, TRUE, 0);
312         filter=gtk_entry_get_text(GTK_ENTRY(main_display_filter_widget));
313         if(filter){
314                 gtk_entry_set_text(GTK_ENTRY(filter_entry), filter);
315         }
316         gtk_widget_show(filter_entry);
317
318         gtk_box_pack_start(GTK_BOX(dlg_box), filter_box, TRUE, TRUE, 0);
319         gtk_widget_show(filter_box);
320
321         /* button box */
322     bbox = dlg_button_row_new(ETHEREAL_STOCK_CREATE_STAT, GTK_STOCK_CANCEL, NULL);
323         gtk_box_pack_start(GTK_BOX(dlg_box), bbox, FALSE, FALSE, 0);
324     gtk_widget_show(bbox);
325
326     start_button = OBJECT_GET_DATA(bbox, ETHEREAL_STOCK_CREATE_STAT);
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     window_set_cancel_button(dlg, cancel_button, window_cancel_button_cb);
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     gtk_widget_grab_default(start_button );
341
342     /* Give the initial focus to the "Filter" entry box. */
343         gtk_widget_grab_focus(filter_entry);
344
345     SIGNAL_CONNECT(dlg, "delete_event", window_delete_event_cb, NULL);
346         SIGNAL_CONNECT(dlg, "destroy", dlg_destroy_cb, NULL);
347
348     gtk_widget_show_all(dlg);
349     window_present(dlg);
350 }
351
352 void
353 register_tap_listener_gtksmbstat(void)
354 {
355         register_stat_cmd_arg("smb,srt", gtk_smbstat_init);
356
357         register_stat_menu_item("SMB...", REGISTER_STAT_GROUP_RESPONSE_TIME,
358             gtk_smbstat_cb, NULL, NULL, NULL);
359 }