renamed ui_util.c/.h to gui_utils.c/.h to prevent confusion with identical named...
[obnox/wireshark/wip.git] / gtk / h225_ras_srt.c
1 /* h225_ras_srt.c
2  * h225 RAS Service Response Time statistics for ethereal
3  * Copyright 2003 Lars Roland
4  *
5  * $Id$
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@ethereal.com>
9  * Copyright 1998 Gerald Combs
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #ifdef HAVE_SYS_TYPES_H
31 # include <sys/types.h>
32 #endif
33
34 #include <string.h>
35
36 #include <gtk/gtk.h>
37
38 #include <epan/packet_info.h>
39 #include <epan/epan.h>
40 #include <epan/value_string.h>
41
42 #include <epan/stat.h>
43 #include "stat_menu.h"
44 #include <epan/tap.h>
45 #include "../register.h"
46 #include <epan/dissectors/packet-h225.h>
47 #include "../timestats.h"
48 #include "gtk_stat_util.h"
49 #include "compat_macros.h"
50 #include "../simple_dialog.h"
51 #include "dlg_utils.h"
52 #include "../file.h"
53 #include "../globals.h"
54 #include "../tap_dfilter_dlg.h"
55 #include "tap_dfilter_dlg.h"
56 #include "gui_utils.h"
57
58
59 static void gtk_h225rassrt_init(const char *optarg);
60
61 static tap_dfilter_dlg h225_rassrt_dlg = {
62         "H.225 RAS Service Response Time",
63         "h225,srt",
64         gtk_h225rassrt_init,
65         -1
66 };
67
68 /* following values represent the size of their valuestring arrays */
69 #define NUM_RAS_STATS 7
70
71 static const value_string ras_message_category[] = {
72   {  0, "Gatekeeper    "},
73   {  1, "Registration  "},
74   {  2, "UnRegistration"},
75   {  3, "Admission     "},
76   {  4, "Bandwidth     "},
77   {  5, "Disengage     "},
78   {  6, "Location      "},
79   {  0, NULL }
80 };
81
82 typedef enum _ras_type {
83         RAS_REQUEST,
84         RAS_CONFIRM,
85         RAS_REJECT,
86         RAS_OTHER
87 }ras_type;
88
89 typedef enum _ras_category {
90         RAS_GATEKEEPER,
91         RAS_REGISTRATION,
92         RAS_UNREGISTRATION,
93         RAS_ADMISSION,
94         RAS_BANDWIDTH,
95         RAS_DISENGAGE,
96         RAS_LOCATION,
97         RAS_OTHERS
98 }ras_category;
99
100 /* Summary of response-time calculations*/
101 typedef struct _h225_rtd_t {
102         guint32 open_req_num;
103         guint32 disc_rsp_num;
104         guint32 req_dup_num;
105         guint32 rsp_dup_num;
106         timestat_t stats;
107 } h225_rtd_t;
108
109 /* used to keep track of the statistics for an entire program interface */
110 typedef struct _h225rassrt_t {
111         GtkWidget *win;
112         GtkWidget *vbox;
113         char *filter;
114         GtkWidget *scrolled_window;
115         GtkCList *table;
116         h225_rtd_t ras_rtd[NUM_RAS_STATS];
117 } h225rassrt_t;
118
119
120 static void
121 h225rassrt_reset(void *phs)
122 {
123         h225rassrt_t *hs=(h225rassrt_t *)phs;
124         int i;
125
126         for(i=0;i<NUM_RAS_STATS;i++) {
127                 hs->ras_rtd[i].stats.num = 0;
128                 hs->ras_rtd[i].stats.min_num = 0;
129                 hs->ras_rtd[i].stats.max_num = 0;
130                 hs->ras_rtd[i].stats.min.secs = 0;
131                 hs->ras_rtd[i].stats.min.nsecs = 0;
132                 hs->ras_rtd[i].stats.max.secs = 0;
133                 hs->ras_rtd[i].stats.max.nsecs = 0;
134                 hs->ras_rtd[i].stats.tot.secs = 0;
135                 hs->ras_rtd[i].stats.tot.nsecs = 0;
136                 hs->ras_rtd[i].open_req_num = 0;
137                 hs->ras_rtd[i].disc_rsp_num = 0;
138                 hs->ras_rtd[i].req_dup_num = 0;
139                 hs->ras_rtd[i].rsp_dup_num = 0;
140         }
141
142 }
143
144
145 static int
146 h225rassrt_packet(void *phs, packet_info *pinfo _U_, epan_dissect_t *edt _U_, const void *phi)
147 {
148         h225rassrt_t *hs=(h225rassrt_t *)phs;
149         const h225_packet_info *pi=phi;
150
151         ras_type rasmsg_type = RAS_OTHER;
152         ras_category rascategory = RAS_OTHERS;
153
154         if (pi->msg_type != H225_RAS || pi->msg_tag == -1) {
155                 /* No RAS Message or uninitialized msg_tag -> return */
156                 return 0;
157         }
158
159         if (pi->msg_tag < 21) {
160                 /* */
161                 rascategory = pi->msg_tag / 3;
162                 rasmsg_type = pi->msg_tag % 3;
163         }
164         else {
165                 /* No SRT yet (ToDo) */
166                 return 0;
167         }
168
169         switch(rasmsg_type) {
170
171         case RAS_REQUEST:
172                 if(pi->is_duplicate){
173                         hs->ras_rtd[rascategory].req_dup_num++;
174                 }
175                 else {
176                         hs->ras_rtd[rascategory].open_req_num++;
177                 }
178                 break;
179
180         case RAS_CONFIRM:
181                 /* no break - delay stats are identical for Confirm and Reject  */
182         case RAS_REJECT:
183                 if(pi->is_duplicate){
184                         /* Duplicate is ignored */
185                         hs->ras_rtd[rascategory].rsp_dup_num++;
186                 }
187                 else if (!pi->request_available) {
188                         /* no request was seen, ignore response  */
189                         hs->ras_rtd[rascategory].disc_rsp_num++;
190                 }
191                 else {
192                         hs->ras_rtd[rascategory].open_req_num--;
193                         time_stat_update(&(hs->ras_rtd[rascategory].stats),&(pi->delta_time), pinfo);
194                 }
195                 break;
196
197         default:
198                 return 0;
199                 break;
200         }
201         return 1;
202 }
203
204 static void
205 h225rassrt_draw(void *phs)
206 {
207         h225rassrt_t *hs=(h225rassrt_t *)phs;
208         int i;
209         char *str[11];
210
211         for(i=0;i<11;i++) {
212                 str[i]=g_malloc(sizeof(char[256]));
213         }
214         /* Now print Message and Reason Counter Table */
215         /* clear list before printing */
216         gtk_clist_clear(hs->table);
217
218         for(i=0;i<NUM_RAS_STATS;i++) {
219                 /* nothing seen, nothing to do */
220                 if(hs->ras_rtd[i].stats.num==0){
221                         continue;
222                 }
223
224                 g_snprintf(str[0], sizeof(char[256]), 
225             "%s", val_to_str(i,ras_message_category,"Other"));
226                 g_snprintf(str[1], sizeof(char[256]), 
227             "%7d", hs->ras_rtd[i].stats.num);
228                 g_snprintf(str[2], sizeof(char[256]), 
229             "%8.2f msec", nstime_to_msec(&(hs->ras_rtd[i].stats.min)));
230                 g_snprintf(str[3], sizeof(char[256]), 
231             "%8.2f msec", nstime_to_msec(&(hs->ras_rtd[i].stats.max)));;
232                 g_snprintf(str[4], sizeof(char[256]), 
233             "%8.2f msec", get_average(&(hs->ras_rtd[i].stats.tot), hs->ras_rtd[i].stats.num));
234                 g_snprintf(str[5], sizeof(char[256]), 
235             "%6u", hs->ras_rtd[i].stats.min_num);
236                 g_snprintf(str[6], sizeof(char[256]), 
237             "%6u", hs->ras_rtd[i].stats.max_num);
238                 g_snprintf(str[7], sizeof(char[256]), 
239             "%4u", hs->ras_rtd[i].open_req_num);
240                 g_snprintf(str[8], sizeof(char[256]), 
241             "%4u", hs->ras_rtd[i].disc_rsp_num);
242                 g_snprintf(str[9], sizeof(char[256]), 
243             "%4u", hs->ras_rtd[i].req_dup_num);
244                 g_snprintf(str[10], sizeof(char[256]), 
245             "%4u", hs->ras_rtd[i].rsp_dup_num);
246                 gtk_clist_append(GTK_CLIST(hs->table), str);
247         }
248
249         gtk_widget_show(GTK_WIDGET(hs->table));
250
251 }
252
253 void protect_thread_critical_region(void);
254 void unprotect_thread_critical_region(void);
255 static void
256 win_destroy_cb(GtkWindow *win _U_, gpointer data)
257 {
258         h225rassrt_t *hs=(h225rassrt_t *)data;
259
260         protect_thread_critical_region();
261         remove_tap_listener(hs);
262         unprotect_thread_critical_region();
263
264         if(hs->filter){
265                 g_free(hs->filter);
266                 hs->filter=NULL;
267         }
268         g_free(hs);
269 }
270
271
272 static const gchar *titles[]={
273                         "RAS-Type",
274                         "Measurements",
275                         "Min RTT",
276                         "Max RTT",
277                         "Avg RTT",
278                         "Min in Frame",
279                         "Max in Frame",
280                         "Open Requests",
281                         "Discarded Responses",
282                         "Repeated Requests",
283                         "Repeated Responses" };
284
285 static void
286 gtk_h225rassrt_init(const char *optarg)
287 {
288         h225rassrt_t *hs;
289         const char *filter=NULL;
290         GString *error_string;
291         GtkWidget *bbox;
292         GtkWidget *close_bt;
293
294         if(strncmp(optarg,"h225,srt,",9) == 0){
295                 filter=optarg+9;
296         } else {
297                 filter="";
298         }
299
300         hs=g_malloc(sizeof(h225rassrt_t));
301         hs->filter=g_strdup(filter);
302
303         h225rassrt_reset(hs);
304
305         hs->win=window_new(GTK_WINDOW_TOPLEVEL, "h225-ras-srt");
306         gtk_window_set_default_size(GTK_WINDOW(hs->win), 600, 300);
307
308         hs->vbox=gtk_vbox_new(FALSE, 3);
309         gtk_container_set_border_width(GTK_CONTAINER(hs->vbox), 12);
310
311         init_main_stat_window(hs->win, hs->vbox, "H.225 RAS Service Response Time", filter);
312
313         /* init a scrolled window*/
314         hs->scrolled_window = scrolled_window_new(NULL, NULL);
315
316         hs->table = create_stat_table(hs->scrolled_window, hs->vbox, 11, titles);
317
318         error_string=register_tap_listener("h225", hs, filter, h225rassrt_reset, h225rassrt_packet, h225rassrt_draw);
319         if(error_string){
320                 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, error_string->str);
321                 g_string_free(error_string, TRUE);
322                 g_free(hs->filter);
323                 g_free(hs);
324                 return;
325         }
326
327         /* Button row. */
328         bbox = dlg_button_row_new(GTK_STOCK_CLOSE, NULL);
329         gtk_box_pack_end(GTK_BOX(hs->vbox), bbox, FALSE, FALSE, 0);
330
331         close_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_CLOSE);
332         window_set_cancel_button(hs->win, close_bt, window_cancel_button_cb);
333
334         SIGNAL_CONNECT(hs->win, "delete_event", window_delete_event_cb, NULL);
335         SIGNAL_CONNECT(hs->win, "destroy", win_destroy_cb, hs);
336
337         gtk_widget_show_all(hs->win);
338         window_present(hs->win);
339
340         cf_retap_packets(&cfile);
341 }
342
343 void
344 register_tap_listener_gtk_h225rassrt(void)
345 {
346         register_stat_cmd_arg("h225,srt", gtk_h225rassrt_init);
347
348         register_stat_menu_item("H.225 RAS...", REGISTER_STAT_GROUP_RESPONSE_TIME,
349             gtk_tap_dfilter_dlg_cb, NULL, NULL, &(h225_rassrt_dlg));
350 }