bugfix: using the "rtp_example.raw.gz" from the wiki, the dialog runs into an endless...
[metze/wireshark/wip.git] / gtk / voip_calls.c
1 /* voip_calls.c
2  * VoIP calls summary addition for ethereal
3  *
4  * $Id$
5  *
6  * Copyright 2004, Ericsson, Spain
7  * By Francisco Alcoba <francisco.alcoba@ericsson.com>
8  *
9  * based on h323_calls.c
10  * Copyright 2004, Iskratel, Ltd, Kranj
11  * By Miha Jemec <m.jemec@iskratel.si>
12  * 
13  * H323, RTP and Graph Support
14  * By Alejandro Vaquero, alejandro.vaquero@verso.com
15  * Copyright 2005, Verso Technologies Inc.
16  *
17  * Ethereal - Network traffic analyzer
18  * By Gerald Combs <gerald@ethereal.com>
19  * Copyright 1998 Gerald Combs
20  *
21  * This program is free software; you can redistribute it and/or
22  * modify it under the terms of the GNU General Public License
23  * as published by the Free Software Foundation; either version 2
24  * of the License, or (at your option) any later version.
25  *
26  * This program is distributed in the hope that it will be useful,
27  * but WITHOUT ANY WARRANTY; without even the implied warranty of
28  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29  * GNU General Public License for more details.
30  *
31  * You should have received a copy of the GNU General Public License
32  * along with this program; if not, write to the Free Software
33  * Foundation,  Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
34  */
35
36 #ifdef HAVE_CONFIG_H
37 # include "config.h"
38 #endif
39
40 #include <string.h>
41
42 #include "graph_analysis.h"
43 #include "voip_calls.h"
44 #include "voip_calls_dlg.h"
45
46 #include "globals.h"
47
48 #include <epan/tap.h>
49 #include <epan/dissectors/packet-sip.h>
50 #include <epan/dissectors/packet-mtp3.h>
51 #include <epan/dissectors/packet-isup.h>
52 #include <epan/dissectors/packet-h225.h>
53 #include <epan/dissectors/packet-h245.h>
54 #include <epan/dissectors/packet-q931.h>
55 #include <epan/dissectors/packet-sdp.h>
56 #include <plugins/mgcp/packet-mgcp.h>
57 #include <epan/dissectors/packet-rtp.h>
58 #include "rtp_pt.h"
59
60 #include "alert_box.h"
61 #include "simple_dialog.h"
62
63 char *voip_call_state_name[7]={
64         "CALL SETUP",
65         "RINGING",
66         "IN CALL",
67         "CANCELLED",
68         "COMPLETED",
69         "REJECTED",
70         "UNKNOWN"
71         };
72
73 /* defines whether we can consider the call active */
74 char *voip_protocol_name[4]={
75         "SIP",
76         "ISUP",
77         "H323",
78         "MGCP"
79         };
80
81
82
83 /****************************************************************************/
84 /* the one and only global voip_calls_tapinfo_t structure */
85 static voip_calls_tapinfo_t the_tapinfo_struct =
86         {0, NULL, 0, NULL, 0, 0, 0, 0, NULL, 0, 0, 0, 0, 0, 0, 0, 0};
87
88 /* the one and only global voip_rtp_tapinfo_t structure */
89 static voip_rtp_tapinfo_t the_tapinfo_rtp_struct =
90         {0, NULL, 0};
91
92 /****************************************************************************/
93 /* when there is a [re]reading of packet's */
94 void voip_calls_reset(voip_calls_tapinfo_t *tapinfo)
95 {
96         voip_calls_info_t *strinfo;
97         sip_calls_info_t *tmp_sipinfo;
98         h323_calls_info_t *tmp_h323info;
99
100         graph_analysis_item_t *graph_item;
101
102         GList* list;
103         GList* list2;
104
105         /* free the data items first */
106         list = g_list_first(tapinfo->strinfo_list);
107         while (list)
108         {
109                 strinfo = list->data;
110                 g_free(strinfo->from_identity);
111                 g_free(strinfo->to_identity);
112                 if (strinfo->protocol == VOIP_SIP){
113                         tmp_sipinfo = strinfo->prot_info;
114                         g_free(tmp_sipinfo->call_identifier);
115                 }
116                 if (strinfo->protocol == VOIP_H323){
117                         tmp_h323info = strinfo->prot_info;
118                         g_free(tmp_h323info->guid);
119                         /* free the H245 list address */
120                         list2 = g_list_first(tmp_h323info->h245_list);
121                         while (list2)
122                         {
123                                 g_free(list2->data);
124                                 list2 = g_list_next(list2);
125                         }
126                         g_list_free(tmp_h323info->h245_list);
127                         tmp_h323info->h245_list = NULL;
128                 }
129                 g_free(strinfo->prot_info);
130
131                 g_free(list->data);
132                 list = g_list_next(list);
133         }
134         g_list_free(tapinfo->strinfo_list);
135         tapinfo->strinfo_list = NULL;
136         tapinfo->ncalls = 0;
137         tapinfo->npackets = 0;
138         tapinfo->start_packets = 0;
139     tapinfo->completed_calls = 0;
140     tapinfo->rejected_calls = 0;
141
142         /* free the graph data items first */
143         list = g_list_first(tapinfo->graph_analysis->list);
144         while (list)
145         {
146                 graph_item = list->data;
147                 g_free(graph_item->frame_label);
148                 g_free(graph_item->comment);
149                 g_free(list->data);
150                 list = g_list_next(list);
151         }
152         g_list_free(tapinfo->graph_analysis->list);
153         tapinfo->graph_analysis->nconv = 0;
154         tapinfo->graph_analysis->list = NULL;
155
156         ++(tapinfo->launch_count);
157
158         return;
159 }
160
161 /****************************************************************************/
162 void graph_analysis_data_init(void){
163         the_tapinfo_struct.graph_analysis = g_malloc(sizeof(graph_analysis_info_t));
164         the_tapinfo_struct.graph_analysis->nconv = 0;
165         the_tapinfo_struct.graph_analysis->list = NULL;
166
167 }
168
169 /****************************************************************************/
170 /* Add a new item into the graph */
171 int add_to_graph(voip_calls_tapinfo_t *tapinfo _U_, packet_info *pinfo, gchar *frame_label, gchar *comment, guint16 call_num)
172 {
173         graph_analysis_item_t *gai;
174
175         gai = g_malloc(sizeof(graph_analysis_item_t));
176         gai->frame_num = pinfo->fd->num;
177         gai->time= (double)pinfo->fd->rel_secs + (double) pinfo->fd->rel_usecs/1000000;
178         g_memmove(&gai->ip_src, pinfo->src.data, 4);
179         g_memmove(&gai->ip_dst, pinfo->dst.data, 4);
180         gai->port_src=pinfo->srcport;
181         gai->port_dst=pinfo->destport;
182         if (frame_label != NULL)
183                 gai->frame_label = g_strdup(frame_label);
184         else
185                 gai->frame_label = g_strdup("");
186
187         if (comment != NULL)
188                 gai->comment = g_strdup(comment);
189         else
190                 gai->comment = g_strdup("");
191         gai->conv_num=call_num;
192         gai->line_style=1;
193         gai->display=FALSE;
194
195         tapinfo->graph_analysis->list = g_list_append(tapinfo->graph_analysis->list, gai);
196
197         return 1;
198
199 }
200
201 /****************************************************************************/
202 /* Append str to frame_label and comment in a graph item */
203 /* return 0 if the frame_num is not in the graph list */
204 int append_to_frame_graph(voip_calls_tapinfo_t *tapinfo _U_, guint32 frame_num, const gchar *new_frame_label, const gchar *new_comment)
205 {
206         graph_analysis_item_t *gai;
207         GList* list;
208         gchar *tmp_str = NULL;
209         gchar *tmp_str2 = NULL;
210
211         list = g_list_first(tapinfo->graph_analysis->list);
212         while (list)
213         {
214                 gai = list->data;
215                 if (gai->frame_num == frame_num){
216                         tmp_str = gai->frame_label;
217                         tmp_str2 = gai->comment;
218
219                         if (new_frame_label != NULL){
220                                 gai->frame_label = g_strdup_printf("%s %s", gai->frame_label, new_frame_label);
221                                 g_free(tmp_str);
222                         }
223
224
225                         if (new_comment != NULL){
226                                 gai->comment = g_strdup_printf("%s %s", gai->comment, new_comment);
227                                 g_free(tmp_str2);
228                         }
229                         break;
230                 }
231                 list = g_list_next (list);
232         }
233         if (tmp_str == NULL) return 0;          /* it is not in the list */
234         return 1;
235
236 }
237
238 /****************************************************************************/
239 /* Change all the graph items with call_num to new_call_num */
240 guint change_call_num_graph(voip_calls_tapinfo_t *tapinfo _U_, guint16 call_num, guint16 new_call_num)
241 {
242         graph_analysis_item_t *gai;
243         GList* list;
244         guint items_changed;
245
246         items_changed = 0;
247         list = g_list_first(tapinfo->graph_analysis->list);
248         while (list)
249         {
250                 gai = list->data;
251                 if (gai->conv_num == call_num){
252                         gai->conv_num = new_call_num;
253                         items_changed++;
254                 }
255                 list = g_list_next (list);
256         }
257         return items_changed;
258 }
259
260 /****************************************************************************/
261 /* ***************************TAP for RTP **********************************/
262 /****************************************************************************/
263
264 /****************************************************************************/
265 /* when there is a [re]reading of RTP packet's */
266 void voip_rtp_reset(void *ptr _U_)
267 {
268         voip_rtp_tapinfo_t *tapinfo = &the_tapinfo_rtp_struct;
269         GList* list;
270         /* free the data items first */
271         list = g_list_first(tapinfo->list);
272         while (list)
273         {
274                 g_free(list->data);
275                 list = g_list_next(list);
276         }
277         g_list_free(tapinfo->list);
278         tapinfo->list = NULL;
279         tapinfo->nstreams = 0;
280         return;
281 }
282
283 /****************************************************************************/
284 /* whenever a RTP packet is seen by the tap listener */
285 static int 
286 RTP_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *RTPinfo)
287 {
288         voip_rtp_tapinfo_t *tapinfo = &the_tapinfo_rtp_struct;
289         voip_rtp_stream_info_t *tmp_listinfo;
290         voip_rtp_stream_info_t *strinfo = NULL;
291         GList* list;
292
293         const struct _rtp_info *pi = RTPinfo;
294
295         /* do not consider RTP packets without a setup frame */
296         if (pi->info_setup_frame_num == 0){
297                 return 0;
298         }
299
300         /* check wether we already have a RTP stream with this setup frame and ssrc in the list */
301         list = g_list_first(tapinfo->list);
302         while (list)
303         {
304                 tmp_listinfo=list->data;
305                 if ( (tmp_listinfo->setup_frame_number == pi->info_setup_frame_num) && (tmp_listinfo->ssrc == pi->info_sync_src) ){
306                                 strinfo = (voip_rtp_stream_info_t*)(list->data);
307                                 break;
308                 }
309                 list = g_list_next (list);
310         }
311
312         /* not in the list? then create a new entry */
313         if (strinfo==NULL){
314                 strinfo = g_malloc(sizeof(voip_rtp_stream_info_t));
315                 COPY_ADDRESS(&(strinfo->src_addr), &(pinfo->src));
316                 strinfo->src_port = pinfo->srcport;
317                 COPY_ADDRESS(&(strinfo->dest_addr), &(pinfo->dst));
318                 strinfo->dest_port = pinfo->destport;
319                 strinfo->ssrc = pi->info_sync_src;
320                 strinfo->pt = pi->info_payload_type;
321                 strinfo->npackets = 0;
322                 strinfo->first_frame_num = pinfo->fd->num;
323                 strinfo->start_rel_sec = pinfo->fd->rel_secs;
324                 strinfo->start_rel_usec = pinfo->fd->rel_usecs;
325                 strinfo->setup_frame_number = pi->info_setup_frame_num;
326                 tapinfo->list = g_list_append(tapinfo->list, strinfo);
327         }
328
329         if (strinfo!=NULL){
330                 /* Add the info to the existing RTP stream */
331                 strinfo->npackets++;
332                 strinfo->stop_rel_sec = pinfo->fd->rel_secs;
333                 strinfo->stop_rel_usec = pinfo->fd->rel_usecs;
334         }
335         return 1;
336 }
337
338 /****************************************************************************/
339 /* whenever a redraw in the RTP tap listener */
340 void RTP_packet_draw(void *prs _U_)
341 {
342         voip_rtp_tapinfo_t *rtp_tapinfo = &the_tapinfo_rtp_struct;
343         GList* rtp_streams_list;
344         voip_rtp_stream_info_t *rtp_listinfo;
345         GList* voip_calls_graph_list;
346         guint item;
347         graph_analysis_item_t *gai;
348         graph_analysis_item_t *new_gai;
349         guint16 conv_num;
350         guint32 duration;
351
352         /* add each rtp stream to the graph */
353         rtp_streams_list = g_list_first(rtp_tapinfo->list);
354         while (rtp_streams_list)
355         {
356                 rtp_listinfo = rtp_streams_list->data;
357
358                 /* using the setup frame number of the RTP stream, we get the call number that it belongs */
359                 voip_calls_graph_list = g_list_first(the_tapinfo_struct.graph_analysis->list);
360                 item = 0;
361                 while (voip_calls_graph_list)
362                 {                       
363                         gai = voip_calls_graph_list->data;
364                         conv_num = gai->conv_num;
365                         /* if we get the setup frame number, then get the time position to graph the RTP arrow */
366                         if (rtp_listinfo->setup_frame_number == gai->frame_num){
367                                 while(voip_calls_graph_list){
368                                         gai = voip_calls_graph_list->data;
369                                         /* if RTP was already in the Graph, just update the comment information */
370                                         if (rtp_listinfo->first_frame_num == gai->frame_num){
371                                                 duration = (rtp_listinfo->stop_rel_sec*1000000 + rtp_listinfo->stop_rel_usec) - (rtp_listinfo->start_rel_sec*1000000 + rtp_listinfo->start_rel_usec);
372                                                 g_free(gai->comment);
373                                                 gai->comment = g_strdup_printf("RTP Num packets:%d  Duration:%d.%03ds ssrc:%d", rtp_listinfo->npackets, duration/1000000,(duration%1000000)/1000, rtp_listinfo->ssrc);
374                                                 break;
375                                         /* add the RTP item to the graph if was not there*/
376                                         } else if (rtp_listinfo->first_frame_num<gai->frame_num){
377                                                 new_gai = g_malloc(sizeof(graph_analysis_item_t));
378                                                 new_gai->frame_num = rtp_listinfo->first_frame_num;
379                                                 new_gai->time = (double)rtp_listinfo->start_rel_sec + (double)rtp_listinfo->start_rel_usec/1000000;
380                                                 g_memmove(&new_gai->ip_src, rtp_listinfo->src_addr.data, 4);
381                                                 g_memmove(&new_gai->ip_dst, rtp_listinfo->dest_addr.data, 4);
382                                                 new_gai->port_src = rtp_listinfo->src_port;
383                                                 new_gai->port_dst = rtp_listinfo->dest_port;
384                                                 duration = (rtp_listinfo->stop_rel_sec*1000000 + rtp_listinfo->stop_rel_usec) - (rtp_listinfo->start_rel_sec*1000000 + rtp_listinfo->start_rel_usec);
385                                                 new_gai->frame_label = g_strdup_printf("RTP (%s)", val_to_str(rtp_listinfo->pt, rtp_payload_type_short_vals, "%u"));
386                                                 new_gai->comment = g_strdup_printf("RTP Num packets:%d  Duration:%d.%03ds ssrc:%d", rtp_listinfo->npackets, duration/1000000,(duration%1000000)/1000, rtp_listinfo->ssrc);
387                                                 new_gai->conv_num = conv_num;
388                                                 new_gai->display=FALSE;
389                                                 new_gai->line_style = 2;  /* the arrow line will be 2 pixels width */
390                                                 the_tapinfo_struct.graph_analysis->list = g_list_insert(the_tapinfo_struct.graph_analysis->list, new_gai, item);
391                                                 break;
392                                         }
393                                         
394                                         voip_calls_graph_list = g_list_next(voip_calls_graph_list);
395                                         item++;
396                                 }
397                                 break;
398                         }
399                         voip_calls_graph_list = g_list_next(voip_calls_graph_list);
400                         item++;
401                 }
402                 rtp_streams_list = g_list_next(rtp_streams_list);
403         }
404 }
405
406 static gboolean have_RTP_tap_listener=FALSE;
407 /****************************************************************************/
408 void
409 rtp_init_tap(void)
410 {
411         GString *error_string;
412
413         if(have_RTP_tap_listener==FALSE)
414         {
415                 /* don't register tap listener, if we have it already */
416                 error_string = register_tap_listener("rtp", &(the_tapinfo_rtp_struct.rtp_dummy), NULL,
417                         voip_rtp_reset, 
418                         RTP_packet, 
419                         RTP_packet_draw
420                         );
421                 if (error_string != NULL) {
422                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
423                                       error_string->str);
424                         g_string_free(error_string, TRUE);
425                         exit(1);
426                 }
427                 have_RTP_tap_listener=TRUE;
428         }
429 }
430
431
432
433 /* XXX just copied from gtk/rpc_stat.c */
434 void protect_thread_critical_region(void);
435 void unprotect_thread_critical_region(void);
436
437 /****************************************************************************/
438 void
439 remove_tap_listener_rtp(void)
440 {
441         protect_thread_critical_region();
442         remove_tap_listener(&(the_tapinfo_rtp_struct.rtp_dummy));
443         unprotect_thread_critical_region();
444
445         have_RTP_tap_listener=FALSE;
446 }
447
448 /****************************************************************************/
449 /* ***************************TAP for SIP **********************************/
450 /****************************************************************************/
451
452 /****************************************************************************/
453 /* whenever a SIP packet is seen by the tap listener */
454 static int 
455 SIPcalls_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *SIPinfo)
456 {
457         voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
458         /* we just take note of the ISUP data here; when we receive the MTP3 part everything will
459            be compared with existing calls */
460
461         voip_calls_info_t *tmp_listinfo;
462         voip_calls_info_t *strinfo = NULL;
463         sip_calls_info_t *tmp_sipinfo = NULL;
464         GList* list;
465         guint32 tmp_src, tmp_dst;
466         gchar *frame_label = NULL;
467         gchar *comment = NULL;
468
469         const sip_info_value_t *pi = SIPinfo;
470
471         /* do not consider packets without call_id */
472         if (pi->tap_call_id ==NULL){
473                 return 0;
474         }
475
476         /* check wether we already have a call with these parameters in the list */
477         list = g_list_first(tapinfo->strinfo_list);
478         while (list)
479         {
480                 tmp_listinfo=list->data;
481                 if (tmp_listinfo->protocol == VOIP_SIP){
482                         tmp_sipinfo = tmp_listinfo->prot_info;
483                         if (strcmp(tmp_sipinfo->call_identifier,pi->tap_call_id)==0){
484                                 strinfo = (voip_calls_info_t*)(list->data);
485                                 break;
486                         }
487                 }
488                 list = g_list_next (list);
489         }
490
491         /* not in the list? then create a new entry if the message is INVITE -i.e. if this session is a call*/
492         if ((strinfo==NULL) &&(pi->request_method!=NULL)){
493                 if (strcmp(pi->request_method,"INVITE")==0){
494                         strinfo = g_malloc(sizeof(voip_calls_info_t));
495                         strinfo->call_active_state = VOIP_ACTIVE;
496                         strinfo->call_state = VOIP_CALL_SETUP;
497                         strinfo->from_identity=g_strdup(pi->tap_from_addr);
498                         strinfo->to_identity=g_strdup(pi->tap_to_addr);
499                         g_memmove(&(strinfo->initial_speaker), pinfo->src.data, 4);
500                         strinfo->first_frame_num=pinfo->fd->num;
501                         strinfo->selected=FALSE;
502                         strinfo->start_sec=pinfo->fd->rel_secs;
503                         strinfo->start_usec=pinfo->fd->rel_usecs;
504                         strinfo->protocol=VOIP_SIP;
505                         strinfo->prot_info=g_malloc(sizeof(sip_calls_info_t));
506                         tmp_sipinfo=strinfo->prot_info;
507                         tmp_sipinfo->call_identifier=strdup(pi->tap_call_id);
508                         tmp_sipinfo->sip_state=SIP_INVITE_SENT;
509                         tmp_sipinfo->invite_cseq=pi->tap_cseq_number;
510                         strinfo->npackets = 0;
511                         strinfo->call_num = tapinfo->ncalls++;
512                         tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
513                 }
514         }
515
516         g_free(pi->tap_from_addr);
517         g_free(pi->tap_to_addr);
518         g_free(pi->tap_call_id);
519
520         if (strinfo!=NULL){
521
522                 /* let's analyze the call state */
523
524                 g_memmove(&(tmp_src), pinfo->src.data, 4);
525                 g_memmove(&(tmp_dst), pinfo->dst.data, 4);
526                 
527                 if (pi->request_method == NULL){
528                         frame_label = g_strdup_printf("%d %s", pi->response_code, pi->reason_phrase );
529                         comment = g_strdup_printf("SIP Status");
530
531                         if ((tmp_sipinfo && pi->tap_cseq_number == tmp_sipinfo->invite_cseq)&&(tmp_dst==strinfo->initial_speaker)){
532                                 if ((pi->response_code > 199) && (pi->response_code<300) && (tmp_sipinfo->sip_state == SIP_INVITE_SENT)){
533                                         tmp_sipinfo->sip_state = SIP_200_REC;
534                                 }
535                                 else if ((pi->response_code>299)&&(tmp_sipinfo->sip_state == SIP_INVITE_SENT)){
536                                         strinfo->call_state = VOIP_REJECTED;
537                                         tapinfo->rejected_calls++;
538                                 }
539                         }
540
541                 }
542                 else{
543                         frame_label = g_strdup(pi->request_method);
544
545                         if ((strcmp(pi->request_method,"INVITE")==0)&&(tmp_src == strinfo->initial_speaker)){
546                                 tmp_sipinfo->invite_cseq = pi->tap_cseq_number;
547                                 comment = g_strdup_printf("SIP From: %s To:%s", strinfo->from_identity, strinfo->to_identity);
548                         }
549                         else if ((strcmp(pi->request_method,"ACK")==0)&&(pi->tap_cseq_number == tmp_sipinfo->invite_cseq)
550                                 &&(tmp_src == strinfo->initial_speaker)&&(tmp_sipinfo->sip_state==SIP_200_REC)){
551                                 strinfo->call_state = VOIP_IN_CALL;
552                                 comment = g_strdup_printf("SIP Request");
553                         }
554                         else if (strcmp(pi->request_method,"BYE")==0){
555                                 strinfo->call_state = VOIP_COMPLETED;
556                                 tapinfo->completed_calls++;
557                                 comment = g_strdup_printf("SIP Request");
558                         }
559                         else if ((strcmp(pi->request_method,"CANCEL")==0)&&(pi->tap_cseq_number == tmp_sipinfo->invite_cseq)
560                                 &&(tmp_src == strinfo->initial_speaker)&&(strinfo->call_state==VOIP_CALL_SETUP)){
561                                 strinfo->call_state = VOIP_CANCELLED;
562                                 tmp_sipinfo->sip_state = SIP_CANCEL_SENT;
563                                 comment = g_strdup_printf("SIP Request");
564                         } else {
565                                 comment = g_strdup_printf("SIP Request");
566                         }
567                 }
568
569                 strinfo->stop_sec=pinfo->fd->rel_secs;
570                 strinfo->stop_usec=pinfo->fd->rel_usecs;
571                 strinfo->last_frame_num=pinfo->fd->num;
572                 ++(strinfo->npackets);
573                 /* increment the packets counter of all calls */
574                 ++(tapinfo->npackets);
575
576                 /* add to the graph */
577                 add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num);  
578                 g_free(comment);
579                 g_free(frame_label);
580         }
581         return 1;  /* refresh output */
582 }
583
584
585 /****************************************************************************/
586 const voip_calls_tapinfo_t* voip_calls_get_info(void)
587 {
588         return &the_tapinfo_struct;
589 }
590
591
592 /****************************************************************************/
593 /* TAP INTERFACE */
594 /****************************************************************************/
595 static gboolean have_SIP_tap_listener=FALSE;
596 /****************************************************************************/
597 void
598 sip_calls_init_tap(void)
599 {
600         GString *error_string;
601
602         if(have_SIP_tap_listener==FALSE)
603         {
604                 /* don't register tap listener, if we have it already */
605                 error_string = register_tap_listener("sip", &(the_tapinfo_struct.sip_dummy), NULL,
606                         voip_calls_dlg_reset, 
607                         SIPcalls_packet, 
608                         voip_calls_dlg_draw
609                         );
610                 if (error_string != NULL) {
611                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
612                                       error_string->str);
613                         g_string_free(error_string, TRUE);
614                         exit(1);
615                 }
616                 have_SIP_tap_listener=TRUE;
617         }
618 }
619
620
621
622 /* XXX just copied from gtk/rpc_stat.c */
623 void protect_thread_critical_region(void);
624 void unprotect_thread_critical_region(void);
625
626 /****************************************************************************/
627 void
628 remove_tap_listener_sip_calls(void)
629 {
630         protect_thread_critical_region();
631         remove_tap_listener(&(the_tapinfo_struct.sip_dummy));
632         unprotect_thread_critical_region();
633
634         have_SIP_tap_listener=FALSE;
635 }
636
637 /****************************************************************************/
638 /* ***************************TAP for ISUP **********************************/
639 /****************************************************************************/
640
641 static gchar            isup_called_number[255], isup_calling_number[255];
642 static guint16          isup_cic;
643 static guint8           isup_message_type;
644 static guint8           isup_cause_value;
645
646 /****************************************************************************/
647 /* whenever a isup_ packet is seen by the tap listener */
648 static int 
649 isup_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *isup_info _U_)
650 {
651         /*voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct; unused */
652         const isup_tap_rec_t *pi = isup_info;
653
654         if (pi->calling_number!=NULL){
655                 strcpy(isup_calling_number, pi->calling_number);
656         }
657         if (pi->called_number!=NULL){
658                 strcpy(isup_called_number, pi->called_number);
659         }
660         isup_message_type = pi->message_type;
661         isup_cause_value = pi->cause_value;
662         isup_cic = pinfo->circuit_id;
663
664         return 0;
665 }
666
667 /****************************************************************************/
668
669 static gboolean have_isup_tap_listener=FALSE;
670
671 void
672 isup_calls_init_tap(void)
673 {
674         GString *error_string;
675
676
677         if(have_isup_tap_listener==FALSE)
678         {
679                 error_string = register_tap_listener("isup", &(the_tapinfo_struct.isup_dummy),
680                         NULL,
681                         voip_calls_dlg_reset, 
682                         isup_calls_packet, 
683                         voip_calls_dlg_draw
684                         );
685         
686                 if (error_string != NULL) {
687                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
688                                       error_string->str);
689                         g_string_free(error_string, TRUE);
690                         exit(1);
691                 }
692                 have_isup_tap_listener=TRUE;
693         }
694 }
695
696 /****************************************************************************/
697
698 void
699 remove_tap_listener_isup_calls(void)
700 {
701         protect_thread_critical_region();
702         remove_tap_listener(&(the_tapinfo_struct.isup_dummy));
703         unprotect_thread_critical_region();
704
705         have_isup_tap_listener=FALSE;
706 }
707
708
709 /****************************************************************************/
710 /* ***************************TAP for MTP3 **********************************/
711 /****************************************************************************/
712
713
714 /****************************************************************************/
715 /* whenever a mtp3_ packet is seen by the tap listener */
716 static int 
717 mtp3_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *mtp3_info _U_)
718 {
719         voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
720         voip_calls_info_t *tmp_listinfo;
721         voip_calls_info_t *strinfo = NULL;
722         isup_calls_info_t *tmp_isupinfo;
723         gboolean found = FALSE;
724         gboolean forward = FALSE;
725         gboolean right_pair = TRUE;
726         GList* list;
727         gchar *frame_label = NULL;
728         gchar *comment = NULL;
729         int i;
730
731         const mtp3_tap_rec_t *pi = mtp3_info;
732
733         /* check wether we already have a call with these parameters in the list */
734         list = g_list_first(tapinfo->strinfo_list);
735         while (list)
736         {
737                 tmp_listinfo=list->data;
738                 if ((tmp_listinfo->protocol == VOIP_ISUP)&&(tmp_listinfo->call_active_state==VOIP_ACTIVE)){
739                         tmp_isupinfo = tmp_listinfo->prot_info;
740                         if ((tmp_isupinfo->cic == isup_cic)&&(tmp_isupinfo->ni == pi->addr_opc.ni)) {
741                                 if ((tmp_isupinfo->opc == pi->addr_opc.pc)&&(tmp_isupinfo->dpc == pi->addr_dpc.pc)){
742                                          forward = TRUE;
743                                  }
744                                  else if ((tmp_isupinfo->dpc == pi->addr_opc.pc)&&(tmp_isupinfo->opc == pi->addr_dpc.pc)){
745                                          forward = FALSE;
746                                  }
747                                  else{
748                                          /* XXX: what about forward is it FALSE as declared or should it be true */
749                                          right_pair = FALSE;
750                                  }
751                                  if (right_pair){
752                                         /* if there is an IAM for a call that is not in setup state, that means the previous call in the same
753                                            cic is no longer active */
754                                         if (tmp_listinfo->call_state == VOIP_CALL_SETUP){
755                                                 found = TRUE;
756                                         }
757                                         else if (isup_message_type != 1){
758                                                 found = TRUE;
759                                         }
760                                         else{
761                                                 tmp_listinfo->call_active_state=VOIP_INACTIVE;
762                                         }
763                                 }
764                                 if (found){
765                                         strinfo = (voip_calls_info_t*)(list->data);
766                                         break;
767                                 }
768                         }
769                 }
770                 list = g_list_next (list);
771         }
772
773         /* not in the list? then create a new entry if the message is IAM
774            -i.e. if this session is a call*/
775
776
777         if ((strinfo==NULL) &&(isup_message_type==1)){
778
779                 strinfo = g_malloc(sizeof(voip_calls_info_t));
780                 strinfo->call_active_state = VOIP_ACTIVE;
781                 strinfo->call_state = VOIP_UNKNOWN;
782                 g_memmove(&(strinfo->initial_speaker), pinfo->src.data, 4);
783                 strinfo->selected=FALSE;
784                 strinfo->first_frame_num=pinfo->fd->num;
785                 strinfo->start_sec=pinfo->fd->rel_secs;
786                 strinfo->start_usec=pinfo->fd->rel_usecs;
787                 strinfo->protocol=VOIP_ISUP;
788                 strinfo->from_identity=g_strdup(isup_calling_number);
789                 strinfo->to_identity=g_strdup(isup_called_number);
790                 strinfo->prot_info=g_malloc(sizeof(isup_calls_info_t));
791                 tmp_isupinfo=strinfo->prot_info;
792                 tmp_isupinfo->opc = pi->addr_opc.pc;
793                 tmp_isupinfo->dpc = pi->addr_dpc.pc;
794                 tmp_isupinfo->ni = pi->addr_opc.ni;
795                 tmp_isupinfo->cic = pinfo->circuit_id;
796                 strinfo->npackets = 0;
797                 strinfo->call_num = tapinfo->ncalls++;
798                 tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
799         }
800
801         if (strinfo!=NULL){
802                 strinfo->stop_sec=pinfo->fd->rel_secs;
803                 strinfo->stop_usec=pinfo->fd->rel_usecs;
804                 strinfo->last_frame_num=pinfo->fd->num;
805                 ++(strinfo->npackets);
806
807                 /* Let's analyze the call state */
808
809
810                 for (i=0;(isup_message_type_value[i].strptr!=NULL)&& (isup_message_type_value[i].value!=isup_message_type);i++);
811
812                 if (isup_message_type_value[i].value==isup_message_type){
813                         frame_label = g_strdup(isup_message_type_value_acro[i].strptr);
814                 }
815                 else{
816                         frame_label = g_strdup_printf("Unknown");
817                 }
818
819                 if (strinfo->npackets == 1){ /* this is the first packet, that must be an IAM */
820                         comment = g_strdup_printf("Call from %s to %s",
821                          isup_calling_number, isup_called_number);
822                 }
823                 else if (strinfo->npackets == 2){ /* in the second packet we show the SPs */
824                         if (forward){
825                                 comment = g_strdup_printf("%i-%i -> %i-%i. Cic:%i",
826                                  pi->addr_opc.ni, pi->addr_opc.pc,
827                                  pi->addr_opc.ni, pi->addr_dpc.pc, pinfo->circuit_id);
828
829                         }
830                         else{
831                                 comment = g_strdup_printf("%i-%i -> %i-%i. Cic:%i",
832                                  pi->addr_opc.ni, pi->addr_dpc.pc,
833                                  pi->addr_opc.ni, pi->addr_opc.pc, pinfo->circuit_id);
834
835                         }
836                 }
837
838                 switch(isup_message_type){
839                         case 1: /* IAM */
840                                 strinfo->call_state=VOIP_CALL_SETUP;
841                                 break;
842                         case 7: /* CONNECT */
843                         case 9: /* ANSWER */
844                                 strinfo->call_state=VOIP_IN_CALL;
845                                 break;
846                         case 12: /* RELEASE */
847                                 if (strinfo->call_state==VOIP_CALL_SETUP){
848                                         if (forward){
849                                                 strinfo->call_state=VOIP_CANCELLED;
850                                         }
851                                         else{
852                                                 strinfo->call_state=VOIP_REJECTED;
853                                                 tapinfo->rejected_calls++;
854                                         }
855                                 }
856                                 else if (strinfo->call_state == VOIP_IN_CALL){
857                                         strinfo->call_state = VOIP_COMPLETED;
858                                         tapinfo->completed_calls++;
859                                 }
860                                 for (i=0;(q931_cause_code_vals[i].strptr!=NULL)&& (q931_cause_code_vals[i].value!=isup_cause_value);i++);
861                                 if (q931_cause_code_vals[i].value==isup_cause_value){
862                                         comment = g_strdup_printf("Cause %i - %s",isup_cause_value, q931_cause_code_vals[i].strptr);
863                                 }
864                                 else{
865                                         comment = g_strdup_printf("Cause %i",isup_cause_value);
866                                 }
867                                 break;
868                 }
869
870                 /* increment the packets counter of all calls */
871                 ++(tapinfo->npackets);
872
873                 /* add to the graph */
874                 add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num);  
875                 g_free(comment);
876                 g_free(frame_label);
877         }
878
879
880         return 1;
881 }
882
883 /****************************************************************************/
884
885 static gboolean have_mtp3_tap_listener=FALSE;
886
887 void
888 mtp3_calls_init_tap(void)
889 {
890         GString *error_string;
891
892
893         if(have_mtp3_tap_listener==FALSE)
894         {
895                 error_string = register_tap_listener("mtp3", &(the_tapinfo_struct.mtp3_dummy),
896                         NULL,
897                         voip_calls_dlg_reset, 
898                         mtp3_calls_packet, 
899                         voip_calls_dlg_draw
900                         );
901
902                 if (error_string != NULL) {
903                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
904                                       error_string->str);
905                         g_string_free(error_string, TRUE);
906                         exit(1);
907                 }
908                 have_mtp3_tap_listener=TRUE;
909         }
910 }
911
912 /****************************************************************************/
913
914 void
915 remove_tap_listener_mtp3_calls(void)
916 {
917         protect_thread_critical_region();
918         remove_tap_listener(&(the_tapinfo_struct.mtp3_dummy));
919         unprotect_thread_critical_region();
920
921         have_mtp3_tap_listener=FALSE;
922 }
923
924 /****************************************************************************/
925 /* ***************************TAP for Q931 **********************************/
926 /****************************************************************************/
927
928 static gchar *q931_calling_number;
929 static gchar *q931_called_number;
930 static guint8 q931_cause_value;
931 static gint32 q931_crv;
932 static guint32 q931_frame_num;
933
934 /****************************************************************************/
935 /* whenever a q931_ packet is seen by the tap listener */
936 static int 
937 q931_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *q931_info _U_)
938 {
939         /*voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct; */
940         const q931_packet_info *pi = q931_info;
941
942         /* free previously allocated q931_calling/ed_number */
943         g_free(q931_calling_number);
944         g_free(q931_called_number);
945         
946         if (pi->calling_number!=NULL)
947                 q931_calling_number = g_strdup(pi->calling_number);
948         else
949                 q931_calling_number = g_strdup("");
950
951         if (pi->called_number!=NULL)
952                 q931_called_number = g_strdup(pi->called_number);
953         else
954                 q931_called_number = g_strdup("");
955         q931_cause_value = pi->cause_value;
956         q931_frame_num = pinfo->fd->num;
957         q931_crv = pi->crv;
958
959         return 0;
960 }
961
962 /****************************************************************************/
963 static gboolean have_q931_tap_listener=FALSE;
964
965 void
966 q931_calls_init_tap(void)
967 {
968         GString *error_string;
969
970
971         if(have_q931_tap_listener==FALSE)
972         {
973                 error_string = register_tap_listener("q931", &(the_tapinfo_struct.q931_dummy),
974                         NULL,
975                         voip_calls_dlg_reset,
976                         q931_calls_packet,
977                         voip_calls_dlg_draw
978                         );
979                         
980                 if (error_string != NULL) {
981                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
982                                       error_string->str);
983                         g_string_free(error_string, TRUE);
984                         exit(1);
985                 }
986                 have_q931_tap_listener=TRUE;
987         }
988 }
989
990 /****************************************************************************/
991
992 void
993 remove_tap_listener_q931_calls(void)
994 {
995         protect_thread_critical_region();
996         remove_tap_listener(&(the_tapinfo_struct.q931_dummy));
997         unprotect_thread_critical_region();
998
999         have_q931_tap_listener=FALSE;
1000 }
1001
1002 /****************************************************************************/
1003 /****************************TAP for H323 ***********************************/
1004 /****************************************************************************/
1005
1006 #define GUID_LEN        16
1007 static const guint8 guid_allzero[GUID_LEN] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
1008 /* defines specific H323 data */
1009
1010 void add_h245_Address(h323_calls_info_t *h323info, guint32 h245_address, guint16 h245_port)
1011 {
1012         h245_address_t *h245_add = NULL;
1013
1014         h245_add = g_malloc(sizeof(h245_address_t));
1015                 h245_add->h245_address = h245_address;
1016                 h245_add->h245_port = h245_port;
1017
1018         h323info->h245_list = g_list_append(h323info->h245_list, h245_add);                             
1019 }
1020
1021 /****************************************************************************/
1022 /* whenever a H225 packet is seen by the tap listener */
1023 static int 
1024 H225calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *H225info)
1025 {
1026         voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1027         voip_calls_info_t *tmp_listinfo;
1028         voip_calls_info_t *strinfo = NULL;
1029         h323_calls_info_t *tmp_h323info = NULL;
1030         h323_calls_info_t *tmp2_h323info;
1031         gchar *frame_label;
1032         gchar *comment;
1033         GList* list;
1034         guint32 tmp_src, tmp_dst;
1035         guint foo;
1036         
1037         const h225_packet_info *pi = H225info;
1038         
1039         /* if not guid and RAS and not LRQ, LCF or LRJ return because did not belong to a call */
1040         if ((memcmp(pi->guid, guid_allzero, GUID_LEN) == 0) && (pi->msg_type == H225_RAS) && ((pi->msg_tag < 18) || (pi->msg_tag > 20)))
1041                 return 0;
1042         
1043         
1044         if ( (memcmp(pi->guid, guid_allzero, GUID_LEN) == 0) && (q931_frame_num == pinfo->fd->num) ){
1045                 /* check wether we already have a call with this Q931 CRV */
1046                 list = g_list_first(tapinfo->strinfo_list);
1047                 while (list)
1048                 {
1049                         tmp_listinfo=list->data;
1050                         if (tmp_listinfo->protocol == VOIP_H323){
1051                                 tmp_h323info = tmp_listinfo->prot_info;
1052                                 if ( ((tmp_h323info->q931_crv == q931_crv) || (tmp_h323info->q931_crv2 == q931_crv)) && (q931_crv!=-1)){
1053                                         strinfo = (voip_calls_info_t*)(list->data);
1054                                         break;
1055                                 }
1056                         }
1057                         list = g_list_next (list);
1058                 }
1059                 if (strinfo==NULL)      return 0;               
1060         } else if ( (pi->msg_type == H225_RAS) && ((pi->msg_tag == 19) || (pi->msg_tag == 20))) { /* RAS LCF or LRJ*/
1061                 /* if the LCF/LRJ doesn't match to a LRQ, just return */
1062                 if (!pi->request_available) return 0;
1063                 
1064                 /* check wether we already have a call with this request SeqNum */
1065                 list = g_list_first(tapinfo->strinfo_list);
1066                 while (list)
1067                 {
1068                         tmp_listinfo=list->data;
1069                         if (tmp_listinfo->protocol == VOIP_H323){
1070                                 tmp_h323info = tmp_listinfo->prot_info;
1071                                 if (tmp_h323info->requestSeqNum == pi->requestSeqNum) {
1072                                         strinfo = (voip_calls_info_t*)(list->data);
1073                                         break;
1074                                 }
1075                         }
1076                         list = g_list_next (list);
1077                 }
1078         } else {
1079                 /* check wether we already have a call with this guid in the list */
1080                 list = g_list_first(tapinfo->strinfo_list);
1081                 while (list)
1082                 {
1083                         tmp_listinfo=list->data;
1084                         if (tmp_listinfo->protocol == VOIP_H323){
1085                                 tmp_h323info = tmp_listinfo->prot_info;
1086                                 if ( (memcmp(tmp_h323info->guid, guid_allzero, GUID_LEN) != 0) && (memcmp(tmp_h323info->guid, pi->guid,GUID_LEN)==0) ){ 
1087                                         strinfo = (voip_calls_info_t*)(list->data);
1088                                         break;
1089                                 }
1090                         }
1091                         list = g_list_next (list);
1092                 }
1093         }
1094         
1095         /* not in the list? then create a new entry */
1096         if ((strinfo==NULL)){
1097                 strinfo = g_malloc(sizeof(voip_calls_info_t));
1098                 strinfo->call_active_state = VOIP_ACTIVE;
1099                 strinfo->call_state = VOIP_UNKNOWN;
1100                 strinfo->from_identity=g_strdup("");
1101                 strinfo->to_identity=g_strdup("");
1102                 
1103                 g_memmove(&(strinfo->initial_speaker), pinfo->src.data,4);
1104                 strinfo->selected=FALSE;
1105                 strinfo->first_frame_num=pinfo->fd->num;
1106                 strinfo->start_sec=pinfo->fd->rel_secs;
1107                 strinfo->start_usec=pinfo->fd->rel_usecs;
1108                 strinfo->protocol=VOIP_H323;
1109                 strinfo->prot_info=g_malloc(sizeof(h323_calls_info_t));
1110                 tmp_h323info = strinfo->prot_info;
1111                 tmp_h323info->guid = (guint8 *) g_memdup(pi->guid,GUID_LEN);
1112                 tmp_h323info->h225SetupAddr = 0;
1113                 tmp_h323info->h245_list = NULL;
1114                 tmp_h323info->is_faststart_Setup = FALSE;
1115                 tmp_h323info->is_faststart_Proc = FALSE;
1116                 tmp_h323info->is_h245Tunneling = FALSE;
1117                 tmp_h323info->is_h245 = FALSE;
1118                 tmp_h323info->q931_crv = -1;
1119                 tmp_h323info->q931_crv2 = -1;
1120                 tmp_h323info->requestSeqNum = 0;
1121                 strinfo->call_num = tapinfo->ncalls++;
1122                 strinfo->npackets = 0;
1123                 
1124                 tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);                          
1125         }
1126         
1127         /* let's analyze the call state */
1128         
1129         g_memmove(&(tmp_src), pinfo->src.data, 4);
1130         g_memmove(&(tmp_dst), pinfo->dst.data, 4);
1131         
1132         strinfo->stop_sec=pinfo->fd->rel_secs;
1133         strinfo->stop_usec=pinfo->fd->rel_usecs;
1134         strinfo->last_frame_num=pinfo->fd->num;
1135         ++(strinfo->npackets);
1136         /* increment the packets counter of all calls */
1137         ++(tapinfo->npackets);
1138         
1139         /* XXX: it is supposed to be initialized isn't it? */
1140         g_assert(tmp_h323info != NULL);
1141         
1142         /* change the status */
1143         if (pi->msg_type == H225_CS) {
1144                 if (tmp_h323info->q931_crv == -1) {
1145                         tmp_h323info->q931_crv = q931_crv;
1146                 } else if (tmp_h323info->q931_crv != q931_crv) {
1147                         tmp_h323info->q931_crv2 = q931_crv;
1148                 }
1149                 
1150                 if (pi->is_h245 == TRUE){
1151                         add_h245_Address(tmp_h323info, pi->h245_address, pi->h245_port);
1152                 }
1153                 
1154                 if (pi->cs_type != H225_RELEASE_COMPLET) tmp_h323info->is_h245Tunneling = pi->is_h245Tunneling;
1155                 
1156                 frame_label = g_strdup(pi->frame_label);
1157                 
1158                 switch(pi->cs_type){
1159                         case H225_SETUP:
1160                                 tmp_h323info->is_faststart_Setup = pi->is_faststart;
1161                                 /* set te calling and called number from the Q931 packet */
1162                                 if (q931_frame_num == pinfo->fd->num){
1163                                         if (q931_calling_number != NULL){
1164                                                 g_free(strinfo->from_identity);
1165                                                 strinfo->from_identity=g_strdup(q931_calling_number);
1166                                         }
1167                                         if (q931_called_number != NULL){
1168                                                 g_free(strinfo->to_identity);
1169                                                 strinfo->to_identity=g_strdup(q931_called_number);
1170                                         }
1171                                 }
1172                                         /* check if there is an LRQ/LCF that match this Setup */
1173                                         /* TODO: we are just checking the DialedNumer in LRQ/LCF agains the Setup 
1174                                         we should also check if the h225 signaling IP and port match the destination 
1175                                         Setup ip and port */
1176                                         list = g_list_first(tapinfo->strinfo_list);
1177                                 foo=    g_list_length(list);
1178                                 while (list)
1179                                 {
1180                                         tmp_listinfo=list->data;
1181                                         if (tmp_listinfo->protocol == VOIP_H323){
1182                                                 tmp2_h323info = tmp_listinfo->prot_info;
1183                                                 
1184                                                 /* check if there called number match a LRQ/LCF */
1185                                                 if ( (strcmp(strinfo->to_identity, tmp_listinfo->to_identity)==0)  
1186                                                          && (memcmp(tmp2_h323info->guid, guid_allzero, GUID_LEN) == 0) ){ 
1187                                                         /* change the call graph to the LRQ/LCF to belong to this call */
1188                                                         strinfo->npackets += change_call_num_graph(tapinfo, tmp_listinfo->call_num, strinfo->call_num);
1189                                                         
1190                                                         /* remove this LRQ/LCF call entry because we have found the Setup that match them */
1191                                                         g_free(tmp_listinfo->from_identity);
1192                                                         g_free(tmp_listinfo->to_identity);
1193                                                         g_free(tmp2_h323info->guid);
1194                                                         g_list_free(tmp2_h323info->h245_list);
1195                                                         tmp2_h323info->h245_list = NULL;                
1196                                                         g_free(tmp_listinfo->prot_info);
1197                                                         tapinfo->strinfo_list = g_list_remove(tapinfo->strinfo_list, tmp_listinfo);
1198                                                         break;
1199                                                 }
1200                                         }
1201                                 list = g_list_next (list);
1202                                 }
1203                                         foo = g_list_length(list);
1204                                 /* Set the Setup address if it was not set */
1205                                 if (tmp_h323info->h225SetupAddr == 0) g_memmove(&(tmp_h323info->h225SetupAddr), pinfo->src.data,4);
1206                                         strinfo->call_state=VOIP_CALL_SETUP;
1207                                 comment = g_strdup_printf("H225 From: %s To:%s  TunnH245:%s FS:%s", strinfo->from_identity, strinfo->to_identity, (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"), 
1208                                                                                   (pi->is_faststart==TRUE?"on":"off"));
1209                                 break;
1210                         case H225_CONNECT:
1211                                 strinfo->call_state=VOIP_IN_CALL;
1212                                 if (pi->is_faststart == TRUE) tmp_h323info->is_faststart_Proc = TRUE;
1213                                         comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"), 
1214                                                                                           (pi->is_faststart==TRUE?"on":"off"));
1215                                 break;
1216                         case H225_RELEASE_COMPLET:
1217                                 g_memmove(&(tmp_src), pinfo->src.data, 4);
1218                                 if (strinfo->call_state==VOIP_CALL_SETUP){
1219                                         if (tmp_h323info->h225SetupAddr == tmp_src){  /* forward direction */
1220                                                 strinfo->call_state=VOIP_CANCELLED;
1221                                         }
1222                                         else{                                                                                           /* reverse */
1223                                                 strinfo->call_state=VOIP_REJECTED;
1224                                                 tapinfo->rejected_calls++;
1225                                         }
1226                                 }
1227                                         else {
1228                                                 strinfo->call_state=VOIP_REJECTED;
1229                                                 tapinfo->rejected_calls++;
1230                                         }
1231                                         /* get the Q931 Release cause code */
1232                                         if (q931_frame_num == pinfo->fd->num &&
1233                                                 q931_cause_value != 0xFF){              
1234                                                 comment = g_strdup_printf("H225 Q931 Rel Cause (%i):%s", q931_cause_value, val_to_str(q931_cause_value, q931_cause_code_vals, "<unknown>"));
1235                                         } else {                        /* Cause not set */
1236                                                 comment = g_strdup("H225 No Q931 Rel Cause");
1237                                         }
1238                                         break;
1239                         case H225_PROGRESS:
1240                         case H225_ALERTING:
1241                         case H225_CALL_PROCEDING:
1242                                 if (pi->is_faststart == TRUE) tmp_h323info->is_faststart_Proc = TRUE;
1243                                 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"), 
1244                                                                                   (pi->is_faststart==TRUE?"on":"off"));
1245                                 break;
1246                         default:
1247                                 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"), 
1248                                                                                   (pi->is_faststart==TRUE?"on":"off"));
1249                                 
1250                 }
1251         } else if (pi->msg_type == H225_RAS){
1252                 switch(pi->msg_tag){
1253                         case 18:  /* LRQ */
1254                                 if (!pi->is_duplicate){
1255                                         g_free(strinfo->to_identity);
1256                                         strinfo->to_identity=g_strdup(pi->dialedDigits);
1257                                         tmp_h323info->requestSeqNum = pi->requestSeqNum;
1258                                 }
1259                         case 19: /* LCF */
1260                                 if (strlen(pi->dialedDigits)) 
1261                                         comment = g_strdup_printf("H225 RAS dialedDigits: %s", pi->dialedDigits);
1262                                 else
1263                                         comment = g_strdup("H225 RAS");
1264                                 break;
1265                         default:
1266                                 comment = g_strdup("H225 RAS");
1267                 }
1268                 frame_label = g_strdup_printf("%s", val_to_str(pi->msg_tag, RasMessage_vals, "<unknown>"));
1269         } else {
1270                 frame_label = g_strdup("H225: Unknown");
1271                 comment = g_strdup("");
1272         }
1273
1274         /* add to graph analysis */
1275
1276         /* if the frame number exists in graph, append to it*/
1277         if (!append_to_frame_graph(tapinfo, pinfo->fd->num, pi->frame_label, comment)) {
1278                 /* if not exist, add to the graph */
1279                 add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num);
1280         }
1281
1282         g_free(frame_label);
1283         g_free(comment);
1284         
1285         return 1;  /* refresh output */
1286 }
1287
1288
1289 /****************************************************************************/
1290 /* TAP INTERFACE */
1291 /****************************************************************************/
1292 static gboolean have_H225_tap_listener=FALSE;
1293 /****************************************************************************/
1294 void
1295 h225_calls_init_tap(void)
1296 {
1297         GString *error_string;
1298
1299         if(have_H225_tap_listener==FALSE)
1300         {
1301                 /* don't register tap listener, if we have it already */
1302                 error_string = register_tap_listener("h225", &(the_tapinfo_struct.h225_dummy), NULL,
1303                         voip_calls_dlg_reset, 
1304                         H225calls_packet, 
1305                         voip_calls_dlg_draw
1306                         );
1307                         
1308                 if (error_string != NULL) {
1309                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1310                                       error_string->str);
1311                         g_string_free(error_string, TRUE);
1312                         exit(1);
1313                 }
1314                 have_H225_tap_listener=TRUE;
1315         }
1316 }
1317
1318
1319
1320 /* XXX just copied from gtk/rpc_stat.c */
1321 void protect_thread_critical_region(void);
1322 void unprotect_thread_critical_region(void);
1323
1324 /****************************************************************************/
1325 void
1326 remove_tap_listener_h225_calls(void)
1327 {
1328         protect_thread_critical_region();
1329         remove_tap_listener(&(the_tapinfo_struct.h225_dummy));
1330         unprotect_thread_critical_region();
1331
1332         have_H225_tap_listener=FALSE;
1333 }
1334
1335
1336 /****************************************************************************/
1337 /* whenever a H245dg packet is seen by the tap listener (when H245 tunneling is ON) */
1338 static int 
1339 H245dgcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *H245info)
1340 {
1341         voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1342         voip_calls_info_t *tmp_listinfo;
1343         voip_calls_info_t *strinfo = NULL;
1344         h323_calls_info_t *tmp_h323info;
1345         gchar *frame_label;
1346         gchar *comment;
1347         GList* list;
1348         GList* list2;
1349         guint32 tmp_src, tmp_dst;
1350         h245_address_t *h245_add = NULL;
1351
1352         const h245_packet_info *pi = H245info;
1353
1354         /* if H245 tunneling is on, append to graph */
1355         if (append_to_frame_graph(tapinfo, pinfo->fd->num, pi->frame_label, pi->comment)) return 1;
1356
1357
1358         /* it is not Tunneling or it is not in the list. So check if there is no tunneling
1359            and there is a call with this H245 address */
1360         list = g_list_first(tapinfo->strinfo_list);
1361         while (list)
1362         {
1363                 tmp_listinfo=list->data;
1364                 if (tmp_listinfo->protocol == VOIP_H323){
1365                         tmp_h323info = tmp_listinfo->prot_info;
1366
1367                         g_memmove(&(tmp_src), pinfo->src.data, 4);
1368                         g_memmove(&(tmp_dst), pinfo->dst.data, 4);
1369                         list2 = g_list_first(tmp_h323info->h245_list);
1370                         while (list2)
1371                         {
1372                                 h245_add=list2->data;
1373                                 if ( ((h245_add->h245_address == tmp_src) && (h245_add->h245_port == pinfo->srcport))
1374                                         || ((h245_add->h245_address == tmp_dst) && (h245_add->h245_port == pinfo->destport)) ){
1375                                         strinfo = (voip_calls_info_t*)(list->data);
1376
1377                                         ++(strinfo->npackets);
1378                                         /* increment the packets counter of all calls */
1379                                         ++(tapinfo->npackets);
1380
1381                                         break;
1382                                 }                       
1383                         list2 = g_list_next(list2);
1384                         }
1385                         if (strinfo!=NULL) break;
1386                 }
1387                 list = g_list_next(list);
1388         }
1389
1390         if (strinfo!=NULL){
1391                 frame_label = g_strdup(pi->frame_label);
1392                 comment = g_strdup(pi->comment);
1393                 add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num);
1394                 g_free(frame_label);
1395                 g_free(comment);
1396         }
1397
1398         return 1;  /* refresh output */
1399 }
1400
1401
1402 /****************************************************************************/
1403 /* TAP INTERFACE */
1404 /****************************************************************************/
1405 static gboolean have_H245dg_tap_listener=FALSE;
1406 /****************************************************************************/
1407 void
1408 h245dg_calls_init_tap(void)
1409 {
1410         GString *error_string;
1411
1412         if(have_H245dg_tap_listener==FALSE)
1413         {
1414                 /* don't register tap listener, if we have it already */
1415                 error_string = register_tap_listener("h245dg", &(the_tapinfo_struct.h245dg_dummy), NULL,
1416                         voip_calls_dlg_reset,
1417                         H245dgcalls_packet, 
1418                         voip_calls_dlg_draw
1419                         );
1420                 
1421                 if (error_string != NULL) {
1422                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1423                                       error_string->str);
1424                         g_string_free(error_string, TRUE);
1425                         exit(1);
1426                 }
1427                 have_H245dg_tap_listener=TRUE;
1428         }
1429 }
1430
1431
1432 /* XXX just copied from gtk/rpc_stat.c */
1433 void protect_thread_critical_region(void);
1434 void unprotect_thread_critical_region(void);
1435
1436 /****************************************************************************/
1437 void
1438 remove_tap_listener_h245dg_calls(void)
1439 {
1440         protect_thread_critical_region();
1441         remove_tap_listener(&(the_tapinfo_struct.h245dg_dummy));
1442         unprotect_thread_critical_region();
1443
1444         have_H245dg_tap_listener=FALSE;
1445 }
1446
1447 static gchar *sdp_summary = NULL;
1448 static guint32 sdp_frame_num = 0;
1449
1450 /****************************************************************************/
1451 /****************************TAP for SDP PROTOCOL ***************************/
1452 /****************************************************************************/
1453 /* whenever a SDP packet is seen by the tap listener */
1454 static int 
1455 SDPcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *SDPinfo)
1456 {
1457         voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1458         const sdp_packet_info *pi = SDPinfo;
1459
1460         /* There are protocols like MGCP where the SDP is called before the tap for the
1461            MGCP packet, in those cases we assign the SPD summary to global lastSDPsummary
1462            to use it later 
1463         */
1464         g_free(sdp_summary);
1465         sdp_frame_num = pinfo->fd->num;
1466         /* Append to graph the SDP summary if the packet exists */
1467         sdp_summary = g_strdup_printf("SDP (%s)", pi->summary_str);
1468         append_to_frame_graph(tapinfo, pinfo->fd->num, sdp_summary, NULL);
1469
1470         return 1;  /* refresh output */
1471 }
1472
1473
1474 /****************************************************************************/
1475 /* TAP INTERFACE */
1476 /****************************************************************************/
1477 static gboolean have_sdp_tap_listener=FALSE;
1478 /****************************************************************************/
1479 void
1480 sdp_calls_init_tap(void)
1481 {
1482         GString *error_string;
1483
1484         if(have_sdp_tap_listener==FALSE)
1485         {
1486                 /* don't register tap listener, if we have it already */
1487                 error_string = register_tap_listener("sdp", &(the_tapinfo_struct.sdp_dummy), NULL,
1488                         voip_calls_dlg_reset, 
1489                         SDPcalls_packet, 
1490                         voip_calls_dlg_draw
1491                         );
1492                         
1493                 if (error_string != NULL) {
1494                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1495                                       error_string->str);
1496                         g_string_free(error_string, TRUE);
1497                         exit(1);
1498                 }
1499                 have_sdp_tap_listener=TRUE;
1500         }
1501 }
1502
1503
1504 /* XXX just copied from gtk/rpc_stat.c */
1505 void protect_thread_critical_region(void);
1506 void unprotect_thread_critical_region(void);
1507
1508 /****************************************************************************/
1509 void
1510 remove_tap_listener_sdp_calls(void)
1511 {
1512         protect_thread_critical_region();
1513         remove_tap_listener(&(the_tapinfo_struct.sdp_dummy));
1514         unprotect_thread_critical_region();
1515
1516         have_sdp_tap_listener=FALSE;
1517 }
1518
1519
1520
1521 /****************************************************************************/
1522 /* ***************************TAP for MGCP **********************************/
1523 /****************************************************************************/
1524
1525 /*
1526    This function will look for a signal/event in the SignalReq/ObsEvent string
1527    and return true if it is found 
1528 */
1529 gboolean isSignal(gchar *signal, gchar *signalStr)
1530 {
1531         gint i; 
1532         gchar **resultArray;
1533         
1534         /* if there is no signalStr, just return false */
1535         if (signalStr == NULL) return FALSE;
1536
1537         /* if are both "blank" return true */
1538         if ( (*signal == '\0') &&  (*signalStr == '\0') ) return TRUE;
1539
1540         /* look for signal in signalSre */
1541         resultArray = g_strsplit(signalStr, ",", 10);
1542
1543         for (i = 0; resultArray[i]; i++) {
1544                 g_strstrip(resultArray[i]);
1545                 if (strcmp(resultArray[i], signal) == 0) return TRUE;
1546         }
1547
1548         g_strfreev(resultArray);
1549         
1550         return FALSE;
1551 }
1552
1553 /*
1554    This function will get the Caller ID info and replace the current string
1555    This is how it looks the caller Id: rg, ci(02/16/08/29, "3035550002","Ale Sipura 2")
1556 */
1557 void mgcpCallerID(gchar *signalStr, gchar **callerId)
1558 {
1559         gint i; 
1560         gchar **resultArray;
1561         gchar **arrayStr;
1562         
1563         /* if there is no signalStr, just return false */
1564         if (signalStr == NULL) return;
1565
1566         arrayStr = g_strsplit(signalStr, "\"", 10);
1567
1568         if (arrayStr[0] == NULL) return;
1569
1570         /* look for the ci signal */
1571         resultArray = g_strsplit(arrayStr[0], ",(", 10);
1572
1573         for (i = 0; resultArray[i]; i++) {
1574                 g_strstrip(resultArray[i]);
1575                 if (strcmp(resultArray[i], "ci") == 0){
1576                         if (arrayStr[1] != NULL){
1577                                 /* free the previous "From" field of the call, and assign the new */
1578                                 g_free(*callerId);
1579                                 *callerId = g_strdup(arrayStr[1]);
1580                         }
1581                         g_strfreev(arrayStr);
1582                         g_strfreev(resultArray);
1583                         return;
1584                 }
1585         }
1586
1587         g_strfreev(arrayStr);
1588         g_strfreev(resultArray);
1589
1590         return;
1591 }
1592
1593
1594 /*
1595    This function will get the Dialed Digits and replace the current string
1596    This is how it looks the dialed digits 5,5,5,0,0,0,2,#,*
1597 */
1598 void mgcpDialedDigits(gchar *signalStr, gchar **dialedDigits)
1599 {
1600         gchar *tmpStr;
1601         gchar resultStr[50];
1602         gint i,j; 
1603
1604         /* if there is no signalStr, just return false */
1605         if (signalStr == NULL) return;
1606
1607         tmpStr = g_strdup(signalStr);
1608         
1609         for ( i = 0 ; tmpStr[i] ; i++) {
1610                 switch (tmpStr[i]) {
1611                         case '0' : case '1' : case '2' : case '3' : case '4' :
1612                         case '5' : case '6' : case '7' : case '8' : case '9' :
1613                         case '#' : case '*' :
1614                                 break;
1615                         default:
1616                                 tmpStr[i] = '?';
1617                                 break;
1618                 }
1619         }
1620         
1621         for (i = 0, j = 0; tmpStr[i] && i<50; i++) {
1622                 if (tmpStr[i] != '?')
1623                         resultStr[j++] = tmpStr[i];
1624         }
1625         resultStr[j] = '\0';
1626
1627         if (*resultStr == '\0') return;
1628         
1629         g_free(*dialedDigits);
1630         *dialedDigits = g_strdup(resultStr);
1631         g_free(tmpStr);
1632
1633         return;
1634 }
1635
1636
1637
1638 /****************************************************************************/
1639 /* whenever a MGCP packet is seen by the tap listener */
1640 static int 
1641 MGCPcalls_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *MGCPinfo)
1642 {
1643         voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1644
1645         voip_calls_info_t *tmp_listinfo;
1646         voip_calls_info_t *strinfo = NULL;
1647         mgcp_calls_info_t *tmp_mgcpinfo = NULL;
1648         GList* list;
1649         GList* listGraph;
1650         gchar *frame_label = NULL;
1651         gchar *comment = NULL;
1652         graph_analysis_item_t *gai;
1653         gboolean new = FALSE;
1654         gboolean fromEndpoint = FALSE; /* true for calls originated in Endpoints, false for calls from MGC */
1655         gdouble diff_time;
1656
1657         const mgcp_info_t *pi = MGCPinfo;
1658
1659
1660         if ((pi->mgcp_type == MGCP_REQUEST) && !pi->is_duplicate ){
1661                 /* check wether we already have a call with this Endpoint and it is active*/
1662                 list = g_list_first(tapinfo->strinfo_list);
1663                 while (list)
1664                 {
1665                         tmp_listinfo=list->data;
1666                         if ((tmp_listinfo->protocol == VOIP_MGCP) && (tmp_listinfo->call_active_state == VOIP_ACTIVE)){
1667                                 tmp_mgcpinfo = tmp_listinfo->prot_info;
1668                                 if (pi->endpointId != NULL){
1669                                         if (g_strcasecmp(tmp_mgcpinfo->endpointId,pi->endpointId) == 0){
1670                                                 /*
1671                                                    check first if it is an ended call. We consider an ended call after 1sec we don't 
1672                                                    get a packet in this Endpoint and the call has been released
1673                                                 */
1674                                                 diff_time = (pinfo->fd->rel_secs + (double)pinfo->fd->rel_secs/1000000) - (tmp_listinfo->stop_sec + (double)tmp_listinfo->stop_usec/1000000);
1675                                                 if ( ((tmp_listinfo->call_state == VOIP_CANCELLED) || (tmp_listinfo->call_state == VOIP_COMPLETED)  || (tmp_listinfo->call_state == VOIP_REJECTED)) && (diff_time > 1) ){
1676                                                         tmp_listinfo->call_active_state = VOIP_INACTIVE;
1677                                                 } else {
1678                                                         strinfo = (voip_calls_info_t*)(list->data);
1679                                                         break;
1680                                                 }
1681                                         }
1682                                 }
1683                         }
1684                         list = g_list_next (list);
1685                 }
1686                 
1687                 /* there is no call with this Endpoint, lets see if this a new call or not */
1688                 if (strinfo == NULL){
1689                         if ( (strcmp(pi->code, "NTFY") == 0) && isSignal("hd", pi->observedEvents) ){ /* off hook transition */
1690                                 /* this is a new call from the Endpoint */      
1691                                 fromEndpoint = TRUE;
1692                                 new = TRUE;
1693                         } else if (strcmp(pi->code, "CRCX") == 0){
1694                                 /* this is a new call from the MGC */
1695                                 fromEndpoint = FALSE;
1696                                 new = TRUE;
1697                         }
1698                         if (!new) return 0;
1699                 } 
1700         } else if ( ((pi->mgcp_type == MGCP_RESPONSE) && pi->request_available) ||
1701                         ((pi->mgcp_type == MGCP_REQUEST) && pi->is_duplicate) ) {
1702                 /* if it is a response OR if it is a duplicated Request, lets look in the Graph if thre is a request that match */
1703                 listGraph = g_list_first(tapinfo->graph_analysis->list);
1704                 while (listGraph)
1705                 {
1706                         gai = listGraph->data;
1707                         if (gai->frame_num == pi->req_num){
1708                                 /* there is a request that match, so look the associated call with this call_num */
1709                                 list = g_list_first(tapinfo->strinfo_list);
1710                                 while (list)
1711                                 {
1712                                         tmp_listinfo=list->data;
1713                                         if (tmp_listinfo->protocol == VOIP_MGCP){
1714                                                 if (tmp_listinfo->call_num == gai->conv_num){
1715                                                         tmp_mgcpinfo = tmp_listinfo->prot_info;
1716                                                         strinfo = (voip_calls_info_t*)(list->data);
1717                                                         break;
1718                                                 }
1719                                         }
1720                                         list = g_list_next (list);
1721                                 }
1722                                 if (strinfo != NULL) break;
1723                         }
1724                         listGraph = g_list_next(listGraph);
1725                 }
1726                 /* if there is not a matching request, just return */
1727                 if (strinfo == NULL) return 0;
1728         } else return 0;
1729
1730         /* not in the list? then create a new entry */
1731         if (strinfo==NULL){
1732                 strinfo = g_malloc(sizeof(voip_calls_info_t));
1733                 strinfo->call_active_state = VOIP_ACTIVE;
1734                 strinfo->call_state = VOIP_CALL_SETUP;
1735                 if (fromEndpoint) {
1736                         strinfo->from_identity=g_strdup(pi->endpointId);
1737                         strinfo->to_identity=g_strdup("");
1738                 } else {
1739                         strinfo->from_identity=g_strdup("");
1740                         strinfo->to_identity=g_strdup(pi->endpointId);
1741                 }
1742                 g_memmove(&(strinfo->initial_speaker), pinfo->src.data, 4);
1743                 strinfo->first_frame_num=pinfo->fd->num;
1744                 strinfo->selected=FALSE;
1745                 strinfo->start_sec=pinfo->fd->rel_secs;
1746                 strinfo->start_usec=pinfo->fd->rel_usecs;
1747                 strinfo->protocol=VOIP_MGCP;
1748                 strinfo->prot_info=g_malloc(sizeof(mgcp_calls_info_t));
1749                 tmp_mgcpinfo=strinfo->prot_info;
1750                 tmp_mgcpinfo->endpointId = g_strdup(pi->endpointId);
1751                 tmp_mgcpinfo->fromEndpoint = fromEndpoint;
1752                 strinfo->npackets = 0;
1753                 strinfo->call_num = tapinfo->ncalls++;
1754                 tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
1755         }
1756
1757         g_assert(tmp_mgcpinfo != NULL);
1758
1759         /* change call state and add to graph */
1760         switch (pi->mgcp_type)
1761         {
1762         case MGCP_REQUEST:
1763                 if ( (strcmp(pi->code, "NTFY") == 0) && (pi->observedEvents != NULL) ){
1764                         frame_label = g_strdup_printf("%s ObsEvt:%s",pi->code, pi->observedEvents);
1765
1766                         if (tmp_mgcpinfo->fromEndpoint){
1767                                 /* use the Dialed digits to fill the "To" for the call */
1768                                 mgcpDialedDigits(pi->observedEvents, &(strinfo->to_identity));
1769
1770                         /* from MGC and the user picked up, the call is connected */
1771                         } else if (isSignal("hd", pi->observedEvents))  
1772                                 strinfo->call_state=VOIP_IN_CALL;
1773
1774                         /* hung up signal */
1775                         if (isSignal("hu", pi->observedEvents)) {
1776                                 if ((strinfo->call_state == VOIP_CALL_SETUP) || (strinfo->call_state == VOIP_RINGING)){
1777                                         strinfo->call_state = VOIP_CANCELLED;
1778                                 } else {
1779                                         strinfo->call_state = VOIP_COMPLETED;
1780                                 }
1781                         }       
1782                         
1783                 } else if (strcmp(pi->code, "RQNT") == 0) {
1784                         /* for calls from Endpoint: if there is a "no signal" RQNT and the call was RINGING, we assume this is the CONNECT */
1785                         if ( tmp_mgcpinfo->fromEndpoint && isSignal("", pi->signalReq) && (strinfo->call_state == VOIP_RINGING) ) { 
1786                                         strinfo->call_state = VOIP_IN_CALL;
1787                         }
1788
1789                         /* if there is ringback or ring tone, change state to ringing */
1790                         if ( isSignal("rg", pi->signalReq) || isSignal("rt", pi->signalReq) ) { 
1791                                         strinfo->call_state = VOIP_RINGING;
1792                         }
1793
1794                         /* if there is a Busy or ReorderTone, and the call was Ringing or Setup the call is Rejected */
1795                         if ( (isSignal("ro", pi->signalReq) || isSignal("bz", pi->signalReq)) && ((strinfo->call_state == VOIP_CALL_SETUP) || (strinfo->call_state = VOIP_RINGING)) ) { 
1796                                         strinfo->call_state = VOIP_REJECTED;
1797                         }
1798
1799                         if (pi->signalReq != NULL)
1800                                 frame_label = g_strdup_printf("%s%sSigReq:%s",pi->code, (pi->hasDigitMap == TRUE)?" DigitMap ":"", pi->signalReq);
1801                         else
1802                                 frame_label = g_strdup_printf("%s%s",pi->code, (pi->hasDigitMap == TRUE)?" DigitMap ":"");
1803                         
1804                         /* use the CallerID info to fill the "From" for the call */
1805                         if (!tmp_mgcpinfo->fromEndpoint) mgcpCallerID(pi->signalReq, &(strinfo->from_identity));
1806
1807                 } else if (strcmp(pi->code, "DLCX") == 0) {
1808                         /*
1809                           if there is a DLCX in a call To an Endpoint and the call was not connected, we use
1810                           the DLCX as the end of the call
1811                         */
1812                         if (!tmp_mgcpinfo->fromEndpoint){
1813                                 if ((strinfo->call_state == VOIP_CALL_SETUP) || (strinfo->call_state == VOIP_RINGING)){
1814                                         strinfo->call_state = VOIP_CANCELLED;
1815                                 } 
1816                         } 
1817                 }
1818
1819                 if (frame_label == NULL) frame_label = g_strdup_printf("%s",pi->code);
1820                 break;
1821         case MGCP_RESPONSE:
1822                 frame_label = g_strdup_printf("%d (%s)",pi->rspcode, pi->code);
1823                 break;
1824         case MGCP_OTHERS:
1825                 /* XXX what to do? */
1826                 break;
1827         }
1828
1829
1830         comment = g_strdup_printf("MGCP %s %s%s", tmp_mgcpinfo->endpointId, (pi->mgcp_type == MGCP_REQUEST)?"Request":"Response", pi->is_duplicate?" Duplicate":"");
1831
1832         strinfo->stop_sec=pinfo->fd->rel_secs;
1833         strinfo->stop_usec=pinfo->fd->rel_usecs;
1834         strinfo->last_frame_num=pinfo->fd->num;
1835         ++(strinfo->npackets);
1836         /* increment the packets counter of all calls */
1837         ++(tapinfo->npackets);
1838
1839         /* add to the graph */
1840         add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num);  
1841         g_free(comment);
1842         g_free(frame_label);
1843
1844         /* add SDP info if apply */
1845         if ( (sdp_summary != NULL) && (sdp_frame_num == pinfo->fd->num) ){
1846                         append_to_frame_graph(tapinfo, pinfo->fd->num, sdp_summary, NULL);
1847                         g_free(sdp_summary);
1848                         sdp_summary = NULL;
1849         }
1850
1851         return 1;  /* refresh output */
1852 }
1853
1854
1855 /****************************************************************************/
1856 /* TAP INTERFACE */
1857 /****************************************************************************/
1858 static gboolean have_MGCP_tap_listener=FALSE;
1859 /****************************************************************************/
1860 void
1861 mgcp_calls_init_tap(void)
1862 {
1863         GString *error_string;
1864
1865         if(have_MGCP_tap_listener==FALSE)
1866         {
1867                 /* don't register tap listener, if we have it already */
1868                 /* we send an empty filter, to force a non null "tree" in the mgcp dissector */
1869                 error_string = register_tap_listener("mgcp", &(the_tapinfo_struct.mgcp_dummy), strdup(""),
1870                         voip_calls_dlg_reset, 
1871                         MGCPcalls_packet, 
1872                         voip_calls_dlg_draw
1873                         );
1874                 if (error_string != NULL) {
1875                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1876                                       error_string->str);
1877                         g_string_free(error_string, TRUE);
1878                         exit(1);
1879                 }
1880                 have_MGCP_tap_listener=TRUE;
1881         }
1882 }
1883
1884
1885
1886 /* XXX just copied from gtk/rpc_stat.c */
1887 void protect_thread_critical_region(void);
1888 void unprotect_thread_critical_region(void);
1889
1890 /****************************************************************************/
1891 void
1892 remove_tap_listener_mgcp_calls(void)
1893 {
1894         protect_thread_critical_region();
1895         remove_tap_listener(&(the_tapinfo_struct.mgcp_dummy));
1896         unprotect_thread_critical_region();
1897
1898         have_MGCP_tap_listener=FALSE;
1899 }
1900
1901
1902
1903 /****************************************************************************/
1904 /* ***************************TAP for OTHER PROTOCOL **********************************/
1905 /****************************************************************************/
1906
1907 /****************************************************************************/
1908 /* whenever a prot_ packet is seen by the tap listener */
1909 /*
1910 static int 
1911 prot_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prot_info _U_)
1912 {
1913         voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1914         if (strinfo!=NULL){
1915                 strinfo->stop_sec=pinfo->fd->rel_secs;
1916                 strinfo->stop_usec=pinfo->fd->rel_usecs;
1917                 strinfo->last_frame_num=pinfo->fd->num;
1918                 ++(strinfo->npackets);
1919                 ++(tapinfo->npackets);
1920         }
1921
1922         return 1;
1923 }
1924 */
1925 /****************************************************************************/
1926 /*
1927 static gboolean have_prot__tap_listener=FALSE;
1928
1929 void
1930 prot_calls_init_tap(void)
1931 {
1932         GString *error_string;
1933
1934         if(have_prot__tap_listener==FALSE)
1935         {
1936                 error_string = register_tap_listener("prot_", &(the_tapinfo_struct.prot__dummy),
1937                         NULL,
1938                         voip_calls_dlg_reset,
1939                         prot__calls_packet, 
1940                         voip_calls_dlg_draw
1941                         );
1942
1943                 if (error_string != NULL) {
1944                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1945                                       error_string->str);
1946                         g_string_free(error_string, TRUE);
1947                         exit(1);
1948                 }
1949                 have_prot__tap_listener=TRUE;
1950         }
1951 }
1952 */
1953 /****************************************************************************/
1954 /*
1955 void
1956 remove_tap_listener_prot__calls(void)
1957 {
1958         protect_thread_critical_region();
1959         remove_tap_listener(&(the_tapinfo_struct.prot__dummy));
1960         unprotect_thread_critical_region();
1961
1962         have_prot__tap_listener=FALSE;
1963 }
1964 */
1965