Get rid of -Wshadow warning - I guess we're including something that
[metze/wireshark/wip.git] / ui / cli / tap-rtspstat.c
1 /* tap-rtspstat.c
2  * tap-rtspstat   March 2011 
3  *
4  * Stephane GORSE (Orange Labs / France Telecom)
5  * Copied from Jean-Michel FAYARD's works (HTTP)
6  *
7  * $Id$
8  *
9  * Wireshark - Network traffic analyzer
10  * By Gerald Combs <gerald@wireshark.org>
11  * Copyright 1998 Gerald Combs
12  * 
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  * 
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  * 
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26  */
27
28 #include "config.h"
29
30 #include <stdio.h>
31 #include <string.h>
32
33 #include "epan/packet_info.h"
34 #include "epan/value_string.h"
35 #include <epan/tap.h>
36 #include <epan/stat_cmd_args.h>
37 #include "register.h"
38 #include <epan/dissectors/packet-rtsp.h>
39
40         
41 /* used to keep track of the statictics for an entire program interface */
42 typedef struct _rtsp_stats_t {
43         char            *filter;
44         GHashTable      *hash_responses;
45         GHashTable      *hash_requests;
46 } rtspstat_t;
47
48 /* used to keep track of the stats for a specific response code
49  * for example it can be { 3, 404, "Not Found" ,...}
50  * which means we captured 3 reply rtsp/1.1 404 Not Found */
51 typedef struct _rtsp_response_code_t {
52         guint32          packets;               /* 3 */
53         guint            response_code; /* 404 */
54         const gchar     *name;                  /* Not Found */
55         rtspstat_t      *sp;
56 } rtsp_response_code_t;
57
58 /* used to keep track of the stats for a specific request string */
59 typedef struct _rtsp_request_methode_t {
60         gchar           *response;      /* eg. : SETUP */
61         guint32          packets;
62         rtspstat_t      *sp;
63 } rtsp_request_methode_t;
64
65
66 /* insert some entries */
67 static void
68 rtsp_init_hash( rtspstat_t *sp)
69 {
70         int i;
71
72         sp->hash_responses = g_hash_table_new( g_int_hash, g_int_equal);                
73                         
74         for (i=0 ; rtsp_status_code_vals[i].strptr ; i++ )
75         {
76                 gint *key = g_new (gint,1);
77                 rtsp_response_code_t *sc = g_new (rtsp_response_code_t,1);
78                 *key = rtsp_status_code_vals[i].value;
79                 sc->packets=0;
80                 sc->response_code =  *key;
81                 sc->name=rtsp_status_code_vals[i].strptr;
82                 sc->sp = sp;
83                 g_hash_table_insert( sc->sp->hash_responses, key, sc);
84         }
85         sp->hash_requests = g_hash_table_new( g_str_hash, g_str_equal);
86 }
87 static void
88 rtsp_draw_hash_requests( gchar *key _U_ , rtsp_request_methode_t *data, gchar * format)
89 {
90         if (data->packets==0)
91                 return;
92         printf( format, data->response, data->packets);                 
93 }
94
95 static void
96 rtsp_draw_hash_responses( gint * key _U_ , rtsp_response_code_t *data, char * format)
97 {
98         if (data==NULL) {
99                 g_warning("No data available, key=%d\n", *key);
100                 exit(EXIT_FAILURE);
101         }
102         if (data->packets==0)
103                 return;
104         /* "     RTSP %3d %-35s %9d packets", */
105         printf(format,  data->response_code, data->name, data->packets );
106 }
107                 
108
109                 
110 /* NOT USED at this moment */
111 /*
112 static void
113 rtsp_free_hash( gpointer key, gpointer value, gpointer user_data _U_ )
114 {
115         g_free(key);
116         g_free(value);
117 }
118 */
119 static void
120 rtsp_reset_hash_responses(gchar *key _U_ , rtsp_response_code_t *data, gpointer ptr _U_ )
121 {       
122         data->packets = 0;
123 }
124 static void
125 rtsp_reset_hash_requests(gchar *key _U_ , rtsp_request_methode_t *data, gpointer ptr _U_ )
126 {       
127         data->packets = 0;
128 }
129
130 static void
131 rtspstat_reset(void *psp  )
132 {
133         rtspstat_t *sp=(rtspstat_t *)psp;
134
135         g_hash_table_foreach( sp->hash_responses, (GHFunc)rtsp_reset_hash_responses, NULL);
136         g_hash_table_foreach( sp->hash_requests, (GHFunc)rtsp_reset_hash_requests, NULL);
137
138 }
139
140 static int
141 rtspstat_packet(void *psp , packet_info *pinfo _U_, epan_dissect_t *edt _U_, const void *pri)
142 {
143         const rtsp_info_value_t *value=(const rtsp_info_value_t *)pri;
144         rtspstat_t *sp=(rtspstat_t *) psp;
145
146         /* We are only interested in reply packets with a status code */
147         /* Request or reply packets ? */
148         if (value->response_code!=0) {
149                 guint *key=g_new(guint,1);
150                 rtsp_response_code_t *sc;
151
152                 *key=value->response_code;
153                 sc =  (rtsp_response_code_t *)g_hash_table_lookup( 
154                                 sp->hash_responses, 
155                                 key);
156                 if (sc==NULL){
157                         /* non standard status code ; we classify it as others
158                          * in the relevant category (Informational,Success,Redirection,Client Error,Server Error)
159                          */
160                         int i = value->response_code;
161                         if ((i<100) || (i>=600)) {
162                                 return 0;
163                         }
164                         else if (i<200){
165                                 *key=199;       /* Hopefully, this status code will never be used */
166                         }
167                         else if (i<300){
168                                 *key=299;
169                         }
170                         else if (i<400){
171                                 *key=399;
172                         }
173                         else if (i<500){
174                                 *key=499;
175                         }
176                         else{
177                                 *key=599;
178                         }
179                         sc =  (rtsp_response_code_t *)g_hash_table_lookup( 
180                                 sp->hash_responses, 
181                                 key);
182                         if (sc==NULL)
183                                 return 0;
184                 }
185                 sc->packets++;
186         } 
187         else if (value->request_method){
188                 rtsp_request_methode_t *sc;
189
190                 sc =  (rtsp_request_methode_t *)g_hash_table_lookup( 
191                                 sp->hash_requests, 
192                                 value->request_method);
193                 if (sc==NULL){
194                         sc=g_new(rtsp_request_methode_t,1);
195                         sc->response=g_strdup( value->request_method );
196                         sc->packets=1;
197                         sc->sp = sp;
198                         g_hash_table_insert( sp->hash_requests, sc->response, sc);
199                 } else {
200                         sc->packets++;
201                 }
202         } else {
203                 return 0;
204         }
205         return 1;
206 }
207
208
209 static void
210 rtspstat_draw(void *psp  )
211 {
212         rtspstat_t *sp=(rtspstat_t *)psp;
213         printf("\n");
214         printf("===================================================================\n");
215         if (! sp->filter[0])
216                 printf("RTSP Statistics\n");
217         else
218                 printf("RTSP Statistics with filter %s\n", sp->filter);
219
220         printf( "* RTSP Status Codes in reply packets\n");
221         g_hash_table_foreach( sp->hash_responses, (GHFunc)rtsp_draw_hash_responses,
222                 (gpointer)"    RTSP %3d %s\n");
223         printf("* List of RTSP Request methods\n");
224         g_hash_table_foreach( sp->hash_requests,  (GHFunc)rtsp_draw_hash_requests,
225                 (gpointer)"    %9s %d \n");
226         printf("===================================================================\n");
227 }
228
229
230
231 /* When called, this function will create a new instance of gtk_rtspstat.
232  */
233 static void
234 gtk_rtspstat_init(const char *opt_arg,void* userdata _U_)
235 {
236         rtspstat_t *sp;
237         const char *filter=NULL;
238         GString *error_string;
239         
240         if (!strncmp (opt_arg, "rtsp,stat,", 10)){
241                 filter=opt_arg+10;
242         } else {
243                 filter=NULL;
244         }
245         
246         sp = (rtspstat_t *)g_malloc( sizeof(rtspstat_t) );
247         if(filter){
248                 sp->filter=g_strdup(filter);
249         } else {
250                 sp->filter=NULL;
251         }
252         /*g_hash_table_foreach( rtsp_status, (GHFunc)rtsp_reset_hash_responses, NULL);*/
253
254
255         error_string = register_tap_listener( 
256                         "rtsp",
257                         sp,
258                         filter,
259                         0,
260                         rtspstat_reset,
261                         rtspstat_packet,
262                         rtspstat_draw);
263         if (error_string){
264                 /* error, we failed to attach to the tap. clean up */
265                 g_free(sp->filter);
266                 g_free(sp);
267                 fprintf (stderr, "tshark: Couldn't register rtsp,stat tap: %s\n",
268                                 error_string->str);
269                 g_string_free(error_string, TRUE);
270                 exit(1);
271         }
272
273         rtsp_init_hash(sp);
274 }
275
276 void
277 register_tap_listener_gtkrtspstat(void)
278 {
279         register_stat_cmd_arg("rtsp,stat,", gtk_rtspstat_init,NULL);
280 }