5b255b53182f05edbb08c439e922d26ac8246efc
[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, RTP Event, MGCP, AudioCodes (ISDN PRI and CAS) 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-actrace.h>
58 #include <epan/dissectors/packet-rtp.h>
59 #include <epan/dissectors/packet-rtp-events.h>
60 #include <epan/conversation.h>
61 #include "rtp_pt.h"
62
63 #include "alert_box.h"
64 #include "simple_dialog.h"
65
66 const char *voip_call_state_name[7]={
67         "CALL SETUP",
68         "RINGING",
69         "IN CALL",
70         "CANCELLED",
71         "COMPLETED",
72         "REJECTED",
73         "UNKNOWN"
74         };
75
76 /* defines whether we can consider the call active */
77 const char *voip_protocol_name[6]={
78         "SIP",
79         "ISUP",
80         "H323",
81         "MGCP",
82         "AC_ISDN",
83         "AC_CAS"
84         };
85
86 typedef struct {
87         gchar *frame_label;
88         gchar *comment;
89 } graph_str;
90
91 #define H245_MAX 6
92
93 typedef struct {
94         guint32 frame_num;
95         gint8 labels_count;
96         graph_str labels[H245_MAX];
97 } h245_labels_t;
98
99 static h245_labels_t h245_labels;
100
101 /****************************************************************************/
102 /* the one and only global voip_calls_tapinfo_t structure */
103 static voip_calls_tapinfo_t the_tapinfo_struct =
104         {0, NULL, 0, NULL, 0, 0, 0, 0, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
105
106 /* the one and only global voip_rtp_tapinfo_t structure */
107 static voip_rtp_tapinfo_t the_tapinfo_rtp_struct =
108         {0, NULL, 0, 0};
109
110 /****************************************************************************/
111 /* when there is a [re]reading of packet's */
112 void voip_calls_reset(voip_calls_tapinfo_t *tapinfo)
113 {
114         voip_calls_info_t *strinfo;
115         sip_calls_info_t *tmp_sipinfo;
116         h323_calls_info_t *tmp_h323info;
117         h245_address_t *h245_add;
118
119         graph_analysis_item_t *graph_item;
120
121         GList* list;
122         GList* list2;
123
124         /* free the data items first */
125         list = g_list_first(tapinfo->strinfo_list);
126         while (list)
127         {
128                 strinfo = list->data;
129                 g_free(strinfo->from_identity);
130                 g_free(strinfo->to_identity);
131                 g_free((void *)(strinfo->initial_speaker.data));
132                 if (strinfo->protocol == VOIP_SIP){
133                         tmp_sipinfo = strinfo->prot_info;
134                         g_free(tmp_sipinfo->call_identifier);
135                 }
136                 if (strinfo->protocol == VOIP_H323){
137                         tmp_h323info = strinfo->prot_info;
138                         g_free(tmp_h323info->guid);
139                         /* free the H245 list address */
140                         list2 = g_list_first(tmp_h323info->h245_list);
141                         while (list2)
142                         {
143                                 h245_add=list2->data;
144                                 g_free((void *)h245_add->h245_address.data);
145                                 g_free(list2->data);
146                                 list2 = g_list_next(list2);
147                         }
148                         g_list_free(tmp_h323info->h245_list);
149                         tmp_h323info->h245_list = NULL;
150                 }
151                 g_free(strinfo->prot_info);
152
153                 g_free(list->data);
154                 list = g_list_next(list);
155         }
156         g_list_free(tapinfo->strinfo_list);
157         tapinfo->strinfo_list = NULL;
158         tapinfo->ncalls = 0;
159         tapinfo->npackets = 0;
160         tapinfo->start_packets = 0;
161     tapinfo->completed_calls = 0;
162     tapinfo->rejected_calls = 0;
163
164         /* free the graph data items first */
165         list = g_list_first(tapinfo->graph_analysis->list);
166         while (list)
167         {
168                 graph_item = list->data;
169                 g_free(graph_item->frame_label);
170                 g_free(graph_item->comment);
171                 g_free(list->data);
172                 list = g_list_next(list);
173         }
174         g_list_free(tapinfo->graph_analysis->list);
175         tapinfo->graph_analysis->nconv = 0;
176         tapinfo->graph_analysis->list = NULL;
177
178         ++(tapinfo->launch_count);
179
180         return;
181 }
182
183 /****************************************************************************/
184 void graph_analysis_data_init(void){
185         the_tapinfo_struct.graph_analysis = g_malloc(sizeof(graph_analysis_info_t));
186         the_tapinfo_struct.graph_analysis->nconv = 0;
187         the_tapinfo_struct.graph_analysis->list = NULL;
188
189 }
190
191 /****************************************************************************/
192 /* Add a new item into the graph */
193 static int add_to_graph(voip_calls_tapinfo_t *tapinfo _U_, packet_info *pinfo, const gchar *frame_label, gchar *comment, guint16 call_num, address *src_addr, address *dst_addr)
194 {
195         graph_analysis_item_t *gai;
196
197         gai = g_malloc(sizeof(graph_analysis_item_t));
198         gai->frame_num = pinfo->fd->num;
199         gai->time= (double)pinfo->fd->rel_secs + (double) pinfo->fd->rel_usecs/1000000;
200         COPY_ADDRESS(&(gai->src_addr),src_addr);
201         COPY_ADDRESS(&(gai->dst_addr),dst_addr);
202
203         gai->port_src=pinfo->srcport;
204         gai->port_dst=pinfo->destport;
205         if (frame_label != NULL)
206                 gai->frame_label = g_strdup(frame_label);
207         else
208                 gai->frame_label = g_strdup("");
209
210         if (comment != NULL)
211                 gai->comment = g_strdup(comment);
212         else
213                 gai->comment = g_strdup("");
214         gai->conv_num=call_num;
215         gai->line_style=1;
216         gai->display=FALSE;
217
218         tapinfo->graph_analysis->list = g_list_append(tapinfo->graph_analysis->list, gai);
219
220         return 1;
221
222 }
223
224 /****************************************************************************/
225 /* Append str to frame_label and comment in a graph item */
226 /* return 0 if the frame_num is not in the graph list */
227 static int append_to_frame_graph(voip_calls_tapinfo_t *tapinfo _U_, guint32 frame_num, const gchar *new_frame_label, const gchar *new_comment)
228 {
229         graph_analysis_item_t *gai;
230         GList* list;
231         gchar *tmp_str = NULL;
232         gchar *tmp_str2 = NULL;
233
234         list = g_list_first(tapinfo->graph_analysis->list);
235         while (list)
236         {
237                 gai = list->data;
238                 if (gai->frame_num == frame_num){
239                         tmp_str = gai->frame_label;
240                         tmp_str2 = gai->comment;
241
242                         if (new_frame_label != NULL){
243                                 gai->frame_label = g_strdup_printf("%s %s", gai->frame_label, new_frame_label);
244                                 g_free(tmp_str);
245                         }
246
247
248                         if (new_comment != NULL){
249                                 gai->comment = g_strdup_printf("%s %s", gai->comment, new_comment);
250                                 g_free(tmp_str2);
251                         }
252                         break;
253                 }
254                 list = g_list_next (list);
255         }
256         if (tmp_str == NULL) return 0;          /* it is not in the list */
257         return 1;
258
259 }
260
261 /****************************************************************************/
262 /* Change the frame_label and comment in a graph item if not NULL*/
263 /* return 0 if the frame_num is not in the graph list */
264 static int change_frame_graph(voip_calls_tapinfo_t *tapinfo _U_, guint32 frame_num, const gchar *new_frame_label, const gchar *new_comment)
265 {
266         graph_analysis_item_t *gai;
267         GList* list;
268         gchar *tmp_str = NULL;
269         gchar *tmp_str2 = NULL;
270
271         list = g_list_first(tapinfo->graph_analysis->list);
272         while (list)
273         {
274                 gai = list->data;
275                 if (gai->frame_num == frame_num){
276                         tmp_str = gai->frame_label;
277                         tmp_str2 = gai->comment;
278
279                         if (new_frame_label != NULL){
280                                 gai->frame_label = g_strdup(new_frame_label);
281                                 g_free(tmp_str);
282                         }
283
284                         if (new_comment != NULL){
285                                 gai->comment = g_strdup(new_comment);
286                                 g_free(tmp_str2);
287                         }
288                         break;
289                 }
290                 list = g_list_next (list);
291         }
292         if (tmp_str == NULL) return 0;          /* it is not in the list */
293         return 1;
294
295 }
296
297 /****************************************************************************/
298 /* Change all the graph items with call_num to new_call_num */
299 static guint change_call_num_graph(voip_calls_tapinfo_t *tapinfo _U_, guint16 call_num, guint16 new_call_num)
300 {
301         graph_analysis_item_t *gai;
302         GList* list;
303         guint items_changed;
304
305         items_changed = 0;
306         list = g_list_first(tapinfo->graph_analysis->list);
307         while (list)
308         {
309                 gai = list->data;
310                 if (gai->conv_num == call_num){
311                         gai->conv_num = new_call_num;
312                         items_changed++;
313                 }
314                 list = g_list_next (list);
315         }
316         return items_changed;
317 }
318
319 /* XXX just copied from gtk/rpc_stat.c */
320 void protect_thread_critical_region(void);
321 void unprotect_thread_critical_region(void);
322
323 /****************************************************************************/
324 /* ***************************TAP for RTP Events*****************************/
325 /****************************************************************************/
326
327 /****************************************************************************/
328 /* whenever a rtp event packet is seen by the tap listener */
329 static int 
330 rtp_event_packet(void *ptr _U_, packet_info *pinfo _U_, epan_dissect_t *edt _U_, const void *rtp_event_info)
331 {
332         const struct _rtp_event_info *pi = rtp_event_info;
333         voip_rtp_tapinfo_t *tapinfo = &the_tapinfo_rtp_struct;
334         voip_rtp_stream_info_t *tmp_listinfo;
335         voip_rtp_stream_info_t *strinfo = NULL;
336         GList* list;
337
338         /* do not consider RTP events packets without a setup frame */
339         if (pi->info_setup_frame_num == 0){
340                 return 0;
341         }
342
343         /* check wether we already have a RTP stream with this setup frame in the list */
344         list = g_list_first(tapinfo->list);
345         while (list)
346         {
347                 tmp_listinfo=list->data;
348                 if ( (tmp_listinfo->setup_frame_number == pi->info_setup_frame_num) 
349                         && (tmp_listinfo->end_stream == FALSE) && (tmp_listinfo->rtp_event == -1)){
350                                 strinfo = (voip_rtp_stream_info_t*)(list->data);
351                                 strinfo->rtp_event = pi->info_rtp_evt;
352                                 break;
353                 }
354                 list = g_list_next (list);
355         }
356
357
358         return 0;
359 }
360
361 /****************************************************************************/
362 static gboolean have_rtp_event_tap_listener=FALSE;
363
364 void
365 rtp_event_init_tap(void)
366 {
367         GString *error_string;
368
369
370         if(have_rtp_event_tap_listener==FALSE)
371         {
372                 error_string = register_tap_listener("rtpevent", &(the_tapinfo_rtp_struct.rtp_event_dummy),
373                         NULL,
374                         NULL,
375                         rtp_event_packet,
376                         NULL
377                         );
378                         
379                 if (error_string != NULL) {
380                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
381                                       error_string->str);
382                         g_string_free(error_string, TRUE);
383                         exit(1);
384                 }
385                 have_rtp_event_tap_listener=TRUE;
386         }
387 }
388
389 /****************************************************************************/
390
391 void
392 remove_tap_listener_rtp_event(void)
393 {
394         protect_thread_critical_region();
395         remove_tap_listener(&(the_tapinfo_rtp_struct.rtp_event_dummy));
396         unprotect_thread_critical_region();
397
398         have_rtp_event_tap_listener=FALSE;
399 }
400
401 /****************************************************************************/
402 /* ***************************TAP for RTP **********************************/
403 /****************************************************************************/
404
405 /****************************************************************************/
406 /* when there is a [re]reading of RTP packet's */
407 static void voip_rtp_reset(void *ptr _U_)
408 {
409         voip_rtp_tapinfo_t *tapinfo = &the_tapinfo_rtp_struct;
410         GList* list;
411         /* free the data items first */
412         list = g_list_first(tapinfo->list);
413         while (list)
414         {
415                 g_free(list->data);
416                 list = g_list_next(list);
417         }
418         g_list_free(tapinfo->list);
419         tapinfo->list = NULL;
420         tapinfo->nstreams = 0;
421         return;
422 }
423
424 /****************************************************************************/
425 /* whenever a RTP packet is seen by the tap listener */
426 static int 
427 RTP_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *RTPinfo)
428 {
429         voip_rtp_tapinfo_t *tapinfo = &the_tapinfo_rtp_struct;
430         voip_rtp_stream_info_t *tmp_listinfo;
431         voip_rtp_stream_info_t *strinfo = NULL;
432         GList* list;
433         struct _rtp_conversation_info *p_conv_data = NULL;
434
435         const struct _rtp_info *pi = RTPinfo;
436
437         /* do not consider RTP packets without a setup frame */
438         if (pi->info_setup_frame_num == 0){
439                 return 0;
440         }
441
442         /* check wether we already have a RTP stream with this setup frame and ssrc in the list */
443         list = g_list_first(tapinfo->list);
444         while (list)
445         {
446                 tmp_listinfo=list->data;
447                 if ( (tmp_listinfo->setup_frame_number == pi->info_setup_frame_num) 
448                         && (tmp_listinfo->ssrc == pi->info_sync_src) && (tmp_listinfo->end_stream == FALSE)){
449                         /* if the payload type has changed, we mark the stream as finished to create a new one
450                            this is to show multiple payload changes in the Graph for example for DTMF RFC2833 */           
451                         if ( tmp_listinfo->pt != pi->info_payload_type ) 
452                                 tmp_listinfo->end_stream = TRUE;
453                         else {
454                                 strinfo = (voip_rtp_stream_info_t*)(list->data);
455                                 break;
456                         }
457                 }
458                 list = g_list_next (list);
459         }
460
461         /* not in the list? then create a new entry */
462         if (strinfo==NULL){
463                 strinfo = g_malloc(sizeof(voip_rtp_stream_info_t));
464                 COPY_ADDRESS(&(strinfo->src_addr), &(pinfo->src));
465                 strinfo->src_port = pinfo->srcport;
466                 COPY_ADDRESS(&(strinfo->dest_addr), &(pinfo->dst));
467                 strinfo->dest_port = pinfo->destport;
468                 strinfo->ssrc = pi->info_sync_src;
469                 strinfo->end_stream = FALSE;
470                 strinfo->pt = pi->info_payload_type;
471                 strinfo->pt_str = NULL;
472                 /* if it is dynamic payload, let use the conv data to see if it is defined */
473                 if ( (strinfo->pt>95) && (strinfo->pt<128) ) {
474                         /* Use existing packet info if available */
475                         p_conv_data = p_get_proto_data(pinfo->fd, proto_get_id_by_filter_name("rtp"));
476                         if (p_conv_data)
477                                 strinfo->pt_str = g_strdup(g_hash_table_lookup(p_conv_data->rtp_dyn_payload, &strinfo->pt));
478                 }
479                 if (!strinfo->pt_str) strinfo->pt_str = g_strdup(val_to_str(strinfo->pt, rtp_payload_type_short_vals, "%u"));
480                 strinfo->npackets = 0;
481                 strinfo->first_frame_num = pinfo->fd->num;
482                 strinfo->start_rel_sec = pinfo->fd->rel_secs;
483                 strinfo->start_rel_usec = pinfo->fd->rel_usecs;
484                 strinfo->setup_frame_number = pi->info_setup_frame_num;
485                 strinfo->rtp_event = -1;
486                 tapinfo->list = g_list_append(tapinfo->list, strinfo);
487         }
488
489         if (strinfo!=NULL){
490                 /* Add the info to the existing RTP stream */
491                 strinfo->npackets++;
492                 strinfo->stop_rel_sec = pinfo->fd->rel_secs;
493                 strinfo->stop_rel_usec = pinfo->fd->rel_usecs;
494         }
495
496         the_tapinfo_struct.redraw = TRUE;
497
498         return 1;
499 }
500
501 /****************************************************************************/
502 /* whenever a redraw in the RTP tap listener */
503 static void RTP_packet_draw(void *prs _U_)
504 {
505         voip_rtp_tapinfo_t *rtp_tapinfo = &the_tapinfo_rtp_struct;
506         GList* rtp_streams_list;
507         voip_rtp_stream_info_t *rtp_listinfo;
508         GList* voip_calls_graph_list;
509         guint item;
510         graph_analysis_item_t *gai;
511         graph_analysis_item_t *new_gai;
512         guint16 conv_num;
513         guint32 duration;
514
515         /* add each rtp stream to the graph */
516         rtp_streams_list = g_list_first(rtp_tapinfo->list);
517         while (rtp_streams_list)
518         {
519                 rtp_listinfo = rtp_streams_list->data;
520
521                 /* using the setup frame number of the RTP stream, we get the call number that it belongs */
522                 voip_calls_graph_list = g_list_first(the_tapinfo_struct.graph_analysis->list);
523                 item = 0;
524                 while (voip_calls_graph_list)
525                 {                       
526                         gai = voip_calls_graph_list->data;
527                         conv_num = gai->conv_num;
528                         /* if we get the setup frame number, then get the time position to graph the RTP arrow */
529                         if (rtp_listinfo->setup_frame_number == gai->frame_num){
530                                 while(voip_calls_graph_list){
531                                         gai = voip_calls_graph_list->data;
532                                         /* if RTP was already in the Graph, just update the comment information */
533                                         if (rtp_listinfo->first_frame_num == gai->frame_num){
534                                                 duration = (rtp_listinfo->stop_rel_sec*1000000 + rtp_listinfo->stop_rel_usec) - (rtp_listinfo->start_rel_sec*1000000 + rtp_listinfo->start_rel_usec);
535                                                 g_free(gai->comment);
536                                                 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);
537                                                 break;
538                                         /* add the RTP item to the graph if was not there*/
539                                         } else if (rtp_listinfo->first_frame_num<gai->frame_num){
540                                                 new_gai = g_malloc(sizeof(graph_analysis_item_t));
541                                                 new_gai->frame_num = rtp_listinfo->first_frame_num;
542                                                 new_gai->time = (double)rtp_listinfo->start_rel_sec + (double)rtp_listinfo->start_rel_usec/1000000;
543                                                 COPY_ADDRESS(&(new_gai->src_addr),&(rtp_listinfo->src_addr));
544                                                 COPY_ADDRESS(&(new_gai->dst_addr),&(rtp_listinfo->dest_addr));
545                                                 new_gai->port_src = rtp_listinfo->src_port;
546                                                 new_gai->port_dst = rtp_listinfo->dest_port;
547                                                 duration = (rtp_listinfo->stop_rel_sec*1000000 + rtp_listinfo->stop_rel_usec) - (rtp_listinfo->start_rel_sec*1000000 + rtp_listinfo->start_rel_usec);
548                                                 new_gai->frame_label = g_strdup_printf("RTP (%s) %s", rtp_listinfo->pt_str, (rtp_listinfo->rtp_event == -1)?"":val_to_str(rtp_listinfo->rtp_event, rtp_event_type_values, "Uknown RTP Event")); 
549                                                 g_free(rtp_listinfo->pt_str);
550                                                 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);
551                                                 new_gai->conv_num = conv_num;
552                                                 new_gai->display=FALSE;
553                                                 new_gai->line_style = 2;  /* the arrow line will be 2 pixels width */
554                                                 the_tapinfo_struct.graph_analysis->list = g_list_insert(the_tapinfo_struct.graph_analysis->list, new_gai, item);
555                                                 break;
556                                         }
557                                         
558                                         voip_calls_graph_list = g_list_next(voip_calls_graph_list);
559                                         item++;
560                                 }
561                                 break;
562                         }
563                         voip_calls_graph_list = g_list_next(voip_calls_graph_list);
564                         item++;
565                 }
566                 rtp_streams_list = g_list_next(rtp_streams_list);
567         }
568 }
569
570 static gboolean have_RTP_tap_listener=FALSE;
571 /****************************************************************************/
572 void
573 rtp_init_tap(void)
574 {
575         GString *error_string;
576
577         if(have_RTP_tap_listener==FALSE)
578         {
579                 /* don't register tap listener, if we have it already */
580                 error_string = register_tap_listener("rtp", &(the_tapinfo_rtp_struct.rtp_dummy), NULL,
581                         voip_rtp_reset, 
582                         RTP_packet, 
583                         RTP_packet_draw
584                         );
585                 if (error_string != NULL) {
586                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
587                                       error_string->str);
588                         g_string_free(error_string, TRUE);
589                         exit(1);
590                 }
591                 have_RTP_tap_listener=TRUE;
592         }
593 }
594
595 /****************************************************************************/
596 void
597 remove_tap_listener_rtp(void)
598 {
599         protect_thread_critical_region();
600         remove_tap_listener(&(the_tapinfo_rtp_struct.rtp_dummy));
601         unprotect_thread_critical_region();
602
603         have_RTP_tap_listener=FALSE;
604 }
605
606 /****************************************************************************/
607 static gchar *sdp_summary = NULL;
608 static guint32 sdp_frame_num = 0;
609
610 /****************************************************************************/
611 /* ***************************TAP for SIP **********************************/
612 /****************************************************************************/
613
614 /****************************************************************************/
615 /* whenever a SIP packet is seen by the tap listener */
616 static int 
617 SIPcalls_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *SIPinfo)
618 {
619         voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
620         /* we just take note of the ISUP data here; when we receive the MTP3 part everything will
621            be compared with existing calls */
622
623         voip_calls_info_t *tmp_listinfo;
624         voip_calls_info_t *strinfo = NULL;
625         sip_calls_info_t *tmp_sipinfo = NULL;
626         GList* list;
627         address tmp_src, tmp_dst;
628         gchar *frame_label = NULL;
629         gchar *comment = NULL;
630
631         const sip_info_value_t *pi = SIPinfo;
632
633         /* do not consider packets without call_id */
634         if (pi->tap_call_id ==NULL){
635                 return 0;
636         }
637
638         /* check wether we already have a call with these parameters in the list */
639         list = g_list_first(tapinfo->strinfo_list);
640         while (list)
641         {
642                 tmp_listinfo=list->data;
643                 if (tmp_listinfo->protocol == VOIP_SIP){
644                         tmp_sipinfo = tmp_listinfo->prot_info;
645                         if (strcmp(tmp_sipinfo->call_identifier,pi->tap_call_id)==0){
646                                 strinfo = (voip_calls_info_t*)(list->data);
647                                 break;
648                         }
649                 }
650                 list = g_list_next (list);
651         }
652
653         /* not in the list? then create a new entry if the message is INVITE -i.e. if this session is a call*/
654         if ((strinfo==NULL) &&(pi->request_method!=NULL)){
655                 if (strcmp(pi->request_method,"INVITE")==0){
656                         strinfo = g_malloc(sizeof(voip_calls_info_t));
657                         strinfo->call_active_state = VOIP_ACTIVE;
658                         strinfo->call_state = VOIP_CALL_SETUP;
659                         strinfo->from_identity=g_strdup(pi->tap_from_addr);
660                         strinfo->to_identity=g_strdup(pi->tap_to_addr);
661                         COPY_ADDRESS(&(strinfo->initial_speaker),&(pinfo->src));
662                         strinfo->first_frame_num=pinfo->fd->num;
663                         strinfo->selected=FALSE;
664                         strinfo->start_sec=pinfo->fd->rel_secs;
665                         strinfo->start_usec=pinfo->fd->rel_usecs;
666                         strinfo->protocol=VOIP_SIP;
667                         strinfo->prot_info=g_malloc(sizeof(sip_calls_info_t));
668                         tmp_sipinfo=strinfo->prot_info;
669                         tmp_sipinfo->call_identifier=strdup(pi->tap_call_id);
670                         tmp_sipinfo->sip_state=SIP_INVITE_SENT;
671                         tmp_sipinfo->invite_cseq=pi->tap_cseq_number;
672                         strinfo->npackets = 0;
673                         strinfo->call_num = tapinfo->ncalls++;
674                         tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
675                 }
676         }
677
678         if (strinfo!=NULL){
679
680                 /* let's analyze the call state */
681
682                 COPY_ADDRESS(&(tmp_src), &(pinfo->src));
683                 COPY_ADDRESS(&(tmp_dst), &(pinfo->dst));
684                 
685                 if (pi->request_method == NULL){
686                         frame_label = g_strdup_printf("%d %s", pi->response_code, pi->reason_phrase );
687                         comment = g_strdup_printf("SIP Status");
688
689                         if ((tmp_sipinfo && pi->tap_cseq_number == tmp_sipinfo->invite_cseq)&&(ADDRESSES_EQUAL(&tmp_dst,&(strinfo->initial_speaker)))){
690                                 if ((pi->response_code > 199) && (pi->response_code<300) && (tmp_sipinfo->sip_state == SIP_INVITE_SENT)){
691                                         tmp_sipinfo->sip_state = SIP_200_REC;
692                                 }
693                                 else if ((pi->response_code>299)&&(tmp_sipinfo->sip_state == SIP_INVITE_SENT)){
694                                         strinfo->call_state = VOIP_REJECTED;
695                                         tapinfo->rejected_calls++;
696                                 }
697                         }
698
699                 }
700                 else{
701                         frame_label = g_strdup(pi->request_method);
702
703                         if ((strcmp(pi->request_method,"INVITE")==0)&&(ADDRESSES_EQUAL(&tmp_src,&(strinfo->initial_speaker)))){
704                                 tmp_sipinfo->invite_cseq = pi->tap_cseq_number;
705                                 strinfo->call_state = VOIP_CALL_SETUP;
706                                 comment = g_strdup_printf("SIP From: %s To:%s", strinfo->from_identity, strinfo->to_identity);
707                         }
708                         else if ((strcmp(pi->request_method,"ACK")==0)&&(pi->tap_cseq_number == tmp_sipinfo->invite_cseq)
709                                 &&(ADDRESSES_EQUAL(&tmp_src,&(strinfo->initial_speaker)))&&(tmp_sipinfo->sip_state==SIP_200_REC)
710                                 &&(strinfo->call_state == VOIP_CALL_SETUP)){
711                                 strinfo->call_state = VOIP_IN_CALL;
712                                 comment = g_strdup_printf("SIP Request");
713                         }
714                         else if (strcmp(pi->request_method,"BYE")==0){
715                                 strinfo->call_state = VOIP_COMPLETED;
716                                 tapinfo->completed_calls++;
717                                 comment = g_strdup_printf("SIP Request");
718                         }
719                         else if ((strcmp(pi->request_method,"CANCEL")==0)&&(pi->tap_cseq_number == tmp_sipinfo->invite_cseq)
720                                 &&(ADDRESSES_EQUAL(&tmp_src,&(strinfo->initial_speaker)))&&(strinfo->call_state==VOIP_CALL_SETUP)){
721                                 strinfo->call_state = VOIP_CANCELLED;
722                                 tmp_sipinfo->sip_state = SIP_CANCEL_SENT;
723                                 comment = g_strdup_printf("SIP Request");
724                         } else {
725                                 comment = g_strdup_printf("SIP Request");
726                         }
727                 }
728
729                 strinfo->stop_sec=pinfo->fd->rel_secs;
730                 strinfo->stop_usec=pinfo->fd->rel_usecs;
731                 strinfo->last_frame_num=pinfo->fd->num;
732                 ++(strinfo->npackets);
733                 /* increment the packets counter of all calls */
734                 ++(tapinfo->npackets);
735
736                 /* add to the graph */
737                 add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num, &(pinfo->src), &(pinfo->dst));  
738                 g_free(comment);
739                 g_free(frame_label);
740                 g_free((void *)tmp_src.data);
741                 g_free((void *)tmp_dst.data);
742
743                 /* add SDP info if apply */
744                 if ( (sdp_summary != NULL) && (sdp_frame_num == pinfo->fd->num) ){
745                                 append_to_frame_graph(tapinfo, pinfo->fd->num, sdp_summary, NULL);
746                                 g_free(sdp_summary);
747                                 sdp_summary = NULL;
748                 }
749         }
750
751         tapinfo->redraw = TRUE;
752
753         return 1;  /* refresh output */
754 }
755
756
757 /****************************************************************************/
758 voip_calls_tapinfo_t* voip_calls_get_info(void)
759 {
760         return &the_tapinfo_struct;
761 }
762
763
764 /****************************************************************************/
765 /* TAP INTERFACE */
766 /****************************************************************************/
767 static gboolean have_SIP_tap_listener=FALSE;
768 /****************************************************************************/
769 void
770 sip_calls_init_tap(void)
771 {
772         GString *error_string;
773
774         if(have_SIP_tap_listener==FALSE)
775         {
776                 /* don't register tap listener, if we have it already */
777                 error_string = register_tap_listener("sip", &(the_tapinfo_struct.sip_dummy), NULL,
778                         voip_calls_dlg_reset, 
779                         SIPcalls_packet, 
780                         voip_calls_dlg_draw
781                         );
782                 if (error_string != NULL) {
783                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
784                                       error_string->str);
785                         g_string_free(error_string, TRUE);
786                         exit(1);
787                 }
788                 have_SIP_tap_listener=TRUE;
789         }
790 }
791
792
793
794 /* XXX just copied from gtk/rpc_stat.c */
795 void protect_thread_critical_region(void);
796 void unprotect_thread_critical_region(void);
797
798 /****************************************************************************/
799 void
800 remove_tap_listener_sip_calls(void)
801 {
802         protect_thread_critical_region();
803         remove_tap_listener(&(the_tapinfo_struct.sip_dummy));
804         unprotect_thread_critical_region();
805
806         have_SIP_tap_listener=FALSE;
807 }
808
809 /****************************************************************************/
810 /* ***************************TAP for ISUP **********************************/
811 /****************************************************************************/
812
813 static  guint32         mtp3_opc, mtp3_dpc;
814 static  guint8          mtp3_ni;
815 static  guint32         mtp3_frame_num;
816
817
818 /****************************************************************************/
819 /* whenever a isup_ packet is seen by the tap listener */
820 static int 
821 isup_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *isup_info _U_)
822 {
823         voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
824         voip_calls_info_t *tmp_listinfo;
825         voip_calls_info_t *strinfo = NULL;
826         isup_calls_info_t *tmp_isupinfo;
827         gboolean found = FALSE;
828         gboolean forward = FALSE;
829         gboolean right_pair;
830         GList* list;
831         gchar *frame_label = NULL;
832         gchar *comment = NULL;
833         int i;
834
835         /*voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct; unused */
836         const isup_tap_rec_t *pi = isup_info;
837
838
839         /* check if the lower layer is MTP matching the frame number */
840         if (mtp3_frame_num != pinfo->fd->num) return 0;
841         
842         /* check wether we already have a call with these parameters in the list */
843         list = g_list_first(tapinfo->strinfo_list);
844         while (list)
845         {
846                 right_pair = TRUE;
847                 tmp_listinfo=list->data;
848                 if ((tmp_listinfo->protocol == VOIP_ISUP)&&(tmp_listinfo->call_active_state==VOIP_ACTIVE)){
849                         tmp_isupinfo = tmp_listinfo->prot_info;
850                         if ((tmp_isupinfo->cic == pinfo->circuit_id)&&(tmp_isupinfo->ni == mtp3_ni)) {
851                                 if ((tmp_isupinfo->opc == mtp3_opc)&&(tmp_isupinfo->dpc == mtp3_dpc)){
852                                          forward = TRUE;
853                                  }
854                                  else if ((tmp_isupinfo->dpc == mtp3_opc)&&(tmp_isupinfo->opc == mtp3_dpc)){
855                                          forward = FALSE;
856                                  }
857                                  else{
858                                          right_pair = FALSE;
859                                  }
860                                  if (right_pair){
861                                         /* if there is an IAM for a call that is not in setup state, that means the previous call in the same
862                                            cic is no longer active */
863                                         if (tmp_listinfo->call_state == VOIP_CALL_SETUP){
864                                                 found = TRUE;
865                                         }
866                                         else if (pi->message_type != 1){
867                                                 found = TRUE;
868                                         }
869                                         else{
870                                                 tmp_listinfo->call_active_state=VOIP_INACTIVE;
871                                         }
872                                 }
873                                 if (found){
874                                         strinfo = (voip_calls_info_t*)(list->data);
875                                         break;
876                                 }
877                         }
878                 }
879                 list = g_list_next (list);
880         }
881
882         /* not in the list? then create a new entry if the message is IAM
883            -i.e. if this session is a call*/
884
885
886         if ((strinfo==NULL) &&(pi->message_type==1)){
887
888                 strinfo = g_malloc(sizeof(voip_calls_info_t));
889                 strinfo->call_active_state = VOIP_ACTIVE;
890                 strinfo->call_state = VOIP_UNKNOWN;
891                 COPY_ADDRESS(&(strinfo->initial_speaker),&(pinfo->src));
892                 strinfo->selected=FALSE;
893                 strinfo->first_frame_num=pinfo->fd->num;
894                 strinfo->start_sec=pinfo->fd->rel_secs;
895                 strinfo->start_usec=pinfo->fd->rel_usecs;
896                 strinfo->protocol=VOIP_ISUP;
897                 if (pi->calling_number!=NULL){
898                         strinfo->from_identity=g_strdup(pi->calling_number);
899                 }
900                 if (pi->called_number!=NULL){
901                         strinfo->to_identity=g_strdup(pi->called_number);
902                 }
903                 strinfo->prot_info=g_malloc(sizeof(isup_calls_info_t));
904                 tmp_isupinfo=strinfo->prot_info;
905                 tmp_isupinfo->opc = mtp3_opc;
906                 tmp_isupinfo->dpc = mtp3_dpc;
907                 tmp_isupinfo->ni = mtp3_ni;
908                 tmp_isupinfo->cic = pinfo->circuit_id;
909                 strinfo->npackets = 0;
910                 strinfo->call_num = tapinfo->ncalls++;
911                 tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
912         }
913
914         if (strinfo!=NULL){
915                 strinfo->stop_sec=pinfo->fd->rel_secs;
916                 strinfo->stop_usec=pinfo->fd->rel_usecs;
917                 strinfo->last_frame_num=pinfo->fd->num;
918                 ++(strinfo->npackets);
919
920                 /* Let's analyze the call state */
921
922
923                 for (i=0;(isup_message_type_value[i].strptr!=NULL)&& (isup_message_type_value[i].value!=pi->message_type);i++);
924
925                 if (isup_message_type_value[i].value==pi->message_type){
926                         frame_label = g_strdup(isup_message_type_value_acro[i].strptr);
927                 }
928                 else{
929                         frame_label = g_strdup_printf("Unknown");
930                 }
931
932                 if (strinfo->npackets == 1){ /* this is the first packet, that must be an IAM */
933                         if ((pi->calling_number!=NULL)&&(pi->called_number !=NULL)){
934                                 comment = g_strdup_printf("Call from %s to %s",
935                                  pi->calling_number, pi->called_number);
936                          }
937                 }
938                 else if (strinfo->npackets == 2){ /* in the second packet we show the SPs */
939                         if (forward){
940                                 comment = g_strdup_printf("%i-%i -> %i-%i. Cic:%i",
941                                  mtp3_ni, mtp3_opc,
942                                  mtp3_ni, mtp3_dpc, pinfo->circuit_id);
943
944                         }
945                         else{
946                                 comment = g_strdup_printf("%i-%i -> %i-%i. Cic:%i",
947                                  mtp3_ni, mtp3_dpc,
948                                  mtp3_ni, mtp3_opc, pinfo->circuit_id);
949
950                         }
951                 }
952
953                 switch(pi->message_type){
954                         case 1: /* IAM */
955                                 strinfo->call_state=VOIP_CALL_SETUP;
956                                 break;
957                         case 7: /* CONNECT */
958                         case 9: /* ANSWER */
959                                 strinfo->call_state=VOIP_IN_CALL;
960                                 break;
961                         case 12: /* RELEASE */
962                                 if (strinfo->call_state==VOIP_CALL_SETUP){
963                                         if (forward){
964                                                 strinfo->call_state=VOIP_CANCELLED;
965                                         }
966                                         else{
967                                                 strinfo->call_state=VOIP_REJECTED;
968                                                 tapinfo->rejected_calls++;
969                                         }
970                                 }
971                                 else if (strinfo->call_state == VOIP_IN_CALL){
972                                         strinfo->call_state = VOIP_COMPLETED;
973                                         tapinfo->completed_calls++;
974                                 }
975                                 for (i=0;(q931_cause_code_vals[i].strptr!=NULL)&& (q931_cause_code_vals[i].value!=pi->cause_value);i++);
976                                 if (q931_cause_code_vals[i].value==pi->cause_value){
977                                         comment = g_strdup_printf("Cause %i - %s",pi->cause_value, q931_cause_code_vals[i].strptr);
978                                 }
979                                 else{
980                                         comment = g_strdup_printf("Cause %i",pi->cause_value);
981                                 }
982                                 break;
983                 }
984
985                 /* increment the packets counter of all calls */
986                 ++(tapinfo->npackets);
987
988                 /* add to the graph */
989                 add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num, &(pinfo->src), &(pinfo->dst));  
990                 g_free(comment);
991                 g_free(frame_label);
992         }
993
994         tapinfo->redraw = TRUE;
995
996         return 1;  /* refresh output */
997 }
998
999 /****************************************************************************/
1000
1001 static gboolean have_isup_tap_listener=FALSE;
1002
1003 void
1004 isup_calls_init_tap(void)
1005 {
1006         GString *error_string;
1007
1008
1009         if(have_isup_tap_listener==FALSE)
1010         {
1011                 error_string = register_tap_listener("isup", &(the_tapinfo_struct.isup_dummy),
1012                         NULL,
1013                         voip_calls_dlg_reset, 
1014                         isup_calls_packet, 
1015                         voip_calls_dlg_draw
1016                         );
1017         
1018                 if (error_string != NULL) {
1019                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1020                                       error_string->str);
1021                         g_string_free(error_string, TRUE);
1022                         exit(1);
1023                 }
1024                 have_isup_tap_listener=TRUE;
1025         }
1026 }
1027
1028 /****************************************************************************/
1029
1030 void
1031 remove_tap_listener_isup_calls(void)
1032 {
1033         protect_thread_critical_region();
1034         remove_tap_listener(&(the_tapinfo_struct.isup_dummy));
1035         unprotect_thread_critical_region();
1036
1037         have_isup_tap_listener=FALSE;
1038 }
1039
1040
1041 /****************************************************************************/
1042 /* ***************************TAP for MTP3 **********************************/
1043 /****************************************************************************/
1044
1045
1046 /****************************************************************************/
1047 /* whenever a mtp3_ packet is seen by the tap listener */
1048 static int 
1049 mtp3_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *mtp3_info _U_)
1050 {
1051         const mtp3_tap_rec_t *pi = mtp3_info;
1052
1053         /* keep the data in memory to use when the ISUP information arrives */
1054
1055         mtp3_opc = pi->addr_opc.pc;
1056         mtp3_dpc = pi->addr_dpc.pc;
1057         mtp3_ni = pi->addr_opc.ni;
1058         mtp3_frame_num = pinfo->fd->num;
1059
1060         return 0;
1061 }
1062
1063 /****************************************************************************/
1064
1065 static gboolean have_mtp3_tap_listener=FALSE;
1066
1067 void
1068 mtp3_calls_init_tap(void)
1069 {
1070         GString *error_string;
1071
1072
1073         if(have_mtp3_tap_listener==FALSE)
1074         {
1075                 error_string = register_tap_listener("mtp3", &(the_tapinfo_struct.mtp3_dummy),
1076                         NULL,
1077                         voip_calls_dlg_reset, 
1078                         mtp3_calls_packet, 
1079                         voip_calls_dlg_draw
1080                         );
1081
1082                 if (error_string != NULL) {
1083                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1084                                       error_string->str);
1085                         g_string_free(error_string, TRUE);
1086                         exit(1);
1087                 }
1088                 have_mtp3_tap_listener=TRUE;
1089         }
1090 }
1091
1092 /****************************************************************************/
1093
1094 void
1095 remove_tap_listener_mtp3_calls(void)
1096 {
1097         protect_thread_critical_region();
1098         remove_tap_listener(&(the_tapinfo_struct.mtp3_dummy));
1099         unprotect_thread_critical_region();
1100
1101         have_mtp3_tap_listener=FALSE;
1102 }
1103
1104 /****************************************************************************/
1105 /* ***************************TAP for Q931 **********************************/
1106 /****************************************************************************/
1107 void h245_add_to_graph(guint32 new_frame_num);
1108 #define GUID_LEN        16
1109 static const guint8 guid_allzero[GUID_LEN] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
1110 /* defines specific H323 data */
1111
1112 static gchar *q931_calling_number;
1113 static gchar *q931_called_number;
1114 static guint8 q931_cause_value;
1115 static gint32 q931_crv;
1116 static guint32 q931_frame_num;
1117
1118 static guint32 h225_frame_num = 0;
1119 static guint16 h225_call_num = 0;
1120 static h225_cs_type h225_cstype = H225_OTHER;
1121 static gboolean h225_is_faststart;
1122
1123 static guint32 actrace_frame_num = 0;
1124 static gint32 actrace_trunk = 0;
1125 static gint32 actrace_direction = 0;
1126
1127
1128 /****************************************************************************/
1129 /* whenever a q931_ packet is seen by the tap listener */
1130 static int 
1131 q931_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *q931_info _U_)
1132 {
1133         GList *list,*list2;
1134         voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct; 
1135         h323_calls_info_t *tmp_h323info,*tmp2_h323info;
1136         actrace_isdn_calls_info_t *tmp_actrace_isdn_info;
1137         voip_calls_info_t *tmp_listinfo;
1138         voip_calls_info_t *strinfo = NULL;
1139         h245_address_t *h245_add = NULL;
1140         gchar *comment;
1141
1142         const q931_packet_info *pi = q931_info;
1143
1144         /* free previously allocated q931_calling/ed_number */
1145         g_free(q931_calling_number);
1146         g_free(q931_called_number);
1147         
1148         if (pi->calling_number!=NULL)
1149                 q931_calling_number = g_strdup(pi->calling_number);
1150         else
1151                 q931_calling_number = g_strdup("");
1152
1153         if (pi->called_number!=NULL)
1154                 q931_called_number = g_strdup(pi->called_number);
1155         else
1156                 q931_called_number = g_strdup("");
1157         q931_cause_value = pi->cause_value;
1158         q931_frame_num = pinfo->fd->num;
1159         q931_crv = pi->crv;
1160
1161
1162         /* add staff to H323 calls */
1163         if (h225_frame_num == q931_frame_num) {
1164                 tmp_h323info = NULL;
1165                 list = g_list_first(tapinfo->strinfo_list);
1166                 while (list)
1167                 {
1168                         tmp_listinfo=list->data;
1169                         if ( (tmp_listinfo->protocol == VOIP_H323) && (tmp_listinfo->call_num == h225_call_num) ){
1170                                 tmp_h323info = tmp_listinfo->prot_info;
1171                                 strinfo = (voip_calls_info_t*)(list->data);
1172
1173                                 /* Add the CRV to the h323 call */
1174                                 if (tmp_h323info->q931_crv == -1) {
1175                                         tmp_h323info->q931_crv = q931_crv;
1176                                 } else if (tmp_h323info->q931_crv != q931_crv) {
1177                                         tmp_h323info->q931_crv2 = q931_crv;
1178                                 }
1179                                 break;
1180                         }
1181                         list = g_list_next (list);
1182                 }
1183
1184                 if (strinfo != NULL) {
1185                         comment = NULL;
1186                         if (h225_cstype == H225_SETUP) {
1187                                 /* set te calling and called number from the Q931 packet */
1188                                 if (q931_calling_number != NULL){
1189                                         g_free(strinfo->from_identity);
1190                                         strinfo->from_identity=g_strdup(q931_calling_number);
1191                                 }
1192                                 if (q931_called_number != NULL){
1193                                         g_free(strinfo->to_identity);
1194                                         strinfo->to_identity=g_strdup(q931_called_number);
1195                                 }
1196
1197                                 /* check if there is an LRQ/LCF that match this Setup */
1198                                 /* TODO: we are just checking the DialedNumer in LRQ/LCF agains the Setup 
1199                                         we should also check if the h225 signaling IP and port match the destination 
1200                                         Setup ip and port */
1201                                 list = g_list_first(tapinfo->strinfo_list);
1202                                 while (list)
1203                                 {
1204                                         tmp_listinfo=list->data;
1205                                         if (tmp_listinfo->protocol == VOIP_H323){
1206                                                 tmp2_h323info = tmp_listinfo->prot_info;
1207                                                 
1208                                                 /* check if the called number match a LRQ/LCF */
1209                                                 if ( (strcmp(strinfo->to_identity, tmp_listinfo->to_identity)==0)  
1210                                                          && (memcmp(tmp2_h323info->guid, guid_allzero, GUID_LEN) == 0) ){ 
1211                                                         /* change the call graph to the LRQ/LCF to belong to this call */
1212                                                         strinfo->npackets += change_call_num_graph(tapinfo, tmp_listinfo->call_num, strinfo->call_num);
1213                                                         
1214                                                         /* remove this LRQ/LCF call entry because we have found the Setup that match them */
1215                                                         g_free(tmp_listinfo->from_identity);
1216                                                         g_free(tmp_listinfo->to_identity);
1217                                                         g_free(tmp2_h323info->guid);
1218                                                         
1219                                                         list2 = g_list_first(tmp2_h323info->h245_list);
1220                                                         while (list2)
1221                                                         {
1222                                                                 h245_add=list2->data;
1223                                                                 g_free((void *)h245_add->h245_address.data);
1224                                                                 g_free(list2->data);
1225                                                                 list2 = g_list_next(list2);
1226                                                         }
1227                                                         g_list_free(tmp_h323info->h245_list);
1228                                                         tmp_h323info->h245_list = NULL;
1229                                                         g_free(tmp_listinfo->prot_info);
1230                                                         tapinfo->strinfo_list = g_list_remove(tapinfo->strinfo_list, tmp_listinfo);
1231                                                         break;
1232                                                 }
1233                                         }
1234                                 list = g_list_next (list);
1235                                 }
1236
1237                                 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"), 
1238                                                           (h225_is_faststart==TRUE?"on":"off"));
1239                         } else if (h225_cstype == H225_RELEASE_COMPLET) {
1240                                 /* get the Q931 Release cause code */
1241                                 if (q931_cause_value != 0xFF){          
1242                                         comment = g_strdup_printf("H225 Q931 Rel Cause (%i):%s", q931_cause_value, val_to_str(q931_cause_value, q931_cause_code_vals, "<unknown>"));
1243                                 } else { /* Cause not set */
1244                                         comment = g_strdup("H225 No Q931 Rel Cause");
1245                                 }
1246                         }
1247                         /* change the graph comment for this new one */
1248                         if (comment != NULL) {
1249                                 change_frame_graph(tapinfo, h225_frame_num, NULL, comment);
1250                                 g_free(comment);
1251                         }
1252                 }
1253                 /* we reset the h225_frame_num to 0 because there could be empty h225 in the same frame
1254                    as non empty h225 (e.g connect), so we don't have to be here twice */
1255                 h225_frame_num = 0;
1256
1257         /* add staff to H245 */
1258         } else if (h245_labels.frame_num == q931_frame_num) {
1259         /* there are empty H225 frames that don't have guid (guaid=0) but they have h245 info, 
1260            so the only way to match those frames is with the Q931 CRV number */ 
1261                 list = g_list_first(tapinfo->strinfo_list);
1262                 while (list)
1263                 {
1264                         tmp_listinfo=list->data;
1265                         if (tmp_listinfo->protocol == VOIP_H323){
1266                                 tmp_h323info = tmp_listinfo->prot_info;
1267                                 if ( ((tmp_h323info->q931_crv == q931_crv) || (tmp_h323info->q931_crv2 == q931_crv)) && (q931_crv!=-1)){
1268
1269                                         comment = g_strdup("");
1270
1271                                         /* if the frame number exists in graph, append to it*/
1272                                         if (!append_to_frame_graph(tapinfo, q931_frame_num, "", comment)) {
1273                                                 /* if not exist, add to the graph */
1274                                                 add_to_graph(tapinfo, pinfo, "", comment, tmp_listinfo->call_num, &(pinfo->src), &(pinfo->dst));
1275                                                 ++(tmp_listinfo->npackets);
1276                                                 /* increment the packets counter of all calls */
1277                                                 ++(tapinfo->npackets);
1278                                         }
1279                                         
1280                                         /* Add the H245 info if exists to the Graph */
1281                                         h245_add_to_graph(pinfo->fd->num);
1282                                         g_free(comment);
1283                                         break;
1284                                 }
1285                         }
1286                         list = g_list_next (list);
1287                 }
1288
1289         /* add staff to ACTRACE */
1290         } else if (actrace_frame_num == q931_frame_num) {
1291                 address pstn_add;
1292                 gchar *comment = NULL;
1293
1294                 strinfo = NULL;
1295                 list = g_list_first(tapinfo->strinfo_list);
1296                 while (list)
1297                 {
1298                         tmp_listinfo=list->data;
1299                         if ( tmp_listinfo->protocol == VOIP_AC_ISDN ){
1300                                 tmp_actrace_isdn_info = tmp_listinfo->prot_info;
1301                                 /* TODO: Also check the IP of the Blade, and if the call is complete (no active) */
1302                                 if ( (tmp_actrace_isdn_info->crv == q931_crv) && (tmp_actrace_isdn_info->trunk == actrace_trunk) ) {
1303                                         strinfo = (voip_calls_info_t*)(list->data);
1304                                         break;
1305                                 }
1306                         }
1307                         list = g_list_next (list);
1308                 }
1309
1310                 SET_ADDRESS(&pstn_add, AT_STRINGZ, 5, g_strdup("PSTN"));
1311
1312                 /* if it is a new call, add it to the list */
1313                 if (!strinfo) {
1314                         strinfo = g_malloc(sizeof(voip_calls_info_t));
1315                         strinfo->call_active_state = VOIP_ACTIVE;
1316                         strinfo->call_state = VOIP_CALL_SETUP;
1317                         strinfo->from_identity=g_strdup(q931_calling_number);
1318                         strinfo->to_identity=g_strdup(q931_called_number);
1319                         COPY_ADDRESS(&(strinfo->initial_speaker),actrace_direction?&pstn_add:&(pinfo->src));
1320                         strinfo->first_frame_num=pinfo->fd->num;
1321                         strinfo->selected=FALSE;
1322                         strinfo->start_sec=pinfo->fd->rel_secs;
1323                         strinfo->start_usec=pinfo->fd->rel_usecs;
1324                         strinfo->protocol=VOIP_AC_ISDN;
1325                         strinfo->prot_info=g_malloc(sizeof(actrace_isdn_calls_info_t));
1326                         tmp_actrace_isdn_info=strinfo->prot_info;
1327                         tmp_actrace_isdn_info->crv=q931_crv;
1328                         tmp_actrace_isdn_info->trunk=actrace_trunk;
1329                         strinfo->npackets = 0;
1330                         strinfo->call_num = tapinfo->ncalls++;
1331                         tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
1332                 }
1333
1334                 strinfo->stop_sec=pinfo->fd->rel_secs;
1335                 strinfo->stop_usec=pinfo->fd->rel_usecs;
1336                 strinfo->last_frame_num=pinfo->fd->num;
1337                 ++(strinfo->npackets);
1338                 /* increment the packets counter of all calls */
1339                 ++(tapinfo->npackets);
1340
1341                 switch(pi->message_type){
1342                 case Q931_SETUP:
1343                         comment = g_strdup_printf("AC_ISDN trunk:%u Calling: %s  Called:%s", actrace_trunk, q931_calling_number, q931_called_number);
1344                         strinfo->call_state=VOIP_CALL_SETUP;
1345                         break;
1346                 case Q931_CONNECT:
1347                         strinfo->call_state=VOIP_IN_CALL;
1348                         break;
1349                 case Q931_RELEASE_COMPLETE:
1350                 case Q931_RELEASE:
1351                 case Q931_DISCONNECT:
1352                         if (strinfo->call_state==VOIP_CALL_SETUP){
1353                                 if (ADDRESSES_EQUAL(&(strinfo->initial_speaker), actrace_direction?&pstn_add:&(pinfo->src) )){  /* forward direction */
1354                                         strinfo->call_state=VOIP_CANCELLED;
1355                                 }
1356                                 else{                                                                                           /* reverse */
1357                                         strinfo->call_state=VOIP_REJECTED;
1358                                         tapinfo->rejected_calls++;
1359                                 }
1360                         } else if ( (strinfo->call_state!=VOIP_CANCELLED) && (strinfo->call_state!=VOIP_REJECTED) ){
1361                                         strinfo->call_state=VOIP_COMPLETED;
1362                                         tapinfo->completed_calls++;
1363                         }
1364                         if (q931_cause_value != 0xFF){          
1365                                 comment = g_strdup_printf("AC_ISDN trunk:%u Q931 Rel Cause (%i):%s", actrace_trunk, q931_cause_value, val_to_str(q931_cause_value, q931_cause_code_vals, "<unknown>"));
1366                         } else { /* Cause not set */
1367                                 comment = g_strdup("AC_ISDN No Q931 Rel Cause");
1368                         }
1369                         break;
1370                 }
1371
1372                 if (!comment)
1373                         comment = g_strdup_printf("AC_ISDN  trunk:%u", actrace_trunk );
1374
1375                 add_to_graph(tapinfo, pinfo, val_to_str(pi->message_type, q931_message_type_vals, "<unknown>") , comment, strinfo->call_num, 
1376                                 actrace_direction?&pstn_add:&(pinfo->src),
1377                                 actrace_direction?&(pinfo->src):&pstn_add);
1378
1379                 g_free(comment);
1380                 g_free((char *)pstn_add.data);
1381         }
1382
1383         tapinfo->redraw = TRUE;
1384
1385         return 1;  /* refresh output */
1386 }
1387
1388 /****************************************************************************/
1389 static gboolean have_q931_tap_listener=FALSE;
1390
1391 void
1392 q931_calls_init_tap(void)
1393 {
1394         GString *error_string;
1395
1396
1397         if(have_q931_tap_listener==FALSE)
1398         {
1399                 error_string = register_tap_listener("q931", &(the_tapinfo_struct.q931_dummy),
1400                         NULL,
1401                         voip_calls_dlg_reset,
1402                         q931_calls_packet,
1403                         voip_calls_dlg_draw
1404                         );
1405                         
1406                 if (error_string != NULL) {
1407                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1408                                       error_string->str);
1409                         g_string_free(error_string, TRUE);
1410                         exit(1);
1411                 }
1412                 have_q931_tap_listener=TRUE;
1413         }
1414 }
1415
1416 /****************************************************************************/
1417
1418 void
1419 remove_tap_listener_q931_calls(void)
1420 {
1421         protect_thread_critical_region();
1422         remove_tap_listener(&(the_tapinfo_struct.q931_dummy));
1423         unprotect_thread_critical_region();
1424
1425         have_q931_tap_listener=FALSE;
1426 }
1427
1428 /****************************************************************************/
1429 /****************************TAP for H323 ***********************************/
1430 /****************************************************************************/
1431
1432 static void add_h245_Address(h323_calls_info_t *h323info,  h245_address_t *h245_address)
1433 {
1434         h323info->h245_list = g_list_append(h323info->h245_list, h245_address);                         
1435 }
1436
1437 /****************************************************************************/
1438 /* whenever a H225 packet is seen by the tap listener */
1439 static int 
1440 H225calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *H225info)
1441 {
1442         voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1443         voip_calls_info_t *tmp_listinfo;
1444         voip_calls_info_t *strinfo = NULL;
1445         h323_calls_info_t *tmp_h323info = NULL;
1446         gchar *frame_label;
1447         gchar *comment;
1448         GList *list;
1449         address tmp_src, tmp_dst;
1450         h245_address_t *h245_add = NULL;
1451         
1452         const h225_packet_info *pi = H225info;
1453         
1454         /* if not guid and RAS and not LRQ, LCF or LRJ return because did not belong to a call */
1455         /* OR, if not guid and is H225 return because doesn't belong to a call */
1456         if ((memcmp(pi->guid, guid_allzero, GUID_LEN) == 0))
1457                 if ( ((pi->msg_type == H225_RAS) && ((pi->msg_tag < 18) || (pi->msg_tag > 20))) || (pi->msg_type != H225_RAS) )
1458                         return 0;
1459         
1460         /* if it is RAS LCF or LRJ*/
1461         if ( (pi->msg_type == H225_RAS) && ((pi->msg_tag == 19) || (pi->msg_tag == 20))) { 
1462                 /* if the LCF/LRJ doesn't match to a LRQ, just return */
1463                 if (!pi->request_available) return 0;
1464                 
1465                 /* check wether we already have a call with this request SeqNum */
1466                 list = g_list_first(tapinfo->strinfo_list);
1467                 while (list)
1468                 {
1469                         tmp_listinfo=list->data;
1470                         if (tmp_listinfo->protocol == VOIP_H323){
1471                                 tmp_h323info = tmp_listinfo->prot_info;
1472                                 if (tmp_h323info->requestSeqNum == pi->requestSeqNum) {
1473                                         strinfo = (voip_calls_info_t*)(list->data);
1474                                         break;
1475                                 }
1476                         }
1477                         list = g_list_next (list);
1478                 }
1479         } else {
1480                 /* check wether we already have a call with this guid in the list */
1481                 list = g_list_first(tapinfo->strinfo_list);
1482                 while (list)
1483                 {
1484                         tmp_listinfo=list->data;
1485                         if (tmp_listinfo->protocol == VOIP_H323){
1486                                 tmp_h323info = tmp_listinfo->prot_info;
1487                                 if ( (memcmp(tmp_h323info->guid, guid_allzero, GUID_LEN) != 0) && (memcmp(tmp_h323info->guid, pi->guid,GUID_LEN)==0) ){ 
1488                                         strinfo = (voip_calls_info_t*)(list->data);
1489                                         break;
1490                                 }
1491                         }
1492                         list = g_list_next (list);
1493                 }
1494         }
1495         
1496         h225_cstype = pi->cs_type;
1497         h225_is_faststart = pi->is_faststart;
1498
1499         /* not in the list? then create a new entry */
1500         if ((strinfo==NULL)){
1501                 strinfo = g_malloc(sizeof(voip_calls_info_t));
1502                 strinfo->call_active_state = VOIP_ACTIVE;
1503                 strinfo->call_state = VOIP_UNKNOWN;
1504                 strinfo->from_identity=g_strdup("");
1505                 strinfo->to_identity=g_strdup("");
1506                 COPY_ADDRESS(&(strinfo->initial_speaker),&(pinfo->src));
1507                 strinfo->selected=FALSE;
1508                 strinfo->first_frame_num=pinfo->fd->num;
1509                 strinfo->start_sec=pinfo->fd->rel_secs;
1510                 strinfo->start_usec=pinfo->fd->rel_usecs;
1511                 strinfo->protocol=VOIP_H323;
1512                 strinfo->prot_info=g_malloc(sizeof(h323_calls_info_t));
1513                 tmp_h323info = strinfo->prot_info;
1514                 tmp_h323info->guid = (guint8 *) g_memdup(pi->guid,GUID_LEN);
1515                 tmp_h323info->h225SetupAddr.type = AT_NONE;
1516                 tmp_h323info->h225SetupAddr.len = 0;
1517                 tmp_h323info->h245_list = NULL;
1518                 tmp_h323info->is_faststart_Setup = FALSE;
1519                 tmp_h323info->is_faststart_Proc = FALSE;
1520                 tmp_h323info->is_h245Tunneling = FALSE;
1521                 tmp_h323info->is_h245 = FALSE;
1522                 tmp_h323info->q931_crv = -1;
1523                 tmp_h323info->q931_crv2 = -1;
1524                 tmp_h323info->requestSeqNum = 0;
1525                 strinfo->call_num = tapinfo->ncalls++;
1526                 strinfo->npackets = 0;
1527                 
1528                 tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);                          
1529         }
1530
1531         if (strinfo!=NULL){
1532
1533                 h225_frame_num = pinfo->fd->num;
1534                 h225_call_num = strinfo->call_num;
1535
1536                 /* let's analyze the call state */
1537
1538                 COPY_ADDRESS(&(tmp_src),&(pinfo->src));
1539                 COPY_ADDRESS(&(tmp_dst),&(pinfo->dst));
1540
1541                 strinfo->stop_sec=pinfo->fd->rel_secs;
1542                 strinfo->stop_usec=pinfo->fd->rel_usecs;
1543                 strinfo->last_frame_num=pinfo->fd->num;
1544                 ++(strinfo->npackets);
1545                 /* increment the packets counter of all calls */
1546                 ++(tapinfo->npackets);
1547
1548
1549                 /* XXX: it is supposed to be initialized isn't it? */
1550                 g_assert(tmp_h323info != NULL);
1551
1552                 /* change the status */
1553                 if (pi->msg_type == H225_CS){
1554
1555                         /* this is still IPv4 only, because the dissector is */
1556                         if (pi->is_h245 == TRUE){
1557                                 h245_add = g_malloc(sizeof (h245_address_t));
1558                                 h245_add->h245_address.type=AT_IPv4;
1559                                 h245_add->h245_address.len=4;
1560                                 h245_add->h245_address.data = g_malloc(sizeof(pi->h245_address));
1561                                 g_memmove((void *)(h245_add->h245_address.data), &(pi->h245_address), 4);
1562                                 h245_add->h245_port = pi->h245_port;
1563                                 add_h245_Address(tmp_h323info, h245_add);
1564                         }
1565
1566                         if (pi->cs_type != H225_RELEASE_COMPLET) tmp_h323info->is_h245Tunneling = pi->is_h245Tunneling;
1567
1568                         frame_label = g_strdup(pi->frame_label);
1569
1570                         switch(pi->cs_type){
1571                         case H225_SETUP:
1572                                 tmp_h323info->is_faststart_Setup = pi->is_faststart;
1573
1574                                 /* Set the Setup address if it was not set */
1575                                 if (tmp_h323info->h225SetupAddr.type == AT_NONE) 
1576                                   COPY_ADDRESS(&(tmp_h323info->h225SetupAddr), &(pinfo->src));
1577                                         strinfo->call_state=VOIP_CALL_SETUP;
1578                                 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"), 
1579                                                                                   (pi->is_faststart==TRUE?"on":"off"));
1580                                 break;
1581                         case H225_CONNECT:
1582                                 strinfo->call_state=VOIP_IN_CALL;
1583                                 if (pi->is_faststart == TRUE) tmp_h323info->is_faststart_Proc = TRUE;
1584                                         comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"), 
1585                                                                                           (pi->is_faststart==TRUE?"on":"off"));
1586                                 break;
1587                         case H225_RELEASE_COMPLET:
1588                             COPY_ADDRESS(&tmp_src,&(pinfo->src));
1589                                 if (strinfo->call_state==VOIP_CALL_SETUP){
1590                                         if (ADDRESSES_EQUAL(&(tmp_h323info->h225SetupAddr),&tmp_src)){  /* forward direction */
1591                                                 strinfo->call_state=VOIP_CANCELLED;
1592                                         }
1593                                         else{                                                                                           /* reverse */
1594                                                 strinfo->call_state=VOIP_REJECTED;
1595                                                 tapinfo->rejected_calls++;
1596                                         }
1597                                 } else {
1598                                                 strinfo->call_state=VOIP_COMPLETED;
1599                                                 tapinfo->completed_calls++;
1600                                 }
1601                                 comment = g_strdup("H225 No Q931 Rel Cause");
1602                                 break;
1603                         case H225_PROGRESS:
1604                         case H225_ALERTING:
1605                         case H225_CALL_PROCEDING:
1606                                 if (pi->is_faststart == TRUE) tmp_h323info->is_faststart_Proc = TRUE;
1607                                 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"), 
1608                                                                                   (pi->is_faststart==TRUE?"on":"off"));
1609                                 break;
1610                         default:
1611                                 comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"), 
1612                                                                                   (pi->is_faststart==TRUE?"on":"off"));
1613                                 
1614                         } 
1615                 } 
1616                 else if (pi->msg_type == H225_RAS){
1617                 switch(pi->msg_tag){
1618                         case 18:  /* LRQ */
1619                                 if (!pi->is_duplicate){
1620                                         g_free(strinfo->to_identity);
1621                                         strinfo->to_identity=g_strdup(pi->dialedDigits);
1622                                         tmp_h323info->requestSeqNum = pi->requestSeqNum;
1623                                 }
1624                         case 19: /* LCF */
1625                                 if (strlen(pi->dialedDigits)) 
1626                                         comment = g_strdup_printf("H225 RAS dialedDigits: %s", pi->dialedDigits);
1627                                 else
1628                                         comment = g_strdup("H225 RAS");
1629                                 break;
1630                         default:
1631                                 comment = g_strdup("H225 RAS");
1632                 }
1633                 frame_label = g_strdup_printf("%s", val_to_str(pi->msg_tag, RasMessage_vals, "<unknown>"));
1634         } else {
1635                 frame_label = g_strdup("H225: Unknown");
1636                 comment = g_strdup("");
1637         }
1638
1639         /* add to graph analysis */
1640
1641         /* if the frame number exists in graph, append to it*/
1642         if (!append_to_frame_graph(tapinfo, pinfo->fd->num, pi->frame_label, comment)) {
1643                 /* if not exist, add to the graph */
1644                 add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num, &(pinfo->src), &(pinfo->dst));
1645                 g_free((void *)tmp_src.data);
1646                 g_free((void *)tmp_dst.data);
1647         }
1648
1649         /* Add the H245 info if exists to the Graph */
1650         h245_add_to_graph(pinfo->fd->num);
1651
1652         g_free(frame_label);
1653         g_free(comment);
1654         
1655         } 
1656         
1657         tapinfo->redraw = TRUE;
1658
1659         return 1;  /* refresh output */
1660 }
1661
1662
1663 /****************************************************************************/
1664 /* TAP INTERFACE */
1665 /****************************************************************************/
1666 static gboolean have_H225_tap_listener=FALSE;
1667 /****************************************************************************/
1668 void
1669 h225_calls_init_tap(void)
1670 {
1671         GString *error_string;
1672
1673         if(have_H225_tap_listener==FALSE)
1674         {
1675                 /* don't register tap listener, if we have it already */
1676                 error_string = register_tap_listener("h225", &(the_tapinfo_struct.h225_dummy), NULL,
1677                         voip_calls_dlg_reset, 
1678                         H225calls_packet, 
1679                         voip_calls_dlg_draw
1680                         );
1681                         
1682                 if (error_string != NULL) {
1683                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1684                                       error_string->str);
1685                         g_string_free(error_string, TRUE);
1686                         exit(1);
1687                 }
1688                 have_H225_tap_listener=TRUE;
1689         }
1690 }
1691
1692
1693
1694 /* XXX just copied from gtk/rpc_stat.c */
1695 void protect_thread_critical_region(void);
1696 void unprotect_thread_critical_region(void);
1697
1698 /****************************************************************************/
1699 void
1700 remove_tap_listener_h225_calls(void)
1701 {
1702         protect_thread_critical_region();
1703         remove_tap_listener(&(the_tapinfo_struct.h225_dummy));
1704         unprotect_thread_critical_region();
1705
1706         have_H225_tap_listener=FALSE;
1707 }
1708
1709 /* Add the h245 label info to the graph */ 
1710 void h245_add_to_graph(guint32 new_frame_num)
1711 {
1712         gint8 n;
1713         
1714         if (new_frame_num != h245_labels.frame_num) return;
1715
1716         for (n=0; n<h245_labels.labels_count; n++) {
1717                 append_to_frame_graph(&the_tapinfo_struct, new_frame_num, h245_labels.labels[n].frame_label, h245_labels.labels[n].comment);
1718                 g_free(h245_labels.labels[n].frame_label);
1719                 h245_labels.labels[n].frame_label = NULL;
1720                 g_free(h245_labels.labels[n].comment);
1721                 h245_labels.labels[n].comment = NULL;
1722         }
1723         h245_labels.frame_num = 0;
1724         h245_labels.labels_count = 0;
1725 }
1726
1727 /* free the h245_labels if the frame number is different */ 
1728 static void h245_free_labels(guint32 new_frame_num)
1729 {
1730         gint8 n;
1731         
1732         if (new_frame_num == h245_labels.frame_num) return;
1733
1734         for (n=0; n<h245_labels.labels_count; n++) {
1735                 g_free(h245_labels.labels[n].frame_label);
1736                 h245_labels.labels[n].frame_label = NULL;
1737                 g_free(h245_labels.labels[n].comment);
1738                 h245_labels.labels[n].comment = NULL;
1739         }
1740         h245_labels.frame_num = 0;
1741         h245_labels.labels_count = 0;
1742 }
1743
1744 /* add the frame_label and comment to h245_labels and free the actual one if it is different frame num */ 
1745 static void h245_add_label(guint32 new_frame_num, gchar *frame_label, gchar *comment)
1746 {
1747         h245_free_labels(new_frame_num);
1748
1749         h245_labels.frame_num = new_frame_num;
1750         h245_labels.labels[h245_labels.labels_count].frame_label = g_strdup(frame_label);
1751         h245_labels.labels[h245_labels.labels_count].comment = g_strdup(comment);
1752
1753         if (h245_labels.labels_count < (H245_MAX-1))
1754                 h245_labels.labels_count++;
1755
1756 }
1757
1758 /****************************************************************************/
1759 /* whenever a H245dg packet is seen by the tap listener (when H245 tunneling is ON) */
1760 static int 
1761 H245dgcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *H245info)
1762 {
1763         voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1764         voip_calls_info_t *tmp_listinfo;
1765         voip_calls_info_t *strinfo = NULL;
1766         h323_calls_info_t *tmp_h323info;
1767         gchar *frame_label;
1768         gchar *comment;
1769         GList* list;
1770         GList* list2;
1771         address tmp_src, tmp_dst;
1772         h245_address_t *h245_add = NULL;
1773
1774         const h245_packet_info *pi = H245info;
1775
1776         /* check if Tunneling is OFF and we have a call with this H245 add */
1777         list = g_list_first(tapinfo->strinfo_list);
1778         while (list)
1779         {
1780                 tmp_listinfo=list->data;
1781                 if (tmp_listinfo->protocol == VOIP_H323){
1782                         tmp_h323info = tmp_listinfo->prot_info;
1783
1784                         COPY_ADDRESS(&(tmp_src), &(pinfo->src));
1785                         COPY_ADDRESS(&(tmp_dst), &(pinfo->dst));
1786                         list2 = g_list_first(tmp_h323info->h245_list);
1787                         while (list2)
1788                         {
1789                                 h245_add=list2->data;
1790                                 if ( (ADDRESSES_EQUAL(&(h245_add->h245_address),&tmp_src) && (h245_add->h245_port == pinfo->srcport))
1791                                         || (ADDRESSES_EQUAL(&(h245_add->h245_address),&tmp_dst) && (h245_add->h245_port == pinfo->destport)) ){
1792                                         strinfo = (voip_calls_info_t*)(list->data);
1793
1794                                         ++(strinfo->npackets);
1795                                         /* increment the packets counter of all calls */
1796                                         ++(tapinfo->npackets);
1797
1798                                         break;
1799                                 }                       
1800                         list2 = g_list_next(list2);
1801                         }
1802                         if (strinfo!=NULL) break;
1803                         g_free((void *)tmp_src.data);
1804                         g_free((void *)tmp_dst.data);
1805                 }
1806                 list = g_list_next(list);
1807         }
1808
1809         /* Tunnel is OFF, and we matched the h245 add so we add it to graph */
1810         if (strinfo!=NULL){
1811                 ++(strinfo->npackets);
1812                 /* increment the packets counter of all calls */
1813                 ++(tapinfo->npackets);
1814                 frame_label = g_strdup(pi->frame_label);
1815                 comment = g_strdup(pi->comment);
1816                 /* if the frame number exists in graph, append to it*/
1817                 if (!append_to_frame_graph(tapinfo, pinfo->fd->num, frame_label, comment)) {
1818                         /* if not exist, add to the graph */
1819                         add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num, &(pinfo->src), &(pinfo->dst));
1820                 }
1821                 g_free(frame_label);
1822                 g_free(comment);
1823         } else { 
1824         /* Tunnel is ON, so we save the label info to use it into h225 or q931 tap. OR may be 
1825                  tunnel OFF but we did not matched the h245 add, in this case nobady will set this label 
1826                  since the frame_num will not match */ 
1827         
1828                 h245_add_label(pinfo->fd->num, (gchar *) pi->frame_label, (gchar *) pi->comment);
1829         }
1830
1831         tapinfo->redraw = TRUE;
1832
1833         return 1;  /* refresh output */
1834 }
1835
1836
1837 /****************************************************************************/
1838 /* TAP INTERFACE */
1839 /****************************************************************************/
1840 static gboolean have_H245dg_tap_listener=FALSE;
1841 /****************************************************************************/
1842 void
1843 h245dg_calls_init_tap(void)
1844 {
1845         GString *error_string;
1846
1847         if(have_H245dg_tap_listener==FALSE)
1848         {
1849                 /* don't register tap listener, if we have it already */
1850                 error_string = register_tap_listener("h245dg", &(the_tapinfo_struct.h245dg_dummy), NULL,
1851                         voip_calls_dlg_reset,
1852                         H245dgcalls_packet, 
1853                         voip_calls_dlg_draw
1854                         );
1855                 
1856                 if (error_string != NULL) {
1857                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1858                                       error_string->str);
1859                         g_string_free(error_string, TRUE);
1860                         exit(1);
1861                 }
1862                 have_H245dg_tap_listener=TRUE;
1863         }
1864 }
1865
1866
1867 /* XXX just copied from gtk/rpc_stat.c */
1868 void protect_thread_critical_region(void);
1869 void unprotect_thread_critical_region(void);
1870
1871 /****************************************************************************/
1872 void
1873 remove_tap_listener_h245dg_calls(void)
1874 {
1875         protect_thread_critical_region();
1876         remove_tap_listener(&(the_tapinfo_struct.h245dg_dummy));
1877         unprotect_thread_critical_region();
1878
1879         have_H245dg_tap_listener=FALSE;
1880 }
1881
1882 /****************************************************************************/
1883 /****************************TAP for SDP PROTOCOL ***************************/
1884 /****************************************************************************/
1885 /* whenever a SDP packet is seen by the tap listener */
1886 static int 
1887 SDPcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *SDPinfo)
1888 {
1889         voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
1890         const sdp_packet_info *pi = SDPinfo;
1891
1892         /* There are protocols like MGCP/SIP where the SDP is called before the tap for the
1893            MGCP/SIP packet, in those cases we assign the SPD summary to global lastSDPsummary
1894            to use it later 
1895         */
1896         g_free(sdp_summary);
1897         sdp_frame_num = pinfo->fd->num;
1898         /* Append to graph the SDP summary if the packet exists */
1899         sdp_summary = g_strdup_printf("SDP (%s)", pi->summary_str);
1900         append_to_frame_graph(tapinfo, pinfo->fd->num, sdp_summary, NULL);
1901
1902         tapinfo->redraw = TRUE;
1903
1904         return 1;  /* refresh output */
1905 }
1906
1907
1908 /****************************************************************************/
1909 /* TAP INTERFACE */
1910 /****************************************************************************/
1911 static gboolean have_sdp_tap_listener=FALSE;
1912 /****************************************************************************/
1913 void
1914 sdp_calls_init_tap(void)
1915 {
1916         GString *error_string;
1917
1918         if(have_sdp_tap_listener==FALSE)
1919         {
1920                 /* don't register tap listener, if we have it already */
1921                 error_string = register_tap_listener("sdp", &(the_tapinfo_struct.sdp_dummy), NULL,
1922                         voip_calls_dlg_reset, 
1923                         SDPcalls_packet, 
1924                         voip_calls_dlg_draw
1925                         );
1926                         
1927                 if (error_string != NULL) {
1928                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1929                                       error_string->str);
1930                         g_string_free(error_string, TRUE);
1931                         exit(1);
1932                 }
1933                 have_sdp_tap_listener=TRUE;
1934         }
1935 }
1936
1937
1938 /* XXX just copied from gtk/rpc_stat.c */
1939 void protect_thread_critical_region(void);
1940 void unprotect_thread_critical_region(void);
1941
1942 /****************************************************************************/
1943 void
1944 remove_tap_listener_sdp_calls(void)
1945 {
1946         protect_thread_critical_region();
1947         remove_tap_listener(&(the_tapinfo_struct.sdp_dummy));
1948         unprotect_thread_critical_region();
1949
1950         have_sdp_tap_listener=FALSE;
1951 }
1952
1953
1954
1955 /****************************************************************************/
1956 /* ***************************TAP for MGCP **********************************/
1957 /****************************************************************************/
1958
1959 /*
1960    This function will look for a signal/event in the SignalReq/ObsEvent string
1961    and return true if it is found 
1962 */
1963 static gboolean isSignal(const gchar *signal, const gchar *signalStr)
1964 {
1965         gint i; 
1966         gchar **resultArray;
1967         
1968         /* if there is no signalStr, just return false */
1969         if (signalStr == NULL) return FALSE;
1970
1971         /* if are both "blank" return true */
1972         if ( (*signal == '\0') &&  (*signalStr == '\0') ) return TRUE;
1973
1974         /* look for signal in signalSre */
1975         resultArray = g_strsplit(signalStr, ",", 10);
1976
1977         for (i = 0; resultArray[i]; i++) {
1978                 g_strstrip(resultArray[i]);
1979                 if (strcmp(resultArray[i], signal) == 0) return TRUE;
1980         }
1981
1982         g_strfreev(resultArray);
1983         
1984         return FALSE;
1985 }
1986
1987 /*
1988    This function will get the Caller ID info and replace the current string
1989    This is how it looks the caller Id: rg, ci(02/16/08/29, "3035550002","Ale Sipura 2")
1990 */
1991 static void mgcpCallerID(gchar *signalStr, gchar **callerId)
1992 {
1993         gchar **arrayStr;
1994         
1995         /* if there is no signalStr, just return false */
1996         if (signalStr == NULL) return;
1997
1998         arrayStr = g_strsplit(signalStr, "\"", 10);
1999
2000         if (arrayStr[0] == NULL) return;
2001
2002         /* look for the ci signal */
2003         if (strstr(arrayStr[0], "ci(") && (arrayStr[1] != NULL) ) {
2004                 /* free the previous "From" field of the call, and assign the new */
2005                 g_free(*callerId);
2006                 *callerId = g_strdup(arrayStr[1]);
2007         }
2008         g_strfreev(arrayStr);
2009
2010         return;
2011 }
2012
2013
2014 /*
2015    This function will get the Dialed Digits and replace the current string
2016    This is how it looks the dialed digits 5,5,5,0,0,0,2,#,*
2017 */
2018 static void mgcpDialedDigits(gchar *signalStr, gchar **dialedDigits)
2019 {
2020         gchar *tmpStr;
2021         gchar resultStr[50];
2022         gint i,j; 
2023
2024         /* if there is no signalStr, just return false */
2025         if (signalStr == NULL) return;
2026
2027         tmpStr = g_strdup(signalStr);
2028         
2029         for ( i = 0 ; tmpStr[i] ; i++) {
2030                 switch (tmpStr[i]) {
2031                         case '0' : case '1' : case '2' : case '3' : case '4' :
2032                         case '5' : case '6' : case '7' : case '8' : case '9' :
2033                         case '#' : case '*' :
2034                                 break;
2035                         default:
2036                                 tmpStr[i] = '?';
2037                                 break;
2038                 }
2039         }
2040         
2041         for (i = 0, j = 0; tmpStr[i] && i<50; i++) {
2042                 if (tmpStr[i] != '?')
2043                         resultStr[j++] = tmpStr[i];
2044         }
2045         resultStr[j] = '\0';
2046
2047         if (*resultStr == '\0') return;
2048         
2049         g_free(*dialedDigits);
2050         *dialedDigits = g_strdup(resultStr);
2051         g_free(tmpStr);
2052
2053         return;
2054 }
2055
2056
2057
2058 /****************************************************************************/
2059 /* whenever a MGCP packet is seen by the tap listener */
2060 static int 
2061 MGCPcalls_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *MGCPinfo)
2062 {
2063         voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2064
2065         voip_calls_info_t *tmp_listinfo;
2066         voip_calls_info_t *strinfo = NULL;
2067         mgcp_calls_info_t *tmp_mgcpinfo = NULL;
2068         GList* list;
2069         GList* listGraph;
2070         gchar *frame_label = NULL;
2071         gchar *comment = NULL;
2072         graph_analysis_item_t *gai;
2073         gboolean new = FALSE;
2074         gboolean fromEndpoint = FALSE; /* true for calls originated in Endpoints, false for calls from MGC */
2075         gdouble diff_time;
2076
2077         const mgcp_info_t *pi = MGCPinfo;
2078
2079
2080         if ((pi->mgcp_type == MGCP_REQUEST) && !pi->is_duplicate ){
2081                 /* check wether we already have a call with this Endpoint and it is active*/
2082                 list = g_list_first(tapinfo->strinfo_list);
2083                 while (list)
2084                 {
2085                         tmp_listinfo=list->data;
2086                         if ((tmp_listinfo->protocol == VOIP_MGCP) && (tmp_listinfo->call_active_state == VOIP_ACTIVE)){
2087                                 tmp_mgcpinfo = tmp_listinfo->prot_info;
2088                                 if (pi->endpointId != NULL){
2089                                         if (g_strcasecmp(tmp_mgcpinfo->endpointId,pi->endpointId) == 0){
2090                                                 /*
2091                                                    check first if it is an ended call. We consider an ended call after 1sec we don't 
2092                                                    get a packet in this Endpoint and the call has been released
2093                                                 */
2094                                                 diff_time = (pinfo->fd->rel_secs + (double)pinfo->fd->rel_secs/1000000) - (tmp_listinfo->stop_sec + (double)tmp_listinfo->stop_usec/1000000);
2095                                                 if ( ((tmp_listinfo->call_state == VOIP_CANCELLED) || (tmp_listinfo->call_state == VOIP_COMPLETED)  || (tmp_listinfo->call_state == VOIP_REJECTED)) && (diff_time > 1) ){
2096                                                         tmp_listinfo->call_active_state = VOIP_INACTIVE;
2097                                                 } else {
2098                                                         strinfo = (voip_calls_info_t*)(list->data);
2099                                                         break;
2100                                                 }
2101                                         }
2102                                 }
2103                         }
2104                         list = g_list_next (list);
2105                 }
2106                 
2107                 /* there is no call with this Endpoint, lets see if this a new call or not */
2108                 if (strinfo == NULL){
2109                         if ( (strcmp(pi->code, "NTFY") == 0) && isSignal("hd", pi->observedEvents) ){ /* off hook transition */
2110                                 /* this is a new call from the Endpoint */      
2111                                 fromEndpoint = TRUE;
2112                                 new = TRUE;
2113                         } else if (strcmp(pi->code, "CRCX") == 0){
2114                                 /* this is a new call from the MGC */
2115                                 fromEndpoint = FALSE;
2116                                 new = TRUE;
2117                         }
2118                         if (!new) return 0;
2119                 } 
2120         } else if ( ((pi->mgcp_type == MGCP_RESPONSE) && pi->request_available) ||
2121                         ((pi->mgcp_type == MGCP_REQUEST) && pi->is_duplicate) ) {
2122                 /* if it is a response OR if it is a duplicated Request, lets look in the Graph if thre is a request that match */
2123                 listGraph = g_list_first(tapinfo->graph_analysis->list);
2124                 while (listGraph)
2125                 {
2126                         gai = listGraph->data;
2127                         if (gai->frame_num == pi->req_num){
2128                                 /* there is a request that match, so look the associated call with this call_num */
2129                                 list = g_list_first(tapinfo->strinfo_list);
2130                                 while (list)
2131                                 {
2132                                         tmp_listinfo=list->data;
2133                                         if (tmp_listinfo->protocol == VOIP_MGCP){
2134                                                 if (tmp_listinfo->call_num == gai->conv_num){
2135                                                         tmp_mgcpinfo = tmp_listinfo->prot_info;
2136                                                         strinfo = (voip_calls_info_t*)(list->data);
2137                                                         break;
2138                                                 }
2139                                         }
2140                                         list = g_list_next (list);
2141                                 }
2142                                 if (strinfo != NULL) break;
2143                         }
2144                         listGraph = g_list_next(listGraph);
2145                 }
2146                 /* if there is not a matching request, just return */
2147                 if (strinfo == NULL) return 0;
2148         } else return 0;
2149
2150         /* not in the list? then create a new entry */
2151         if (strinfo==NULL){
2152                 strinfo = g_malloc(sizeof(voip_calls_info_t));
2153                 strinfo->call_active_state = VOIP_ACTIVE;
2154                 strinfo->call_state = VOIP_CALL_SETUP;
2155                 if (fromEndpoint) {
2156                         strinfo->from_identity=g_strdup(pi->endpointId);
2157                         strinfo->to_identity=g_strdup("");
2158                 } else {
2159                         strinfo->from_identity=g_strdup("");
2160                         strinfo->to_identity=g_strdup(pi->endpointId);
2161                 }
2162                 COPY_ADDRESS(&(strinfo->initial_speaker),&(pinfo->src));
2163                 strinfo->first_frame_num=pinfo->fd->num;
2164                 strinfo->selected=FALSE;
2165                 strinfo->start_sec=pinfo->fd->rel_secs;
2166                 strinfo->start_usec=pinfo->fd->rel_usecs;
2167                 strinfo->protocol=VOIP_MGCP;
2168                 strinfo->prot_info=g_malloc(sizeof(mgcp_calls_info_t));
2169                 tmp_mgcpinfo=strinfo->prot_info;
2170                 tmp_mgcpinfo->endpointId = g_strdup(pi->endpointId);
2171                 tmp_mgcpinfo->fromEndpoint = fromEndpoint;
2172                 strinfo->npackets = 0;
2173                 strinfo->call_num = tapinfo->ncalls++;
2174                 tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
2175         }
2176
2177         g_assert(tmp_mgcpinfo != NULL);
2178
2179         /* change call state and add to graph */
2180         switch (pi->mgcp_type)
2181         {
2182         case MGCP_REQUEST:
2183                 if ( (strcmp(pi->code, "NTFY") == 0) && (pi->observedEvents != NULL) ){
2184                         frame_label = g_strdup_printf("%s ObsEvt:%s",pi->code, pi->observedEvents);
2185
2186                         if (tmp_mgcpinfo->fromEndpoint){
2187                                 /* use the Dialed digits to fill the "To" for the call */
2188                                 mgcpDialedDigits(pi->observedEvents, &(strinfo->to_identity));
2189
2190                         /* from MGC and the user picked up, the call is connected */
2191                         } else if (isSignal("hd", pi->observedEvents))  
2192                                 strinfo->call_state=VOIP_IN_CALL;
2193
2194                         /* hung up signal */
2195                         if (isSignal("hu", pi->observedEvents)) {
2196                                 if ((strinfo->call_state == VOIP_CALL_SETUP) || (strinfo->call_state == VOIP_RINGING)){
2197                                         strinfo->call_state = VOIP_CANCELLED;
2198                                 } else {
2199                                         strinfo->call_state = VOIP_COMPLETED;
2200                                 }
2201                         }       
2202                         
2203                 } else if (strcmp(pi->code, "RQNT") == 0) {
2204                         /* for calls from Endpoint: if there is a "no signal" RQNT and the call was RINGING, we assume this is the CONNECT */
2205                         if ( tmp_mgcpinfo->fromEndpoint && isSignal("", pi->signalReq) && (strinfo->call_state == VOIP_RINGING) ) { 
2206                                         strinfo->call_state = VOIP_IN_CALL;
2207                         }
2208
2209                         /* if there is ringback or ring tone, change state to ringing */
2210                         if ( isSignal("rg", pi->signalReq) || isSignal("rt", pi->signalReq) ) { 
2211                                         strinfo->call_state = VOIP_RINGING;
2212                         }
2213
2214                         /* if there is a Busy or ReorderTone, and the call was Ringing or Setup the call is Rejected */
2215                         if ( (isSignal("ro", pi->signalReq) || isSignal("bz", pi->signalReq)) && ((strinfo->call_state == VOIP_CALL_SETUP) || (strinfo->call_state = VOIP_RINGING)) ) { 
2216                                         strinfo->call_state = VOIP_REJECTED;
2217                         }
2218
2219                         if (pi->signalReq != NULL)
2220                                 frame_label = g_strdup_printf("%s%sSigReq:%s",pi->code, (pi->hasDigitMap == TRUE)?" DigitMap ":"", pi->signalReq);
2221                         else
2222                                 frame_label = g_strdup_printf("%s%s",pi->code, (pi->hasDigitMap == TRUE)?" DigitMap ":"");
2223                         
2224                         /* use the CallerID info to fill the "From" for the call */
2225                         if (!tmp_mgcpinfo->fromEndpoint) mgcpCallerID(pi->signalReq, &(strinfo->from_identity));
2226
2227                 } else if (strcmp(pi->code, "DLCX") == 0) {
2228                         /*
2229                           if there is a DLCX in a call To an Endpoint and the call was not connected, we use
2230                           the DLCX as the end of the call
2231                         */
2232                         if (!tmp_mgcpinfo->fromEndpoint){
2233                                 if ((strinfo->call_state == VOIP_CALL_SETUP) || (strinfo->call_state == VOIP_RINGING)){
2234                                         strinfo->call_state = VOIP_CANCELLED;
2235                                 } 
2236                         } 
2237                 }
2238
2239                 if (frame_label == NULL) frame_label = g_strdup_printf("%s",pi->code);
2240                 break;
2241         case MGCP_RESPONSE:
2242                 frame_label = g_strdup_printf("%d (%s)",pi->rspcode, pi->code);
2243                 break;
2244         case MGCP_OTHERS:
2245                 /* XXX what to do? */
2246                 break;
2247         }
2248
2249
2250         comment = g_strdup_printf("MGCP %s %s%s", tmp_mgcpinfo->endpointId, (pi->mgcp_type == MGCP_REQUEST)?"Request":"Response", pi->is_duplicate?" Duplicate":"");
2251
2252         strinfo->stop_sec=pinfo->fd->rel_secs;
2253         strinfo->stop_usec=pinfo->fd->rel_usecs;
2254         strinfo->last_frame_num=pinfo->fd->num;
2255         ++(strinfo->npackets);
2256         /* increment the packets counter of all calls */
2257         ++(tapinfo->npackets);
2258
2259         /* add to the graph */
2260         add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num, &(pinfo->src), &(pinfo->dst));  
2261         g_free(comment);
2262         g_free(frame_label);
2263
2264         /* add SDP info if apply */
2265         if ( (sdp_summary != NULL) && (sdp_frame_num == pinfo->fd->num) ){
2266                         append_to_frame_graph(tapinfo, pinfo->fd->num, sdp_summary, NULL);
2267                         g_free(sdp_summary);
2268                         sdp_summary = NULL;
2269         }
2270
2271         tapinfo->redraw = TRUE;
2272
2273         return 1;  /* refresh output */
2274 }
2275
2276
2277 /****************************************************************************/
2278 /* TAP INTERFACE */
2279 /****************************************************************************/
2280 static gboolean have_MGCP_tap_listener=FALSE;
2281 /****************************************************************************/
2282 void
2283 mgcp_calls_init_tap(void)
2284 {
2285         GString *error_string;
2286
2287         if(have_MGCP_tap_listener==FALSE)
2288         {
2289                 /* don't register tap listener, if we have it already */
2290                 /* we send an empty filter, to force a non null "tree" in the mgcp dissector */
2291                 error_string = register_tap_listener("mgcp", &(the_tapinfo_struct.mgcp_dummy), strdup(""),
2292                         voip_calls_dlg_reset, 
2293                         MGCPcalls_packet, 
2294                         voip_calls_dlg_draw
2295                         );
2296                 if (error_string != NULL) {
2297                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2298                                       error_string->str);
2299                         g_string_free(error_string, TRUE);
2300                         exit(1);
2301                 }
2302                 have_MGCP_tap_listener=TRUE;
2303         }
2304 }
2305
2306
2307
2308 /* XXX just copied from gtk/rpc_stat.c */
2309 void protect_thread_critical_region(void);
2310 void unprotect_thread_critical_region(void);
2311
2312 /****************************************************************************/
2313 void
2314 remove_tap_listener_mgcp_calls(void)
2315 {
2316         protect_thread_critical_region();
2317         remove_tap_listener(&(the_tapinfo_struct.mgcp_dummy));
2318         unprotect_thread_critical_region();
2319
2320         have_MGCP_tap_listener=FALSE;
2321 }
2322
2323
2324 /****************************************************************************/
2325 /****************************TAP for ACTRACE (AudioCodes trace)**************/
2326 /****************************************************************************/
2327
2328 /* whenever a ACTRACE packet is seen by the tap listener */
2329 static int 
2330 ACTRACEcalls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *ACTRACEinfo)
2331 {
2332         voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2333         const actrace_info_t *pi = ACTRACEinfo;
2334         GList *list;
2335         actrace_cas_calls_info_t *tmp_actrace_cas_info;
2336         voip_calls_info_t *tmp_listinfo;
2337         voip_calls_info_t *strinfo = NULL;
2338
2339
2340         actrace_frame_num = pinfo->fd->num;
2341         actrace_trunk = pi->trunk;
2342         actrace_direction = pi->direction;
2343
2344         if (pi->type == 1){ /* is CAS protocol */
2345                 address pstn_add;
2346                 gchar *comment = NULL;
2347
2348                 strinfo = NULL;
2349                 list = g_list_first(tapinfo->strinfo_list);
2350                 while (list)
2351                 {
2352                         tmp_listinfo=list->data;
2353                         if ( tmp_listinfo->protocol == VOIP_AC_CAS ){
2354                                 tmp_actrace_cas_info = tmp_listinfo->prot_info;
2355                                 /* TODO: Also check the IP of the Blade, and if the call is complete (no active) */
2356                                 if ( (tmp_actrace_cas_info->bchannel == pi->cas_bchannel) && (tmp_actrace_cas_info->trunk == actrace_trunk) ) {
2357                                         strinfo = (voip_calls_info_t*)(list->data);
2358                                         break;
2359                                 }
2360                         }
2361                         list = g_list_next (list);
2362                 }
2363
2364                 SET_ADDRESS(&pstn_add, AT_STRINGZ, 5, g_strdup("PSTN"));
2365
2366                 /* if it is a new call, add it to the list */
2367                 if (!strinfo) {
2368                         strinfo = g_malloc(sizeof(voip_calls_info_t));
2369                         strinfo->call_active_state = VOIP_ACTIVE;
2370                         strinfo->call_state = VOIP_CALL_SETUP;
2371                         strinfo->from_identity=g_strdup("N/A");
2372                         strinfo->to_identity=g_strdup("N/A");
2373                         COPY_ADDRESS(&(strinfo->initial_speaker),actrace_direction?&pstn_add:&(pinfo->src));
2374                         strinfo->first_frame_num=pinfo->fd->num;
2375                         strinfo->selected=FALSE;
2376                         strinfo->start_sec=pinfo->fd->rel_secs;
2377                         strinfo->start_usec=pinfo->fd->rel_usecs;
2378                         strinfo->protocol=VOIP_AC_CAS;
2379                         strinfo->prot_info=g_malloc(sizeof(actrace_cas_calls_info_t));
2380                         tmp_actrace_cas_info=strinfo->prot_info;
2381                         tmp_actrace_cas_info->bchannel=pi->cas_bchannel;
2382                         tmp_actrace_cas_info->trunk=actrace_trunk;
2383                         strinfo->npackets = 0;
2384                         strinfo->call_num = tapinfo->ncalls++;
2385                         tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
2386                 }
2387
2388                 strinfo->stop_sec=pinfo->fd->rel_secs;
2389                 strinfo->stop_usec=pinfo->fd->rel_usecs;
2390                 strinfo->last_frame_num=pinfo->fd->num;
2391                 ++(strinfo->npackets);
2392                 /* increment the packets counter of all calls */
2393                 ++(tapinfo->npackets);
2394
2395                 if (!comment)
2396                         comment = g_strdup_printf("AC_CAS  trunk:%u", actrace_trunk );
2397
2398                 add_to_graph(tapinfo, pinfo, pi->cas_frame_label , comment, strinfo->call_num, 
2399                                 actrace_direction?&pstn_add:&(pinfo->src),
2400                                 actrace_direction?&(pinfo->src):&pstn_add);
2401
2402                 g_free(comment);
2403                 g_free((char *)pstn_add.data);
2404         }
2405
2406         tapinfo->redraw = TRUE;
2407
2408         return 1;  /* refresh output */
2409 }
2410
2411
2412 /****************************************************************************/
2413 /* TAP INTERFACE */
2414 /****************************************************************************/
2415 static gboolean have_actrace_tap_listener=FALSE;
2416 /****************************************************************************/
2417 void
2418 actrace_calls_init_tap(void)
2419 {
2420         GString *error_string;
2421
2422         if(have_actrace_tap_listener==FALSE)
2423         {
2424                 /* don't register tap listener, if we have it already */
2425                 error_string = register_tap_listener("actrace", &(the_tapinfo_struct.actrace_dummy), NULL,
2426                         voip_calls_dlg_reset, 
2427                         ACTRACEcalls_packet, 
2428                         voip_calls_dlg_draw
2429                         );
2430                         
2431                 if (error_string != NULL) {
2432                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2433                                       error_string->str);
2434                         g_string_free(error_string, TRUE);
2435                         exit(1);
2436                 }
2437                 have_actrace_tap_listener=TRUE;
2438         }
2439 }
2440
2441
2442 /* XXX just copied from gtk/rpc_stat.c */
2443 void protect_thread_critical_region(void);
2444 void unprotect_thread_critical_region(void);
2445
2446 /****************************************************************************/
2447 void
2448 remove_tap_listener_actrace_calls(void)
2449 {
2450         protect_thread_critical_region();
2451         remove_tap_listener(&(the_tapinfo_struct.actrace_dummy));
2452         unprotect_thread_critical_region();
2453
2454         have_actrace_tap_listener=FALSE;
2455 }
2456
2457 /****************************************************************************/
2458 /* ***************************TAP for OTHER PROTOCOL **********************************/
2459 /****************************************************************************/
2460
2461 /****************************************************************************/
2462 /* whenever a prot_ packet is seen by the tap listener */
2463 /*
2464 static int 
2465 prot_calls_packet(void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prot_info _U_)
2466 {
2467         voip_calls_tapinfo_t *tapinfo = &the_tapinfo_struct;
2468         if (strinfo!=NULL){
2469                 strinfo->stop_sec=pinfo->fd->rel_secs;
2470                 strinfo->stop_usec=pinfo->fd->rel_usecs;
2471                 strinfo->last_frame_num=pinfo->fd->num;
2472                 ++(strinfo->npackets);
2473                 ++(tapinfo->npackets);
2474         }
2475
2476         tapinfo->redraw = TRUE;
2477
2478         return 1;
2479 }
2480 */
2481 /****************************************************************************/
2482 /*
2483 static gboolean have_prot__tap_listener=FALSE;
2484
2485 void
2486 prot_calls_init_tap(void)
2487 {
2488         GString *error_string;
2489
2490         if(have_prot__tap_listener==FALSE)
2491         {
2492                 error_string = register_tap_listener("prot_", &(the_tapinfo_struct.prot__dummy),
2493                         NULL,
2494                         voip_calls_dlg_reset,
2495                         prot__calls_packet, 
2496                         voip_calls_dlg_draw
2497                         );
2498
2499                 if (error_string != NULL) {
2500                         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2501                                       error_string->str);
2502                         g_string_free(error_string, TRUE);
2503                         exit(1);
2504                 }
2505                 have_prot__tap_listener=TRUE;
2506         }
2507 }
2508 */
2509 /****************************************************************************/
2510 /*
2511 void
2512 remove_tap_listener_prot__calls(void)
2513 {
2514         protect_thread_critical_region();
2515         remove_tap_listener(&(the_tapinfo_struct.prot__dummy));
2516         unprotect_thread_critical_region();
2517
2518         have_prot__tap_listener=FALSE;
2519 }
2520 */