Have tap listeners specify whether the "packet" routine requires
[obnox/wireshark/wip.git] / gtk / h225_ras_srt.c
1 /* h225_ras_srt.c
2  * H.225 RAS Service Response Time statistics for Wireshar
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.h>
39 #include <epan/packet_info.h>
40 #include <epan/epan.h>
41 #include <epan/value_string.h>
42 #include <epan/tap.h>
43 #include <epan/dissectors/packet-h225.h>
44
45 #include "../register.h"
46 #include "../timestats.h"
47 #include "../simple_dialog.h"
48 #include "../file.h"
49 #include "../globals.h"
50 #include "../stat_menu.h"
51
52 #include "gtk/gui_stat_util.h"
53 #include "gtk/dlg_utils.h"
54 #include "gtk/tap_dfilter_dlg.h"
55 #include "gtk/gui_utils.h"
56 #include "gtk/main.h"
57
58
59 static void gtk_h225rassrt_init(const char *optarg, void *userdata);
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         }
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 static void
253 win_destroy_cb(GtkWindow *win _U_, gpointer data)
254 {
255         h225rassrt_t *hs=(h225rassrt_t *)data;
256
257         protect_thread_critical_region();
258         remove_tap_listener(hs);
259         unprotect_thread_critical_region();
260
261         if(hs->filter){
262                 g_free(hs->filter);
263                 hs->filter=NULL;
264         }
265         g_free(hs);
266 }
267
268
269 static const gchar *titles[]={
270                         "RAS-Type",
271                         "Measurements",
272                         "Min RTT",
273                         "Max RTT",
274                         "Avg RTT",
275                         "Min in Frame",
276                         "Max in Frame",
277                         "Open Requests",
278                         "Discarded Responses",
279                         "Repeated Requests",
280                         "Repeated Responses" };
281
282 static void
283 gtk_h225rassrt_init(const char *optarg, void *userdata _U_)
284 {
285         h225rassrt_t *hs;
286         GString *error_string;
287         GtkWidget *bbox;
288         GtkWidget *close_bt;
289
290         hs=g_malloc(sizeof(h225rassrt_t));
291
292         if(strncmp(optarg,"h225,srt,",9) == 0){
293                 hs->filter=g_strdup(optarg+9);
294         } else {
295                 hs->filter=NULL;
296         }
297
298         h225rassrt_reset(hs);
299
300         hs->win=window_new(GTK_WINDOW_TOPLEVEL, "h225-ras-srt");
301         gtk_window_set_default_size(GTK_WINDOW(hs->win), 600, 300);
302
303         hs->vbox=gtk_vbox_new(FALSE, 3);
304         gtk_container_set_border_width(GTK_CONTAINER(hs->vbox), 12);
305
306         init_main_stat_window(hs->win, hs->vbox, "H.225 RAS Service Response Time", hs->filter);
307
308         /* init a scrolled window*/
309         hs->scrolled_window = scrolled_window_new(NULL, NULL);
310
311         hs->table = create_stat_table(hs->scrolled_window, hs->vbox, 11, titles);
312
313         error_string=register_tap_listener("h225", hs, hs->filter, 0, h225rassrt_reset, h225rassrt_packet, h225rassrt_draw);
314         if(error_string){
315                 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", error_string->str);
316                 g_string_free(error_string, TRUE);
317                 g_free(hs->filter);
318                 g_free(hs);
319                 return;
320         }
321
322         /* Button row. */
323         bbox = dlg_button_row_new(GTK_STOCK_CLOSE, NULL);
324         gtk_box_pack_end(GTK_BOX(hs->vbox), bbox, FALSE, FALSE, 0);
325
326         close_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CLOSE);
327         window_set_cancel_button(hs->win, close_bt, window_cancel_button_cb);
328
329         g_signal_connect(hs->win, "delete_event", G_CALLBACK(window_delete_event_cb), NULL);
330         g_signal_connect(hs->win, "destroy", G_CALLBACK(win_destroy_cb), hs);
331
332         gtk_widget_show_all(hs->win);
333         window_present(hs->win);
334
335         cf_retap_packets(&cfile);
336         gdk_window_raise(hs->win->window);
337 }
338
339 void
340 register_tap_listener_gtk_h225rassrt(void)
341 {
342         register_dfilter_stat(&h225_rassrt_dlg, "H.225 RAS",
343             REGISTER_STAT_GROUP_RESPONSE_TIME);
344 }