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