From Lars Roland: printf fix.
[obnox/wireshark/wip.git] / tap-mgcpstat.c
1 /* tap-mgcpstat.c
2  * mgcpstat   2003 Lars Roland
3  *
4  * $Id: tap-mgcpstat.c,v 1.3 2003/03/12 00:36:22 guy Exp $
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@ethereal.com>
8  * Copyright 1998 Gerald Combs
9  * 
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  * 
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  * 
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #include <stdio.h>
30
31 #ifdef HAVE_SYS_TYPES_H
32 # include <sys/types.h>
33 #endif
34
35 #include <string.h>
36 #include "epan/packet_info.h"
37 #include "tap.h"
38 #include "epan/value_string.h"
39 #include "register.h"
40 #include "plugins/mgcp/packet-mgcp.h"
41
42
43 /* Summary of response-time calculations*/
44 typedef struct _rtd_t {
45         long int num;
46         nstime_t min;
47         nstime_t max;
48         nstime_t tot;
49 } rtd_t;
50
51 /* used to keep track of the statistics for an entire program interface */
52 typedef struct _mgcpstat_t {
53         char *filter;
54         rtd_t rtd;
55         long int open_req_num;
56         long int disc_rsp_num;
57         long int req_dup_num;
58         long int rsp_dup_num;
59 } mgcpstat_t;
60
61 /* A Function to update a mgcp_rtd_t struct */
62
63 void
64 rtd_stat_update(rtd_t *rtd,nstime_t delta)
65 {
66         rtd->num++;
67         if((rtd->max.secs==0)
68         && (rtd->max.nsecs==0) ){
69                 rtd->max.secs=delta.secs;
70                 rtd->max.nsecs=delta.nsecs;
71         }
72         
73         if((rtd->min.secs==0)
74         && (rtd->min.nsecs==0) ){
75                 rtd->min.secs=delta.secs;
76                 rtd->min.nsecs=delta.nsecs;
77         }
78         
79         if( (delta.secs<rtd->min.secs)
80         ||( (delta.secs==rtd->min.secs)
81           &&(delta.nsecs<rtd->min.nsecs) ) ){
82                 rtd->min.secs=delta.secs;
83                 rtd->min.nsecs=delta.nsecs;
84         }
85         
86         if( (delta.secs>rtd->max.secs)
87         ||( (delta.secs==rtd->max.secs)
88           &&(delta.nsecs>rtd->max.nsecs) ) ){
89                 rtd->max.secs=delta.secs;
90                 rtd->max.nsecs=delta.nsecs;
91         }
92                 
93         rtd->tot.secs += delta.secs;
94         rtd->tot.nsecs += delta.nsecs;
95         if(rtd->tot.nsecs>1000000000){
96                 rtd->tot.nsecs-=1000000000;
97                 rtd->tot.secs++;        
98         }
99         
100         
101 }
102
103 static int
104 mgcpstat_packet(void *pms, packet_info *pinfo, epan_dissect_t *edt _U_, void *pmi)
105 {
106         mgcpstat_t *ms=(mgcpstat_t *)pms;
107         mgcp_info_t *mi=pmi;
108         nstime_t delta;
109
110         switch (mi->mgcp_type) {
111         
112         case MGCP_REQUEST:
113                 if(mi->is_duplicate){
114                         /* Duplicate is ignored */
115                         ms->req_dup_num++;
116                         return 0;
117                 }
118                 else {
119                         ms->open_req_num++;
120                         return 0;
121                 }
122         break;
123                         
124         case MGCP_RESPONSE:
125                 if(mi->is_duplicate){
126                         /* Duplicate is ignored */
127                         ms->rsp_dup_num++;
128                         return 0;
129                 }
130                 else if (!mi->request_available) {
131                         /* no request was seen */
132                         ms->disc_rsp_num++;
133                         return 0;
134                 }
135                 else {
136                         ms->open_req_num--;
137                         /* calculate time delta between request and response */
138                         delta.secs=pinfo->fd->abs_secs-mi->req_time.secs;
139                         delta.nsecs=pinfo->fd->abs_usecs*1000-mi->req_time.nsecs;
140                         if(delta.nsecs<0){
141                                 delta.nsecs+=1000000000;
142                                 delta.secs--;
143                         }
144                         
145                         rtd_stat_update(&(ms->rtd),delta);
146                         return 1;
147                 }
148         break;
149
150         default:
151                 return 0;
152         break;
153         }
154 }
155
156 static void
157 mgcpstat_draw(void *pms)
158 {
159         mgcpstat_t *ms=(mgcpstat_t *)pms;
160         
161 #ifdef G_HAVE_UINT64
162         guint64 avg;
163 #else
164         guint32 avg;
165 #endif
166  
167
168         /* calculating average rtd */
169         /* scale it to units of 10us.*/
170         /* for long captures with a large tot time, this can overflow on 32bit */
171         avg=(int)ms->rtd.tot.secs;
172         avg=avg*100000+(int)ms->rtd.tot.nsecs/10000;
173         if(ms->rtd.num){
174                 avg/=ms->rtd.num;
175         } else {
176                 avg=0;
177         }
178
179         /* printing results */
180         printf("\n");
181         printf("===================================================================\n");
182         printf("MGCP Response Time Delay (RTD) Statistics:\n");
183         printf("Filter: %s\n",ms->filter?ms->filter:"");
184         printf("Duplicate requests: %ld\n",ms->req_dup_num);
185         printf("Duplicate responses: %ld\n",ms->rsp_dup_num);
186         printf("Open requests: %ld\n",ms->open_req_num);
187         printf("Discarded responses: %ld\n",ms->disc_rsp_num);
188         printf("Messages   |     Min RTD     |     Max RTD     |     Avg RTD \n");
189         printf("%7ld    |  %5d.%03d msec |  %5d.%03d msec | %5d.%02d0 msec\n",
190                 ms->rtd.num,
191                 (int)((ms->rtd.min.secs*1000)+(ms->rtd.min.nsecs/1000000)),(ms->rtd.min.nsecs%1000000)/1000,
192                 (int)((ms->rtd.max.secs*1000)+(ms->rtd.max.nsecs/1000000)),(ms->rtd.max.nsecs%1000000)/1000,
193                 avg/100, avg%100
194         );
195         printf("===================================================================\n");
196 }
197
198
199 static void
200 mgcpstat_init(char *optarg)
201 {
202         mgcpstat_t *ms;
203         char *filter=NULL;
204
205
206         if(!strncmp(optarg,"mgcp,rtd,",9)){
207                 filter=optarg+9;
208         } else {
209                 filter=NULL;
210         }
211
212         ms=g_malloc(sizeof(mgcpstat_t));
213         if(filter){
214                 ms->filter=g_malloc(strlen(filter)+1);
215                 strcpy(ms->filter, filter);
216         } else {
217                 ms->filter=NULL;
218         }
219
220         ms->rtd.num=0;
221         ms->rtd.min.secs=0;
222         ms->rtd.min.nsecs=0;
223         ms->rtd.max.secs=0;
224         ms->rtd.max.nsecs=0;
225         ms->rtd.tot.secs=0;
226         ms->rtd.tot.nsecs=0;
227
228         ms->open_req_num=0;
229         ms->disc_rsp_num=0;
230         ms->req_dup_num=0;
231         ms->rsp_dup_num=0;
232
233         if(register_tap_listener("mgcp", ms, filter, NULL, mgcpstat_packet, mgcpstat_draw)){
234                 /* error, we failed to attach to the tap. clean up */
235                 g_free(ms->filter);
236                 g_free(ms);
237
238                 fprintf(stderr,"tethereal: mgcpstat_init() failed to attach to tap.\n");
239                 exit(1);
240         }
241 }
242
243
244 void
245 register_tap_listener_mgcpstat(void)
246 {
247         register_ethereal_tap("mgcp,rtd", mgcpstat_init, NULL, NULL);
248 }
249