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