18119e5a753ac6ca802abb450c1125dd51566804
[obnox/wireshark/wip.git] / gtk / mgcp_stat.c
1 /* mgcp_stat.c
2  * mgcp-statistics for ethereal
3  * Copyright 2003 Lars Roland
4  *
5  * $Id: mgcp_stat.c,v 1.4 2003/04/23 08:20:05 guy Exp $
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 #include <stdio.h>
31
32 #ifdef HAVE_SYS_TYPES_H
33 # include <sys/types.h>
34 #endif
35
36 #include <gtk/gtk.h>
37 #include <string.h>
38 #include "menu.h"
39 #include "../epan/packet_info.h"
40 #include "../tap.h"
41 #include "../epan/value_string.h"
42 #include "../register.h"
43 #include "../plugins/mgcp/packet-mgcp.h"
44 #include "../timestats.h"
45 #include "compat_macros.h"
46 #include "../simple_dialog.h"
47 #include "../file.h"
48 #include "../globals.h"
49
50 #define NUM_TIMESTATS 11
51
52 /* used to keep track of the statistics for an entire program interface */
53 typedef struct _mgcpstat_t {
54         GtkWidget *win;
55         GtkWidget *vbox;
56         char *filter;
57         GtkWidget *table;
58         int table_height;
59         timestat_t rtd[NUM_TIMESTATS];
60         guint32 open_req_num;
61         guint32 disc_rsp_num;
62         guint32 req_dup_num;
63         guint32 rsp_dup_num;
64 } mgcpstat_t;
65
66 static const value_string mgcp_mesage_type[] = {
67   {  0, "Overall"},
68   {  1, "EPCF"},
69   {  2, "CRCX"},
70   {  3, "MDCX"},
71   {  4, "DLCX"},
72   {  5, "RQNT"},
73   {  6, "NTFY"},
74   {  7, "AUEP"},
75   {  8, "AUCX"},
76   {  9, "RSIP"},
77 };
78
79 static void
80 add_table_entry(mgcpstat_t *ss, char *str, int x, int y)
81 {
82         GtkWidget *tmp;
83
84         if(y>=ss->table_height){
85                 ss->table_height=y+1;
86                 gtk_table_resize(GTK_TABLE(ss->table), ss->table_height, 7);
87         }
88         tmp=gtk_label_new(str);
89         gtk_table_attach_defaults(GTK_TABLE(ss->table), tmp, x, x+1, y, y+1);
90         gtk_label_set_justify(GTK_LABEL(tmp), GTK_JUSTIFY_LEFT);
91         gtk_widget_show(tmp);
92 }
93
94
95 static void
96 mgcpstat_reset(void *pms)
97 {
98         mgcpstat_t *ms=(mgcpstat_t *)pms;
99         int i;
100
101         for(i=0;i<NUM_TIMESTATS;i++) {
102                 ms->rtd[i].num=0;
103                 ms->rtd[i].min_num=0;
104                 ms->rtd[i].max_num=0;
105                 ms->rtd[i].min.secs=0;
106                 ms->rtd[i].min.nsecs=0;
107                 ms->rtd[i].max.secs=0;
108                 ms->rtd[i].max.nsecs=0;
109                 ms->rtd[i].tot.secs=0;
110                 ms->rtd[i].tot.nsecs=0;
111         }
112
113         ms->open_req_num=0;
114         ms->disc_rsp_num=0;
115         ms->req_dup_num=0;
116         ms->rsp_dup_num=0;
117
118 }
119
120
121 static int
122 mgcpstat_packet(void *pms, packet_info *pinfo, epan_dissect_t *edt _U_, void *pmi)
123 {
124         mgcpstat_t *ms=(mgcpstat_t *)pms;
125         mgcp_info_t *mi=pmi;
126         nstime_t delta;
127
128         switch (mi->mgcp_type) {
129
130         case MGCP_REQUEST:
131                 if(mi->is_duplicate){
132                         /* Duplicate is ignored */
133                         ms->req_dup_num++;
134                         return 0;
135                 }
136                 else {
137                         ms->open_req_num++;
138                         return 0;
139                 }
140         break;
141
142         case MGCP_RESPONSE:
143                 if(mi->is_duplicate){
144                         /* Duplicate is ignored */
145                         ms->rsp_dup_num++;
146                         return 0;
147                 }
148                 else if (!mi->request_available) {
149                         /* no request was seen */
150                         ms->disc_rsp_num++;
151                         return 0;
152                 }
153                 else {
154                         ms->open_req_num--;
155                         /* calculate time delta between request and response */
156                         delta.secs=pinfo->fd->abs_secs-mi->req_time.secs;
157                         delta.nsecs=pinfo->fd->abs_usecs*1000-mi->req_time.nsecs;
158                         if(delta.nsecs<0){
159                                 delta.nsecs+=1000000000;
160                                 delta.secs--;
161                         }
162
163                         time_stat_update(&(ms->rtd[0]),&delta, pinfo);
164
165                         if (strncasecmp(mi->code, "EPCF", 4) == 0 ) {
166                                 time_stat_update(&(ms->rtd[1]),&delta, pinfo);
167                         }
168                         else if (strncasecmp(mi->code, "CRCX", 4) == 0 ) {
169                                 time_stat_update(&(ms->rtd[2]),&delta, pinfo);
170                         }
171                         else if (strncasecmp(mi->code, "MDCX", 4) == 0 ) {
172                                 time_stat_update(&(ms->rtd[3]),&delta, pinfo);
173                         }
174                         else if (strncasecmp(mi->code, "DLCX", 4) == 0 ) {
175                                 time_stat_update(&(ms->rtd[4]),&delta, pinfo);
176                         }
177                         else if (strncasecmp(mi->code, "RQNT", 4) == 0 ) {
178                                 time_stat_update(&(ms->rtd[5]),&delta, pinfo);
179                         }
180                         else if (strncasecmp(mi->code, "NTFY", 4) == 0 ) {
181                                 time_stat_update(&(ms->rtd[6]),&delta, pinfo);
182                         }
183                         else if (strncasecmp(mi->code, "AUEP", 4) == 0 ) {
184                                 time_stat_update(&(ms->rtd[7]),&delta, pinfo);
185                         }
186                         else if (strncasecmp(mi->code, "AUCX", 4) == 0 ) {
187                                 time_stat_update(&(ms->rtd[8]),&delta, pinfo);
188                         }
189                         else if (strncasecmp(mi->code, "RSIP", 4) == 0 ) {
190                                 time_stat_update(&(ms->rtd[9]),&delta, pinfo);
191                         }
192                         else {
193                                 time_stat_update(&(ms->rtd[10]),&delta, pinfo);
194                         }
195
196                         return 1;
197                 }
198         break;
199
200         default:
201                 return 0;
202         break;
203         }
204 }
205
206 static void
207 mgcpstat_draw(void *pms)
208 {
209         mgcpstat_t *ms=(mgcpstat_t *)pms;
210         int i;
211         int pos;
212         char str[256];
213
214         gtk_widget_destroy(ms->table);
215         ms->table_height=5;
216         ms->table=gtk_table_new(ms->table_height, 7, TRUE);
217         gtk_container_add(GTK_CONTAINER(ms->vbox), ms->table);
218
219         pos=0;
220
221         add_table_entry(ms, "Type", 0, pos);
222         add_table_entry(ms, "Messages", 1, pos);
223         add_table_entry(ms, "Min RTD", 2, pos);
224         add_table_entry(ms, "Max RTD", 3, pos);
225         add_table_entry(ms, "Avg RTD", 4, pos);
226         add_table_entry(ms, "Min in Frame", 5, pos);
227         add_table_entry(ms, "Max in Frame", 6, pos);
228         pos++;
229
230         for(i=0;i<NUM_TIMESTATS;i++) {
231                 /* nothing seen, nothing to do */
232                 if(ms->rtd[i].num==0){
233                         continue;
234                 }
235
236                 sprintf(str, "%s", val_to_str(i,mgcp_mesage_type,"Other"));
237                 add_table_entry(ms, str, 0, pos);
238                 sprintf(str, "%d", ms->rtd[i].num);
239                 add_table_entry(ms, str, 1, pos);
240                 sprintf(str, "%8.2f msec", nstime_to_msec(&(ms->rtd[i].min)));
241                 add_table_entry(ms, str, 2, pos);
242                 sprintf(str, "%8.2f msec", nstime_to_msec(&(ms->rtd[i].max)));
243                 add_table_entry(ms, str, 3, pos);
244                 sprintf(str, "%8.2f msec", get_average(&(ms->rtd[i].tot), ms->rtd[i].num));
245                 add_table_entry(ms, str, 4, pos);
246                 sprintf(str, "%6u", ms->rtd[i].min_num);
247                 add_table_entry(ms, str, 5, pos);
248                 sprintf(str, "%6u", ms->rtd[i].max_num);
249                 add_table_entry(ms, str, 6, pos);
250                 pos++;
251         }
252
253         gtk_widget_show(ms->table);
254 }
255
256 void protect_thread_critical_region(void);
257 void unprotect_thread_critical_region(void);
258 static void
259 win_destroy_cb(GtkWindow *win _U_, gpointer data)
260 {
261         mgcpstat_t *ms=(mgcpstat_t *)data;
262
263         protect_thread_critical_region();
264         remove_tap_listener(ms);
265         unprotect_thread_critical_region();
266
267         if(ms->filter){
268                 g_free(ms->filter);
269                 ms->filter=NULL;
270         }
271         g_free(ms);
272 }
273
274 void
275 gtk_mgcpstat_init(char *optarg)
276 {
277         mgcpstat_t *ms;
278         char *filter=NULL;
279         GtkWidget *stat_label;
280         GtkWidget *filter_label;
281         char filter_string[256];
282         GString *error_string;
283
284         if(!strncmp(optarg,"mgcp,rtd,",9)){
285                 filter=optarg+9;
286         } else {
287                 filter=g_malloc(1);
288                 *filter='\0';
289         }
290
291         ms=g_malloc(sizeof(mgcpstat_t));
292         ms->filter=g_malloc(strlen(filter)+1);
293         strcpy(ms->filter, filter);
294
295         mgcpstat_reset(ms);
296
297         ms->win=gtk_window_new(GTK_WINDOW_TOPLEVEL);
298         gtk_window_set_title(GTK_WINDOW(ms->win), "MGCP Response Time Delay (RTD) Statistics");
299         SIGNAL_CONNECT(ms->win, "destroy", win_destroy_cb, ms);
300
301         ms->vbox=gtk_vbox_new(FALSE, 0);
302         gtk_container_add(GTK_CONTAINER(ms->win), ms->vbox);
303         gtk_container_set_border_width(GTK_CONTAINER(ms->vbox), 10);
304         gtk_widget_show(ms->vbox);
305
306         stat_label=gtk_label_new("MGCP Response Time Delay (RTD) Statistics");
307         gtk_box_pack_start(GTK_BOX(ms->vbox), stat_label, FALSE, FALSE, 0);
308         gtk_widget_show(stat_label);
309
310         snprintf(filter_string,255,"Filter:%s",filter?filter:"");
311         filter_label=gtk_label_new(filter_string);
312         gtk_box_pack_start(GTK_BOX(ms->vbox), filter_label, FALSE, FALSE, 0);
313         gtk_widget_show(filter_label);
314
315         ms->table_height=5;
316         ms->table=gtk_table_new(ms->table_height, 7, TRUE);
317         gtk_container_add(GTK_CONTAINER(ms->vbox), ms->table);
318
319         add_table_entry(ms, "Type", 0, 0);
320         add_table_entry(ms, "Messages", 1, 0);
321         add_table_entry(ms, "Min RTD", 2, 0);
322         add_table_entry(ms, "Max RTD", 3, 0);
323         add_table_entry(ms, "Avg RTD", 4, 0);
324         add_table_entry(ms, "Min in Frame", 5, 0);
325         add_table_entry(ms, "Max in Frame", 6, 0);
326
327         gtk_widget_show(ms->table);
328
329         error_string=register_tap_listener("mgcp", ms, filter, mgcpstat_reset, mgcpstat_packet, mgcpstat_draw);
330         if(error_string){
331                 simple_dialog(ESD_TYPE_WARN, NULL, error_string->str);
332                 g_string_free(error_string, TRUE);
333                 g_free(ms->filter);
334                 g_free(ms);
335                 return;
336         }
337
338         gtk_widget_show_all(ms->win);
339         redissect_packets(&cfile);
340 }
341
342 void
343 register_tap_listener_gtkmgcpstat(void)
344 {
345         register_ethereal_tap("mgcp,rtd", gtk_mgcpstat_init);
346 }
347
348
349 static void
350 gtk_mgcpstat_cb(GtkWidget *w _U_, gpointer d _U_)
351 {
352         gtk_mgcpstat_init("mgcp,rtd");
353 }
354
355 void
356 register_tap_menu_gtkmgcpstat(void)
357 {
358         if (find_tap_id("mgcp"))
359                 register_tap_menu_item("MGCP/RTD", gtk_mgcpstat_cb);
360 }
361