from Alejandro Vaquero
[obnox/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                                 }
1202                                         foo = g_list_length(list);
1203                                 /* Set the Setup address if it was not set */
1204                                 if (tmp_h323info->h225SetupAddr == 0) g_memmove(&(tmp_h323info->h225SetupAddr), pinfo->src.data,4);
1205                                         strinfo->call_state=VOIP_CALL_SETUP;
1206                                 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"), 
1207                                                                                   (pi->is_faststart==TRUE?"on":"off"));
1208                                 break;
1209                         case H225_CONNECT:
1210                                 strinfo->call_state=VOIP_IN_CALL;
1211                                 if (pi->is_faststart == TRUE) tmp_h323info->is_faststart_Proc = TRUE;
1212                                         comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"), 
1213                                                                                           (pi->is_faststart==TRUE?"on":"off"));
1214                                 break;
1215                         case H225_RELEASE_COMPLET:
1216                                 g_memmove(&(tmp_src), pinfo->src.data, 4);
1217                                 if (strinfo->call_state==VOIP_CALL_SETUP){
1218                                         if (tmp_h323info->h225SetupAddr == tmp_src){  /* forward direction */
1219                                                 strinfo->call_state=VOIP_CANCELLED;
1220                                         }
1221                                         else{                                                                                           /* reverse */
1222                                                 strinfo->call_state=VOIP_REJECTED;
1223                                                 tapinfo->rejected_calls++;
1224                                         }
1225                                 }
1226                                         else {
1227                                                 strinfo->call_state=VOIP_REJECTED;
1228                                                 tapinfo->rejected_calls++;
1229                                         }
1230                                         /* get the Q931 Release cause code */
1231                                         if (q931_frame_num == pinfo->fd->num &&
1232                                                 q931_cause_value != 0xFF){              
1233                                                 comment = g_strdup_printf("H225 Q931 Rel Cause (%i):%s", q931_cause_value, val_to_str(q931_cause_value, q931_cause_code_vals, "<unknown>"));
1234                                         } else {                        /* Cause not set */
1235                                                 comment = g_strdup("H225 No Q931 Rel Cause");
1236                                         }
1237                                         break;
1238                         case H225_PROGRESS:
1239                         case H225_ALERTING:
1240                         case H225_CALL_PROCEDING:
1241                                 if (pi->is_faststart == TRUE) tmp_h323info->is_faststart_Proc = TRUE;
1242                                 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"), 
1243                                                                                   (pi->is_faststart==TRUE?"on":"off"));
1244                                 break;
1245                         default:
1246                                 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"), 
1247                                                                                   (pi->is_faststart==TRUE?"on":"off"));
1248                                 
1249                 }
1250         } else if (pi->msg_type == H225_RAS){
1251                 switch(pi->msg_tag){
1252                         case 18:  /* LRQ */
1253                                 if (!pi->is_duplicate){
1254                                         g_free(strinfo->to_identity);
1255                                         strinfo->to_identity=g_strdup(pi->dialedDigits);
1256                                         tmp_h323info->requestSeqNum = pi->requestSeqNum;
1257                                 }
1258                         case 19: /* LCF */
1259                                 if (strlen(pi->dialedDigits)) 
1260                                         comment = g_strdup_printf("H225 RAS dialedDigits: %s", pi->dialedDigits);
1261                                 else
1262                                         comment = g_strdup("H225 RAS");
1263                                 break;
1264                         default:
1265                                 comment = g_strdup("H225 RAS");
1266                 }
1267                 frame_label = g_strdup_printf("%s", val_to_str(pi->msg_tag, RasMessage_vals, "<unknown>"));
1268         } else {
1269                 frame_label = g_strdup("H225: Unknown");
1270                 comment = g_strdup("");
1271         }
1272
1273         /* add to graph analysis */
1274
1275         /* if the frame number exists in graph, append to it*/
1276         if (!append_to_frame_graph(tapinfo, pinfo->fd->num, pi->frame_label, comment)) {
1277                 /* if not exist, add to the graph */
1278                 add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num);
1279         }
1280
1281         g_free(frame_label);
1282         g_free(comment);
1283         
1284         return 1;  /* refresh output */
1285 }
1286
1287
1288 /****************************************************************************/
1289 /* TAP INTERFACE */
1290 /****************************************************************************/
1291 static gboolean have_H225_tap_listener=FALSE;
1292 /****************************************************************************/
1293 void
1294 h225_calls_init_tap(void)
1295 {
1296         GString *error_string;
1297
1298         if(have_H225_tap_listener==FALSE)
1299         {
1300                 /* don't register tap listener, if we have it already */
1301                 error_string = register_tap_listener("h225", &(the_tapinfo_struct.h225_dummy), NULL,
1302                         voip_calls_dlg_reset, 
1303                         H225calls_packet, 
1304                         voip_calls_dlg_draw
1305                         );
1306                         
1307                 if (error_string != NULL) {
1308                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1309                                       error_string->str);
1310                         g_string_free(error_string, TRUE);
1311                         exit(1);
1312                 }
1313                 have_H225_tap_listener=TRUE;
1314         }
1315 }
1316
1317
1318
1319 /* XXX just copied from gtk/rpc_stat.c */
1320 void protect_thread_critical_region(void);
1321 void unprotect_thread_critical_region(void);
1322
1323 /****************************************************************************/
1324 void
1325 remove_tap_listener_h225_calls(void)
1326 {
1327         protect_thread_critical_region();
1328         remove_tap_listener(&(the_tapinfo_struct.h225_dummy));
1329         unprotect_thread_critical_region();
1330
1331         have_H225_tap_listener=FALSE;
1332 }
1333
1334
1335 /****************************************************************************/
1336 /* whenever a H245dg packet is seen by the tap listener (when H245 tunneling is ON) */
1337 static int 
1338 H245dgcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *H245info)
1339 {
1340         voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1341         voip_calls_info_t *tmp_listinfo;
1342         voip_calls_info_t *strinfo = NULL;
1343         h323_calls_info_t *tmp_h323info;
1344         gchar *frame_label;
1345         gchar *comment;
1346         GList* list;
1347         GList* list2;
1348         guint32 tmp_src, tmp_dst;
1349         h245_address_t *h245_add = NULL;
1350
1351         const h245_packet_info *pi = H245info;
1352
1353         /* if H245 tunneling is on, append to graph */
1354         if (append_to_frame_graph(tapinfo, pinfo->fd->num, pi->frame_label, pi->comment)) return 1;
1355
1356
1357         /* it is not Tunneling or it is not in the list. So check if there is no tunneling
1358            and there is a call with this H245 address */
1359         list = g_list_first(tapinfo->strinfo_list);
1360         while (list)
1361         {
1362                 tmp_listinfo=list->data;
1363                 if (tmp_listinfo->protocol == VOIP_H323){
1364                         tmp_h323info = tmp_listinfo->prot_info;
1365
1366                         g_memmove(&(tmp_src), pinfo->src.data, 4);
1367                         g_memmove(&(tmp_dst), pinfo->dst.data, 4);
1368                         list2 = g_list_first(tmp_h323info->h245_list);
1369                         while (list2)
1370                         {
1371                                 h245_add=list2->data;
1372                                 if ( ((h245_add->h245_address == tmp_src) && (h245_add->h245_port == pinfo->srcport))
1373                                         || ((h245_add->h245_address == tmp_dst) && (h245_add->h245_port == pinfo->destport)) ){
1374                                         strinfo = (voip_calls_info_t*)(list->data);
1375
1376                                         ++(strinfo->npackets);
1377                                         /* increment the packets counter of all calls */
1378                                         ++(tapinfo->npackets);
1379
1380                                         break;
1381                                 }                       
1382                         list2 = g_list_next(list2);
1383                         }
1384                         if (strinfo!=NULL) break;
1385                 }
1386                 list = g_list_next(list);
1387         }
1388
1389         if (strinfo!=NULL){
1390                 frame_label = g_strdup(pi->frame_label);
1391                 comment = g_strdup(pi->comment);
1392                 add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num);
1393                 g_free(frame_label);
1394                 g_free(comment);
1395         }
1396
1397         return 1;  /* refresh output */
1398 }
1399
1400
1401 /****************************************************************************/
1402 /* TAP INTERFACE */
1403 /****************************************************************************/
1404 static gboolean have_H245dg_tap_listener=FALSE;
1405 /****************************************************************************/
1406 void
1407 h245dg_calls_init_tap(void)
1408 {
1409         GString *error_string;
1410
1411         if(have_H245dg_tap_listener==FALSE)
1412         {
1413                 /* don't register tap listener, if we have it already */
1414                 error_string = register_tap_listener("h245dg", &(the_tapinfo_struct.h245dg_dummy), NULL,
1415                         voip_calls_dlg_reset,
1416                         H245dgcalls_packet, 
1417                         voip_calls_dlg_draw
1418                         );
1419                 
1420                 if (error_string != NULL) {
1421                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1422                                       error_string->str);
1423                         g_string_free(error_string, TRUE);
1424                         exit(1);
1425                 }
1426                 have_H245dg_tap_listener=TRUE;
1427         }
1428 }
1429
1430
1431 /* XXX just copied from gtk/rpc_stat.c */
1432 void protect_thread_critical_region(void);
1433 void unprotect_thread_critical_region(void);
1434
1435 /****************************************************************************/
1436 void
1437 remove_tap_listener_h245dg_calls(void)
1438 {
1439         protect_thread_critical_region();
1440         remove_tap_listener(&(the_tapinfo_struct.h245dg_dummy));
1441         unprotect_thread_critical_region();
1442
1443         have_H245dg_tap_listener=FALSE;
1444 }
1445
1446 static gchar *sdp_summary = NULL;
1447 static guint32 sdp_frame_num = 0;
1448
1449 /****************************************************************************/
1450 /****************************TAP for SDP PROTOCOL ***************************/
1451 /****************************************************************************/
1452 /* whenever a SDP packet is seen by the tap listener */
1453 static int 
1454 SDPcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *SDPinfo)
1455 {
1456         voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1457         const sdp_packet_info *pi = SDPinfo;
1458
1459         /* There are protocols like MGCP where the SDP is called before the tap for the
1460            MGCP packet, in those cases we assign the SPD summary to global lastSDPsummary
1461            to use it later 
1462         */
1463         g_free(sdp_summary);
1464         sdp_frame_num = pinfo->fd->num;
1465         /* Append to graph the SDP summary if the packet exists */
1466         sdp_summary = g_strdup_printf("SDP (%s)", pi->summary_str);
1467         append_to_frame_graph(tapinfo, pinfo->fd->num, sdp_summary, NULL);
1468
1469         return 1;  /* refresh output */
1470 }
1471
1472
1473 /****************************************************************************/
1474 /* TAP INTERFACE */
1475 /****************************************************************************/
1476 static gboolean have_sdp_tap_listener=FALSE;
1477 /****************************************************************************/
1478 void
1479 sdp_calls_init_tap(void)
1480 {
1481         GString *error_string;
1482
1483         if(have_sdp_tap_listener==FALSE)
1484         {
1485                 /* don't register tap listener, if we have it already */
1486                 error_string = register_tap_listener("sdp", &(the_tapinfo_struct.sdp_dummy), NULL,
1487                         voip_calls_dlg_reset, 
1488                         SDPcalls_packet, 
1489                         voip_calls_dlg_draw
1490                         );
1491                         
1492                 if (error_string != NULL) {
1493                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1494                                       error_string->str);
1495                         g_string_free(error_string, TRUE);
1496                         exit(1);
1497                 }
1498                 have_sdp_tap_listener=TRUE;
1499         }
1500 }
1501
1502
1503 /* XXX just copied from gtk/rpc_stat.c */
1504 void protect_thread_critical_region(void);
1505 void unprotect_thread_critical_region(void);
1506
1507 /****************************************************************************/
1508 void
1509 remove_tap_listener_sdp_calls(void)
1510 {
1511         protect_thread_critical_region();
1512         remove_tap_listener(&(the_tapinfo_struct.sdp_dummy));
1513         unprotect_thread_critical_region();
1514
1515         have_sdp_tap_listener=FALSE;
1516 }
1517
1518
1519
1520 /****************************************************************************/
1521 /* ***************************TAP for MGCP **********************************/
1522 /****************************************************************************/
1523
1524 /*
1525    This function will look for a signal/event in the SignalReq/ObsEvent string
1526    and return true if it is found 
1527 */
1528 gboolean isSignal(gchar *signal, gchar *signalStr)
1529 {
1530         gint i; 
1531         gchar **resultArray;
1532         
1533         /* if there is no signalStr, just return false */
1534         if (signalStr == NULL) return FALSE;
1535
1536         /* if are both "blank" return true */
1537         if ( (*signal == '\0') &&  (*signalStr == '\0') ) return TRUE;
1538
1539         /* look for signal in signalSre */
1540         resultArray = g_strsplit(signalStr, ",", 10);
1541
1542         for (i = 0; resultArray[i]; i++) {
1543                 g_strstrip(resultArray[i]);
1544                 if (strcmp(resultArray[i], signal) == 0) return TRUE;
1545         }
1546
1547         g_strfreev(resultArray);
1548         
1549         return FALSE;
1550 }
1551
1552 /*
1553    This function will get the Caller ID info and replace the current string
1554    This is how it looks the caller Id: rg, ci(02/16/08/29, "3035550002","Ale Sipura 2")
1555 */
1556 void mgcpCallerID(gchar *signalStr, gchar **callerId)
1557 {
1558         gint i; 
1559         gchar **resultArray;
1560         gchar **arrayStr;
1561         
1562         /* if there is no signalStr, just return false */
1563         if (signalStr == NULL) return;
1564
1565         arrayStr = g_strsplit(signalStr, "\"", 10);
1566
1567         if (arrayStr[0] == NULL) return;
1568
1569         /* look for the ci signal */
1570         resultArray = g_strsplit(arrayStr[0], ",(", 10);
1571
1572         for (i = 0; resultArray[i]; i++) {
1573                 g_strstrip(resultArray[i]);
1574                 if (strcmp(resultArray[i], "ci") == 0){
1575                         if (arrayStr[1] != NULL){
1576                                 /* free the previous "From" field of the call, and assign the new */
1577                                 g_free(*callerId);
1578                                 *callerId = g_strdup(arrayStr[1]);
1579                         }
1580                         g_strfreev(arrayStr);
1581                         g_strfreev(resultArray);
1582                         return;
1583                 }
1584         }
1585
1586         g_strfreev(arrayStr);
1587         g_strfreev(resultArray);
1588
1589         return;
1590 }
1591
1592
1593 /*
1594    This function will get the Dialed Digits and replace the current string
1595    This is how it looks the dialed digits 5,5,5,0,0,0,2,#,*
1596 */
1597 void mgcpDialedDigits(gchar *signalStr, gchar **dialedDigits)
1598 {
1599         gchar *tmpStr;
1600         gchar resultStr[50];
1601         gint i,j; 
1602
1603         /* if there is no signalStr, just return false */
1604         if (signalStr == NULL) return;
1605
1606         tmpStr = g_strdup(signalStr);
1607         
1608         for ( i = 0 ; tmpStr[i] ; i++) {
1609                 switch (tmpStr[i]) {
1610                         case '0' : case '1' : case '2' : case '3' : case '4' :
1611                         case '5' : case '6' : case '7' : case '8' : case '9' :
1612                         case '#' : case '*' :
1613                                 break;
1614                         default:
1615                                 tmpStr[i] = '?';
1616                                 break;
1617                 }
1618         }
1619         
1620         for (i = 0, j = 0; tmpStr[i] && i<50; i++) {
1621                 if (tmpStr[i] != '?')
1622                         resultStr[j++] = tmpStr[i];
1623         }
1624         resultStr[j] = '\0';
1625
1626         if (*resultStr == '\0') return;
1627         
1628         g_free(*dialedDigits);
1629         *dialedDigits = g_strdup(resultStr);
1630         g_free(tmpStr);
1631
1632         return;
1633 }
1634
1635
1636
1637 /****************************************************************************/
1638 /* whenever a MGCP packet is seen by the tap listener */
1639 static int 
1640 MGCPcalls_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *MGCPinfo)
1641 {
1642         voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1643
1644         voip_calls_info_t *tmp_listinfo;
1645         voip_calls_info_t *strinfo = NULL;
1646         mgcp_calls_info_t *tmp_mgcpinfo = NULL;
1647         GList* list;
1648         GList* listGraph;
1649         gchar *frame_label = NULL;
1650         gchar *comment = NULL;
1651         graph_analysis_item_t *gai;
1652         gboolean new = FALSE;
1653         gboolean fromEndpoint = FALSE; /* true for calls originated in Endpoints, false for calls from MGC */
1654         gdouble diff_time;
1655
1656         const mgcp_info_t *pi = MGCPinfo;
1657
1658
1659         if ((pi->mgcp_type == MGCP_REQUEST) && !pi->is_duplicate ){
1660                 /* check wether we already have a call with this Endpoint and it is active*/
1661                 list = g_list_first(tapinfo->strinfo_list);
1662                 while (list)
1663                 {
1664                         tmp_listinfo=list->data;
1665                         if ((tmp_listinfo->protocol == VOIP_MGCP) && (tmp_listinfo->call_active_state == VOIP_ACTIVE)){
1666                                 tmp_mgcpinfo = tmp_listinfo->prot_info;
1667                                 if (pi->endpointId != NULL){
1668                                         if (g_strcasecmp(tmp_mgcpinfo->endpointId,pi->endpointId) == 0){
1669                                                 /*
1670                                                    check first if it is an ended call. We consider an ended call after 1sec we don't 
1671                                                    get a packet in this Endpoint and the call has been released
1672                                                 */
1673                                                 diff_time = (pinfo->fd->rel_secs + (double)pinfo->fd->rel_secs/1000000) - (tmp_listinfo->stop_sec + (double)tmp_listinfo->stop_usec/1000000);
1674                                                 if ( ((tmp_listinfo->call_state == VOIP_CANCELLED) || (tmp_listinfo->call_state == VOIP_COMPLETED)  || (tmp_listinfo->call_state == VOIP_REJECTED)) && (diff_time > 1) ){
1675                                                         tmp_listinfo->call_active_state = VOIP_INACTIVE;
1676                                                 } else {
1677                                                         strinfo = (voip_calls_info_t*)(list->data);
1678                                                         break;
1679                                                 }
1680                                         }
1681                                 }
1682                         }
1683                         list = g_list_next (list);
1684                 }
1685                 
1686                 /* there is no call with this Endpoint, lets see if this a new call or not */
1687                 if (strinfo == NULL){
1688                         if ( (strcmp(pi->code, "NTFY") == 0) && isSignal("hd", pi->observedEvents) ){ /* off hook transition */
1689                                 /* this is a new call from the Endpoint */      
1690                                 fromEndpoint = TRUE;
1691                                 new = TRUE;
1692                         } else if (strcmp(pi->code, "CRCX") == 0){
1693                                 /* this is a new call from the MGC */
1694                                 fromEndpoint = FALSE;
1695                                 new = TRUE;
1696                         }
1697                         if (!new) return 0;
1698                 } 
1699         } else if ( ((pi->mgcp_type == MGCP_RESPONSE) && pi->request_available) ||
1700                         ((pi->mgcp_type == MGCP_REQUEST) && pi->is_duplicate) ) {
1701                 /* if it is a response OR if it is a duplicated Request, lets look in the Graph if thre is a request that match */
1702                 listGraph = g_list_first(tapinfo->graph_analysis->list);
1703                 while (listGraph)
1704                 {
1705                         gai = listGraph->data;
1706                         if (gai->frame_num == pi->req_num){
1707                                 /* there is a request that match, so look the associated call with this call_num */
1708                                 list = g_list_first(tapinfo->strinfo_list);
1709                                 while (list)
1710                                 {
1711                                         tmp_listinfo=list->data;
1712                                         if (tmp_listinfo->protocol == VOIP_MGCP){
1713                                                 if (tmp_listinfo->call_num == gai->conv_num){
1714                                                         tmp_mgcpinfo = tmp_listinfo->prot_info;
1715                                                         strinfo = (voip_calls_info_t*)(list->data);
1716                                                         break;
1717                                                 }
1718                                         }
1719                                         list = g_list_next (list);
1720                                 }
1721                                 if (strinfo != NULL) break;
1722                         }
1723                         listGraph = g_list_next(listGraph);
1724                 }
1725                 /* if there is not a matching request, just return */
1726                 if (strinfo == NULL) return 0;
1727         } else return 0;
1728
1729         /* not in the list? then create a new entry */
1730         if (strinfo==NULL){
1731                 strinfo = g_malloc(sizeof(voip_calls_info_t));
1732                 strinfo->call_active_state = VOIP_ACTIVE;
1733                 strinfo->call_state = VOIP_CALL_SETUP;
1734                 if (fromEndpoint) {
1735                         strinfo->from_identity=g_strdup(pi->endpointId);
1736                         strinfo->to_identity=g_strdup("");
1737                 } else {
1738                         strinfo->from_identity=g_strdup("");
1739                         strinfo->to_identity=g_strdup(pi->endpointId);
1740                 }
1741                 g_memmove(&(strinfo->initial_speaker), pinfo->src.data, 4);
1742                 strinfo->first_frame_num=pinfo->fd->num;
1743                 strinfo->selected=FALSE;
1744                 strinfo->start_sec=pinfo->fd->rel_secs;
1745                 strinfo->start_usec=pinfo->fd->rel_usecs;
1746                 strinfo->protocol=VOIP_MGCP;
1747                 strinfo->prot_info=g_malloc(sizeof(mgcp_calls_info_t));
1748                 tmp_mgcpinfo=strinfo->prot_info;
1749                 tmp_mgcpinfo->endpointId = g_strdup(pi->endpointId);
1750                 tmp_mgcpinfo->fromEndpoint = fromEndpoint;
1751                 strinfo->npackets = 0;
1752                 strinfo->call_num = tapinfo->ncalls++;
1753                 tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
1754         }
1755
1756         g_assert(tmp_mgcpinfo != NULL);
1757
1758         /* change call state and add to graph */
1759         switch (pi->mgcp_type)
1760         {
1761         case MGCP_REQUEST:
1762                 if ( (strcmp(pi->code, "NTFY") == 0) && (pi->observedEvents != NULL) ){
1763                         frame_label = g_strdup_printf("%s ObsEvt:%s",pi->code, pi->observedEvents);
1764
1765                         if (tmp_mgcpinfo->fromEndpoint){
1766                                 /* use the Dialed digits to fill the "To" for the call */
1767                                 mgcpDialedDigits(pi->observedEvents, &(strinfo->to_identity));
1768
1769                         /* from MGC and the user picked up, the call is connected */
1770                         } else if (isSignal("hd", pi->observedEvents))  
1771                                 strinfo->call_state=VOIP_IN_CALL;
1772
1773                         /* hung up signal */
1774                         if (isSignal("hu", pi->observedEvents)) {
1775                                 if ((strinfo->call_state == VOIP_CALL_SETUP) || (strinfo->call_state == VOIP_RINGING)){
1776                                         strinfo->call_state = VOIP_CANCELLED;
1777                                 } else {
1778                                         strinfo->call_state = VOIP_COMPLETED;
1779                                 }
1780                         }       
1781                         
1782                 } else if (strcmp(pi->code, "RQNT") == 0) {
1783                         /* for calls from Endpoint: if there is a "no signal" RQNT and the call was RINGING, we assume this is the CONNECT */
1784                         if ( tmp_mgcpinfo->fromEndpoint && isSignal("", pi->signalReq) && (strinfo->call_state == VOIP_RINGING) ) { 
1785                                         strinfo->call_state = VOIP_IN_CALL;
1786                         }
1787
1788                         /* if there is ringback or ring tone, change state to ringing */
1789                         if ( isSignal("rg", pi->signalReq) || isSignal("rt", pi->signalReq) ) { 
1790                                         strinfo->call_state = VOIP_RINGING;
1791                         }
1792
1793                         /* if there is a Busy or ReorderTone, and the call was Ringing or Setup the call is Rejected */
1794                         if ( (isSignal("ro", pi->signalReq) || isSignal("bz", pi->signalReq)) && ((strinfo->call_state == VOIP_CALL_SETUP) || (strinfo->call_state = VOIP_RINGING)) ) { 
1795                                         strinfo->call_state = VOIP_REJECTED;
1796                         }
1797
1798                         if (pi->signalReq != NULL)
1799                                 frame_label = g_strdup_printf("%s%sSigReq:%s",pi->code, (pi->hasDigitMap == TRUE)?" DigitMap ":"", pi->signalReq);
1800                         else
1801                                 frame_label = g_strdup_printf("%s%s",pi->code, (pi->hasDigitMap == TRUE)?" DigitMap ":"");
1802                         
1803                         /* use the CallerID info to fill the "From" for the call */
1804                         if (!tmp_mgcpinfo->fromEndpoint) mgcpCallerID(pi->signalReq, &(strinfo->from_identity));
1805
1806                 } else if (strcmp(pi->code, "DLCX") == 0) {
1807                         /*
1808                           if there is a DLCX in a call To an Endpoint and the call was not connected, we use
1809                           the DLCX as the end of the call
1810                         */
1811                         if (!tmp_mgcpinfo->fromEndpoint){
1812                                 if ((strinfo->call_state == VOIP_CALL_SETUP) || (strinfo->call_state == VOIP_RINGING)){
1813                                         strinfo->call_state = VOIP_CANCELLED;
1814                                 } 
1815                         } 
1816                 }
1817
1818                 if (frame_label == NULL) frame_label = g_strdup_printf("%s",pi->code);
1819                 break;
1820         case MGCP_RESPONSE:
1821                 frame_label = g_strdup_printf("%d (%s)",pi->rspcode, pi->code);
1822                 break;
1823         case MGCP_OTHERS:
1824                 /* XXX what to do? */
1825                 break;
1826         }
1827
1828
1829         comment = g_strdup_printf("MGCP %s %s%s", tmp_mgcpinfo->endpointId, (pi->mgcp_type == MGCP_REQUEST)?"Request":"Response", pi->is_duplicate?" Duplicate":"");
1830
1831         strinfo->stop_sec=pinfo->fd->rel_secs;
1832         strinfo->stop_usec=pinfo->fd->rel_usecs;
1833         strinfo->last_frame_num=pinfo->fd->num;
1834         ++(strinfo->npackets);
1835         /* increment the packets counter of all calls */
1836         ++(tapinfo->npackets);
1837
1838         /* add to the graph */
1839         add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num);  
1840         g_free(comment);
1841         g_free(frame_label);
1842
1843         /* add SDP info if apply */
1844         if ( (sdp_summary != NULL) && (sdp_frame_num == pinfo->fd->num) ){
1845                         append_to_frame_graph(tapinfo, pinfo->fd->num, sdp_summary, NULL);
1846                         g_free(sdp_summary);
1847                         sdp_summary = NULL;
1848         }
1849
1850         return 1;  /* refresh output */
1851 }
1852
1853
1854 /****************************************************************************/
1855 /* TAP INTERFACE */
1856 /****************************************************************************/
1857 static gboolean have_MGCP_tap_listener=FALSE;
1858 /****************************************************************************/
1859 void
1860 mgcp_calls_init_tap(void)
1861 {
1862         GString *error_string;
1863
1864         if(have_MGCP_tap_listener==FALSE)
1865         {
1866                 /* don't register tap listener, if we have it already */
1867                 /* we send an empty filter, to force a non null "tree" in the mgcp dissector */
1868                 error_string = register_tap_listener("mgcp", &(the_tapinfo_struct.mgcp_dummy), strdup(""),
1869                         voip_calls_dlg_reset, 
1870                         MGCPcalls_packet, 
1871                         voip_calls_dlg_draw
1872                         );
1873                 if (error_string != NULL) {
1874                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1875                                       error_string->str);
1876                         g_string_free(error_string, TRUE);
1877                         exit(1);
1878                 }
1879                 have_MGCP_tap_listener=TRUE;
1880         }
1881 }
1882
1883
1884
1885 /* XXX just copied from gtk/rpc_stat.c */
1886 void protect_thread_critical_region(void);
1887 void unprotect_thread_critical_region(void);
1888
1889 /****************************************************************************/
1890 void
1891 remove_tap_listener_mgcp_calls(void)
1892 {
1893         protect_thread_critical_region();
1894         remove_tap_listener(&(the_tapinfo_struct.mgcp_dummy));
1895         unprotect_thread_critical_region();
1896
1897         have_MGCP_tap_listener=FALSE;
1898 }
1899
1900
1901
1902 /****************************************************************************/
1903 /* ***************************TAP for OTHER PROTOCOL **********************************/
1904 /****************************************************************************/
1905
1906 /****************************************************************************/
1907 /* whenever a prot_ packet is seen by the tap listener */
1908 /*
1909 static int 
1910 prot_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prot_info _U_)
1911 {
1912         voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1913         if (strinfo!=NULL){
1914                 strinfo->stop_sec=pinfo->fd->rel_secs;
1915                 strinfo->stop_usec=pinfo->fd->rel_usecs;
1916                 strinfo->last_frame_num=pinfo->fd->num;
1917                 ++(strinfo->npackets);
1918                 ++(tapinfo->npackets);
1919         }
1920
1921         return 1;
1922 }
1923 */
1924 /****************************************************************************/
1925 /*
1926 static gboolean have_prot__tap_listener=FALSE;
1927
1928 void
1929 prot_calls_init_tap(void)
1930 {
1931         GString *error_string;
1932
1933         if(have_prot__tap_listener==FALSE)
1934         {
1935                 error_string = register_tap_listener("prot_", &(the_tapinfo_struct.prot__dummy),
1936                         NULL,
1937                         voip_calls_dlg_reset,
1938                         prot__calls_packet, 
1939                         voip_calls_dlg_draw
1940                         );
1941
1942                 if (error_string != NULL) {
1943                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1944                                       error_string->str);
1945                         g_string_free(error_string, TRUE);
1946                         exit(1);
1947                 }
1948                 have_prot__tap_listener=TRUE;
1949         }
1950 }
1951 */
1952 /****************************************************************************/
1953 /*
1954 void
1955 remove_tap_listener_prot__calls(void)
1956 {
1957         protect_thread_critical_region();
1958         remove_tap_listener(&(the_tapinfo_struct.prot__dummy));
1959         unprotect_thread_critical_region();
1960
1961         have_prot__tap_listener=FALSE;
1962 }
1963 */
1964