Ethereal-dev: [Ethereal-dev] Voip Calls analysis and Graph analysis

Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.

From: Alejandro Vaquero <alejandrovaquero@xxxxxxxxx>
Date: Sat, 29 Jan 2005 20:06:54 -0700
Hi All,
Attached is the new "Voip call analysis" patch file and a screen shot of a SIP to H323 interop call. It is based on Francisco Alcoba source, and added support of H323, RTP and a Graph analysis. The Graph interface can also be used in other no Voip analysis.
    Here are the features:
- Collect ISUP, SIP and H323 calls from a capture and show them in window with the following info:
      - Start and Stop time of the call
- Initial Speaker: the IP source address of the first message that started the call - From and To: In H323 and ISUP, it is the calling and called number. In SIP the From and To fields.
      - Protocol: H323, SIP and ISUP (from now)
      - State: the sate of the call
- Comments: For H323, it shows if the call is a FastSatrt call and if Tunneling H245 is enable or not.
- Prepare a filter of a particular call when selected.
- Select one or multiple calls to "graph analysis"
   And the "Graph Analysis" has:
- Graph up to ten columns or "nodes". Each "node" it is defined as an IP address.
- Shows the direction of the message using arrows
- Display a "frame" label on top of the arrow, and a "comment" at the right of each packet.
- For  SIP and H323 the  "frame" label also shows the Codec used.
- The "comment" column will show different info based on the packet. For Setup and INVITE messages, it shows the calling/called number and From/To fields. For Release H323 messages, the Q931 release cause. For H225 messages, if tunneling is enable or not, and if FastStart is present in the packet. - RTP streams involved in the call. It is displayed as a wider arrow. The "frame" label also shows the Codec for the stream and the "comment" shows the number of RTP packets in this stream, the duration, and ssrc. - When "click" on a frame in the graph, the selected frame number will be selected in the Main windows.
- The graph also shows the time, and the UPD/TCP ports per frame.

I have tested it in a Windows machine using GTK 1 and 2. There is not support for ISUP calls in the Graph yet (don't have such captures).

   Comments and changes are very welcome.

Regards
Alejandro







Index: rtp_pt.h
===================================================================
--- rtp_pt.h	(revision 13162)
+++ rtp_pt.h	(working copy)
@@ -63,5 +63,6 @@
 #define PT_H263		34	/* from Chunrong Zhu of Intel; see the Web page */
 
 ETH_VAR_IMPORT const value_string rtp_payload_type_vals[];
+ETH_VAR_IMPORT const value_string rtp_payload_type_short_vals[];
 
 #endif
Index: asn1/h225/packet-h225-template.c
===================================================================
--- asn1/h225/packet-h225-template.c	(revision 13162)
+++ asn1/h225/packet-h225-template.c	(working copy)
@@ -67,7 +67,9 @@
 static void ras_call_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, h225_packet_info *pi);
 static int dissect_h225_H323UserInformation(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
 
-static h225_packet_info h225_pi; 
+static h225_packet_info pi_arr[5]; /* We assuming a maximum of 5 H225 messaages per packet */
+static int pi_current=0;
+h225_packet_info *h225_pi=NULL;
 
 static dissector_handle_t h225ras_handle;
 static dissector_handle_t H323UserInformation_handle;
@@ -132,9 +134,15 @@
 	proto_tree *tr;
 	int offset = 0;
 
+    pi_current++;
+    if(pi_current==5){
+      pi_current=0;
+    }
+    h225_pi=&pi_arr[pi_current];
+
 	/* Init struct for collecting h225_packet_info */
-	reset_h225_packet_info(&(h225_pi));
-	h225_pi.msg_type = H225_CS;
+    reset_h225_packet_info(h225_pi);
+    h225_pi->msg_type = H225_CS;
 
 	if (check_col(pinfo->cinfo, COL_PROTOCOL)){
 		col_set_str(pinfo->cinfo, COL_PROTOCOL, "H.225.0");
@@ -148,7 +156,7 @@
 
 	offset = dissect_h225_H323_UserInformation(tvb, offset,pinfo, tr, hf_h225_H323_UserInformation);
 
-	tap_queue_packet(h225_tap, pinfo, &h225_pi);
+	tap_queue_packet(h225_tap, pinfo, h225_pi);
 
 	return offset;
 }
@@ -158,9 +166,15 @@
 	proto_tree *tr;
 	guint32 offset=0;
 
+    pi_current++;
+    if(pi_current==5){
+        pi_current=0;
+    }
+    h225_pi=&pi_arr[pi_current];
+
 	/* Init struct for collecting h225_packet_info */
-	reset_h225_packet_info(&(h225_pi));
-	h225_pi.msg_type = H225_RAS;
+    reset_h225_packet_info(h225_pi);
+    h225_pi->msg_type = H225_RAS;
 
 	if (check_col(pinfo->cinfo, COL_PROTOCOL)){
 		col_set_str(pinfo->cinfo, COL_PROTOCOL, "H.225.0");
@@ -171,12 +185,13 @@
 
 	offset = dissect_h225_RasMessage(tvb, 0, pinfo,tr, hf_h225_RasMessage );
 
-	ras_call_matching(tvb, pinfo, tr, &(h225_pi));
+	ras_call_matching(tvb, pinfo, tr, h225_pi);
 
-	tap_queue_packet(h225_tap, pinfo, &h225_pi);
+	tap_queue_packet(h225_tap, pinfo, h225_pi);
 
 	return offset;
 }
+
 /*--- proto_register_h225 -------------------------------------------*/
 void proto_register_h225(void) {
 
@@ -279,8 +294,10 @@
 	pi->request_available = FALSE;
 	pi->is_faststart = FALSE;
 	pi->is_h245 = FALSE;
+	pi->is_h245Tunneling = FALSE;
 	pi->h245_address = 0;
 	pi->h245_port = 0;
+	pi->frame_label[0] = '\0';
 }
 
 /*
Index: asn1/h225/packet-h225-template.h
===================================================================
--- asn1/h225/packet-h225-template.h	(revision 13162)
+++ asn1/h225/packet-h225-template.h	(working copy)
@@ -33,12 +33,20 @@
 } h225_msg_type;
 
 typedef enum _h225_cs_type {
-	H225_SETUP,
-	H225_CALL_PROCEDING,
-	H225_ALERTING,
-	H225_CONNECT,
-	H225_RELEASE_COMPLET,
-	H225_OTHER
+    H225_SETUP,
+    H225_CALL_PROCEDING,
+    H225_CONNECT,
+    H225_ALERTING,
+    H225_INFORMATION,
+    H225_RELEASE_COMPLET,
+    H225_FACILITY,
+    H225_PROGRESS,
+    H225_EMPTY,
+    H225_STATUS,
+    H225_STATUS_INQUIRY,
+    H225_SETUP_ACK,
+    H225_NOTIFY,
+    H225_OTHER
 } h225_cs_type;
 
 typedef struct _h225_packet_info {
@@ -54,8 +62,10 @@
 	/* added for h225 conversations analysis */
 	gboolean is_faststart;		/* true, if faststart field is included */
 	gboolean is_h245;
+	gboolean is_h245Tunneling;
 	guint32 h245_address;
 	guint16 h245_port;
+	gchar frame_label[50]; /* the Fram label used by graph_analysis, what is a abreviation of cinfo */
 } h225_packet_info;
 
 /*
Index: asn1/h225/h225.cnf
===================================================================
--- asn1/h225/h225.cnf	(revision 13162)
+++ asn1/h225/h225.cnf	(working copy)
@@ -147,9 +147,9 @@
 			val_to_str(message_body_val, T_h323_message_body_vals, "<unknown>"));
         }
 
-	if (h225_pi.msg_type == H225_CS) {
+	if (h225_pi->msg_type == H225_CS) {
 		/* Don't override msg_tag value from IRR */
-		h225_pi.msg_tag = message_body_val;
+		h225_pi->msg_tag = message_body_val;
 	}
 
 	if (contains_faststart == TRUE )
@@ -167,14 +167,19 @@
 #.FN_BODY FastStart/_item
 	guint32 newoffset;
 	guint32 length;
+	char codec_str[50];
 
 	offset=dissect_per_length_determinant(tvb, offset, pinfo, tree, hf_h225_fastStart_item_length, &length);
 	newoffset=offset + (length<<3);	/* please note that offset is in bits in
 					   PER dissectors, but the item length
 					   is in octets */
-	offset=dissect_h245_OpenLogicalChannel(tvb,offset, pinfo, tree, hf_index);
+	offset=dissect_h245_OpenLogicalChannelCodec(tvb,offset, pinfo, tree, hf_index, codec_str);
+
+    /* Add to packet info */
+    g_snprintf(h225_pi->frame_label, 50, "%s %s", h225_pi->frame_label, codec_str);
+
 	contains_faststart = TRUE;
-	h225_pi.is_faststart = TRUE;
+	h225_pi->is_faststart = TRUE;
 
 	return newoffset;
 
@@ -192,7 +197,7 @@
 			val_to_str(rasmessage_value, RasMessage_vals, "<unknown>"));
 	}
 
-	h225_pi.msg_tag = rasmessage_value;
+	h225_pi->msg_tag = rasmessage_value;
 #.END
 #----------------------------------------------------------------------------------------
 # TODO asn2eth can't handle restriced string ?
@@ -241,28 +246,82 @@
 
 #.END
 #----------------------------------------------------------------------------------------
+#.FN_FTR NULL
+  if (h225_pi->cs_type == H225_OTHER) h225_pi->cs_type = H225_EMPTY;
+#.END
+#----------------------------------------------------------------------------------------
+#.FN_FTR Status-UUIE
+  /* Add to packet info */
+  h225_pi->cs_type = H225_STATUS;
+  g_snprintf(h225_pi->frame_label, 50, "%s", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>"));
+#.END
+#.FN_FTR Information-UUIE
+  /* Add to packet info */
+  h225_pi->cs_type = H225_INFORMATION;
+  g_snprintf(h225_pi->frame_label, 50, "%s", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>"));
+#.END
+#.FN_FTR Progress-UUIE
+  /* Add to packet info */
+  h225_pi->cs_type = H225_PROGRESS;
+  if (contains_faststart == TRUE )
+        g_snprintf(h225_pi->frame_label, 50, "%s OLC (%s)", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>"), h225_pi->frame_label);
+  else 
+        g_snprintf(h225_pi->frame_label, 50, "%s", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>"));
+#.END
+#.FN_FTR Facility-UUIE
+  /* Add to packet info */
+  h225_pi->cs_type = H225_FACILITY;
+  g_snprintf(h225_pi->frame_label, 50, "%s", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>"));
+#.END
+#----------------------------------------------------------------------------------------
+#.FN_BODY H323-UU-PDU/h245Tunneling
+	offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_h245Tunneling, &(h225_pi->is_h245Tunneling), NULL);
+#.END
+#----------------------------------------------------------------------------------------
 #.FN_HDR Setup-UUIE
   contains_faststart = FALSE;
 #.END
 #----------------------------------------------------------------------------------------
 #.FN_FTR Setup-UUIE
-  h225_pi.cs_type = H225_SETUP;
+  /* Add to packet info */
+  h225_pi->cs_type = H225_SETUP;
+  if (contains_faststart == TRUE )
+      g_snprintf(h225_pi->frame_label, 50, "%s OLC (%s)", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>"), h225_pi->frame_label);
+  else
+      g_snprintf(h225_pi->frame_label, 50, "%s", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>"));
 #.END
 #----------------------------------------------------------------------------------------
 #.FN_FTR CallProceeding-UUIE
-  h225_pi.cs_type = H225_CALL_PROCEDING;
+  /* Add to packet info */
+  h225_pi->cs_type = H225_CALL_PROCEDING;
+  if (contains_faststart == TRUE )
+        g_snprintf(h225_pi->frame_label, 50, "%s OLC (%s)", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>"), h225_pi->frame_label);
+  else
+        g_snprintf(h225_pi->frame_label, 50, "%s", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>"));
 #.END
 #----------------------------------------------------------------------------------------
 #.FN_FTR Alerting-UUIE
-  h225_pi.cs_type = H225_ALERTING;
+  /* Add to packet info */
+  h225_pi->cs_type = H225_ALERTING;
+  if (contains_faststart == TRUE )
+       g_snprintf(h225_pi->frame_label, 50, "%s OLC (%s)", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>"), h225_pi->frame_label);
+  else 
+       g_snprintf(h225_pi->frame_label, 50, "%s", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>"));
 #.END
 #----------------------------------------------------------------------------------------
 #.FN_FTR ReleaseComplete-UUIE
-  h225_pi.cs_type = H225_RELEASE_COMPLET;
+  /* Add to packet info */
+  h225_pi->cs_type = H225_RELEASE_COMPLET;
+  g_snprintf(h225_pi->frame_label, 50, "%s", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>"));
 #.END
 #----------------------------------------------------------------------------------------
 #.FN_FTR Connect-UUIE
-  h225_pi.cs_type = H225_CONNECT;
+  /* Add to packet info */
+  h225_pi->cs_type = H225_CONNECT;
+  if (contains_faststart == TRUE )
+      g_snprintf(h225_pi->frame_label, 50, "%s OLC (%s)", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>"), h225_pi->frame_label);
+  else 
+      g_snprintf(h225_pi->frame_label, 50, "%s", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>"));
 #.END
 #----------------------------------------------------------------------------------------
 #.FN_HDR H245TransportAddress
@@ -273,9 +332,9 @@
 #----------------------------------------------------------------------------------------
 #.FN_FTR H245TransportAddress
 	/* we need this info for TAPing */
-	h225_pi.is_h245 = TRUE;
-	h225_pi.h245_address = ipv4_address;	
-	h225_pi.h245_port = ipv4_port;	
+	h225_pi->is_h245 = TRUE;
+	h225_pi->h245_address = ipv4_address;	
+	h225_pi->h245_port = ipv4_port;	
 
 	if((!pinfo->fd->flags.visited) && ipv4_address!=0 && ipv4_port!=0 && h245_handle){
 		address src_addr;
@@ -300,7 +359,7 @@
   offset = dissect_per_choice(tvb, offset, pinfo, tree, hf_index,
                               ett_h225_FacilityReason, FacilityReason_choice, "FacilityReason",
                               &value);
-	h225_pi.reason = value;
+	h225_pi->reason = value;
 
 #.END
 #----------------------------------------------------------------------------------------
@@ -310,7 +369,7 @@
   offset = dissect_per_choice(tvb, offset, pinfo, tree, hf_index,
                               ett_h225_GatekeeperRejectReason, GatekeeperRejectReason_choice, "GatekeeperRejectReason",
                               &value);
-  h225_pi.reason = value;
+  h225_pi->reason = value;
 
 #.END
 #----------------------------------------------------------------------------------------
@@ -320,7 +379,7 @@
   offset = dissect_per_choice(tvb, offset, pinfo, tree, hf_index,
                               ett_h225_UnregRequestReason, UnregRequestReason_choice, "UnregRequestReason",
                               &value);
-  h225_pi.reason = value;
+  h225_pi->reason = value;
 
 #.END
 #----------------------------------------------------------------------------------------
@@ -330,7 +389,7 @@
   offset = dissect_per_choice(tvb, offset, pinfo, tree, hf_index,
                               ett_h225_UnregRejectReason, UnregRejectReason_choice, "UnregRejectReason",
                               &value);
-  h225_pi.reason = value;
+  h225_pi->reason = value;
 #.END
 #----------------------------------------------------------------------------------------
 #.FN_BODY BandRejectReason
@@ -338,7 +397,7 @@
   offset = dissect_per_choice(tvb, offset, pinfo, tree, hf_index,
                               ett_h225_BandRejectReason, BandRejectReason_choice, "BandRejectReason",
                               &value);
-  h225_pi.reason = value;
+  h225_pi->reason = value;
 #.END
 #----------------------------------------------------------------------------------------
 #.FN_BODY DisengageReason
@@ -347,7 +406,7 @@
   offset = dissect_per_choice(tvb, offset, pinfo, tree, hf_index,
                               ett_h225_DisengageReason, DisengageReason_choice, "DisengageReason",
                               &value);
-  h225_pi.reason = value;
+  h225_pi->reason = value;
 #----------------------------------------------------------------------------------------
 #.FN_BODY DisengageRejectReason
   guint32 value;
@@ -355,7 +414,7 @@
   offset = dissect_per_choice(tvb, offset, pinfo, tree, hf_index,
                               ett_h225_DisengageRejectReason, DisengageRejectReason_choice, "DisengageRejectReason",
                               &value);
-  h225_pi.reason = value;
+  h225_pi->reason = value;
 #.END
 #----------------------------------------------------------------------------------------
 #.FN_BODY AdmissionRejectReason
@@ -364,7 +423,7 @@
   offset = dissect_per_choice(tvb, offset, pinfo, tree, hf_index,
                               ett_h225_AdmissionRejectReason, AdmissionRejectReason_choice, "AdmissionRejectReason",
                               &value);
-  h225_pi.reason = value;
+  h225_pi->reason = value;
 #.END
 #----------------------------------------------------------------------------------------
 #.FN_BODY LocationRejectReason
@@ -373,7 +432,7 @@
   offset = dissect_per_choice(tvb, offset, pinfo, tree, hf_index,
                               ett_h225_LocationRejectReason, LocationRejectReason_choice, "LocationRejectReason",
                               &value);
-  h225_pi.reason = value;
+  h225_pi->reason = value;
 #.END
 #----------------------------------------------------------------------------------------
 #.FN_BODY RegistrationRejectReason
@@ -382,7 +441,7 @@
   offset = dissect_per_choice(tvb, offset, pinfo, tree, hf_index,
                               ett_h225_RegistrationRejectReason, RegistrationRejectReason_choice, "RegistrationRejectReason",
                               &value);
-  h225_pi.reason = value;
+  h225_pi->reason = value;
 #.END
 #----------------------------------------------------------------------------------------
 #.FN_BODY InfoRequestNakReason
@@ -391,7 +450,7 @@
   offset = dissect_per_choice(tvb, offset, pinfo, tree, hf_index,
                               ett_h225_InfoRequestNakReason, InfoRequestNakReason_choice, "InfoRequestNakReason",
                               &value);
-  h225_pi.reason = value;
+  h225_pi->reason = value;
 #.END
 #----------------------------------------------------------------------------------------
 #.FN_BODY ReleaseCompleteReason
@@ -400,19 +459,19 @@
   offset = dissect_per_choice(tvb, offset, pinfo, tree, hf_index,
                               ett_h225_ReleaseCompleteReason, ReleaseCompleteReason_choice, "ReleaseCompleteReason",
                               &value);
-  h225_pi.reason = value;
+  h225_pi->reason = value;
 #.END
 #----------------------------------------------------------------------------------------
 #.FN_BODY CallIdentifier/guid
   guint32 guid_offset,guid_len;
 
   offset = dissect_per_octet_string(tvb,offset,pinfo,tree,hf_index,16,16,&guid_offset,&guid_len);
-  tvb_memcpy(tvb,h225_pi.guid,guid_offset,guid_len);
+  tvb_memcpy(tvb,h225_pi->guid,guid_offset,guid_len);
 #.END
 #----------------------------------------------------------------------------------------
 #.FN_BODY RequestSeqNum
   offset = dissect_per_constrained_integer(tvb, offset, pinfo, tree, hf_index,
-                                           1U, 65535U, &(h225_pi.requestSeqNum), NULL, FALSE);
+                                           1U, 65535U, &(h225_pi->requestSeqNum), NULL, FALSE);
 
 #----------------------------------------------------------------------------------------
 #.FN_BODY H323-UU-PDU/h4501SupplementaryService/_item
Index: asn1/h245/packet-h245-template.c
===================================================================
--- asn1/h245/packet-h245-template.c	(revision 13162)
+++ asn1/h245/packet-h245-template.c	(working copy)
@@ -70,7 +70,10 @@
 static int hf_h245Manufacturer = -1;
 static int h245_tap = -1;
 static int ett_h245 = -1;
-static h245_packet_info h245_pi;
+static int h245dg_tap = -1;
+static h245_packet_info pi_arr[5]; /* We assuming a maximum of 5 H245 messaages per packet */
+static int pi_current=0;
+h245_packet_info *h245_pi=NULL;
 
 static gboolean h245_reassembly = TRUE;
 static gboolean h245_shorttypes = FALSE;
@@ -164,6 +167,34 @@
 	{ 12,	"GC" },
 	{  0, NULL }
 };
+static const value_string h245_AudioCapability_short_vals[] = {
+        {  0, "nonStd" },
+        {  1, "g711A" },
+        {  2, "g711A56k" },
+        {  3, "g711U" },
+        {  4, "g711U56k" },
+        {  5, "g722-64k" },
+        {  6, "g722-56k" },
+        {  7, "g722-48k" },
+        {  8, "g7231" },
+        {  9, "g728" },
+        { 10, "g729" },
+        { 11, "g729A" },
+        { 12, "is11172" },
+        { 13, "is13818" },
+        { 14, "g729B" },
+        { 15, "g729AB" },
+        { 16, "g7231C" },
+        { 17, "gsmFR" },
+        { 18, "gsmHR" },
+        { 19, "gsmEFR" },
+        { 20, "generic" },
+        { 21, "g729Ext" },
+        { 22, "vbd" },
+        { 23, "audioTelEvent" },
+        { 24, "audioTone" },
+        {  0, NULL }
+};
 
 /* To put the codec type only in COL_INFO when
    an OLC is read */
@@ -199,12 +230,18 @@
 void
 dissect_h245(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
 {
-	reset_h245_packet_info(&(h245_pi));
-        h245_pi.msg_type = H245_OTHER;
+    pi_current++;
+    if(pi_current==5){
+        pi_current=0;
+    }
+    h245_pi=&pi_arr[pi_current];
 
+    reset_h245_packet_info(h245_pi);
+       h245_pi->msg_type = H245_OTHER;
+
 	dissect_tpkt_encap(tvb, pinfo, parent_tree, h245_reassembly, MultimediaSystemControlMessage_handle);
 
-	tap_queue_packet(h245_tap, pinfo, &h245_pi);
+	tap_queue_packet(h245_tap, pinfo, h245_pi);
 }
 
 void
@@ -214,7 +251,15 @@
 	proto_tree *tr;
 	guint32 offset=0;
 
+    pi_current++;
+    if(pi_current==5){
+      pi_current=0;
+    }
+    h245_pi=&pi_arr[pi_current];
 
+    reset_h245_packet_info(h245_pi);
+    h245_pi->msg_type = H245_OTHER;
+
 	if (check_col(pinfo->cinfo, COL_PROTOCOL)){
 		col_set_str(pinfo->cinfo, COL_PROTOCOL, "H.245");
 	}
@@ -222,9 +267,24 @@
 	it=proto_tree_add_protocol_format(parent_tree, proto_h245, tvb, 0, tvb_length(tvb), "H.245");
 	tr=proto_item_add_subtree(it, ett_h245);
 	dissect_h245_MultimediaSystemControlMessage(tvb, offset, pinfo ,tr, hf_h245_pdu_type);
+	tap_queue_packet(h245dg_tap, pinfo, h245_pi);
 }
 
+int
+dissect_h245_OpenLogicalChannelCodec(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index, char *codec_str) {
+  offset = dissect_per_sequence(tvb, offset, pinfo, tree, hf_index,
+                                ett_h245_OpenLogicalChannel, OpenLogicalChannel_sequence);
 
+
+  if (h245_pi != NULL) h245_pi->msg_type = H245_OpenLogChn;
+
+  if (codec_str){
+        strcpy(codec_str, codec_type);
+  }
+
+  return offset;
+}
+
 /*--- proto_register_h245 -------------------------------------------*/
 void proto_register_h245(void) {
 
@@ -270,6 +330,7 @@
   nsp_object_dissector_table = register_dissector_table("h245.nsp.object", "H.245 NonStandardParameter (object)", FT_STRING, BASE_NONE);
   nsp_h221_dissector_table = register_dissector_table("h245.nsp.h221", "H.245 NonStandardParameter (h221)", FT_UINT32, BASE_HEX);
   h245_tap = register_tap("h245");
+  h245dg_tap = register_tap("h245dg");
 
   register_ber_oid_name("0.0.8.239.1.1","itu-t(0) recommendation(0) h(8) h239(239) generic-capabilities(1) h239ControlCapability(1)");
   register_ber_oid_name("0.0.8.239.1.2","itu-t(0) recommendation(0) h(8) h239(239) generic-capabilities(1) h239ExtendedVideoCapability(2)");
@@ -309,5 +370,7 @@
         }
 
         pi->msg_type = H245_OTHER;
+		pi->frame_label[0] = '\0';
+		sprintf(pi->comment, "H245 ");
 }
 
Index: asn1/h245/packet-h245-template.h
===================================================================
--- asn1/h245/packet-h245-template.h	(revision 13162)
+++ asn1/h245/packet-h245-template.h	(working copy)
@@ -2,7 +2,7 @@
  * Routines for h245 packet dissection
  * Copyright 2005, Anders Broman <anders.broman@xxxxxxxxxxxx>
  *
- * $Id: packet-h245-template.h 12203 2004-10-05 09:18:55Z guy $
+ * $Id$
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@xxxxxxxxxxxx>
@@ -45,11 +45,15 @@
 
 typedef struct _h245_packet_info {
         h245_msg_type msg_type;         /* type of message */
+        gchar frame_label[50];          /* the Frame label used by graph_analysis, what is a abreviation of cinfo */
+        gchar comment[50];                      /* the Frame Comment used by graph_analysis, what is a message desc */
 } h245_packet_info;
 
 
 #include "packet-h245-exp.h"*/
+int dissect_h245_OpenLogicalChannelCodec(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index, char *codec_str);
 
+
 #endif  /* PACKET_H245_H */
 
 
Index: asn1/h245/h245.cnf
===================================================================
--- asn1/h245/h245.cnf	(revision 13162)
+++ asn1/h245/h245.cnf	(working copy)
@@ -33,6 +33,20 @@
 	}
 
         col_set_fence(pinfo->cinfo,COL_INFO);
+
+    /* Add to packet info */
+
+    /* if it is TCS*/
+    if ((codec_type != NULL) && ( value == 2))
+                g_snprintf(h245_pi->frame_label, 50, "%s (%s) ",val_to_str(value, h245_RequestMessage_short_vals, "UKN"), h245_pi->frame_label);
+    else
+                g_snprintf(h245_pi->frame_label, 50, "%s ", val_to_str(value, h245_RequestMessage_short_vals, "UKN"));
+
+    g_snprintf(h245_pi->comment, 50, "%s %s ", h245_pi->comment, val_to_str(value, h245_RequestMessage_vals, "<unknown>"));
+
+    /* if it is OLC or RM*/
+    if ((codec_type != NULL) && (( value == 3) || ( value == 8)))
+                g_snprintf(h245_pi->frame_label, 50, "%s (%s) ", h245_pi->frame_label, codec_type);
 #.END
 #----------------------------------------------------------------------------------------
 #.FN_BODY ResponseMessage
@@ -56,6 +70,10 @@
 	}
 
 	col_set_fence(pinfo->cinfo,COL_INFO);
+
+    /* Add to packet info */
+    g_snprintf(h245_pi->frame_label, 50, "%s %s ", h245_pi->frame_label, val_to_str(value, h245_ResponseMessage_short_vals, "UKN"));
+    g_snprintf(h245_pi->comment, 50, "%s %s ", h245_pi->comment, val_to_str(value, h245_ResponseMessage_vals, "<unknown>"));
 #.END
 #----------------------------------------------------------------------------------------
 #.FN_BODY IndicationMessage
@@ -79,6 +97,9 @@
 	}
 
 	col_set_fence(pinfo->cinfo,COL_INFO);
+    /* Add to packet info */
+    g_snprintf(h245_pi->frame_label, 50, "%s %s ", h245_pi->frame_label, val_to_str(value, h245_IndicationMessage_short_vals, "UKN"));
+    g_snprintf(h245_pi->comment, 50, "%s %s ", h245_pi->comment, val_to_str(value, h245_IndicationMessage_vals, "<unknown>"));
 #.END
 #----------------------------------------------------------------------------------------
 #.FN_BODY CommandMessage
@@ -102,6 +123,10 @@
 	}
 
 	col_set_fence(pinfo->cinfo,COL_INFO);
+    /* Add to packet info */
+    g_snprintf(h245_pi->frame_label, 50, "%s %s ", h245_pi->frame_label, val_to_str(value, h245_CommandMessage_short_vals, "UKN"));
+    g_snprintf(h245_pi->comment, 50, "%s %s ", h245_pi->comment, val_to_str(value, h245_CommandMessage_vals, "<unknown>"));
+
 #.END
 #----------------------------------------------------------------------------------------
 #.FN_BODY AudioCapability
@@ -111,7 +136,9 @@
                               ett_h245_AudioCapability, AudioCapability_choice, "AudioCapability",
                               &value);
 
-        codec_type = val_to_str(value, h245_AudioCapability_vals, "<unknown>");
+        codec_type = val_to_str(value, h245_AudioCapability_short_vals, "<unknown>");
+		if (h245_pi != NULL) g_snprintf(h245_pi->frame_label, 50, "%s %s", h245_pi->frame_label, val_to_str(value, h245_AudioCapability_short_vals, "ukn"));
+
 #.END
 #----------------------------------------------------------------------------------------
 #.FN_BODY VideoCapability
@@ -122,6 +149,8 @@
                               &value);
 
         codec_type = val_to_str(value, h245_VideoCapability_vals, "<unknown>");
+		if (h245_pi != NULL) g_snprintf(h245_pi->frame_label, 50, "%s %s", h245_pi->frame_label, codec_type);
+
 #.END
 #----------------------------------------------------------------------------------------
 #.FN_BODY Application
@@ -132,76 +161,77 @@
                               &value);
 
         codec_type = val_to_str(value, h245_Application_vals, "<unknown>");
+		if (h245_pi != NULL) g_snprintf(h245_pi->frame_label, 50, "%s %s", h245_pi->frame_label, codec_type);
 #.END
 #----------------------------------------------------------------------------------------
 #.FN_FTR MasterSlaveDeterminationAck
 
-  h245_pi.msg_type = H245_MastSlvDetAck;
+  h245_pi->msg_type = H245_MastSlvDetAck;
 #.END
 #----------------------------------------------------------------------------------------
 #.FN_FTR MasterSlaveDeterminationReject
 
-  h245_pi.msg_type = H245_MastSlvDetRjc;
+  h245_pi->msg_type = H245_MastSlvDetRjc;
 #.END
 #----------------------------------------------------------------------------------------
 #.FN_FTR OpenLogicalChannelReject
 
-  h245_pi.msg_type = H245_OpenLogChnRjc;
+  h245_pi->msg_type = H245_OpenLogChnRjc;
 #.END
 #----------------------------------------------------------------------------------------
 #.FN_FTR CloseLogicalChannel
 
-  h245_pi.msg_type = H245_CloseLogChn;
+  h245_pi->msg_type = H245_CloseLogChn;
 #.END
 #----------------------------------------------------------------------------------------
 #.FN_FTR CloseLogicalChannelAck
 
-  h245_pi.msg_type = H245_CloseLogChnAck;
+  h245_pi->msg_type = H245_CloseLogChnAck;
 #.END
 #----------------------------------------------------------------------------------------
 #.FN_FTR OpenLogicalChannelConfirm
 
-  h245_pi.msg_type = H245_OpenLogChnCnf;
+  h245_pi->msg_type = H245_OpenLogChnCnf;
 #.END
 #----------------------------------------------------------------------------------------
 #.FN_FTR TerminalCapabilitySetAck
 
-  h245_pi.msg_type = H245_TermCapSetAck;
+  h245_pi->msg_type = H245_TermCapSetAck;
 #.END
 #----------------------------------------------------------------------------------------
 #.FN_FTR MasterSlaveDetermination
 
-  h245_pi.msg_type = H245_MastSlvDet;
+  h245_pi->msg_type = H245_MastSlvDet;
 #.END
 #----------------------------------------------------------------------------------------
 #.FN_FTR TerminalCapabilitySetReject
 
-  h245_pi.msg_type = H245_TermCapSetRjc;
+  h245_pi->msg_type = H245_TermCapSetRjc;
 #.END
 #----------------------------------------------------------------------------------------
 #.FN_FTR MasterSlaveDeterminationRelease
 
-  h245_pi.msg_type = H245_MastSlvDetRls;
+  h245_pi->msg_type = H245_MastSlvDetRls;
 #.END
 #----------------------------------------------------------------------------------------
 #.FN_FTR TerminalCapabilitySet
 
-  h245_pi.msg_type = H245_TermCapSet;
+  h245_pi->msg_type = H245_TermCapSet;
 #.END
 #----------------------------------------------------------------------------------------
 #.FN_FTR TerminalCapabilitySetRelease
 
-  h245_pi.msg_type = H245_TermCapSetRls;
+  h245_pi->msg_type = H245_TermCapSetRls;
 #.END
 #----------------------------------------------------------------------------------------
 #.FN_FTR OpenLogicalChannel
 
-  h245_pi.msg_type = H245_OpenLogChn;
+  if (h245_pi != NULL) h245_pi->msg_type = H245_OpenLogChn;
 #.END
 #----------------------------------------------------------------------------------------
 #.FN_FTR OpenLogicalChannelAck
 
-  h245_pi.msg_type = H245_OpenLogChnAck;
+  h245_pi->msg_type = H245_OpenLogChnAck;
 #.END
 #----------------------------------------------------------------------------------------
 #.FN_BODY CapabilityIdentifier/standard
Index: gtk/voip_calls_dlg.c
===================================================================
--- gtk/voip_calls_dlg.c	(revision 0)
+++ gtk/voip_calls_dlg.c	(revision 0)
@@ -0,0 +1,719 @@
+/* voip_calls_dlg.c
+ * VoIP calls summary addition for ethereal
+ *
+ * $Id: voip_calls_dlg.c 12185 2004-10-02 11:05:27Z ulfl $
+ *
+ * Copyright 2004, Ericsson , Spain
+ * By Francisco Alcoba <francisco.alcoba@xxxxxxxxxxxx>
+ *
+ * based on h323_calls_dlg.c
+ * Copyright 2004, Iskratel, Ltd, Kranj
+ * By Miha Jemec <m.jemec@xxxxxxxxxxx>
+ *
+ * H323, RTP and Graph Support
+ * By Alejandro Vaquero, alejandro.vaquero@xxxxxxxxx
+ * Copyright 2005, Verso Technologies Inc.
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@xxxxxxxxxxxx>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation,  Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include "register.h"
+
+#include "graph_analysis.h"
+#include "voip_calls_dlg.h"
+#include "voip_calls.h"
+
+#include "globals.h"
+#include "epan/filesystem.h"
+
+#include "tap_menu.h"
+#include "dlg_utils.h"
+#include "ui_util.h"
+#include "compat_macros.h"
+#include "gtkglobals.h"
+
+#include "image/clist_ascend.xpm"
+#include "image/clist_descend.xpm"
+#include "simple_dialog.h"
+
+#include <epan/to_str.h>
+
+#include <string.h>
+
+
+typedef const guint8 * ip_addr_p;
+
+static const gchar FWD_LABEL_TEXT[] = "Select one call.";
+
+/****************************************************************************/
+/* pointer to the one and only dialog window */
+static GtkWidget *voip_calls_dlg = NULL;
+
+static GtkWidget *clist = NULL;
+static GtkWidget *top_label = NULL;
+static GtkWidget *status_label = NULL;
+static GtkWidget *label_fwd = NULL;
+
+/*static GtkWidet *bt_unselect = NULL;*/
+static GtkWidget *bt_filter = NULL;
+static GtkWidget *bt_graph = NULL;
+
+
+static voip_calls_info_t* selected_call_fwd = NULL;  /* current selection */
+static GList *last_list = NULL;
+
+static guint32 calls_nb = 0;     /* number of displayed calls */
+static guint32 calls_ns = 0;     /* number of selected calls */
+
+static graph_analysis_data_t *graph_analysis_data;
+
+#define NUM_COLS 9
+
+/****************************************************************************/
+/* append a line to clist */
+static void add_to_clist(voip_calls_info_t* strinfo)
+{
+	gchar label_text[256];
+	gint added_row;
+	gchar *data[NUM_COLS];
+	gchar field[NUM_COLS][50];
+	gint c;
+	isup_calls_info_t *tmp_isupinfo;
+	h323_calls_info_t *tmp_h323info;
+	gboolean tmp_bool = FALSE;
+	for (c=0;c<NUM_COLS;c++){
+		data[c]=&field[c][0];
+	}
+
+
+	g_snprintf(field[0], 15, "%i.%2i", strinfo->start_sec, strinfo->start_usec/10000);
+	g_snprintf(field[1], 15, "%i.%2i", strinfo->stop_sec, strinfo->stop_usec/10000);
+//	xxx display_signed_time(data[0], sizeof(field[0]), strinfo->start_sec, strinfo->start_usec, USECS);
+//	display_signed_time(data[1], sizeof(field[0]), strinfo->stop_sec, strinfo->stop_usec, USECS);
+	g_snprintf(field[2], 30, "%s", ip_to_str((const guint8*)&(strinfo->initial_speaker)));
+	g_snprintf(field[3], 50, "%s", strinfo->from_identity);
+	g_snprintf(field[4], 50, "%s", strinfo->to_identity);
+    g_snprintf(field[5], 15, "%s", voip_protocol_name[strinfo->protocol]);
+	g_snprintf(field[6], 15, "%u", strinfo->npackets);
+	g_snprintf(field[7], 15, "%s", voip_call_state_name[strinfo->call_state]);
+
+	/* Add comments based on the protocol */
+	switch(strinfo->protocol){
+		case VOIP_ISUP:
+			tmp_isupinfo = strinfo->prot_info;
+			g_snprintf(field[8],30, "%i-%i -> %i-%i", tmp_isupinfo->ni, tmp_isupinfo->opc,
+				tmp_isupinfo->ni, tmp_isupinfo->dpc);
+			break;
+		case VOIP_H323:
+			tmp_h323info = strinfo->prot_info;
+			if (strinfo->call_state == VOIP_CALL_SETUP) 
+				tmp_bool = tmp_h323info->is_faststart_Setup;
+			else
+				if ((tmp_h323info->is_faststart_Setup == TRUE) && (tmp_h323info->is_faststart_Proc == TRUE)) tmp_bool = TRUE; 
+			g_snprintf(field[8],35, "Tunneling: %s  Fast Start: %s", (tmp_h323info->is_h245Tunneling==TRUE?"ON":"OFF"), 
+				(tmp_bool==TRUE?"ON":"OFF"));
+			break;
+		default:
+			field[8][0]='\0';
+	}
+
+	
+	added_row = gtk_clist_append(GTK_CLIST(clist), data);
+
+	/* set data pointer of last row to point to user data for that row */
+	gtk_clist_set_row_data(GTK_CLIST(clist), added_row, strinfo);
+
+	/* Update the top label with the number of detected calls */
+    calls_nb++;
+	g_snprintf(label_text, 256,
+	        "Detected %d VoIP %s. Selected %d %s.",
+	        calls_nb, 
+            plurality(calls_nb, "Call", "Calls"),
+			calls_ns,
+			plurality(calls_ns, "Call", "Calls"));
+	gtk_label_set(GTK_LABEL(top_label), label_text);
+
+	/* Update the status label with the number of total messages */
+        g_snprintf(label_text, 256,
+       		"Total: Calls: %d   Start packets: %d   Completed calls: %d   Rejected calls: %d",
+			voip_calls_get_info()->ncalls,
+            voip_calls_get_info()->start_packets, 
+			voip_calls_get_info()->completed_calls,
+			voip_calls_get_info()->rejected_calls);
+        gtk_label_set(GTK_LABEL(status_label), label_text);
+}
+
+
+void voip_calls_remove_tap_listener()
+{
+	/* Remove the calls tap listener */
+	remove_tap_listener_sip_calls();
+	remove_tap_listener_isup_calls();
+	remove_tap_listener_mtp3_calls();
+	remove_tap_listener_h225_calls();
+	remove_tap_listener_h245dg_calls();
+	remove_tap_listener_q931_calls();
+	remove_tap_listener_sdp_calls();
+}
+
+/****************************************************************************/
+/* CALLBACKS                                                                */
+/****************************************************************************/
+static void
+voip_calls_on_destroy                      (GtkObject       *object _U_,
+                                        gpointer         user_data _U_)
+{
+	/* Clean up memory used by calls tap */
+	voip_calls_reset((voip_calls_tapinfo_t*) voip_calls_get_info());
+
+	/* Note that we no longer have a "VoIP Calls" dialog box. */
+	voip_calls_dlg = NULL;
+}
+
+
+/****************************************************************************/
+static void
+voip_calls_on_unselect                  (GtkButton       *button _U_,
+                                        gpointer         user_data _U_)
+{
+	selected_call_fwd = NULL;
+	gtk_clist_unselect_all(GTK_CLIST(clist));
+	gtk_label_set_text(GTK_LABEL(label_fwd), FWD_LABEL_TEXT);
+
+    /*gtk_widget_set_sensitive(bt_unselect, FALSE);*/
+    gtk_widget_set_sensitive(bt_filter, FALSE);
+}
+
+
+/****************************************************************************/
+static void
+voip_calls_on_filter                    (GtkButton       *button _U_,
+                                        gpointer         user_data _U_)
+{
+	gchar *filter_string = NULL;
+	gchar *filter_string_fwd = NULL;
+	gchar filter_prepend[5];
+	sip_calls_info_t *tmp_sipinfo;
+	isup_calls_info_t *tmp_isupinfo;
+	h323_calls_info_t *tmp_h323info;
+	h245_address_t *h245_add = NULL;
+	GList* list;
+
+	if (selected_call_fwd==NULL)
+		return;
+
+	filter_string=gtk_entry_get_text(GTK_ENTRY(main_display_filter_widget));
+	if (strcmp(filter_string,"")!=0){ /* this means there is already a display filter, we or it */
+		strcpy(filter_prepend," or ");
+	}
+	else{
+		strcpy(filter_prepend,"");
+	}
+		
+
+	switch(selected_call_fwd->protocol){
+		case VOIP_SIP:
+			tmp_sipinfo = selected_call_fwd->prot_info;
+			filter_string_fwd = g_strdup_printf("%s(sip.Call-ID == \"%s\") ",
+			   filter_prepend, tmp_sipinfo->call_identifier 
+			   );
+			filter_string = filter_string_fwd;
+			gtk_entry_append_text(GTK_ENTRY(main_display_filter_widget), filter_string);
+			break;
+		case VOIP_ISUP:
+			tmp_isupinfo = selected_call_fwd->prot_info;
+			filter_string_fwd = g_strdup_printf("%s(isup.cic == %i and frame.number >=%i and frame.number<=%i and mtp3.network_indicator == %i and ((mtp3.dpc == %i) and (mtp3.opc == %i)) or((mtp3.dpc == %i) and (mtp3.opc == %i))) ",
+			   filter_prepend, tmp_isupinfo->cic,selected_call_fwd->first_frame_num,
+			   selected_call_fwd->last_frame_num, 
+			   tmp_isupinfo->ni, tmp_isupinfo->dpc, tmp_isupinfo->opc, 
+			   tmp_isupinfo->opc, tmp_isupinfo->dpc
+			   );
+			filter_string = filter_string_fwd;
+			gtk_entry_append_text(GTK_ENTRY(main_display_filter_widget), filter_string);
+			break;
+		case VOIP_H323:
+			tmp_h323info = selected_call_fwd->prot_info;
+			filter_string_fwd = g_strdup_printf("%s((h225.guid == %x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x || q931.call_ref == %x:%x || q931.call_ref == %x:%x) ",
+			   filter_prepend, (guint8)tmp_h323info->guid[0], (guint8)tmp_h323info->guid[1], (guint8)tmp_h323info->guid[2],
+			   (guint8)tmp_h323info->guid[3], (guint8)tmp_h323info->guid[4], (guint8)tmp_h323info->guid[5], (guint8)tmp_h323info->guid[6],
+			   (guint8)tmp_h323info->guid[7], (guint8)tmp_h323info->guid[8], (guint8)tmp_h323info->guid[9], (guint8)tmp_h323info->guid[10],
+			   (guint8)tmp_h323info->guid[11], (guint8)tmp_h323info->guid[12], (guint8)tmp_h323info->guid[13], (guint8)tmp_h323info->guid[14],
+			   (guint8)tmp_h323info->guid[15], (guint8)(tmp_h323info->q931_crv & 0xff), (guint8)((tmp_h323info->q931_crv & 0xff00)>>8)
+			   , (guint8)(tmp_h323info->q931_crv2 & 0xff), (guint8)((tmp_h323info->q931_crv2 & 0xff00)>>8));
+
+			list = g_list_first(tmp_h323info->h245_list);
+			while (list)
+			{
+				h245_add=list->data;
+				filter_string_fwd = g_strdup_printf("%s || (ip.addr == %s && tcp.port == %d && h245) ", filter_string_fwd, 
+					ip_to_str((guint8 *)&(h245_add->h245_address)), h245_add->h245_port);
+				list = g_list_next(list);
+			}
+			filter_string_fwd = g_strdup_printf("%s ) ", filter_string_fwd);
+
+			filter_string = filter_string_fwd;
+			gtk_entry_append_text(GTK_ENTRY(main_display_filter_widget), filter_string);
+			break;
+
+	}
+
+	
+	g_free(filter_string);
+
+/*
+	main_filter_packets(&cfile, filter_string, FALSE);
+	voip_calls_dlg_update(voip_calls_get_info()->strinfo_list);
+*/
+}
+
+
+
+
+/****************************************************************************/
+static void
+on_graph_bt_clicked                    (GtkButton       *button _U_,
+                                        gpointer         user_data _U_)
+{
+	graph_analysis_item_t *gai;
+	GList* list;
+	GList* list2;
+	voip_calls_info_t *tmp_listinfo;
+
+	/* reset the "display" parameter in graph analysis */
+	list2 = g_list_first(voip_calls_get_info()->graph_analysis->list);
+	while (list2){
+		gai = list2->data;
+		gai->display = FALSE;
+		list2 = g_list_next(list2);
+	}
+
+
+	/* set the display for selected calls */
+	list = g_list_first(voip_calls_get_info()->strinfo_list);
+	while (list){
+		tmp_listinfo=list->data;
+		if (tmp_listinfo->selected){
+			list2 = g_list_first(voip_calls_get_info()->graph_analysis->list);
+			while (list2){
+				gai = list2->data;
+				if (gai->conv_num == tmp_listinfo->call_num){
+					gai->display = TRUE;
+				}
+				list2 = g_list_next(list2);
+			}
+		}
+		list = g_list_next(list);
+	}
+
+	/* create or refresh the graph windows */
+	if (graph_analysis_data->dlg.window == NULL)	/* create the window */
+		graph_analysis_create(graph_analysis_data);
+	else
+		graph_analysis_update(graph_analysis_data);		/* refresh it */
+}
+
+static const GdkColor COLOR_SELECT = {0, 0x00ff, 0x80ff, 0x80ff};
+static const GdkColor COLOR_DEFAULT = {0, 0xffff, 0xffff, 0xffff};
+
+/****************************************************************************/
+/* when the user selects a row in the calls list */
+static void
+voip_calls_on_select_row(GtkCList *clist,
+                                            gint row _U_,
+                                            gint column _U_,
+                                            GdkEventButton *event _U_,
+                                            gpointer user_data _U_)
+{
+	GdkColor color = COLOR_DEFAULT;
+	gchar label_text[80];
+	
+	selected_call_fwd = gtk_clist_get_row_data(GTK_CLIST(clist), row);
+
+	if (!selected_call_fwd->selected)
+		calls_ns++;
+	else
+		calls_ns--;
+
+	g_snprintf(label_text, 256,
+	        "Detected %d VoIP %s. Selected %d %s.",
+	        calls_nb, 
+            plurality(calls_nb, "Call", "Calls"),
+			calls_ns,
+			plurality(calls_ns, "Call", "Calls"));
+	gtk_label_set(GTK_LABEL(top_label), label_text);
+
+	g_snprintf(label_text, 80, "Selected Call: From  %s  To %s, starting time %i.%i",
+		selected_call_fwd->from_identity,
+		selected_call_fwd->to_identity,
+		selected_call_fwd->start_sec, 
+		selected_call_fwd->start_usec
+	);
+	gtk_label_set_text(GTK_LABEL(label_fwd), label_text);
+
+	selected_call_fwd->selected=!selected_call_fwd->selected;
+	if (selected_call_fwd->selected)
+		color = COLOR_SELECT;
+	else
+		color = COLOR_DEFAULT;
+
+	gtk_clist_set_background(GTK_CLIST(clist), row, &color);
+	
+    /*gtk_widget_set_sensitive(bt_unselect, TRUE);*/
+    gtk_widget_set_sensitive(bt_filter, TRUE);
+
+	/* TODO: activate other buttons when implemented */
+}
+
+
+/****************************************************************************/
+
+typedef struct column_arrows {
+	GtkWidget *table;
+	GtkWidget *ascend_pm;
+	GtkWidget *descend_pm;
+} column_arrows;
+
+
+/****************************************************************************/
+static void
+voip_calls_click_column_cb(GtkCList *clist, gint column, gpointer data)
+{
+	column_arrows *col_arrows = (column_arrows *) data;
+	int i;
+
+	gtk_clist_freeze(clist);
+
+	for (i=0; i<NUM_COLS; i++) {
+		gtk_widget_hide(col_arrows[i].ascend_pm);
+		gtk_widget_hide(col_arrows[i].descend_pm);
+	}
+
+	if (column == clist->sort_column) {
+		if (clist->sort_type == GTK_SORT_ASCENDING) {
+			clist->sort_type = GTK_SORT_DESCENDING;
+			gtk_widget_show(col_arrows[column].descend_pm);
+		} else {
+			clist->sort_type = GTK_SORT_ASCENDING;
+			gtk_widget_show(col_arrows[column].ascend_pm);
+		}
+	} else {
+		clist->sort_type = GTK_SORT_ASCENDING;
+		gtk_widget_show(col_arrows[column].ascend_pm);
+		gtk_clist_set_sort_column(clist, column);
+	}
+	gtk_clist_thaw(clist);
+
+	gtk_clist_sort(clist);
+}
+
+
+/****************************************************************************/
+static gint
+voip_calls_sort_column(GtkCList *clist, gconstpointer ptr1, gconstpointer ptr2)
+{
+	char *text1 = NULL;
+	char *text2 = NULL;
+	int i1, i2;
+
+	const GtkCListRow *row1 = (const GtkCListRow *) ptr1;
+	const GtkCListRow *row2 = (const GtkCListRow *) ptr2;
+
+	text1 = GTK_CELL_TEXT (row1->cell[clist->sort_column])->text;
+	text2 = GTK_CELL_TEXT (row2->cell[clist->sort_column])->text;
+
+	switch(clist->sort_column){
+	case 0:
+	case 1:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+		return strcmp (text1, text2);
+	case 6:
+		i1=atoi(text1);
+		i2=atoi(text2);
+		return i1-i2;
+	}
+	g_assert_not_reached();
+	return 0;
+}
+
+
+/****************************************************************************/
+/* INTERFACE                                                                */
+/****************************************************************************/
+
+static void voip_calls_dlg_create (void)
+{
+	GtkWidget *voip_calls_dlg_w;
+	GtkWidget *main_vb;
+	GtkWidget *scrolledwindow;
+	GtkWidget *hbuttonbox;
+	GtkWidget *bt_close;
+    GtkTooltips *tooltips = gtk_tooltips_new();
+
+	gchar *titles[NUM_COLS] =  {"Start Time", "Stop Time", "Initial Speaker", "From",  "To", "Protocol", "Packets", "State", "Comments"};
+	column_arrows *col_arrows;
+	GtkWidget *column_lb;
+	int i;
+
+    voip_calls_dlg_w=window_new(GTK_WINDOW_TOPLEVEL, "Ethereal: VoIP VoIP Calls");
+
+	gtk_window_set_default_size(GTK_WINDOW(voip_calls_dlg_w), 840, 350);
+
+	main_vb = gtk_vbox_new (FALSE, 0);
+	gtk_container_add(GTK_CONTAINER(voip_calls_dlg_w), main_vb);
+	gtk_container_set_border_width (GTK_CONTAINER (main_vb), 12);
+
+	top_label = gtk_label_new ("Detected 0 VoIP Calls. Selected 0 Calls.");
+	gtk_box_pack_start (GTK_BOX (main_vb), top_label, FALSE, FALSE, 8);
+
+	scrolledwindow = scrolled_window_new (NULL, NULL);
+	gtk_box_pack_start (GTK_BOX (main_vb), scrolledwindow, TRUE, TRUE, 0);
+
+	clist = gtk_clist_new (NUM_COLS);
+	gtk_container_add (GTK_CONTAINER (scrolledwindow), clist);
+
+	gtk_clist_set_column_width (GTK_CLIST (clist), 0, 60);
+	gtk_clist_set_column_width (GTK_CLIST (clist), 1, 60);
+	gtk_clist_set_column_width (GTK_CLIST (clist), 2, 80);
+	gtk_clist_set_column_width (GTK_CLIST (clist), 3, 130);
+	gtk_clist_set_column_width (GTK_CLIST (clist), 4, 130);
+	gtk_clist_set_column_width (GTK_CLIST (clist), 5, 50);
+	gtk_clist_set_column_width (GTK_CLIST (clist), 6, 45);
+	gtk_clist_set_column_width (GTK_CLIST (clist), 7, 60);
+	gtk_clist_set_column_width (GTK_CLIST (clist), 8, 100);
+
+	gtk_clist_set_column_justification(GTK_CLIST(clist), 0, GTK_JUSTIFY_LEFT);
+	gtk_clist_set_column_justification(GTK_CLIST(clist), 1, GTK_JUSTIFY_LEFT);
+	gtk_clist_set_column_justification(GTK_CLIST(clist), 2, GTK_JUSTIFY_LEFT);
+	gtk_clist_set_column_justification(GTK_CLIST(clist), 3, GTK_JUSTIFY_LEFT);
+	gtk_clist_set_column_justification(GTK_CLIST(clist), 4, GTK_JUSTIFY_LEFT);
+	gtk_clist_set_column_justification(GTK_CLIST(clist), 5, GTK_JUSTIFY_CENTER);
+	gtk_clist_set_column_justification(GTK_CLIST(clist), 6, GTK_JUSTIFY_CENTER);
+	gtk_clist_set_column_justification(GTK_CLIST(clist), 7, GTK_JUSTIFY_LEFT);
+	gtk_clist_set_column_justification(GTK_CLIST(clist), 8, GTK_JUSTIFY_LEFT);
+
+	gtk_clist_column_titles_show (GTK_CLIST (clist));
+
+	gtk_clist_set_compare_func(GTK_CLIST(clist), voip_calls_sort_column);
+	gtk_clist_set_sort_column(GTK_CLIST(clist), 0);
+	gtk_clist_set_sort_type(GTK_CLIST(clist), GTK_SORT_ASCENDING);
+
+	gtk_widget_show(voip_calls_dlg_w);
+
+	/* sort by column feature */
+	col_arrows = (column_arrows *) g_malloc(sizeof(column_arrows) * NUM_COLS);
+
+	for (i=0; i<NUM_COLS; i++) {
+		col_arrows[i].table = gtk_table_new(2, 2, FALSE);
+		gtk_table_set_col_spacings(GTK_TABLE(col_arrows[i].table), 5);
+		column_lb = gtk_label_new(titles[i]);
+		gtk_table_attach(GTK_TABLE(col_arrows[i].table), column_lb, 0, 1, 0, 2, GTK_SHRINK, GTK_SHRINK, 0, 0);
+		gtk_widget_show(column_lb);
+
+		col_arrows[i].ascend_pm = xpm_to_widget(clist_ascend_xpm);
+		gtk_table_attach(GTK_TABLE(col_arrows[i].table), col_arrows[i].ascend_pm, 1, 2, 1, 2, GTK_SHRINK, GTK_SHRINK, 0, 0);
+		col_arrows[i].descend_pm = xpm_to_widget(clist_descend_xpm);
+		gtk_table_attach(GTK_TABLE(col_arrows[i].table), col_arrows[i].descend_pm, 1, 2, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0);
+		/* make start time be the default sort order */
+		if (i == 0) {
+			gtk_widget_show(col_arrows[i].ascend_pm);
+		}
+		gtk_clist_set_column_widget(GTK_CLIST(clist), i, col_arrows[i].table);
+		gtk_widget_show(col_arrows[i].table);
+	}
+
+	SIGNAL_CONNECT(clist, "click-column", voip_calls_click_column_cb, col_arrows);
+
+	label_fwd = gtk_label_new (FWD_LABEL_TEXT);
+	gtk_box_pack_start (GTK_BOX (main_vb), label_fwd, FALSE, FALSE, 0);
+
+	status_label = gtk_label_new ("Total: Calls: 0   Start packets: 0   Completed calls: 0   Rejected calls: 0");
+	gtk_box_pack_start (GTK_BOX (main_vb), status_label, FALSE, FALSE, 8);
+
+        /* button row */
+	hbuttonbox = gtk_hbutton_box_new ();
+	gtk_box_pack_start (GTK_BOX (main_vb), hbuttonbox, FALSE, FALSE, 0);
+	gtk_button_box_set_layout (GTK_BUTTON_BOX (hbuttonbox), GTK_BUTTONBOX_SPREAD);
+	gtk_button_box_set_spacing (GTK_BUTTON_BOX (hbuttonbox), 30);
+
+	/*bt_unselect = gtk_button_new_with_label ("Unselect");
+	gtk_container_add (GTK_CONTAINER (hbuttonbox), bt_unselect);
+    gtk_tooltips_set_tip (tooltips, bt_unselect, "Unselect this conversation", NULL);*/
+
+	bt_filter = gtk_button_new_with_label ("Prepare filter");
+	gtk_container_add (GTK_CONTAINER (hbuttonbox), bt_filter);
+    gtk_tooltips_set_tip (tooltips, bt_filter, "Prepare a display filter of the selected conversation", NULL);
+
+    bt_graph = gtk_button_new_with_label("Graph");
+	gtk_container_add(GTK_CONTAINER(hbuttonbox), bt_graph);
+	gtk_widget_show(bt_graph);
+	SIGNAL_CONNECT(bt_graph, "clicked", on_graph_bt_clicked, NULL);
+
+	bt_close = BUTTON_NEW_FROM_STOCK(GTK_STOCK_CLOSE);
+	gtk_container_add (GTK_CONTAINER (hbuttonbox), bt_close);
+	GTK_WIDGET_SET_FLAGS(bt_close, GTK_CAN_DEFAULT);
+    gtk_tooltips_set_tip (tooltips, bt_close, "Close this dialog", NULL);
+
+	SIGNAL_CONNECT(clist, "select_row", voip_calls_on_select_row, NULL);
+	/*SIGNAL_CONNECT(bt_unselect, "clicked", voip_calls_on_unselect, NULL);*/
+	SIGNAL_CONNECT(bt_filter, "clicked", voip_calls_on_filter, NULL);
+
+	window_set_cancel_button(voip_calls_dlg_w, bt_close, window_cancel_button_cb);
+
+	SIGNAL_CONNECT(voip_calls_dlg_w, "delete_event", window_delete_event_cb, NULL);
+	SIGNAL_CONNECT(voip_calls_dlg_w, "destroy", voip_calls_on_destroy, NULL);
+
+	gtk_widget_show_all(voip_calls_dlg_w);
+	window_present(voip_calls_dlg_w);
+
+	voip_calls_on_unselect(NULL, NULL);
+
+	voip_calls_dlg = voip_calls_dlg_w;
+}
+
+
+/****************************************************************************/
+/* PUBLIC								    */
+/****************************************************************************/
+
+/****************************************************************************/
+/* update the contents of the dialog box clist */
+/* list: pointer to list of voip_calls_info_t* */
+
+void voip_calls_dlg_update(GList *list)
+{
+	gchar label_text[256];
+
+	if (voip_calls_dlg != NULL) {
+
+		voip_calls_remove_tap_listener();
+
+		/* Add the RTP streams info for the graph */
+		add_rtp_streams_graph();
+
+		gtk_clist_clear(GTK_CLIST(clist));
+		calls_nb = 0;
+		calls_ns = 0;
+        	g_snprintf(label_text, 256,
+        		"Total: Calls: %d   Start packets: %d   Completed calls: %d   Rejected calls: %d",
+				voip_calls_get_info()->ncalls,
+		        voip_calls_get_info()->start_packets, 
+				voip_calls_get_info()->completed_calls,
+				voip_calls_get_info()->rejected_calls);
+        	gtk_label_set(GTK_LABEL(status_label), label_text);
+
+		list = g_list_first(list);
+		while (list)
+		{
+			add_to_clist((voip_calls_info_t*)(list->data));
+			list = g_list_next(list);
+		}
+
+		g_snprintf(label_text, 256,
+	        "Detected %d VoIP %s. Selected %d %s.",
+	        calls_nb, 
+            plurality(calls_nb, "Call", "Calls"),
+			calls_ns,
+			plurality(calls_ns, "Call", "Calls"));
+		gtk_label_set(GTK_LABEL(top_label), label_text);
+
+		voip_calls_on_unselect(NULL, NULL);
+	}
+
+	last_list = list;
+}
+
+
+/****************************************************************************/
+/* update the contents of the dialog box clist */
+/* list: pointer to list of voip_calls_info_t* */
+void voip_calls_dlg_show(GList *list)
+{
+	if (voip_calls_dlg != NULL) {
+		/* There's already a dialog box; reactivate it. */
+		reactivate_window(voip_calls_dlg);
+		/* Another list since last call? */
+		if (list != last_list) {
+			voip_calls_dlg_update(list);
+		}
+	}
+	else {
+		/* Create and show the dialog box */
+		voip_calls_dlg_create();
+		voip_calls_dlg_update(list);
+	}
+}
+
+/* init function for tap */
+static void
+voip_calls_init_tap(char *dummy _U_)
+{
+	graph_analysis_data_init();
+
+	/* Clean up memory used by calls tap */
+	voip_calls_reset((voip_calls_tapinfo_t*) voip_calls_get_info());
+
+	/* Register the tap listener */
+	sip_calls_init_tap();
+	mtp3_calls_init_tap();
+	isup_calls_init_tap();
+	h225_calls_init_tap();
+	h245dg_calls_init_tap();
+	q931_calls_init_tap();
+	sdp_calls_init_tap();
+
+	/* Scan for VoIP calls calls (redissect all packets) */
+	retap_packets(&cfile);
+
+	/* Show the dialog box with the list of calls */
+	voip_calls_dlg_show(voip_calls_get_info()->strinfo_list);
+
+	/* Tap listener will be removed and cleaned up in voip_calls_on_destroy */
+	
+}
+
+
+/****************************************************************************/
+/* entry point when called via the GTK menu */
+void voip_calls_launch(GtkWidget *w _U_, gpointer data _U_)
+{
+
+	voip_calls_init_tap("");
+
+	/* init the Graph Analysys */
+	graph_analysis_data = graph_analysis_init();
+	graph_analysis_data->graph_info = voip_calls_get_info()->graph_analysis;
+
+}
+
+/****************************************************************************/
+void
+register_tap_listener_voip_calls_dlg(void)
+{
+	register_ethereal_tap("voip,calls",voip_calls_init_tap);
+	register_tap_menu_item("VoIP Calls...", REGISTER_TAP_GROUP_NONE,
+	    voip_calls_launch, NULL, NULL, NULL);
+	    
+}
Index: gtk/voip_calls_dlg.h
===================================================================
--- gtk/voip_calls_dlg.h	(revision 0)
+++ gtk/voip_calls_dlg.h	(revision 0)
@@ -0,0 +1,55 @@
+/* voip_calls_dlg.h
+ * VoIP conversations addition for ethereal
+ *
+ * $Id: voip_calls_dlg.h 12154 2004-09-30 19:49:48Z guy $
+ *
+ * Copyright 2004, Ericsson , Spain
+ * By Francisco Alcoba <francisco.alcoba@xxxxxxxxxxxx>
+ *
+ * based on h323_conversations_dlg.h
+ * Copyright 2004, Iskratel, Ltd, Kranj
+ * By Miha Jemec <m.jemec@xxxxxxxxxxx>
+ * 
+ * H323, RTP and Graph Support
+ * By Alejandro Vaquero, alejandro.vaquero@xxxxxxxxx
+ * Copyright 2005, Verso Technologies Inc.
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@xxxxxxxxxxxx>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation,  Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef VOIP_CALLS_DLG_H_INCLUDED
+#define VOIP_CALLS_DLG_H_INCLUDED
+
+#include <gtk/gtk.h>
+
+/**
+ * Create or reactivate the voip calls dialog box.
+ *
+ * @param list pointer to list of rtp_stream_info_t*
+ */
+void voip_calls_dlg_show(GList *list);
+
+/**
+ * Update the contents of the dialog box clist with that of list.
+ *
+ * @param list pointer to list of rtp_stream_info_t*
+ */
+void voip_calls_dlg_update(GList *list);
+
+#endif /* VOIP_CALLS_DLG_H_INCLUDED*/
Index: gtk/rtp_stream.c
===================================================================
--- gtk/rtp_stream.c	(revision 13162)
+++ gtk/rtp_stream.c	(working copy)
@@ -211,6 +211,8 @@
 	GList* list;
 	rtp_sample_t sample;
 
+	struct _rtp_conversation_info *p_conv_data = NULL;
+
 	/* gather infos on the stream this packet is part of */
 	COPY_ADDRESS(&(tmp_strinfo.src_addr), &(pinfo->src));
 	tmp_strinfo.src_port = pinfo->srcport;
@@ -238,9 +240,20 @@
 			tmp_strinfo.first_frame_num = pinfo->fd->num;
 			tmp_strinfo.start_sec = pinfo->fd->abs_secs;
 			tmp_strinfo.start_usec = pinfo->fd->abs_usecs;
+			tmp_strinfo.start_rel_sec = pinfo->fd->rel_secs;
+			tmp_strinfo.start_rel_usec = pinfo->fd->rel_usecs;
 			tmp_strinfo.tag_vlan_error = 0;
 			tmp_strinfo.tag_diffserv_error = 0;
 			tmp_strinfo.vlan_id = 0;
+			
+            /* Get the Setup frame number who set this RTP stream */
+
+            p_conv_data = p_get_proto_data(pinfo->fd, proto_get_id_by_filter_name("rtp"));
+            if (p_conv_data)
+				tmp_strinfo.setup_frame_number = p_conv_data->frame_number;
+            else
+                tmp_strinfo.setup_frame_number = 0xFFFFFFFF;
+
 			strinfo = g_malloc(sizeof(rtp_stream_info_t));
 			*strinfo = tmp_strinfo;  /* memberwise copy of struct */
 			tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
@@ -248,6 +261,8 @@
 
 		/* increment the packets counter for this stream */
 		++(strinfo->npackets);
+		strinfo->stop_rel_sec = pinfo->fd->rel_secs;
+		strinfo->stop_rel_usec = pinfo->fd->rel_usecs;
 
 		/* increment the packets counter of all streams */
 		++(tapinfo->npackets);
Index: gtk/rtp_stream.h
===================================================================
--- gtk/rtp_stream.h	(revision 13162)
+++ gtk/rtp_stream.h	(working copy)
@@ -65,10 +65,15 @@
 	guint32 npackets;
 
 	guint32 first_frame_num; /* frame number of first frame */
+	guint32 setup_frame_number; /* frame number of setup message */
 	/* start of recording (GMT) of this stream */
     guint32 start_sec;         /* seconds */
     guint32 start_usec;        /* microseconds */
 	gboolean tag_vlan_error;
+	guint32 start_rel_sec;         /* start stream rel seconds */
+	guint32 start_rel_usec;        /* start stream rel microseconds */
+	guint32 stop_rel_sec;         /* stop stream rel seconds */
+	guint32 stop_rel_usec;        /* stop stream rel microseconds */
 	gboolean tag_diffserv_error;
 	guint16 vlan_id;
 
Index: gtk/graph_analysis.c
===================================================================
--- gtk/graph_analysis.c	(revision 0)
+++ gtk/graph_analysis.c	(revision 0)
@@ -0,0 +1,1009 @@
+/* graph_analysis.c
+ * Graphic Analysis addition for ethereal
+ *
+ *
+ *
+ * Copyright 2004, Verso Technologies Inc.
+ * By Alejandro Vaquero <alejandrovaquero@xxxxxxxxx>
+ *
+ * based on rtp_analysis.c and io_stat
+ *
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@xxxxxxxxxxxx>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation,  Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "graph_analysis.h"
+
+#include <epan/epan_dissect.h>
+#include <epan/filesystem.h>
+
+#include "util.h"
+#include <epan/tap.h>
+#include "register.h"
+#include <epan/dissectors/packet-rtp.h>
+
+/* in /gtk ... */
+#include <gtk/gtk.h>
+#include "gtkglobals.h"
+
+#include "dlg_utils.h"
+#include "ui_util.h"
+#include "alert_box.h"
+#include "simple_dialog.h"
+#include "tap_menu.h"
+#include "main.h"
+#include "progress_dlg.h"
+#include "compat_macros.h"
+#include "../color.h"
+
+#include "image/clist_ascend.xpm"
+#include "image/clist_descend.xpm"
+
+#include <math.h>
+#include <fcntl.h>
+#include <string.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#ifdef HAVE_IO_H
+#include <io.h> /* open/close on win32 */
+#endif
+
+/* Win32 needs the O_BINARY flag for open() */
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+/****************************************************************************/
+
+
+#define OK_TEXT "[ Ok ]"
+#define PT_UNDEFINED -1
+
+
+#if GTK_MAJOR_VERSION < 2
+GtkRcStyle *rc_style;
+GdkColormap *colormap;
+#endif
+
+typedef const guint8 * ip_addr_p;
+
+
+/****************************************************************************/
+/* Reset the user_data structure */
+static void graph_analysis_reset(graph_analysis_data_t* user_data)
+{
+	int i;
+
+	user_data->num_nodes = 0;
+	user_data->num_items = 0;
+	for (i=0; i<MAX_NUM_NODES; i++){
+		user_data->nodes[i] = 0;
+	}
+	
+	user_data->dlg.first_node=0;
+	user_data->dlg.first_item=0;
+	user_data->dlg.left_x_border=0;
+	user_data->dlg.selected_item=0xFFFFFFFF;    /*not item selected */
+}
+
+/****************************************************************************/
+/* Reset the user_data structure */
+static void graph_analysis_init_dlg(graph_analysis_data_t* user_data)
+{
+    /* init dialog_graph */
+    user_data->dlg.needs_redraw=TRUE;
+    user_data->dlg.draw_area=NULL;
+    user_data->dlg.pixmap=NULL;
+    user_data->dlg.h_scrollbar=NULL;
+    user_data->dlg.h_scrollbar_adjustment=NULL;
+    user_data->dlg.v_scrollbar=NULL;
+    user_data->dlg.v_scrollbar_adjustment=NULL;
+    user_data->dlg.pixmap_width=600;
+    user_data->dlg.pixmap_height=400;
+	user_data->dlg.first_node=0;
+	user_data->dlg.first_item=0;
+	user_data->dlg.left_x_border=0;
+	user_data->dlg.selected_item=0xFFFFFFFF;    /*not item selected */
+	user_data->dlg.window=NULL;
+}
+
+/****************************************************************************/
+/* CALLBACKS */
+
+
+/****************************************************************************/
+/* close the dialog window and remove the tap listener */
+static void on_destroy(GtkWidget *win _U_, graph_analysis_data_t *user_data _U_)
+{
+
+	g_free(user_data);
+}
+
+
+/****************************************************************************/
+static void dialog_graph_set_title(graph_analysis_data_t* user_data)
+{
+	char            *title;
+	if (!user_data->dlg.window){
+		return;
+	}
+	title = g_strdup_printf("Ale");
+
+	gtk_window_set_title(GTK_WINDOW(user_data->dlg.window), title);
+	g_free(title);	
+}
+
+#define RIGHT_ARROW 1
+#define LEFT_ARROW 0
+#define WIDTH_ARROW 8
+#define HEIGHT_ARROW 6
+
+/****************************************************************************/
+static void draw_arrow(GdkDrawable *pixmap, GdkGC *gc, gint x, gint y, boolean direction)
+{
+	GdkPoint arrow_point[3];
+
+	arrow_point[0].x = x;
+	arrow_point[0].y = y-HEIGHT_ARROW/2;
+	if (direction == RIGHT_ARROW)
+		arrow_point[1].x = x+WIDTH_ARROW;
+	else
+		arrow_point[1].x = x-WIDTH_ARROW;
+	arrow_point[1].y = y;
+	arrow_point[2].x = x;
+	arrow_point[2].y = y+HEIGHT_ARROW/2;;
+
+	gdk_draw_polygon(pixmap, gc, TRUE, 
+		arrow_point, 3);
+}
+
+#define MAX_LABEL 50
+#define MAX_COMMENT 60
+#define ITEM_HEIGHT 20
+#define NODE_WIDTH 100
+#define TOP_Y_BORDER 40
+#define BOTTOM_Y_BORDER 0
+#define COMMENT_WIDTH 250
+
+/****************************************************************************/
+static void dialog_graph_draw(graph_analysis_data_t* user_data)
+{
+        guint32 i, last_item, first_item, last_node, first_node, display_items, display_nodes;
+		guint32 start_arrow, end_arrow, label_x, src_port_x, dst_port_x, arrow_width;
+        guint32 current_item;
+        guint32 left_x_border;
+        guint32 right_x_border;
+        guint32 top_y_border;
+        guint32 bottom_y_border;
+		graph_analysis_item_t *gai;
+		gboolean display_label;
+
+#if GTK_MAJOR_VERSION < 2
+        GdkFont *font;
+		FONT_TYPE *big_font;
+		FONT_TYPE *small_font;
+#else
+        PangoLayout  *layout;
+        PangoLayout  *big_layout;
+        PangoLayout  *small_layout;
+#endif
+        guint32 label_width, label_height;
+        guint32 draw_width, draw_height;
+        char label_string[MAX_COMMENT];
+		GList* list;
+
+        /* new variables */
+
+#if GTK_MAJOR_VERSION <2
+        font = user_data->dlg.draw_area->style->font;
+		big_font = gdk_font_load("-adobe-helvetica-bold-r-normal--12-120-75-75-p-70-iso8859-1");
+		small_font = gdk_font_load("-adobe-helvetica-bold-r-normal--10-120-75-75-p-70-iso8859-1");
+#endif
+        if(!user_data->dlg.needs_redraw){
+                return;
+        }
+        user_data->dlg.needs_redraw=FALSE;
+
+        /*
+         * Clear out old plot
+         */
+        gdk_draw_rectangle(user_data->dlg.pixmap,
+                           user_data->dlg.draw_area->style->white_gc,
+                           TRUE,
+                           0, 0,
+                           user_data->dlg.draw_area->allocation.width,
+                           user_data->dlg.draw_area->allocation.height);
+
+		/* Calculate the y border */
+        top_y_border=TOP_Y_BORDER;	/* to display the node IP address */
+        bottom_y_border=BOTTOM_Y_BORDER;
+
+        draw_height=user_data->dlg.pixmap_height-top_y_border-bottom_y_border;
+
+		first_item = user_data->dlg.first_item;
+		display_items = draw_height/ITEM_HEIGHT;
+		last_item = first_item+display_items-1;
+
+		/* get the items to display and fill the matrix array */
+		list = g_list_first(user_data->graph_info->list);
+		current_item = 0;
+		i = 0;
+		while (list)
+		{
+			gai = list->data;
+			if (gai->display){
+				if (current_item>=display_items) break;		/* the item is outside the display */
+				if (i>=first_item){
+					user_data->dlg.items[current_item].frame_num = gai->frame_num;
+					user_data->dlg.items[current_item].time = gai->time;
+					user_data->dlg.items[current_item].port_src = gai->port_src;
+					user_data->dlg.items[current_item].port_dst = gai->port_dst;
+					/* Add "..." if the length is 50 characters */
+					if (strlen(gai->frame_label) > 48) {
+						gai->frame_label[48] = '.';
+						gai->frame_label[47] = '.';
+						gai->frame_label[46] = '.';
+					}
+					user_data->dlg.items[current_item].frame_label = gai->frame_label;
+					user_data->dlg.items[current_item].comment = gai->comment;
+					user_data->dlg.items[current_item].conv_num = gai->conv_num;
+					user_data->dlg.items[current_item].src_node = gai->src_node;
+					user_data->dlg.items[current_item].dst_node = gai->dst_node;
+					user_data->dlg.items[current_item].line_style = gai->line_style;
+					current_item++;
+				}
+				i++;
+			}
+
+			list = g_list_next(list);
+		}
+		/* in case the windows is resized so we have to move the top item */
+		if ((first_item + display_items) > user_data->num_items){
+			if (display_items>user_data->num_items)
+				first_item=0;
+			else
+				first_item = user_data->num_items - display_items;
+		}
+		
+		/* in case there are less items than possible displayed */
+		display_items = current_item;
+		last_item = first_item+display_items-1;
+
+		/* if not items to display */
+		if (display_items == 0)	return;				
+
+
+		/* Calculate the x borders */
+		/* We use time from the last display item to calcultate the x left border */
+		g_snprintf(label_string, MAX_LABEL, "%.3f", user_data->dlg.items[display_items-1].time);
+#if GTK_MAJOR_VERSION < 2
+        label_width=gdk_string_width(font, label_string);
+        label_height=gdk_string_height(font, label_string);
+#else
+        layout = gtk_widget_create_pango_layout(user_data->dlg.draw_area, label_string);
+        big_layout = gtk_widget_create_pango_layout(user_data->dlg.draw_area, label_string);
+        small_layout = gtk_widget_create_pango_layout(user_data->dlg.draw_area, label_string);
+
+		pango_layout_set_font_description(big_layout, pango_font_description_from_string("Helvetica-Bold 8"));
+		pango_layout_set_font_description(small_layout, pango_font_description_from_string("Helvetica-Bold 7"));
+
+        pango_layout_get_pixel_size(layout, &label_width, &label_height);
+#endif
+        left_x_border=label_width+10;
+		user_data->dlg.left_x_border = left_x_border;
+
+        right_x_border=COMMENT_WIDTH;
+
+		/* Calculate the number of nodes to display */
+        draw_width=user_data->dlg.pixmap_width-right_x_border-left_x_border;
+		display_nodes = draw_width/NODE_WIDTH;
+		first_node = user_data->dlg.first_node;
+
+		/* in case the windows is resized so we have to move the left node */
+		if ((first_node + display_nodes) > user_data->num_nodes){
+			if (display_nodes>user_data->num_nodes) 
+				first_node=0;
+			else
+				first_node=user_data->num_nodes - display_nodes;
+		}
+
+		/* in case there are less nodes than possible displayed */
+		if (display_nodes>user_data->num_nodes) display_nodes=user_data->num_nodes;
+
+		last_node = first_node + display_nodes-1;
+
+		/* Paint the background items */ 
+		for (current_item=0; current_item<display_items; current_item++){
+			/* Paint background */
+	        gdk_draw_rectangle(user_data->dlg.pixmap,
+                           user_data->dlg.bg_gc[user_data->dlg.items[current_item].conv_num%MAX_NUM_COL_CONV],
+                           TRUE,
+                           left_x_border, 
+						   top_y_border+current_item*ITEM_HEIGHT,
+                           draw_width,
+                           ITEM_HEIGHT);
+		}
+
+
+		/* Draw the node names on top and the division lines */
+		for (i=0; i<display_nodes; i++){
+			/* draw the node IPs */
+			g_snprintf(label_string, MAX_LABEL, "%s",
+				ip_to_str((guint8 *)&(user_data->nodes[i+first_node])));
+#if GTK_MAJOR_VERSION < 2
+	        label_width=gdk_string_width(font, label_string);
+	        label_height=gdk_string_height(font, label_string);
+			gdk_draw_string(user_data->dlg.pixmap,
+                font,
+                user_data->dlg.draw_area->style->black_gc,
+                left_x_border+NODE_WIDTH/2-label_width/2+NODE_WIDTH*i,
+                top_y_border/2-label_height/2,
+                label_string);
+#else
+			pango_layout_set_text(layout, label_string, -1);
+	        pango_layout_get_pixel_size(layout, &label_width, &label_height);
+	        gdk_draw_layout(user_data->dlg.pixmap,
+                user_data->dlg.draw_area->style->black_gc,
+                left_x_border+NODE_WIDTH/2-label_width/2+NODE_WIDTH*i,
+                top_y_border/2-label_height/2,
+                layout);
+#endif		
+
+			/* draw the node division lines */
+			gdk_draw_line(user_data->dlg.pixmap, user_data->dlg.div_line_gc,
+				left_x_border+NODE_WIDTH/2+NODE_WIDTH*i,
+				top_y_border,
+				left_x_border+NODE_WIDTH/2+NODE_WIDTH*i,
+				user_data->dlg.pixmap_height-bottom_y_border);
+
+		}
+
+		/*
+		 * Draw the items 
+		 */
+
+
+		for (current_item=0; current_item<display_items; current_item++){
+			/* draw the time */
+			g_snprintf(label_string, MAX_LABEL, "%.3f", user_data->dlg.items[current_item].time);
+#if GTK_MAJOR_VERSION < 2
+	        label_width=gdk_string_width(font, label_string);
+	        label_height=gdk_string_height(font, label_string);
+			gdk_draw_string(user_data->dlg.pixmap,
+                font,
+                user_data->dlg.draw_area->style->black_gc,
+                left_x_border-label_width-4,
+                top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT/2+label_height/4,
+                label_string);
+#else
+			pango_layout_set_text(layout, label_string, -1);
+	        pango_layout_get_pixel_size(layout, &label_width, &label_height);
+	        gdk_draw_layout(user_data->dlg.pixmap,
+                user_data->dlg.draw_area->style->black_gc,
+                left_x_border-label_width-4,
+                top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT/2-label_height/2,
+                layout);
+#endif
+
+			/*draw the comments */
+			g_snprintf(label_string, MAX_COMMENT, "%s", user_data->dlg.items[current_item].comment);
+#if GTK_MAJOR_VERSION < 2
+			label_width=gdk_string_width(small_font, label_string);
+			label_height=gdk_string_height(small_font, label_string);
+			gdk_draw_string(user_data->dlg.pixmap,
+                small_font,
+                user_data->dlg.draw_area->style->black_gc,
+                user_data->dlg.pixmap_width-right_x_border+3,
+                top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT/2+label_height/4,
+                label_string);
+#else
+			pango_layout_set_text(small_layout, label_string, -1);
+			pango_layout_get_pixel_size(small_layout, &label_width, &label_height);
+	        gdk_draw_layout(user_data->dlg.pixmap,
+                user_data->dlg.draw_area->style->black_gc,
+                user_data->dlg.pixmap_width-right_x_border+3,
+                top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT/2-label_height/2,
+                small_layout);
+#endif
+			
+			/* draw the arrow an frame label*/
+			display_label = FALSE;
+			if (user_data->dlg.items[current_item].src_node>=first_node){
+				if (user_data->dlg.items[current_item].src_node<=last_node){
+					start_arrow = left_x_border+(user_data->dlg.items[current_item].src_node-first_node)*NODE_WIDTH+NODE_WIDTH/2;
+					display_label = TRUE;
+				} else {
+					start_arrow = user_data->dlg.pixmap_width - right_x_border;
+				}
+			} else {
+				start_arrow = left_x_border;
+			}
+
+			if (user_data->dlg.items[current_item].dst_node>=first_node){
+				if (user_data->dlg.items[current_item].dst_node<=last_node){
+					end_arrow = left_x_border+(user_data->dlg.items[current_item].dst_node-first_node)*NODE_WIDTH+NODE_WIDTH/2;
+					display_label = TRUE;
+				} else {
+					end_arrow = user_data->dlg.pixmap_width - right_x_border;
+				}
+			} else {
+				end_arrow = left_x_border;
+			}
+
+			if (start_arrow != end_arrow){
+				/* draw the arrow line */
+				gdk_draw_line(user_data->dlg.pixmap, user_data->dlg.draw_area->style->black_gc,
+					start_arrow,
+					top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT-7,
+					end_arrow,
+					top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT-7);
+
+				/* draw the additional line when line style is 2 pixels width */
+				if (user_data->dlg.items[current_item].line_style == 2){
+					gdk_draw_line(user_data->dlg.pixmap, user_data->dlg.draw_area->style->black_gc,
+						start_arrow,
+						top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT-6,
+						end_arrow,
+						top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT-6);
+				}					
+
+				/* draw the arrow */
+				if (start_arrow<end_arrow)
+					draw_arrow(user_data->dlg.pixmap, user_data->dlg.draw_area->style->black_gc, end_arrow-WIDTH_ARROW,top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT-7, RIGHT_ARROW);
+				else
+					draw_arrow(user_data->dlg.pixmap, user_data->dlg.draw_area->style->black_gc, end_arrow+WIDTH_ARROW,top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT-7, LEFT_ARROW);
+			}
+
+			/* draw the frame comment */
+			if (display_label){
+				g_snprintf(label_string, MAX_LABEL, "%s", user_data->dlg.items[current_item].frame_label);
+#if GTK_MAJOR_VERSION < 2
+				label_width=gdk_string_width(big_font, label_string);
+				label_height=gdk_string_height(big_font, label_string);
+#else
+				pango_layout_set_text(big_layout, label_string, -1);
+				pango_layout_get_pixel_size(big_layout, &label_width, &label_height);
+#endif
+
+				if (start_arrow<end_arrow){
+					arrow_width = end_arrow-start_arrow;
+					label_x = arrow_width/2+start_arrow;
+				}
+				else {
+					arrow_width = start_arrow-end_arrow;
+					label_x = arrow_width/2+end_arrow;
+				}
+
+				if (label_width>arrow_width) arrow_width = label_width;
+
+				if (left_x_border > (label_x-label_width/2)) label_x = left_x_border + label_width/2;
+
+				if ((user_data->dlg.pixmap_width - right_x_border) < (label_x+label_width/2)) label_x = user_data->dlg.pixmap_width - right_x_border - label_width/2;
+
+#if GTK_MAJOR_VERSION < 2
+				gdk_draw_string(user_data->dlg.pixmap,
+					big_font,
+					user_data->dlg.draw_area->style->black_gc,
+					label_x - label_width/2,
+					top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT/2+label_height/4-3,
+					label_string);
+#else
+				gdk_draw_layout(user_data->dlg.pixmap,
+					user_data->dlg.draw_area->style->black_gc,
+					label_x - label_width/2,
+					top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT/2-label_height/2-3,
+					big_layout);
+#endif
+
+				/* draw the source port number */
+				if ((start_arrow != left_x_border) && (start_arrow != (user_data->dlg.pixmap_width - right_x_border))){ 
+					g_snprintf(label_string, MAX_LABEL, "(%i)", user_data->dlg.items[current_item].port_src);
+#if GTK_MAJOR_VERSION < 2
+					label_width=gdk_string_width(small_font, label_string);
+					label_height=gdk_string_height(small_font, label_string);
+#else
+					pango_layout_set_text(small_layout, label_string, -1);
+					pango_layout_get_pixel_size(small_layout, &label_width, &label_height);
+#endif
+					if (start_arrow<end_arrow){
+						src_port_x = start_arrow - label_width - 2;
+					}
+					else {
+						src_port_x = start_arrow + 2;
+					}
+#if GTK_MAJOR_VERSION < 2
+					gdk_draw_string(user_data->dlg.pixmap,
+						small_font,
+						user_data->dlg.div_line_gc,
+						src_port_x,
+						top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT-2+label_height/4-2,
+						label_string);
+#else
+					gdk_draw_layout(user_data->dlg.pixmap,
+						user_data->dlg.div_line_gc,
+						src_port_x,
+						top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT-2-label_height/2-2,
+						small_layout);
+#endif
+				}
+
+				/* draw the destination port number */
+				if ((end_arrow != left_x_border) && (end_arrow != (user_data->dlg.pixmap_width - right_x_border))){ 
+					g_snprintf(label_string, MAX_LABEL, "(%i)", user_data->dlg.items[current_item].port_dst);
+#if GTK_MAJOR_VERSION < 2
+					label_width=gdk_string_width(small_font, label_string);
+					label_height=gdk_string_height(small_font, label_string);
+#else
+					pango_layout_set_text(small_layout, label_string, -1);
+					pango_layout_get_pixel_size(small_layout, &label_width, &label_height);
+#endif
+					if (start_arrow<end_arrow){
+						dst_port_x = end_arrow + 2;
+					}
+					else {
+						dst_port_x = end_arrow - label_width - 2;
+					}
+#if GTK_MAJOR_VERSION < 2
+					gdk_draw_string(user_data->dlg.pixmap,
+						small_font,
+						user_data->dlg.div_line_gc,
+						dst_port_x,
+						top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT-2+label_height/4-2,
+						label_string);
+#else
+					gdk_draw_layout(user_data->dlg.pixmap,
+						user_data->dlg.div_line_gc,
+						dst_port_x,
+						top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT-2-label_height/2-2,
+						small_layout);
+#endif
+				}
+
+			}
+		}
+
+#if GTK_MAJOR_VERSION >= 2
+        g_object_unref(G_OBJECT(layout));
+#endif
+
+		/* draw the border on the selected item */
+		if ( (user_data->dlg.selected_item != 0xFFFFFFFF) && ( (user_data->dlg.selected_item>=first_item) && (user_data->dlg.selected_item<=last_item) )){
+			gdk_draw_rectangle(user_data->dlg.pixmap, user_data->dlg.draw_area->style->black_gc,
+				FALSE,
+				left_x_border-1,
+				(user_data->dlg.selected_item-first_item)*ITEM_HEIGHT+TOP_Y_BORDER,
+				user_data->dlg.pixmap_width-COMMENT_WIDTH-left_x_border+1,
+				ITEM_HEIGHT);
+		}
+
+
+
+        gdk_draw_pixmap(user_data->dlg.draw_area->window,
+                        user_data->dlg.draw_area->style->fg_gc[GTK_WIDGET_STATE(user_data->dlg.draw_area)],
+                        user_data->dlg.pixmap,
+                        0, 0,
+                        0, 0,
+                        user_data->dlg.pixmap_width, user_data->dlg.pixmap_height);
+
+
+        /* update the h_scrollbar */
+        user_data->dlg.h_scrollbar_adjustment->upper=(gfloat) user_data->num_nodes-1;
+        user_data->dlg.h_scrollbar_adjustment->step_increment=1;
+        user_data->dlg.h_scrollbar_adjustment->page_increment=(gfloat) (last_node-first_node);
+        user_data->dlg.h_scrollbar_adjustment->page_size=(gfloat) (last_node-first_node);
+        user_data->dlg.h_scrollbar_adjustment->value=(gfloat) first_node;
+
+		gtk_adjustment_changed(user_data->dlg.h_scrollbar_adjustment);
+        gtk_adjustment_value_changed(user_data->dlg.h_scrollbar_adjustment);
+
+        /* update the v_scrollbar */
+        user_data->dlg.v_scrollbar_adjustment->upper=(gfloat) user_data->num_items-1;
+        user_data->dlg.v_scrollbar_adjustment->step_increment=1;
+        user_data->dlg.v_scrollbar_adjustment->page_increment=(gfloat) (last_item-first_item);
+        user_data->dlg.v_scrollbar_adjustment->page_size=(gfloat) (last_item-first_item);
+        user_data->dlg.v_scrollbar_adjustment->value=(gfloat) first_item;
+
+		gtk_adjustment_changed(user_data->dlg.v_scrollbar_adjustment);
+        gtk_adjustment_value_changed(user_data->dlg.v_scrollbar_adjustment);
+
+}
+
+/****************************************************************************/
+static void dialog_graph_redraw(graph_analysis_data_t* user_data)
+{
+        user_data->dlg.needs_redraw=TRUE;
+        dialog_graph_draw(user_data); 
+}
+
+/****************************************************************************/
+static gint quit(GtkWidget *widget, GdkEventExpose *event _U_)
+{
+        graph_analysis_data_t *user_data;
+
+        user_data=(graph_analysis_data_t *)OBJECT_GET_DATA(widget, "graph_analysis_data_t");
+
+		user_data->dlg.window = NULL;
+
+		user_data = NULL;
+        return TRUE;
+}
+
+/****************************************************************************/
+static gint button_press_event(GtkWidget *widget, GdkEventButton *event _U_)
+{
+        graph_analysis_data_t *user_data;
+		guint32 item;
+
+        user_data=(graph_analysis_data_t *)OBJECT_GET_DATA(widget, "graph_analysis_data_t");
+
+		if (event->type != GDK_BUTTON_PRESS) return TRUE;
+
+		if (event->y<TOP_Y_BORDER) return TRUE;
+
+		/* get the item clicked */
+		item = ((guint32)event->y - TOP_Y_BORDER) / ITEM_HEIGHT;
+		user_data->dlg.selected_item = item + user_data->dlg.first_item;
+
+		user_data->dlg.needs_redraw=TRUE;
+		dialog_graph_draw(user_data);
+
+		goto_frame(&cfile, user_data->dlg.items[item].frame_num);
+
+        return TRUE;
+}
+
+/****************************************************************************/
+static gint expose_event(GtkWidget *widget, GdkEventExpose *event)
+{
+	graph_analysis_data_t *user_data;
+
+	user_data=(graph_analysis_data_t *)OBJECT_GET_DATA(widget, "graph_analysis_data_t");
+        if(!user_data){
+                exit(10);
+        }
+
+
+        gdk_draw_pixmap(widget->window,
+                        widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
+                        user_data->dlg.pixmap,
+                        event->area.x, event->area.y,
+                        event->area.x, event->area.y,
+                        event->area.width, event->area.height);
+
+        return FALSE;
+}
+
+static const GdkColor COLOR_GRAY = {0, 0x7fff, 0x7fff, 0x7fff};
+
+/****************************************************************************/
+static gint configure_event(GtkWidget *widget, GdkEventConfigure *event _U_)
+{
+        graph_analysis_data_t *user_data;
+		int i;
+		GdkColor color_div_line = COLOR_GRAY;
+
+		static GdkColor col[MAX_NUM_COL_CONV] = {
+       		{0,     0x00FF, 0xFFFF, 0x00FF},
+        	{0,     0xFFFF, 0xFFFF, 0x00FF},
+        	{0,     0xFFFF, 0x00FF, 0x00FF},
+        	{0,     0xFFFF, 0x00FF, 0xFFFF},
+			{0,     0x00FF, 0x00FF, 0xFFFF},
+			{0,     0x00FF, 0xFFFF, 0xFFFF},
+			{0,     0xFFFF, 0x80FF, 0x00FF},
+			{0,     0x80FF, 0x00FF, 0xFFFF},
+			{0,     0x00FF, 0x80FF, 0xFFFF},
+			{0,     0xFFFF, 0x00FF, 0x80FF}
+		};
+
+        user_data=(graph_analysis_data_t *)OBJECT_GET_DATA(widget, "graph_analysis_data_t");
+
+        if(!user_data){
+                exit(10);
+        }
+
+        if(user_data->dlg.pixmap){
+                gdk_pixmap_unref(user_data->dlg.pixmap);
+                user_data->dlg.pixmap=NULL;
+        }
+
+        user_data->dlg.pixmap=gdk_pixmap_new(widget->window,
+                        widget->allocation.width,
+                        widget->allocation.height,
+                        -1);
+        user_data->dlg.pixmap_width=widget->allocation.width;
+        user_data->dlg.pixmap_height=widget->allocation.height;
+
+        gdk_draw_rectangle(user_data->dlg.pixmap,
+                        widget->style->white_gc,
+                        TRUE,
+                        0, 0,
+                        widget->allocation.width,
+                        widget->allocation.height);
+
+		/* create gc for division lines and set the line stype to dash*/
+		user_data->dlg.div_line_gc=gdk_gc_new(user_data->dlg.pixmap);
+		gdk_gc_set_line_attributes(user_data->dlg.div_line_gc, 1, GDK_LINE_ON_OFF_DASH, 0, 0);
+#if GTK_MAJOR_VERSION < 2
+        colormap = gtk_widget_get_colormap (widget);
+        if (!gdk_color_alloc (colormap, &color_div_line)){
+                     g_warning ("Couldn't allocate color");
+        }
+        gdk_gc_set_foreground(user_data->dlg.div_line_gc, &color_div_line);
+#else
+        gdk_gc_set_rgb_fg_color(user_data->dlg.div_line_gc, &color_div_line);
+#endif
+	
+		/* create gcs for the background items */
+
+		for (i=0; i<MAX_NUM_COL_CONV; i++){
+			user_data->dlg.bg_gc[i]=gdk_gc_new(user_data->dlg.pixmap);
+#if GTK_MAJOR_VERSION < 2
+			colormap = gtk_widget_get_colormap (widget);
+			if (!gdk_color_alloc (colormap, &col[i])){
+						 g_warning ("Couldn't allocate color");
+			}
+			gdk_gc_set_foreground(user_data->dlg.bg_gc[i], &col[i]);
+#else
+	        gdk_gc_set_rgb_fg_color(user_data->dlg.bg_gc[i], &col[i]);
+#endif
+		}
+
+	dialog_graph_redraw(user_data);
+        return TRUE;
+}
+
+/****************************************************************************/
+static gint h_scrollbar_changed(GtkWidget *widget _U_, gpointer data)
+{
+    graph_analysis_data_t *user_data=(graph_analysis_data_t *)data;
+
+	if ((user_data->dlg.first_node+user_data->dlg.h_scrollbar_adjustment->page_size+1 == user_data->num_nodes) 
+		&& (user_data->dlg.h_scrollbar_adjustment->value >= user_data->dlg.first_node ))
+		return TRUE;
+
+	if (user_data->dlg.first_node == (guint16) user_data->dlg.h_scrollbar_adjustment->value)
+		return TRUE;
+
+    user_data->dlg.first_node = (guint16) user_data->dlg.h_scrollbar_adjustment->value;
+
+	dialog_graph_redraw(user_data);
+    return TRUE;
+}
+
+/****************************************************************************/
+static gint v_scrollbar_changed(GtkWidget *widget _U_, gpointer data)
+{
+    graph_analysis_data_t *user_data=(graph_analysis_data_t *)data;
+	if ((user_data->dlg.first_item+user_data->dlg.v_scrollbar_adjustment->page_size+1 == user_data->num_items) 
+		&& (user_data->dlg.v_scrollbar_adjustment->value >= user_data->dlg.first_item ))
+		return TRUE;
+
+	if (user_data->dlg.first_item == user_data->dlg.v_scrollbar_adjustment->value)
+		return TRUE;
+		
+    user_data->dlg.first_item = (guint32) user_data->dlg.v_scrollbar_adjustment->value;
+
+	dialog_graph_redraw(user_data);
+    return TRUE;
+}
+
+/****************************************************************************/
+static void create_draw_area(graph_analysis_data_t* user_data, GtkWidget *box)
+{
+	    GtkWidget *vbox;
+        GtkWidget *hbox;
+
+        hbox=gtk_hbox_new(FALSE, 0);
+        gtk_widget_show(hbox);
+
+        vbox=gtk_vbox_new(FALSE, 0);
+        gtk_widget_show(vbox);
+
+
+        user_data->dlg.draw_area=gtk_drawing_area_new();
+        SIGNAL_CONNECT(user_data->dlg.draw_area, "destroy", quit, user_data);
+        OBJECT_SET_DATA(user_data->dlg.draw_area, "graph_analysis_data_t", user_data);
+
+        WIDGET_SET_SIZE(user_data->dlg.draw_area, user_data->dlg.pixmap_width, user_data->dlg.pixmap_height);
+
+        /* signals needed to handle backing pixmap */
+        SIGNAL_CONNECT(user_data->dlg.draw_area, "expose_event", expose_event, NULL);
+        SIGNAL_CONNECT(user_data->dlg.draw_area, "configure_event", configure_event, user_data);
+
+		gtk_widget_add_events (user_data->dlg.draw_area,
+			 GDK_BUTTON_PRESS_MASK);
+		SIGNAL_CONNECT(user_data->dlg.draw_area, "button_press_event", button_press_event, user_data);
+
+        gtk_widget_show(user_data->dlg.draw_area);
+        gtk_box_pack_start(GTK_BOX(vbox), user_data->dlg.draw_area, TRUE, TRUE, 0);
+
+        /* create the associated h_scrollbar */
+        user_data->dlg.h_scrollbar_adjustment=(GtkAdjustment *)gtk_adjustment_new(0,0,0,0,0,0);
+        user_data->dlg.h_scrollbar=gtk_hscrollbar_new(user_data->dlg.h_scrollbar_adjustment);
+        gtk_widget_show(user_data->dlg.h_scrollbar);
+        gtk_box_pack_end(GTK_BOX(vbox), user_data->dlg.h_scrollbar, FALSE, FALSE, 0);
+        SIGNAL_CONNECT(user_data->dlg.h_scrollbar_adjustment, "value_changed", h_scrollbar_changed, user_data);
+
+        gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 0);
+
+       /* create the associated v_scrollbar */
+        user_data->dlg.v_scrollbar_adjustment=(GtkAdjustment *)gtk_adjustment_new(0,0,0,0,0,0);
+        user_data->dlg.v_scrollbar=gtk_vscrollbar_new(user_data->dlg.v_scrollbar_adjustment);
+        gtk_widget_show(user_data->dlg.v_scrollbar);
+        gtk_box_pack_end(GTK_BOX(hbox), user_data->dlg.v_scrollbar, FALSE, FALSE, 0);
+		SIGNAL_CONNECT(user_data->dlg.v_scrollbar_adjustment, "value_changed", v_scrollbar_changed, user_data);
+
+        gtk_box_pack_start(GTK_BOX(box), hbox, TRUE, TRUE, 0);
+}
+
+
+/****************************************************************************/
+static void dialog_graph_create_window(graph_analysis_data_t* user_data)
+{
+        GtkWidget *vbox;
+        GtkWidget *hbox;
+    	GtkWidget *bt_close;
+		GtkWidget *label = NULL;
+
+        /* create the main window */
+        user_data->dlg.window=window_new(GTK_WINDOW_TOPLEVEL, "Graph Analysis");
+
+
+        vbox=gtk_vbox_new(FALSE, 0);
+        gtk_container_add(GTK_CONTAINER(user_data->dlg.window), vbox);
+        gtk_widget_show(vbox);
+
+        create_draw_area(user_data, vbox);
+
+	    hbox = dlg_button_row_new(GTK_STOCK_CLOSE, NULL);
+        gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+		gtk_widget_show(hbox);
+
+		bt_close = OBJECT_GET_DATA(hbox, GTK_STOCK_CLOSE);
+		window_set_cancel_button(user_data->dlg.window, bt_close, window_cancel_button_cb);
+
+		SIGNAL_CONNECT(user_data->dlg.window, "delete_event", window_delete_event_cb, NULL);
+
+	    gtk_widget_show(user_data->dlg.window);
+	    window_present(user_data->dlg.window);
+}
+
+/* Return the index array if the node is in the array. Return -1 if there is room in the array
+ * and Return -2 if the array is full
+ */
+/****************************************************************************/
+gint is_node_array(graph_analysis_data_t* user_data, guint32 node)
+{
+	int i;
+	for (i=0; i<MAX_NUM_NODES; i++){
+		if (user_data->nodes[i] == 0)	return -1;	/* it is not in the array */
+		if (user_data->nodes[i] == node) return i;	/* it is in the array */
+	}
+	return -2;		/* array full */
+}
+
+
+/* Get the nodes (IPs) from the list */
+/****************************************************************************/
+void get_nodes(graph_analysis_data_t* user_data)
+{
+	GList* list;
+	graph_analysis_item_t *gai;
+	gint index;
+
+	/* fill the node array */
+	list = g_list_first(user_data->graph_info->list);
+	while (list)
+	{
+		gai = list->data;
+		if (gai->display){
+			user_data->num_items++;
+			/* check source IP node */
+			index = is_node_array(user_data, gai->ip_src);
+			switch(index){
+				case -2: /* array full */
+					gai->src_node = NODE_OVERFLOW;
+					break;
+				case -1: /* not in array */
+					user_data->nodes[user_data->num_nodes] = gai->ip_src;
+					gai->src_node = user_data->num_nodes;
+					user_data->num_nodes++;
+					break;
+				default: /* it is in the array, just update the src_node */
+					gai->src_node = (guint16)index;
+			}
+
+			/* check destination  IP node */
+			index = is_node_array(user_data, gai->ip_dst);
+			switch(index){
+				case -2: /* array full */
+					gai->dst_node = NODE_OVERFLOW;
+					break;
+				case -1: /* not in array */
+					user_data->nodes[user_data->num_nodes] = gai->ip_dst;
+					gai->dst_node = user_data->num_nodes;
+					user_data->num_nodes++;
+					break;
+				default: /* it is in the array, just update the dst_node */
+					gai->dst_node = (guint16)index;
+			}
+		}
+
+		list = g_list_next(list);
+	}
+}
+
+/****************************************************************************/
+/* XXX only handles IPv4, should add IPv6 support */
+graph_analysis_data_t* graph_analysis_init()
+{
+	graph_analysis_data_t* user_data;
+	/* init */
+	user_data = g_malloc(sizeof(graph_analysis_data_t));
+
+	/* init user_data */
+	graph_analysis_init_dlg(user_data);
+
+	return user_data;
+}
+
+/****************************************************************************/
+void graph_analysis_create(graph_analysis_data_t* user_data)
+{
+	/* reset the data */
+	graph_analysis_reset(user_data);
+
+	/* get nodes (each node is an IP address) */
+	get_nodes(user_data);
+
+	/* create the graph windows */
+	dialog_graph_create_window(user_data);
+
+	/* redraw the graph */
+	dialog_graph_redraw(user_data); 
+
+	return;
+}
+
+/****************************************************************************/
+void graph_analysis_update(graph_analysis_data_t* user_data)
+{
+	/* reset the data */
+	graph_analysis_reset(user_data);
+
+	/* get nodes (each node is an IP address) */
+	get_nodes(user_data);
+
+	/* redraw the graph */
+	dialog_graph_redraw(user_data); 
+
+    window_present(user_data->dlg.window);
+	return;
+}
Index: gtk/graph_analysis.h
===================================================================
--- gtk/graph_analysis.h	(revision 0)
+++ gtk/graph_analysis.h	(revision 0)
@@ -0,0 +1,121 @@
+/* graph_analysis.h
+ * Graphic Analysis addition for ethereal
+ *
+ *
+ *
+ * Copyright 2004, Verso Technologies Inc.
+ * By Alejandro Vaquero <alejandrovaquero@xxxxxxxxx>
+ *
+ * based on rtp_analysis.c and io_stat
+ *
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@xxxxxxxxxxxx>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation,  Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef GRAPH_ANALYSIS_H_INCLUDED
+#define GRAPH_ANALYSIS_H_INCLUDED
+
+#include <glib.h>
+#include <gtk/gtk.h>
+#include "gtkglobals.h"
+
+#define MAX_NUM_NODES 10
+
+/* defines an entry in for the graph analysis */
+typedef struct _graph_analysis_item {
+	guint32 frame_num;			/* frame number used to "go to" that frame */
+	double time;				/* frame time */
+	guint32 ip_src;				/* XXX we currently support only IP v4 */
+	guint16 port_src;
+	guint32 ip_dst;				
+	guint16 port_dst;
+	gchar *frame_label;			/* the label on top of the arrow */
+	gchar *comment;				/* a comment that appears at the left of the graph */
+	guint16 conv_num;			/* the conversation number, each conversation will be colored */
+	gboolean display;			/* indicate if the packet is displayed or not in the graph */
+	guint16 src_node;			/* this is used by graph_analysis.c to identify the node */
+	guint16 dst_node;			/* a node is an IP address that will be displayed in columns */
+	guint16 line_style;			/* the arrow line width in pixels*/
+} graph_analysis_item_t;
+
+/* defines the graph analysis structure */
+typedef struct _graph_analysis_info {
+	int     nconv;       /* number of conversations in the list */
+	GList*  list;   /* list with the graph analysis items */
+} graph_analysis_info_t;
+
+/* max number of nodes to display, each node will be an IP address */
+#define MAX_NUM_COL_CONV 10
+#define NODE_OVERFLOW MAX_NUM_NODES+1
+#define NUM_DISPLAY_ITEMS 1000
+
+typedef struct _display_items {
+	guint32 frame_num;			/* frame number used to "go to" that frame */
+	double time;				/* frame time */
+	guint16 port_src;
+	guint16 port_dst;
+	gchar *frame_label;			/* the label on top of the arrow */
+	gchar *comment;				/* a comment that appears at the left of the graph */
+	guint16 conv_num;			/* the conversation number, each conversation will be colored */
+	guint16 src_node;			/* this is used by graph_analysis.c to identify the node */
+	guint16 dst_node;			/* a node is an IP address that will be displayed in columns */
+	guint16 line_style;			/* the arrow line width in pixels*/
+} display_items_t;
+
+typedef struct _dialog_data_t {
+	GtkWidget *window;
+	gboolean needs_redraw;
+	gint selected_row;
+    GtkWidget *draw_area;
+    GdkPixmap *pixmap;
+    GtkAdjustment *h_scrollbar_adjustment;
+    GtkWidget *h_scrollbar;
+	GtkWidget *v_scrollbar;
+	GtkAdjustment *v_scrollbar_adjustment;
+	GdkGC *div_line_gc;
+	GdkGC *bg_gc[MAX_NUM_COL_CONV];
+    int pixmap_width;
+    int pixmap_height;
+	guint16 first_node;			/* the first node on the left to show in the screen */
+	guint32	first_item;			/* the first item (row) to show from the top */
+	guint32	selected_item;		/* the selected item */
+	display_items_t items[NUM_DISPLAY_ITEMS];
+    guint32 left_x_border;
+} dialog_data_t;
+
+
+
+/* structure that holds general information and the dialog */
+typedef struct _graph_analysis_data_t {
+	/* graphic data */
+	graph_analysis_info_t *graph_info;
+
+	/* dialog associated data */
+	dialog_data_t dlg;
+	guint32 nodes[MAX_NUM_NODES];
+	guint32 num_nodes;
+	guint32 num_items;
+} graph_analysis_data_t;
+
+graph_analysis_data_t* graph_analysis_init();
+void graph_analysis_create(graph_analysis_data_t* user_data);
+void graph_analysis_update(graph_analysis_data_t* user_data);
+
+
+#endif /*GRAPH_ANALYSIS_H_INCLUDED*/
Index: gtk/Makefile.common
===================================================================
--- gtk/Makefile.common	(revision 13162)
+++ gtk/Makefile.common	(working copy)
@@ -84,6 +84,7 @@
 	text_page.c	\
 	toolbar.c	\
 	ui_util.c \
+	voip_calls.c \
 	webbrowser.c
 
 
@@ -102,6 +103,7 @@
 	conversations_wlan.c	\
 	dcerpc_stat.c	\
 	fc_stat.c	\
+	graph_analysis.c \
 	gsm_a_stat.c	\
 	gsm_map_stat.c	\
 	gsm_map_summary.c	\
@@ -131,4 +133,5 @@
 	sip_stat.c	\
 	smb_stat.c	\
 	tcp_graph.c	\
+	voip_calls_dlg.c \
 	wsp_stat.c
Index: gtk/voip_calls.c
===================================================================
--- gtk/voip_calls.c	(revision 0)
+++ gtk/voip_calls.c	(revision 0)
@@ -0,0 +1,1312 @@
+/* voip_calls.c
+ * VoIP calls summary addition for ethereal
+ *
+ * $Id: voip_calls.c 12179 2004-10-01 22:09:38Z guy $
+ *
+ * Copyright 2004, Ericsson, Spain
+ * By Francisco Alcoba <francisco.alcoba@xxxxxxxxxxxx>
+ *
+ * based on h323_calls.c
+ * Copyright 2004, Iskratel, Ltd, Kranj
+ * By Miha Jemec <m.jemec@xxxxxxxxxxx>
+ * 
+ * H323, RTP and Graph Support
+ * By Alejandro Vaquero, alejandro.vaquero@xxxxxxxxx
+ * Copyright 2005, Verso Technologies Inc.
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@xxxxxxxxxxxx>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation,	Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "graph_analysis.h"
+#include "voip_calls.h"
+#include "voip_calls_dlg.h"
+#include "rtp_stream.h"
+
+#include "globals.h"
+
+#include <epan/tap.h>
+#include <epan/dissectors/packet-sip.h>
+#include <epan/dissectors/packet-mtp3.h>
+#include <epan/dissectors/packet-isup.h>
+#include <epan/dissectors/packet-h225.h>
+#include <epan/dissectors/packet-h245.h>
+#include <epan/dissectors/packet-q931.h>
+#include <epan/dissectors/packet-sdp.h>
+#include <epan/dissectors/packet-rtp.h>
+#include "rtp_pt.h"
+
+#include "alert_box.h"
+#include "simple_dialog.h"
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#include <string.h>
+
+
+char *voip_call_state_name[6]={
+	"CALL SETUP",
+	"IN CALL",
+	"CANCELLED",
+	"COMPLETED",
+	"REJECTED",
+	"UNKNOWN"
+	};
+
+/* defines whether we can consider the call active */
+char *voip_protocol_name[3]={
+	"SIP",
+	"ISUP",
+	"H323"
+	};
+
+
+
+/****************************************************************************/
+/* the one and only global voip_calls_tapinfo_t structure */
+static voip_calls_tapinfo_t the_tapinfo_struct =
+	{0, NULL, 0, NULL, 0, 0, 0, 0, NULL};
+
+/* static voip_calls_tapinfo_t the_tapinfo_struct;
+*/
+
+/****************************************************************************/
+/* when there is a [re]reading of packet's */
+void voip_calls_reset(voip_calls_tapinfo_t *tapinfo)
+{
+	voip_calls_info_t *strinfo;
+	sip_calls_info_t *tmp_sipinfo;
+	h323_calls_info_t *tmp_h323info;
+
+	graph_analysis_item_t *graph_item;
+
+	GList* list;
+	GList* list2;
+
+	/* free the data items first */
+	list = g_list_first(tapinfo->strinfo_list);
+	while (list)
+	{
+		strinfo = list->data;
+		g_free(strinfo->from_identity);
+		g_free(strinfo->to_identity);
+		if (strinfo->protocol == VOIP_SIP){
+			tmp_sipinfo = strinfo->prot_info;
+			g_free(tmp_sipinfo->call_identifier);
+		}
+		if (strinfo->protocol == VOIP_H323){
+			tmp_h323info = strinfo->prot_info;
+			g_free(tmp_h323info->guid);
+			/* free the H245 list address */
+			list2 = g_list_first(tmp_h323info->h245_list);
+			while (list2)
+			{
+				g_free(list2->data);
+				list2 = g_list_next(list2);
+			}
+			g_list_free(tmp_h323info->h245_list);
+			tmp_h323info->h245_list = NULL;
+		}
+		g_free(strinfo->prot_info);
+
+		g_free(list->data);
+		list = g_list_next(list);
+	}
+	g_list_free(tapinfo->strinfo_list);
+	tapinfo->strinfo_list = NULL;
+	tapinfo->ncalls = 0;
+	tapinfo->npackets = 0;
+	tapinfo->start_packets = 0;
+    tapinfo->completed_calls = 0;
+    tapinfo->rejected_calls = 0;
+
+	/* free the graph data items first */
+	list = g_list_first(tapinfo->graph_analysis->list);
+	while (list)
+	{
+		graph_item = list->data;
+		g_free(graph_item->frame_label);
+		g_free(graph_item->comment);
+		g_free(list->data);
+		list = g_list_next(list);
+	}
+	g_list_free(tapinfo->graph_analysis->list);
+	tapinfo->graph_analysis->nconv = 0;
+	tapinfo->graph_analysis->list = NULL;
+
+	++(tapinfo->launch_count);
+
+	return;
+}
+
+/****************************************************************************/
+void graph_analysis_data_init(){
+	the_tapinfo_struct.graph_analysis = g_malloc(sizeof(graph_analysis_info_t));
+	the_tapinfo_struct.graph_analysis->nconv = 0;
+	the_tapinfo_struct.graph_analysis->list = NULL;
+
+}
+
+/****************************************************************************/
+/* Add the RTP streams into the graph data */
+void add_rtp_streams_graph()
+{
+	rtp_stream_info_t *strinfo;
+	GList *strinfo_list;
+	guint nfound;
+	guint item;
+	GList* voip_calls_graph_list;
+	graph_analysis_item_t *gai;
+	graph_analysis_item_t *new_gai;
+	guint16 conv_num;
+	guint32 duration;
+
+	/* Scan for rtpstream */
+	rtpstream_scan();
+
+	/* assigne the RTP streams to calls */
+	nfound = 0;
+	strinfo_list = g_list_first(rtpstream_get_info()->strinfo_list);
+	while (strinfo_list)
+	{
+		strinfo = (rtp_stream_info_t*)(strinfo_list->data);
+
+		/* look in the voip calls graph list if there is a match for this RTP stream */
+		voip_calls_graph_list = g_list_first(the_tapinfo_struct.graph_analysis->list);
+		item = 0;
+		while (voip_calls_graph_list)
+		{			
+			gai = voip_calls_graph_list->data;
+			conv_num = gai->conv_num;
+			if (strinfo->setup_frame_number == gai->frame_num){
+				while(voip_calls_graph_list){
+					gai = voip_calls_graph_list->data;
+					/* add the RTP item to the graph */
+					if (strinfo->first_frame_num<gai->frame_num){
+						new_gai = g_malloc(sizeof(graph_analysis_item_t));
+						new_gai->frame_num = strinfo->first_frame_num;
+						new_gai->time = (double)strinfo->start_rel_sec + (double)strinfo->start_rel_usec/1000000;
+						g_memmove(&new_gai->ip_src, strinfo->src_addr.data, 4);
+						g_memmove(&new_gai->ip_dst, strinfo->dest_addr.data, 4);
+						new_gai->port_src = strinfo->src_port;
+						new_gai->port_dst = strinfo->dest_port;
+						duration = (strinfo->stop_rel_sec*1000000 + strinfo->stop_rel_usec) - (strinfo->start_rel_sec*1000000 + strinfo->start_rel_usec);
+						new_gai->frame_label = g_strdup_printf("RTP (%s)", val_to_str(strinfo->pt, rtp_payload_type_short_vals, "%u"));
+						new_gai->comment = g_strdup_printf("RTP Num packets:%d  Duration:%d.%03ds ssrc:%d", strinfo->npackets, duration/1000000,(duration%1000000)/1000, strinfo->ssrc);
+						new_gai->conv_num = conv_num;
+						new_gai->display=FALSE;
+						new_gai->line_style = 2;  /* the arrow line will be 2 pixels width */
+						the_tapinfo_struct.graph_analysis->list = g_list_insert(the_tapinfo_struct.graph_analysis->list, new_gai, item);
+						
+						break;
+					}
+					voip_calls_graph_list = g_list_next(voip_calls_graph_list);
+					item++;
+				}
+				break;
+			}
+			voip_calls_graph_list = g_list_next(voip_calls_graph_list);
+			item++;
+		}
+		strinfo_list = g_list_next(strinfo_list);
+	}
+}
+
+/****************************************************************************/
+/* Add a new item into the graph */
+int add_to_graph(voip_calls_tapinfo_t *tapinfo _U_, packet_info *pinfo, gchar *frame_label, gchar *comment, guint16 call_num)
+{
+	graph_analysis_item_t *gai;
+
+	gai = g_malloc(sizeof(graph_analysis_item_t));
+	gai->frame_num = pinfo->fd->num;
+	gai->time= (double)pinfo->fd->rel_secs + (double) pinfo->fd->rel_usecs/1000000;
+	g_memmove(&gai->ip_src, pinfo->src.data, 4);
+	g_memmove(&gai->ip_dst, pinfo->dst.data, 4);
+	gai->port_src=pinfo->srcport;
+	gai->port_dst=pinfo->destport;
+	if (frame_label != NULL)
+		gai->frame_label = g_strdup(frame_label);
+	else
+		gai->frame_label = g_strdup("");
+
+	if (comment != NULL)
+		gai->comment = g_strdup(comment);
+	else
+		gai->comment = g_strdup("");
+	gai->conv_num=call_num;
+	gai->line_style=1;
+	gai->display=FALSE;
+
+	tapinfo->graph_analysis->list = g_list_append(tapinfo->graph_analysis->list, gai);
+
+	return 1;
+
+}
+
+/****************************************************************************/
+/* Append str to frame_label and comment in a graph item */
+/* return 0 if the frame_num is not in the graph list */
+int append_to_frame_graph(voip_calls_tapinfo_t *tapinfo _U_, guint32 frame_num, gchar *new_frame_label, gchar *new_comment)
+{
+	graph_analysis_item_t *gai;
+	GList* list;
+	gchar *tmp_str = NULL;
+	gchar *tmp_str2 = NULL;
+
+	list = g_list_first(tapinfo->graph_analysis->list);
+	while (list)
+	{
+		gai = list->data;
+		if (gai->frame_num == frame_num){
+			tmp_str = gai->frame_label;
+			tmp_str2 = gai->comment;
+
+			if (new_frame_label != NULL){
+				gai->frame_label = g_strdup_printf("%s %s", gai->frame_label, new_frame_label);
+				g_free(tmp_str);
+			}
+
+
+			if (new_comment != NULL){
+				gai->comment = g_strdup_printf("%s %s", gai->comment, new_comment);
+				g_free(tmp_str2);
+			}
+			break;
+		}
+		list = g_list_next (list);
+	}
+	if (tmp_str == NULL) return 0;		/* it is not in the list */
+	return 1;
+
+}
+
+/****************************************************************************/
+/* ***************************TAP for SIP **********************************/
+/****************************************************************************/
+
+/****************************************************************************/
+/* whenever a SIP packet is seen by the tap listener */
+int SIPcalls_packet(voip_calls_tapinfo_t *tapinfo _U_, packet_info *pinfo, epan_dissect_t *edt _U_, void *SIPinfo)
+{
+
+	/* we just take note of the ISUP data here; when we receive the MTP3 part everything will
+	   be compared with existing calls */
+
+	voip_calls_info_t *tmp_listinfo;
+	voip_calls_info_t *strinfo = NULL;
+	sip_calls_info_t *tmp_sipinfo;
+	GList* list;
+	guint32 tmp_src, tmp_dst;
+	gchar *frame_label = NULL;
+	gchar *comment = NULL;
+
+	sip_info_value_t *pi = SIPinfo;
+
+	/* do not consider packets without call_id */
+	if (pi->tap_call_id ==NULL){
+		return 0;
+	}
+
+	/* check wether we already have a call with these parameters in the list */
+	list = g_list_first(tapinfo->strinfo_list);
+	while (list)
+	{
+		tmp_listinfo=list->data;
+		if (tmp_listinfo->protocol == VOIP_SIP){
+			tmp_sipinfo = tmp_listinfo->prot_info;
+			if (strcmp(tmp_sipinfo->call_identifier,pi->tap_call_id)==0){
+				strinfo = (voip_calls_info_t*)(list->data);
+				break;
+			}
+		}
+		list = g_list_next (list);
+	}
+
+	/* not in the list? then create a new entry if the message is INVITE -i.e. if this session is a call*/
+	if ((strinfo==NULL) &&(pi->request_method!=NULL)){
+		if (strcmp(pi->request_method,"INVITE")==0){
+			strinfo = g_malloc(sizeof(voip_calls_info_t));
+			strinfo->call_active_state = VOIP_ACTIVE;
+			strinfo->call_state = VOIP_CALL_SETUP;
+			strinfo->from_identity=g_strdup(pi->tap_from_addr);
+			strinfo->to_identity=g_strdup(pi->tap_to_addr);
+			g_memmove(&(strinfo->initial_speaker), pinfo->src.data, 4);
+			strinfo->first_frame_num=pinfo->fd->num;
+			strinfo->selected=FALSE;
+			strinfo->start_sec=pinfo->fd->rel_secs;
+			strinfo->start_usec=pinfo->fd->rel_usecs;
+			strinfo->protocol=VOIP_SIP;
+			strinfo->prot_info=g_malloc(sizeof(sip_calls_info_t));
+			tmp_sipinfo=strinfo->prot_info;
+			tmp_sipinfo->call_identifier=strdup(pi->tap_call_id);
+			tmp_sipinfo->sip_state=SIP_INVITE_SENT;
+			tmp_sipinfo->invite_cseq=pi->tap_cseq_number;
+			strinfo->npackets = 0;
+			strinfo->call_num = tapinfo->ncalls++;
+			tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
+		}
+	}
+
+	g_free(pi->tap_from_addr);
+	g_free(pi->tap_to_addr);
+	g_free(pi->tap_call_id);
+
+	if (strinfo!=NULL){
+
+		/* let's analyze the call state */
+
+		g_memmove(&(tmp_src), pinfo->src.data, 4);
+		g_memmove(&(tmp_dst), pinfo->dst.data, 4);
+		
+		if (pi->request_method == NULL){
+			frame_label = g_strdup_printf("%d %s", pi->response_code, pi->reason_phrase );
+			comment = g_strdup_printf("SIP Status");
+
+			if ((pi->tap_cseq_number == tmp_sipinfo->invite_cseq)&&(tmp_dst==strinfo->initial_speaker)){
+				if ((pi->response_code > 199) && (pi->response_code<300) && (tmp_sipinfo->sip_state == SIP_INVITE_SENT)){
+					tmp_sipinfo->sip_state = SIP_200_REC;
+				}
+				else if ((pi->response_code>299)&&(tmp_sipinfo->sip_state == SIP_INVITE_SENT)){
+					strinfo->call_state = VOIP_REJECTED;
+					tapinfo->rejected_calls++;
+				}
+			}
+
+		}
+		else{
+			frame_label = g_strdup(pi->request_method);
+
+			if ((strcmp(pi->request_method,"INVITE")==0)&&(tmp_src == strinfo->initial_speaker)){
+				tmp_sipinfo->invite_cseq = pi->tap_cseq_number;
+				comment = g_strdup_printf("SIP From: %s To:%s", strinfo->from_identity, strinfo->to_identity);
+			}
+			else if ((strcmp(pi->request_method,"ACK")==0)&&(pi->tap_cseq_number == tmp_sipinfo->invite_cseq)
+				&&(tmp_src == strinfo->initial_speaker)&&(tmp_sipinfo->sip_state==SIP_200_REC)){
+				strinfo->call_state = VOIP_IN_CALL;
+				comment = g_strdup_printf("SIP Request");
+			}
+			else if (strcmp(pi->request_method,"BYE")==0){
+				strinfo->call_state = VOIP_COMPLETED;
+				tapinfo->completed_calls++;
+				comment = g_strdup_printf("SIP Request");
+			}
+			else if ((strcmp(pi->request_method,"CANCEL")==0)&&(pi->tap_cseq_number == tmp_sipinfo->invite_cseq)
+				&&(tmp_src == strinfo->initial_speaker)&&(strinfo->call_state==VOIP_CALL_SETUP)){
+				strinfo->call_state = VOIP_CANCELLED;
+				tmp_sipinfo->sip_state = SIP_CANCEL_SENT;
+				comment = g_strdup_printf("SIP Request");
+			} else {
+				comment = g_strdup_printf("SIP Request");
+			}
+		}
+
+		strinfo->stop_sec=pinfo->fd->rel_secs;
+		strinfo->stop_usec=pinfo->fd->rel_usecs;
+		strinfo->last_frame_num=pinfo->fd->num;
+		++(strinfo->npackets);
+		/* increment the packets counter of all calls */
+		++(tapinfo->npackets);
+
+		/* add to the graph */
+		add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num);  
+		g_free(comment);
+		g_free(frame_label);
+	}
+	return 1;  /* refresh output */
+}
+
+
+/****************************************************************************/
+const voip_calls_tapinfo_t* voip_calls_get_info(void)
+{
+	return &the_tapinfo_struct;
+}
+
+
+/****************************************************************************/
+/* TAP INTERFACE */
+/****************************************************************************/
+static gboolean have_SIP_tap_listener=FALSE;
+/****************************************************************************/
+void
+sip_calls_init_tap(void)
+{
+	GString *error_string;
+
+	if(have_SIP_tap_listener==FALSE)
+	{
+		/* don't register tap listener, if we have it already */
+		error_string = register_tap_listener("sip", &the_tapinfo_struct, NULL,
+			NULL, (void*)SIPcalls_packet, NULL);
+		if (error_string != NULL) {
+			simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+				      error_string->str);
+			g_string_free(error_string, TRUE);
+			exit(1);
+		}
+		have_SIP_tap_listener=TRUE;
+	}
+}
+
+
+
+/* XXX just copied from gtk/rpc_stat.c */
+void protect_thread_critical_region(void);
+void unprotect_thread_critical_region(void);
+
+/****************************************************************************/
+void
+remove_tap_listener_sip_calls(void)
+{
+	protect_thread_critical_region();
+	remove_tap_listener(&the_tapinfo_struct);
+	unprotect_thread_critical_region();
+
+	have_SIP_tap_listener=FALSE;
+}
+
+/****************************************************************************/
+/* ***************************TAP for ISUP **********************************/
+/****************************************************************************/
+
+static gchar		isup_called_number[255], isup_calling_number[255];
+static guint16		isup_cic;
+static guint8		isup_message_type;
+
+/****************************************************************************/
+/* whenever a isup_ packet is seen by the tap listener */
+int isup_calls_packet(voip_calls_tapinfo_t *tapinfo _U_, packet_info *pinfo, epan_dissect_t *edt _U_, void *isup_info _U_)
+{
+
+	isup_tap_rec_t *pi = isup_info;
+
+	if (pi->calling_number!=NULL){
+		strcpy(isup_calling_number, pi->calling_number);
+	}
+	if (pi->called_number!=NULL){
+		strcpy(isup_called_number, pi->called_number);
+	}
+	isup_message_type = pi->message_type;
+	isup_cic = pinfo->circuit_id;
+
+	return 0;
+}
+
+/****************************************************************************/
+
+static gboolean have_isup_tap_listener=FALSE;
+
+void
+isup_calls_init_tap(void)
+{
+	GString *error_string;
+
+
+	if(have_isup_tap_listener==FALSE)
+	{
+		error_string = register_tap_listener("isup", &the_tapinfo_struct,
+			NULL,
+			NULL, (void*)isup_calls_packet, NULL);
+	
+		if (error_string != NULL) {
+			simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+				      error_string->str);
+			g_string_free(error_string, TRUE);
+			exit(1);
+		}
+		have_isup_tap_listener=TRUE;
+	}
+}
+
+/****************************************************************************/
+
+void
+remove_tap_listener_isup_calls(void)
+{
+	protect_thread_critical_region();
+	remove_tap_listener(&the_tapinfo_struct);
+	unprotect_thread_critical_region();
+
+	have_isup_tap_listener=FALSE;
+}
+
+
+/****************************************************************************/
+/* ***************************TAP for MTP3 **********************************/
+/****************************************************************************/
+
+
+/****************************************************************************/
+/* whenever a mtp3_ packet is seen by the tap listener */
+int mtp3_calls_packet(voip_calls_tapinfo_t *tapinfo _U_, packet_info *pinfo, epan_dissect_t *edt _U_, void *mtp3_info _U_)
+{
+
+	voip_calls_info_t *tmp_listinfo;
+	voip_calls_info_t *strinfo = NULL;
+	isup_calls_info_t *tmp_isupinfo;
+	gboolean found = FALSE;
+	gboolean forward;
+	gboolean right_pair = TRUE;
+	GList* list;
+
+	mtp3_tap_rec_t *pi = mtp3_info;
+
+	/* check wether we already have a call with these parameters in the list */
+	list = g_list_first(tapinfo->strinfo_list);
+	while (list)
+	{
+		tmp_listinfo=list->data;
+		if ((tmp_listinfo->protocol == VOIP_ISUP)&&(tmp_listinfo->call_active_state==VOIP_ACTIVE)){
+			tmp_isupinfo = tmp_listinfo->prot_info;
+			if ((tmp_isupinfo->cic == isup_cic)&&(tmp_isupinfo->ni == pi->addr_opc.ni)){
+				if ((tmp_isupinfo->opc == pi->addr_opc.pc)&&(tmp_isupinfo->dpc == pi->addr_dpc.pc)){
+					 forward = TRUE;
+				 }
+				 else if ((tmp_isupinfo->dpc == pi->addr_opc.pc)&&(tmp_isupinfo->opc == pi->addr_dpc.pc)){
+					 forward = FALSE;
+				 }
+				 else{
+					 right_pair = FALSE;
+				 }
+				 if (right_pair){
+					/* if there is an IAM for a call that is not in setup state, that means the previous call in the same
+					   cic is no longer active */
+					if (tmp_listinfo->call_state == VOIP_CALL_SETUP){
+						found = TRUE;
+					}
+					else if (isup_message_type != 1){
+						found = TRUE;
+					}
+					else{
+						tmp_listinfo->call_active_state=VOIP_INACTIVE;
+					}
+				}
+				if (found){
+					strinfo = (voip_calls_info_t*)(list->data);
+					break;
+				}
+			}
+		}
+		list = g_list_next (list);
+	}
+
+	/* not in the list? then create a new entry if the message is IAM
+	   -i.e. if this session is a call*/
+
+
+	if ((strinfo==NULL) &&(isup_message_type==1)){
+
+		strinfo = g_malloc(sizeof(voip_calls_info_t));
+		strinfo->call_active_state = VOIP_ACTIVE;
+		strinfo->call_state = VOIP_UNKNOWN;
+		g_memmove(&(strinfo->initial_speaker), pinfo->src.data, 4);
+		strinfo->selected=FALSE;
+		strinfo->first_frame_num=pinfo->fd->num;
+		strinfo->start_sec=pinfo->fd->rel_secs;
+		strinfo->start_usec=pinfo->fd->rel_usecs;
+		strinfo->protocol=VOIP_ISUP;
+		strinfo->from_identity=g_strdup(isup_calling_number);
+		strinfo->to_identity=g_strdup(isup_called_number);
+		strinfo->prot_info=g_malloc(sizeof(isup_calls_info_t));
+		tmp_isupinfo=strinfo->prot_info;
+		tmp_isupinfo->opc = pi->addr_opc.pc;
+		tmp_isupinfo->dpc = pi->addr_dpc.pc;
+		tmp_isupinfo->ni = pi->addr_opc.ni;
+		tmp_isupinfo->cic = pinfo->circuit_id;
+		strinfo->npackets = 0;
+		strinfo->call_num = tapinfo->ncalls++;
+		tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
+	}
+
+	if (strinfo!=NULL){
+		strinfo->stop_sec=pinfo->fd->rel_secs;
+		strinfo->stop_usec=pinfo->fd->rel_usecs;
+		strinfo->last_frame_num=pinfo->fd->num;
+		++(strinfo->npackets);
+
+		/* Let's analyze the call state */
+
+		switch(isup_message_type){
+			case 1: /* IAM */
+				strinfo->call_state=VOIP_CALL_SETUP;
+				break;
+			case 7: /* CONNECT */
+			case 9: /* ANSWER */
+				strinfo->call_state=VOIP_IN_CALL;
+				break;
+			case 12: /* RELEASE */
+				if (strinfo->call_state==VOIP_CALL_SETUP){
+					if (forward){
+						strinfo->call_state=VOIP_CANCELLED;
+					}
+					else{
+						strinfo->call_state=VOIP_REJECTED;
+						tapinfo->rejected_calls++;
+					}
+				}
+				else if (strinfo->call_state == VOIP_IN_CALL){
+					strinfo->call_state = VOIP_COMPLETED;
+					tapinfo->completed_calls++;
+				}
+				break;
+		}
+
+		/* increment the packets counter of all calls */
+		++(tapinfo->npackets);
+	}
+
+
+	return 1;
+}
+
+/****************************************************************************/
+
+static gboolean have_mtp3_tap_listener=FALSE;
+
+void
+mtp3_calls_init_tap(void)
+{
+	GString *error_string;
+
+
+	if(have_mtp3_tap_listener==FALSE)
+	{
+		error_string = register_tap_listener("mtp3", &the_tapinfo_struct,
+			NULL,
+			NULL, (void*)mtp3_calls_packet, NULL);
+
+		if (error_string != NULL) {
+			simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+				      error_string->str);
+			g_string_free(error_string, TRUE);
+			exit(1);
+		}
+		have_mtp3_tap_listener=TRUE;
+	}
+}
+
+/****************************************************************************/
+
+void
+remove_tap_listener_mtp3_calls(void)
+{
+	protect_thread_critical_region();
+	remove_tap_listener(&the_tapinfo_struct);
+	unprotect_thread_critical_region();
+
+	have_mtp3_tap_listener=FALSE;
+}
+
+/****************************************************************************/
+/* ***************************TAP for Q931 **********************************/
+/****************************************************************************/
+
+static gchar *q931_calling_number;
+static gchar *q931_called_number;
+static guint8 q931_cause_value;
+static gint32 q931_crv;
+static guint8 q931_message_type;
+static guint32 q931_frame_num;
+
+/****************************************************************************/
+/* whenever a q931_ packet is seen by the tap listener */
+int q931_calls_packet(voip_calls_tapinfo_t *tapinfo _U_, packet_info *pinfo, epan_dissect_t *edt _U_, void *q931_info _U_)
+{
+
+	q931_packet_info *pi = q931_info;
+
+	/* free previously allocated q931_calling/ed_number */
+	g_free(q931_calling_number);
+	g_free(q931_called_number);
+	
+	if (pi->calling_number!=NULL)
+		q931_calling_number = g_strdup(pi->calling_number);
+	else
+		q931_calling_number = g_strdup("");
+
+	if (pi->called_number!=NULL)
+		q931_called_number = g_strdup(pi->called_number);
+	else
+		q931_called_number = g_strdup("");
+	q931_cause_value = pi->cause_value;
+	q931_frame_num = pinfo->fd->num;
+	q931_crv = pi->crv;
+
+	return 0;
+}
+
+/****************************************************************************/
+static gboolean have_q931_tap_listener=FALSE;
+
+void
+q931_calls_init_tap(void)
+{
+	GString *error_string;
+
+
+	if(have_q931_tap_listener==FALSE)
+	{
+		error_string = register_tap_listener("q931", &the_tapinfo_struct,
+			NULL,
+			NULL, (void*)q931_calls_packet, NULL);
+			
+		if (error_string != NULL) {
+			simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+				      error_string->str);
+			g_string_free(error_string, TRUE);
+			exit(1);
+		}
+		have_q931_tap_listener=TRUE;
+	}
+}
+
+/****************************************************************************/
+
+void
+remove_tap_listener_q931_calls(void)
+{
+	protect_thread_critical_region();
+	remove_tap_listener(&the_tapinfo_struct);
+	unprotect_thread_critical_region();
+
+	have_q931_tap_listener=FALSE;
+}
+
+/****************************************************************************/
+/****************************TAP for H323 ***********************************/
+/****************************************************************************/
+
+#define GUID_LEN	16
+static const guint8 guid_allzero[GUID_LEN] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+/* defines specific H323 data */
+
+void add_h245_Address(h323_calls_info_t *h323info, guint32 h245_address, guint16 h245_port)
+{
+	h245_address_t *h245_add = NULL;
+
+	h245_add = g_malloc(sizeof(h245_address_t));
+		h245_add->h245_address = h245_address;
+		h245_add->h245_port = h245_port;
+
+	h323info->h245_list = g_list_append(h323info->h245_list, h245_add);				
+}
+
+/****************************************************************************/
+/* whenever a H225 packet is seen by the tap listener */
+int H225calls_packet(voip_calls_tapinfo_t *tapinfo _U_, packet_info *pinfo, epan_dissect_t *edt _U_, void *H225info)
+{
+
+	voip_calls_info_t *tmp_listinfo;
+	voip_calls_info_t *strinfo = NULL;
+	h323_calls_info_t *tmp_h323info;
+	gchar *frame_label;
+	gchar *comment;
+	GList* list;
+	guint32 tmp_src, tmp_dst;
+
+	h225_packet_info *pi = H225info;
+
+	/* we ignore packets that are not displayed */
+	if (pinfo->fd->flags.passed_dfilter == 0)
+		return 0;
+
+	/* if not guid and RAS return because did not belong to a call */
+	if ((memcmp(pi->guid, guid_allzero, GUID_LEN) == 0) && (pi->msg_type == H225_RAS))
+		return 0;
+	
+
+	if ( (memcmp(pi->guid, guid_allzero, GUID_LEN) == 0) && (q931_frame_num == pinfo->fd->num) ){
+		/* check wether we already have a call with this Q931 CRV */
+		list = g_list_first(tapinfo->strinfo_list);
+		while (list)
+		{
+			tmp_listinfo=list->data;
+			if (tmp_listinfo->protocol == VOIP_H323){
+				tmp_h323info = tmp_listinfo->prot_info;
+				if ( ((tmp_h323info->q931_crv == q931_crv) || (tmp_h323info->q931_crv2 == q931_crv)) && (q931_crv!=-1)){
+					strinfo = (voip_calls_info_t*)(list->data);
+					break;
+				}
+			}
+			list = g_list_next (list);
+		}
+		if (strinfo==NULL) 	return 0;		
+	} else {
+		/* check wether we already have a call with this guid in the list */
+		list = g_list_first(tapinfo->strinfo_list);
+		while (list)
+		{
+			tmp_listinfo=list->data;
+			if (tmp_listinfo->protocol == VOIP_H323){
+				tmp_h323info = tmp_listinfo->prot_info;
+				if (memcmp(tmp_h323info->guid, pi->guid,GUID_LEN)==0){ 
+					strinfo = (voip_calls_info_t*)(list->data);
+					break;
+				}
+			}
+			list = g_list_next (list);
+		}
+	}
+
+	/* not in the list? then create a new entry */
+	if ((strinfo==NULL)){
+		strinfo = g_malloc(sizeof(voip_calls_info_t));
+		strinfo->call_active_state = VOIP_ACTIVE;
+		strinfo->call_state = VOIP_UNKNOWN;
+		strinfo->from_identity=g_strdup("");
+		strinfo->to_identity=g_strdup("");
+
+		g_memmove(&(strinfo->initial_speaker), pinfo->src.data,4);
+		strinfo->selected=FALSE;
+		strinfo->first_frame_num=pinfo->fd->num;
+		strinfo->start_sec=pinfo->fd->rel_secs;
+		strinfo->start_usec=pinfo->fd->rel_usecs;
+		strinfo->protocol=VOIP_H323;
+		strinfo->prot_info=g_malloc(sizeof(h323_calls_info_t));
+		tmp_h323info = strinfo->prot_info;
+		tmp_h323info->guid = (guint8 *) g_memdup(pi->guid,GUID_LEN);
+		tmp_h323info->h225SetupAddr = 0;
+		tmp_h323info->h245_list = NULL;
+		tmp_h323info->is_faststart_Setup = FALSE;
+		tmp_h323info->is_faststart_Proc = FALSE;
+		tmp_h323info->is_h245Tunneling = FALSE;
+		tmp_h323info->is_h245 = FALSE;
+		tmp_h323info->q931_crv = -1;
+		tmp_h323info->q931_crv2 = -1;
+		strinfo->call_num = tapinfo->ncalls++;
+		strinfo->npackets = 0;
+
+		tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);				
+	}
+
+	if (strinfo!=NULL){
+
+		/* let's analyze the call state */
+
+		g_memmove(&(tmp_src), pinfo->src.data, 4);
+		g_memmove(&(tmp_dst), pinfo->dst.data, 4);
+
+		strinfo->stop_sec=pinfo->fd->rel_secs;
+		strinfo->stop_usec=pinfo->fd->rel_usecs;
+		strinfo->last_frame_num=pinfo->fd->num;
+		++(strinfo->npackets);
+		/* increment the packets counter of all calls */
+		++(tapinfo->npackets);
+
+		/* change the status */
+		if (pi->msg_type == H225_CS){
+			if (tmp_h323info->q931_crv == -1) {
+				tmp_h323info->q931_crv = q931_crv;
+			} else if (tmp_h323info->q931_crv != q931_crv) {
+				tmp_h323info->q931_crv2 = q931_crv;
+			}
+
+			if (pi->is_h245 == TRUE){
+				add_h245_Address(tmp_h323info, pi->h245_address, pi->h245_port);
+			}
+
+			if (pi->cs_type != H225_RELEASE_COMPLET) tmp_h323info->is_h245Tunneling = pi->is_h245Tunneling;
+
+			frame_label = g_strdup(pi->frame_label);
+
+			switch(pi->cs_type){
+			case H225_SETUP:
+				tmp_h323info->is_faststart_Setup = pi->is_faststart;
+
+				/* set te calling and called number from the Q931 packet */
+				if (q931_frame_num == pinfo->fd->num){
+					if (q931_calling_number != NULL){
+						g_free(strinfo->from_identity);
+						strinfo->from_identity=g_strdup(q931_calling_number);
+					}
+					if (q931_called_number != NULL){
+						g_free(strinfo->to_identity);
+						strinfo->to_identity=g_strdup(q931_called_number);
+					}
+				}
+				if (tmp_h323info->h225SetupAddr == 0) g_memmove(&(tmp_h323info->h225SetupAddr), pinfo->src.data,4);
+				strinfo->call_state=VOIP_CALL_SETUP;
+				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"), 
+											(pi->is_faststart==TRUE?"on":"off"));
+				break;
+			case H225_CONNECT:
+				strinfo->call_state=VOIP_IN_CALL;
+				if (pi->is_faststart == TRUE) tmp_h323info->is_faststart_Proc = TRUE;
+				comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"), 
+											(pi->is_faststart==TRUE?"on":"off"));
+				break;
+			case H225_RELEASE_COMPLET:
+				g_memmove(&(tmp_src), pinfo->src.data, 4);
+				if (strinfo->call_state==VOIP_CALL_SETUP){
+					if (tmp_h323info->h225SetupAddr == tmp_src){  /* forward direction */
+						strinfo->call_state=VOIP_CANCELLED;
+					}
+					else{												/* reverse */
+						strinfo->call_state=VOIP_REJECTED;
+						tapinfo->rejected_calls++;
+					}
+				}
+				else if (strinfo->call_state == VOIP_IN_CALL){
+					strinfo->call_state = VOIP_COMPLETED;
+					tapinfo->completed_calls++;
+				}
+				/* get the Q931 Release cause code */
+				if (q931_frame_num == pinfo->fd->num){
+					if (q931_cause_value != 0xFF){		
+						comment = g_strdup_printf("H225 Q931 Rel Cause (%i):%s", q931_cause_value, val_to_str(q931_cause_value, q931_cause_code_vals, "<unknown>"));
+					} else {			/* Cause not set */
+						comment = g_strdup("H225 No Q931 Rel Cause");
+					}
+				}
+				break;
+			case H225_PROGRESS:
+			case H225_ALERTING:
+			case H225_CALL_PROCEDING:
+				if (pi->is_faststart == TRUE) tmp_h323info->is_faststart_Proc = TRUE;
+				comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"), 
+											(pi->is_faststart==TRUE?"on":"off"));
+				break;
+			default:
+				comment = g_strdup_printf("H225 TunnH245:%s FS:%s", (tmp_h323info->is_h245Tunneling==TRUE?"on":"off"), 
+											(pi->is_faststart==TRUE?"on":"off"));
+
+			}
+		} else if (pi->msg_type == H225_RAS){
+			frame_label = g_strdup_printf("%s", val_to_str(pi->msg_tag, RasMessage_vals, "<unknown>"));
+			comment = g_strdup("H225 RAS");
+		} else {
+			frame_label = g_strdup("H225: Unknown");
+			comment = g_strdup("");
+		}
+
+		/* add to graph analysis */
+		if (!append_to_frame_graph(tapinfo, pinfo->fd->num, pi->frame_label, comment))		/* if the frame number exists in graph, append to it*/
+			add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num);  /* if not exist, add to the graph */
+
+		g_free(frame_label);
+		g_free(comment);
+	}
+
+	return 1;  /* refresh output */
+}
+
+
+/****************************************************************************/
+/* TAP INTERFACE */
+/****************************************************************************/
+static gboolean have_H225_tap_listener=FALSE;
+/****************************************************************************/
+void
+h225_calls_init_tap(void)
+{
+	GString *error_string;
+
+	if(have_H225_tap_listener==FALSE)
+	{
+		/* don't register tap listener, if we have it already */
+		error_string = register_tap_listener("h225", &the_tapinfo_struct, NULL,
+			NULL, (void*)H225calls_packet, NULL);
+			
+		if (error_string != NULL) {
+			simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+				      error_string->str);
+			g_string_free(error_string, TRUE);
+			exit(1);
+		}
+		have_H225_tap_listener=TRUE;
+	}
+}
+
+
+
+/* XXX just copied from gtk/rpc_stat.c */
+void protect_thread_critical_region(void);
+void unprotect_thread_critical_region(void);
+
+/****************************************************************************/
+void
+remove_tap_listener_h225_calls(void)
+{
+	protect_thread_critical_region();
+	remove_tap_listener(&the_tapinfo_struct);
+	unprotect_thread_critical_region();
+
+	have_H225_tap_listener=FALSE;
+}
+
+
+/****************************************************************************/
+/* whenever a H245dg packet is seen by the tap listener (when H245 tunneling is ON) */
+int H245dgcalls_packet(voip_calls_tapinfo_t *tapinfo _U_, packet_info *pinfo, epan_dissect_t *edt _U_, void *H245info)
+{
+
+	voip_calls_info_t *tmp_listinfo;
+	voip_calls_info_t *strinfo = NULL;
+	h323_calls_info_t *tmp_h323info;
+	gchar *frame_label;
+	gchar *comment;
+	GList* list;
+	GList* list2;
+	guint32 tmp_src, tmp_dst;
+	h245_address_t *h245_add = NULL;
+
+	h245_packet_info *pi = H245info;
+
+	/* we ignore packets that are not displayed */
+	if (pinfo->fd->flags.passed_dfilter == 0)
+		return 0;
+
+	/* if H245 tunneling is on, append to graph */
+	if (append_to_frame_graph(tapinfo, pinfo->fd->num, pi->frame_label, pi->comment)) return 1;
+
+
+	/* it is not Tunneling or it is not in the list. So check if there is no tunneling
+	   and there is a call with this H245 address */
+	list = g_list_first(tapinfo->strinfo_list);
+	while (list)
+	{
+		tmp_listinfo=list->data;
+		if (tmp_listinfo->protocol == VOIP_H323){
+			tmp_h323info = tmp_listinfo->prot_info;
+
+			g_memmove(&(tmp_src), pinfo->src.data, 4);
+			g_memmove(&(tmp_dst), pinfo->dst.data, 4);
+			list2 = g_list_first(tmp_h323info->h245_list);
+			while (list2)
+			{
+				h245_add=list2->data;
+				if ( ((h245_add->h245_address == tmp_src) && (h245_add->h245_port == pinfo->srcport))
+					|| ((h245_add->h245_address == tmp_dst) && (h245_add->h245_port == pinfo->destport)) ){
+					strinfo = (voip_calls_info_t*)(list->data);
+
+					++(strinfo->npackets);
+					/* increment the packets counter of all calls */
+					++(tapinfo->npackets);
+
+					break;
+				}			
+			list2 = g_list_next(list2);
+			}
+			if (strinfo!=NULL) break;
+		}
+		list = g_list_next(list);
+	}
+
+	if (strinfo!=NULL){
+		frame_label = g_strdup(pi->frame_label);
+		comment = g_strdup(pi->comment);
+		add_to_graph(tapinfo, pinfo, frame_label, comment, strinfo->call_num);
+		g_free(frame_label);
+		g_free(comment);
+	}
+
+	return 1;  /* refresh output */
+}
+
+
+/****************************************************************************/
+/* TAP INTERFACE */
+/****************************************************************************/
+static gboolean have_H245dg_tap_listener=FALSE;
+/****************************************************************************/
+void
+h245dg_calls_init_tap(void)
+{
+	GString *error_string;
+
+	if(have_H245dg_tap_listener==FALSE)
+	{
+		/* don't register tap listener, if we have it already */
+		error_string = register_tap_listener("h245dg", &the_tapinfo_struct, NULL,
+			NULL, (void*)H245dgcalls_packet, NULL);
+		
+		if (error_string != NULL) {
+			simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+				      error_string->str);
+			g_string_free(error_string, TRUE);
+			exit(1);
+		}
+		have_H245dg_tap_listener=TRUE;
+	}
+}
+
+
+/* XXX just copied from gtk/rpc_stat.c */
+void protect_thread_critical_region(void);
+void unprotect_thread_critical_region(void);
+
+/****************************************************************************/
+void
+remove_tap_listener_h245dg_calls(void)
+{
+	protect_thread_critical_region();
+	remove_tap_listener(&the_tapinfo_struct);
+	unprotect_thread_critical_region();
+
+	have_H245dg_tap_listener=FALSE;
+}
+
+
+/****************************************************************************/
+/****************************TAP for SDP PROTOCOL ***************************/
+/****************************************************************************/
+/* whenever a SDP packet is seen by the tap listener */
+int SDPcalls_packet(voip_calls_tapinfo_t *tapinfo _U_, packet_info *pinfo, epan_dissect_t *edt _U_, void *SDPinfo)
+{
+	sdp_packet_info *pi = SDPinfo;
+
+	/* we ignore packets that are not displayed */
+	if (pinfo->fd->flags.passed_dfilter == 0)
+		return 0;
+
+	/* Append to graph the SDP summary if the packet exists */
+	g_snprintf(pi->summary_str, 50, "SDP (%s)", pi->summary_str);
+	append_to_frame_graph(tapinfo, pinfo->fd->num, pi->summary_str, NULL);
+
+	return 1;  /* refresh output */
+}
+
+
+/****************************************************************************/
+/* TAP INTERFACE */
+/****************************************************************************/
+static gboolean have_sdp_tap_listener=FALSE;
+/****************************************************************************/
+void
+sdp_calls_init_tap(void)
+{
+	GString *error_string;
+
+	if(have_sdp_tap_listener==FALSE)
+	{
+		/* don't register tap listener, if we have it already */
+		error_string = register_tap_listener("sdp", &the_tapinfo_struct, NULL,
+			NULL, (void*)SDPcalls_packet, NULL);
+			
+		if (error_string != NULL) {
+			simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+				      error_string->str);
+			g_string_free(error_string, TRUE);
+			exit(1);
+		}
+		have_sdp_tap_listener=TRUE;
+	}
+}
+
+
+/* XXX just copied from gtk/rpc_stat.c */
+void protect_thread_critical_region(void);
+void unprotect_thread_critical_region(void);
+
+/****************************************************************************/
+void
+remove_tap_listener_sdp_calls(void)
+{
+	protect_thread_critical_region();
+	remove_tap_listener(&the_tapinfo_struct);
+	unprotect_thread_critical_region();
+
+	have_sdp_tap_listener=FALSE;
+}
+
+
+
+
+
+/****************************************************************************/
+/* ***************************TAP for OTHER PROTOCOL **********************************/
+/****************************************************************************/
+
+/****************************************************************************/
+/* redraw the output */
+/*void prot_calls_draw(voip_calls_tapinfo_t *tapinfo _U_)
+{
+	return;
+}
+*/
+/****************************************************************************/
+/* whenever a prot_ packet is seen by the tap listener */
+/*int prot_calls_packet(voip_calls_tapinfo_t *tapinfo _U_, packet_info *pinfo, epan_dissect_t *edt _U_, void *prot_info _U_)
+{
+	if (strinfo!=NULL){
+		strinfo->stop_sec=pinfo->fd->rel_secs;
+		strinfo->stop_usec=pinfo->fd->rel_usecs;
+		strinfo->last_frame_num=pinfo->fd->num;
+		++(strinfo->npackets);
+		++(tapinfo->npackets);
+	}
+
+	return 1;
+}
+*/
+/****************************************************************************/
+/*
+static gboolean have_prot__tap_listener=FALSE;
+
+void
+prot_calls_init_tap(void)
+{
+	GString *error_string;
+
+	if(have_prot__tap_listener==FALSE)
+	{
+		error_string = register_tap_listener("prot_", &the_tapinfo_struct,
+			NULL,
+			NULL, (void*)prot_calls_packet, NULL);
+
+		if (error_string != NULL) {
+			simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+				      error_string->str);
+			g_string_free(error_string, TRUE);
+			exit(1);
+		}
+		have_prot__tap_listener=TRUE;
+	}
+}
+*/
+/****************************************************************************/
+/*
+void
+remove_tap_listener_prot__calls(void)
+{
+	protect_thread_critical_region();
+	remove_tap_listener(&the_tapinfo_struct);
+	unprotect_thread_critical_region();
+
+	have_prot__tap_listener=FALSE;
+}
+*/
+
+/****************************************************************************/
+
+/*void prot_calls_reset(voip_calls_tapinfo_t *tapinfo _U_)
+{
+	return;
+}
+*/
Index: gtk/voip_calls.h
===================================================================
--- gtk/voip_calls.h	(revision 0)
+++ gtk/voip_calls.h	(revision 0)
@@ -0,0 +1,191 @@
+/* voip_calls.h
+ * VoIP calls summary addition for ethereal
+ *
+ * $Id: voip_calls.h 12179 2004-10-01 22:09:38Z guy $
+ *
+ * Copyright 2004, Ericsson , Spain
+ * By Francisco Alcoba <francisco.alcoba@xxxxxxxxxxxx>
+ *
+ * based on h323_calls.h
+ * Copyright 2004, Iskratel, Ltd, Kranj
+ * By Miha Jemec <m.jemec@xxxxxxxxxxx>
+ *
+ * H323, RTP and Graph Support
+ * By Alejandro Vaquero, alejandro.vaquero@xxxxxxxxx
+ * Copyright 2005, Verso Technologies Inc.
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@xxxxxxxxxxxx>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation,  Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef VOIP_CALLS_H_INCLUDED
+#define VOIP_CALLS_H_INCLUDED
+
+#include <glib.h>
+#include <stdio.h>
+
+/****************************************************************************/
+/* defines voip call state */
+typedef enum _voip_call_state {
+        VOIP_CALL_SETUP,
+        VOIP_IN_CALL,
+        VOIP_CANCELLED,
+        VOIP_COMPLETED,
+        VOIP_REJECTED,
+		VOIP_UNKNOWN
+} voip_call_state;
+
+extern char *voip_call_state_name[6];
+
+typedef enum _voip_call_active_state {
+		VOIP_ACTIVE,
+		VOIP_INACTIVE
+} voip_call_active_state;
+
+typedef enum _voip_protocol {
+		VOIP_SIP,
+		VOIP_ISUP,
+		VOIP_H323
+} voip_protocol;
+
+extern char *voip_protocol_name[3];
+
+/* defines specific SIP data */
+
+typedef enum _sip_call_state {
+	SIP_INVITE_SENT,
+	SIP_200_REC,
+	SIP_CANCEL_SENT
+} sip_call_state;
+
+typedef struct _sip_calls_info {
+	gchar *call_identifier;
+	guint32 invite_cseq;
+	sip_call_state sip_state;
+} sip_calls_info_t;
+
+/* defines specific ISUP data */
+
+typedef struct _isup_calls_info {
+	guint16			cic;
+	guint32			opc, dpc;
+	guint8			ni;
+} isup_calls_info_t;
+
+typedef struct _h245_address {
+	guint32 h245_address;
+	guint16 h245_port;
+} h245_address_t;
+
+/* defines specific H323 data */
+typedef struct _h323_calls_info {
+	guint8 *guid;	/* Call ID to identify a H225 */
+	GList*  h245_list;   /* list of H245 Address and ports for tunneling off calls*/
+	guint32 h225SetupAddr; /* we use the SETUP H225 IP to determine if packets are forward or reverse */					
+	gboolean is_h245;
+	gboolean is_faststart_Setup;	/* if faststart field is included in Setup*/
+	gboolean is_faststart_Proc;		/* if faststart field is included in Proce, Alerting, Progress or Connect*/
+	gboolean is_h245Tunneling;
+	gint32 q931_crv;
+	gint32 q931_crv2;
+} h323_calls_info_t;
+
+/* defines a voip call */
+typedef struct _voip_calls_info {
+	voip_call_state call_state;
+	voip_call_active_state call_active_state;
+	gchar *from_identity;
+	gchar *to_identity;
+	gpointer prot_info;
+	guint32 initial_speaker;
+	guint32 npackets;
+	guint32 first_frame_num; /* frame number of first frame */
+	guint32 last_frame_num; 
+	voip_protocol protocol;
+	guint16 call_num;
+	gint32 start_sec, start_usec, stop_sec, stop_usec;
+	gboolean selected;
+
+} voip_calls_info_t;
+
+/* structure that holds the information about all detected calls */
+/* struct holding all information of the tap */
+
+typedef struct _voip_calls_tapinfo {
+	int     ncalls;       /* number of calls in the list */
+	GList*  strinfo_list;   /* list with all calls */
+	int     npackets;       /* total number of packets of all calls */
+	voip_calls_info_t* filter_calls_fwd;  /* used as filter in some tap modes */
+	guint32 launch_count;   /* number of times the tap has been run */
+	int start_packets;
+	int completed_calls;
+	int rejected_calls;
+	graph_analysis_info_t* graph_analysis;
+} voip_calls_tapinfo_t;
+
+
+/****************************************************************************/
+/* INTERFACE */
+
+/*
+* Registers the voip_calls tap listeners (if not already done).
+* From that point on, the calls list will be updated with every redissection.
+* This function is also the entry point for the initialization routine of the tap system.
+* So whenever voip_calls.c is added to the list of ETHEREAL_TAP_SRCs, the tap will be registered on startup.
+* If not, it will be registered on demand by the voip_calls functions that need it.
+*/
+void sip_calls_init_tap(void);
+void isup_calls_init_tap(void);
+void mtp3_calls_init_tap(void);
+void h225_calls_init_tap(void);
+void h245dg_calls_init_tap(void);
+void q931_calls_init_tap(void);
+void sdp_calls_init_tap(void);
+
+
+/*
+* Removes the voip_calls tap listener (if not already done)
+* From that point on, the voip calls list won't be updated any more.
+*/
+void remove_tap_listener_sip_calls(void);
+void remove_tap_listener_isup_calls(void);
+void remove_tap_listener_mtp3_calls(void);
+void remove_tap_listener_h225_calls(void);
+void remove_tap_listener_h245dg_calls(void);
+void remove_tap_listener_q931_calls(void);
+void remove_tap_listener_sdp_calls(void);
+
+/*
+* Retrieves a constant reference to the unique info structure of the voip_calls tap listener.
+* The user should not modify the data pointed to.
+*/
+const voip_calls_tapinfo_t* voip_calls_get_info(void);
+
+/*
+* Cleans up memory of voip calls tap.
+*/
+void voip_calls_reset(voip_calls_tapinfo_t *tapinfo);
+void isup_calls_reset(voip_calls_tapinfo_t *tapinfo);
+void mtp3_calls_reset(voip_calls_tapinfo_t *tapinfo);
+void q931_calls_reset(voip_calls_tapinfo_t *tapinfo);
+
+void graph_analysis_data_init();
+
+void add_rtp_streams_graph();
+
+#endif /*VOIP_CALLS_H_INCLUDED*/
Index: epan/dissectors/packet-sip.c
===================================================================
--- epan/dissectors/packet-sip.c	(revision 13162)
+++ epan/dissectors/packet-sip.c	(working copy)
@@ -605,12 +605,17 @@
 	char *media_type_str_lower_case = NULL;
 	char *content_type_parameter_str = NULL;
 	guint resend_for_packet = 0;
+	char  *string;
 
 	/* Initialise stat info for passing to tap */
 	stat_info = g_malloc(sizeof(sip_info_value_t));
 	stat_info->response_code = 0;
 	stat_info->request_method = NULL;
+	stat_info->reason_phrase = NULL;
 	stat_info->resend = 0;
+    stat_info->tap_call_id = NULL;
+    stat_info->tap_from_addr = NULL;
+    stat_info->tap_to_addr = NULL;
 
         /*
          * Note that "tvb_find_line_end()" will return a value that
@@ -660,6 +665,11 @@
                         col_add_fstr(pinfo->cinfo, COL_INFO, "Status: %s",
                              tvb_format_text(tvb, SIP2_HDR_LEN + 1, linelen - SIP2_HDR_LEN - 1));
                 }
+                string = tvb_get_string(tvb, SIP2_HDR_LEN + 5, linelen - (SIP2_HDR_LEN + 5));
+                stat_info->reason_phrase = g_malloc(linelen - (SIP2_HDR_LEN + 5) + 1);
+                strncpy(stat_info->reason_phrase, string, linelen - (SIP2_HDR_LEN + 5) + 1);
+                /* String no longer needed */
+                g_free(string);
 		break;
 
 	case OTHER_LINE:
@@ -843,6 +853,9 @@
 						parameter_len = parameter_end_offset - parameter_offset;
 						proto_tree_add_item(sip_element_tree, hf_sip_to_addr, tvb, parameter_offset,
 							parameter_len, FALSE);
+                        /*info for the tap for voip_calls.c*/
+                        stat_info->tap_to_addr=tvb_get_string(tvb, parameter_offset, parameter_len);
+
 						parameter_offset = parameter_end_offset + 1;
 						/*  
 						 * URI parameters ?
@@ -875,6 +888,8 @@
 					parameter_len = parameter_end_offset - parameter_offset;
 					proto_tree_add_item(sip_element_tree, hf_sip_to_addr, tvb, parameter_offset,
 						parameter_len, FALSE);
+                    /*info for the tap for voip_calls.c*/
+                    stat_info->tap_to_addr=tvb_get_string(tvb, parameter_offset, parameter_len);
 					offset = parameter_end_offset;
 					}
 					/* Find parameter tag if present.
@@ -948,6 +963,8 @@
 						parameter_len = parameter_end_offset - parameter_offset;
 						dfilter_store_sip_from_addr(tvb, sip_element_tree, 
 							parameter_offset, parameter_len);
+                        /*info for the tap for voip_calls.c*/
+                        stat_info->tap_from_addr=tvb_get_string(tvb, parameter_offset, parameter_len);
 						parameter_offset = parameter_end_offset + 1;
 						/*  
 						 * URI parameters ?
@@ -980,6 +997,8 @@
 					parameter_len = parameter_end_offset - parameter_offset;
 					proto_tree_add_item(sip_element_tree, hf_sip_from_addr, tvb, parameter_offset,
 						parameter_len, FALSE);
+                    /*info for the tap for voip_calls.c*/
+                    stat_info->tap_from_addr=tvb_get_string(tvb, parameter_offset, parameter_len);
 					offset = parameter_end_offset;
 					}
 					/* Find parameter tag if present.
@@ -1008,6 +1027,7 @@
 					/* Store the sequence number */
 					cseq_number = atoi(value);
 					cseq_number_set = 1;
+					stat_info->tap_cseq_number=cseq_number;
 
 					/* Extract method name from value */
 					for (value_offset = 0; value_offset < (gint)strlen(value); value_offset++)
@@ -1034,7 +1054,8 @@
 						strlen(value)+1 < MAX_CALL_ID_SIZE ?
 							strlen(value)+1 :
 							MAX_CALL_ID_SIZE);
-
+					stat_info->tap_call_id = g_strdup(call_id);
+					
 					/* Add 'Call-id' string item to tree */
 					if(hdr_tree) {
 						proto_tree_add_string_format(hdr_tree,
Index: epan/dissectors/packet-sip.h
===================================================================
--- epan/dissectors/packet-sip.h	(revision 13162)
+++ epan/dissectors/packet-sip.h	(working copy)
@@ -31,6 +31,12 @@
     gchar	*request_method;
     guint	 response_code;
 	guchar	resend;
+    /* added for VoIP calls analysis, see gtk/voip_calls.c*/
+    gchar   *tap_call_id;
+    gchar   *tap_from_addr;
+    gchar   *tap_to_addr;
+    guint32 tap_cseq_number;
+    gchar   *reason_phrase;
 } sip_info_value_t;
 
 extern void dfilter_store_sip_from_addr(tvbuff_t *tvb,proto_tree *tree,guint parameter_offset, 
Index: epan/dissectors/packet-h225.c
===================================================================
--- epan/dissectors/packet-h225.c	(revision 13162)
+++ epan/dissectors/packet-h225.c	(working copy)
@@ -1,6 +1,6 @@
 /* Do not modify this file.                                                   */
 /* It is created automatically by the ASN.1 to Ethereal dissector compiler    */
-/* .\packet-h225.c                                                            */
+/* ./packet-h225.c                                                            */
 /* ../../tools/asn2eth.py -X -e -p h225 -c h225.cnf -s packet-h225-template h225.asn */
 
 /* Input file: packet-h225-template.c */
@@ -74,7 +74,9 @@
 static void ras_call_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, h225_packet_info *pi);
 static int dissect_h225_H323UserInformation(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
 
-static h225_packet_info h225_pi; 
+static h225_packet_info pi_arr[5]; /* We assuming a maximum of 5 H225 messaages per packet */
+static int pi_current=0;
+h225_packet_info *h225_pi=NULL;
 
 static dissector_handle_t h225ras_handle;
 static dissector_handle_t H323UserInformation_handle;
@@ -129,7 +131,7 @@
 static int hf_h225_nonStandardData = -1;          /* NonStandardParameter */
 static int hf_h225_h4501SupplementaryService = -1;  /* T_h4501SupplementaryService */
 static int hf_h225_h4501SupplementaryService_item = -1;  /* T_h4501SupplementaryService_item */
-static int hf_h225_h245Tunneling = -1;            /* BOOLEAN */
+static int hf_h225_h245Tunneling = -1;            /* T_h245Tunneling */
 static int hf_h225_h245Control = -1;              /* H245Control */
 static int hf_h225_nonStandardControl = -1;       /* SEQUENCE_OF_NonStandardParameter */
 static int hf_h225_nonStandardControl_item = -1;  /* NonStandardParameter */
@@ -1345,6 +1347,7 @@
   proto_item_append_text(ti_tmp, ": NULL");
   }
 
+  if (h225_pi->cs_type == H225_OTHER) h225_pi->cs_type = H225_EMPTY;
   return offset;
 }
 static int dissect_empty_flg(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
@@ -2209,9 +2212,9 @@
                               NULL);
 
 	/* we need this info for TAPing */
-	h225_pi.is_h245 = TRUE;
-	h225_pi.h245_address = ipv4_address;	
-	h225_pi.h245_port = ipv4_port;	
+	h225_pi->is_h245 = TRUE;
+	h225_pi->h245_address = ipv4_address;	
+	h225_pi->h245_port = ipv4_port;	
 
 	if((!pinfo->fd->flags.visited) && ipv4_address!=0 && ipv4_port!=0 && h245_handle){
 		address src_addr;
@@ -3506,9 +3509,6 @@
 
   return offset;
 }
-static int dissect_h245Tunneling(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
-  return dissect_h225_BOOLEAN(tvb, offset, pinfo, tree, hf_h225_h245Tunneling);
-}
 static int dissect_multipleCalls(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
   return dissect_h225_BOOLEAN(tvb, offset, pinfo, tree, hf_h225_multipleCalls);
 }
@@ -4002,7 +4002,7 @@
   guint32 guid_offset,guid_len;
 
   offset = dissect_per_octet_string(tvb,offset,pinfo,tree,hf_index,16,16,&guid_offset,&guid_len);
-  tvb_memcpy(tvb,h225_pi.guid,guid_offset,guid_len);
+  tvb_memcpy(tvb,h225_pi->guid,guid_offset,guid_len);
 
   return offset;
 }
@@ -4242,14 +4242,19 @@
 dissect_h225_FastStart_item(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) {
 	guint32 newoffset;
 	guint32 length;
+	char codec_str[50];
 
 	offset=dissect_per_length_determinant(tvb, offset, pinfo, tree, hf_h225_fastStart_item_length, &length);
 	newoffset=offset + (length<<3);	/* please note that offset is in bits in
 					   PER dissectors, but the item length
 					   is in octets */
-	offset=dissect_h245_OpenLogicalChannel(tvb,offset, pinfo, tree, hf_index);
+	offset=dissect_h245_OpenLogicalChannelCodec(tvb,offset, pinfo, tree, hf_index, codec_str);
+
+    /* Add to packet info */
+    g_snprintf(h225_pi->frame_label, 50, "%s %s", h225_pi->frame_label, codec_str);
+
 	contains_faststart = TRUE;
-	h225_pi.is_faststart = TRUE;
+	h225_pi->is_faststart = TRUE;
 
 	return newoffset;
 
@@ -5337,7 +5342,12 @@
   offset = dissect_per_sequence(tvb, offset, pinfo, tree, hf_index,
                                 ett_h225_Setup_UUIE, Setup_UUIE_sequence);
 
-  h225_pi.cs_type = H225_SETUP;
+  /* Add to packet info */
+  h225_pi->cs_type = H225_SETUP;
+  if (contains_faststart == TRUE )
+      g_snprintf(h225_pi->frame_label, 50, "%s OLC (%s)", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>"), h225_pi->frame_label);
+  else
+      g_snprintf(h225_pi->frame_label, 50, "%s", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>"));
   return offset;
 }
 static int dissect_setup(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
@@ -5384,7 +5394,12 @@
   offset = dissect_per_sequence(tvb, offset, pinfo, tree, hf_index,
                                 ett_h225_CallProceeding_UUIE, CallProceeding_UUIE_sequence);
 
-  h225_pi.cs_type = H225_CALL_PROCEDING;
+  /* Add to packet info */
+  h225_pi->cs_type = H225_CALL_PROCEDING;
+  if (contains_faststart == TRUE )
+        g_snprintf(h225_pi->frame_label, 50, "%s OLC (%s)", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>"), h225_pi->frame_label);
+  else
+        g_snprintf(h225_pi->frame_label, 50, "%s", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>"));
   return offset;
 }
 static int dissect_callProceeding(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
@@ -5431,7 +5446,12 @@
   offset = dissect_per_sequence(tvb, offset, pinfo, tree, hf_index,
                                 ett_h225_Connect_UUIE, Connect_UUIE_sequence);
 
-  h225_pi.cs_type = H225_CONNECT;
+  /* Add to packet info */
+  h225_pi->cs_type = H225_CONNECT;
+  if (contains_faststart == TRUE )
+      g_snprintf(h225_pi->frame_label, 50, "%s OLC (%s)", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>"), h225_pi->frame_label);
+  else 
+      g_snprintf(h225_pi->frame_label, 50, "%s", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>"));
   return offset;
 }
 static int dissect_connect(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
@@ -5464,7 +5484,12 @@
   offset = dissect_per_sequence(tvb, offset, pinfo, tree, hf_index,
                                 ett_h225_Alerting_UUIE, Alerting_UUIE_sequence);
 
-  h225_pi.cs_type = H225_ALERTING;
+  /* Add to packet info */
+  h225_pi->cs_type = H225_ALERTING;
+  if (contains_faststart == TRUE )
+       g_snprintf(h225_pi->frame_label, 50, "%s OLC (%s)", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>"), h225_pi->frame_label);
+  else 
+       g_snprintf(h225_pi->frame_label, 50, "%s", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>"));
   return offset;
 }
 static int dissect_alerting(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
@@ -5487,6 +5512,9 @@
   offset = dissect_per_sequence(tvb, offset, pinfo, tree, hf_index,
                                 ett_h225_Information_UUIE, Information_UUIE_sequence);
 
+  /* Add to packet info */
+  h225_pi->cs_type = H225_INFORMATION;
+  g_snprintf(h225_pi->frame_label, 50, "%s", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>"));
   return offset;
 }
 static int dissect_information(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
@@ -5618,7 +5646,7 @@
   offset = dissect_per_choice(tvb, offset, pinfo, tree, hf_index,
                               ett_h225_ReleaseCompleteReason, ReleaseCompleteReason_choice, "ReleaseCompleteReason",
                               &value);
-  h225_pi.reason = value;
+  h225_pi->reason = value;
 
   return offset;
 }
@@ -5646,7 +5674,9 @@
   offset = dissect_per_sequence(tvb, offset, pinfo, tree, hf_index,
                                 ett_h225_ReleaseComplete_UUIE, ReleaseComplete_UUIE_sequence);
 
-  h225_pi.cs_type = H225_RELEASE_COMPLET;
+  /* Add to packet info */
+  h225_pi->cs_type = H225_RELEASE_COMPLET;
+  g_snprintf(h225_pi->frame_label, 50, "%s", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>"));
   return offset;
 }
 static int dissect_releaseComplete(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
@@ -5691,7 +5721,7 @@
   offset = dissect_per_choice(tvb, offset, pinfo, tree, hf_index,
                               ett_h225_FacilityReason, FacilityReason_choice, "FacilityReason",
                               &value);
-	h225_pi.reason = value;
+	h225_pi->reason = value;
 
 
   return offset;
@@ -5760,6 +5790,9 @@
   offset = dissect_per_sequence(tvb, offset, pinfo, tree, hf_index,
                                 ett_h225_Facility_UUIE, Facility_UUIE_sequence);
 
+  /* Add to packet info */
+  h225_pi->cs_type = H225_FACILITY;
+  g_snprintf(h225_pi->frame_label, 50, "%s", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>"));
   return offset;
 }
 static int dissect_facility(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
@@ -5786,6 +5819,12 @@
   offset = dissect_per_sequence(tvb, offset, pinfo, tree, hf_index,
                                 ett_h225_Progress_UUIE, Progress_UUIE_sequence);
 
+  /* Add to packet info */
+  h225_pi->cs_type = H225_PROGRESS;
+  if (contains_faststart == TRUE )
+        g_snprintf(h225_pi->frame_label, 50, "%s OLC (%s)", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>"), h225_pi->frame_label);
+  else 
+        g_snprintf(h225_pi->frame_label, 50, "%s", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>"));
   return offset;
 }
 static int dissect_progress(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
@@ -5805,6 +5844,9 @@
   offset = dissect_per_sequence(tvb, offset, pinfo, tree, hf_index,
                                 ett_h225_Status_UUIE, Status_UUIE_sequence);
 
+  /* Add to packet info */
+  h225_pi->cs_type = H225_STATUS;
+  g_snprintf(h225_pi->frame_label, 50, "%s", val_to_str(h225_pi->cs_type, T_h323_message_body_vals, "<unknown>"));
   return offset;
 }
 static int dissect_status(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
@@ -5917,9 +5959,9 @@
 			val_to_str(message_body_val, T_h323_message_body_vals, "<unknown>"));
         }
 
-	if (h225_pi.msg_type == H225_CS) {
+	if (h225_pi->msg_type == H225_CS) {
 		/* Don't override msg_tag value from IRR */
-		h225_pi.msg_tag = message_body_val;
+		h225_pi->msg_tag = message_body_val;
 	}
 
 	if (contains_faststart == TRUE )
@@ -5974,6 +6016,17 @@
 
 
 static int
+dissect_h225_T_h245Tunneling(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) {
+	offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_h245Tunneling, &(h225_pi->is_h245Tunneling), NULL);
+
+  return offset;
+}
+static int dissect_h245Tunneling(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+  return dissect_h225_T_h245Tunneling(tvb, offset, pinfo, tree, hf_h225_h245Tunneling);
+}
+
+
+static int
 dissect_h225_H245Control_item(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) {
 
 	tvbuff_t *h245_tvb;
@@ -6428,7 +6481,7 @@
 static int
 dissect_h225_RequestSeqNum(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) {
   offset = dissect_per_constrained_integer(tvb, offset, pinfo, tree, hf_index,
-                                           1U, 65535U, &(h225_pi.requestSeqNum), NULL, FALSE);
+                                           1U, 65535U, &(h225_pi->requestSeqNum), NULL, FALSE);
 
 
   return offset;
@@ -7055,7 +7108,7 @@
   offset = dissect_per_choice(tvb, offset, pinfo, tree, hf_index,
                               ett_h225_GatekeeperRejectReason, GatekeeperRejectReason_choice, "GatekeeperRejectReason",
                               &value);
-  h225_pi.reason = value;
+  h225_pi->reason = value;
 
 
   return offset;
@@ -7328,7 +7381,7 @@
   offset = dissect_per_choice(tvb, offset, pinfo, tree, hf_index,
                               ett_h225_RegistrationRejectReason, RegistrationRejectReason_choice, "RegistrationRejectReason",
                               &value);
-  h225_pi.reason = value;
+  h225_pi->reason = value;
 
   return offset;
 }
@@ -7390,7 +7443,7 @@
   offset = dissect_per_choice(tvb, offset, pinfo, tree, hf_index,
                               ett_h225_UnregRequestReason, UnregRequestReason_choice, "UnregRequestReason",
                               &value);
-  h225_pi.reason = value;
+  h225_pi->reason = value;
 
 
   return offset;
@@ -7478,7 +7531,7 @@
   offset = dissect_per_choice(tvb, offset, pinfo, tree, hf_index,
                               ett_h225_UnregRejectReason, UnregRejectReason_choice, "UnregRejectReason",
                               &value);
-  h225_pi.reason = value;
+  h225_pi->reason = value;
 
   return offset;
 }
@@ -7784,7 +7837,7 @@
   offset = dissect_per_choice(tvb, offset, pinfo, tree, hf_index,
                               ett_h225_AdmissionRejectReason, AdmissionRejectReason_choice, "AdmissionRejectReason",
                               &value);
-  h225_pi.reason = value;
+  h225_pi->reason = value;
 
   return offset;
 }
@@ -7917,7 +7970,7 @@
   offset = dissect_per_choice(tvb, offset, pinfo, tree, hf_index,
                               ett_h225_BandRejectReason, BandRejectReason_choice, "BandRejectReason",
                               &value);
-  h225_pi.reason = value;
+  h225_pi->reason = value;
 
   return offset;
 }
@@ -7971,7 +8024,7 @@
   offset = dissect_per_choice(tvb, offset, pinfo, tree, hf_index,
                               ett_h225_DisengageReason, DisengageReason_choice, "DisengageReason",
                               &value);
-  h225_pi.reason = value;
+  h225_pi->reason = value;
 
   return offset;
 }
@@ -8061,7 +8114,7 @@
   offset = dissect_per_choice(tvb, offset, pinfo, tree, hf_index,
                               ett_h225_DisengageRejectReason, DisengageRejectReason_choice, "DisengageRejectReason",
                               &value);
-  h225_pi.reason = value;
+  h225_pi->reason = value;
 
   return offset;
 }
@@ -8212,7 +8265,7 @@
   offset = dissect_per_choice(tvb, offset, pinfo, tree, hf_index,
                               ett_h225_LocationRejectReason, LocationRejectReason_choice, "LocationRejectReason",
                               &value);
-  h225_pi.reason = value;
+  h225_pi->reason = value;
 
   return offset;
 }
@@ -8605,7 +8658,7 @@
   offset = dissect_per_choice(tvb, offset, pinfo, tree, hf_index,
                               ett_h225_InfoRequestNakReason, InfoRequestNakReason_choice, "InfoRequestNakReason",
                               &value);
-  h225_pi.reason = value;
+  h225_pi->reason = value;
 
   return offset;
 }
@@ -8832,7 +8885,7 @@
 			val_to_str(rasmessage_value, RasMessage_vals, "<unknown>"));
 	}
 
-	h225_pi.msg_tag = rasmessage_value;
+	h225_pi->msg_tag = rasmessage_value;
 
   return offset;
 }
@@ -8849,9 +8902,15 @@
 	proto_tree *tr;
 	int offset = 0;
 
+    pi_current++;
+    if(pi_current==5){
+      pi_current=0;
+    }
+    h225_pi=&pi_arr[pi_current];
+
 	/* Init struct for collecting h225_packet_info */
-	reset_h225_packet_info(&(h225_pi));
-	h225_pi.msg_type = H225_CS;
+    reset_h225_packet_info(h225_pi);
+    h225_pi->msg_type = H225_CS;
 
 	if (check_col(pinfo->cinfo, COL_PROTOCOL)){
 		col_set_str(pinfo->cinfo, COL_PROTOCOL, "H.225.0");
@@ -8865,7 +8924,7 @@
 
 	offset = dissect_h225_H323_UserInformation(tvb, offset,pinfo, tr, hf_h225_H323_UserInformation);
 
-	tap_queue_packet(h225_tap, pinfo, &h225_pi);
+	tap_queue_packet(h225_tap, pinfo, h225_pi);
 
 	return offset;
 }
@@ -8875,9 +8934,15 @@
 	proto_tree *tr;
 	guint32 offset=0;
 
+    pi_current++;
+    if(pi_current==5){
+        pi_current=0;
+    }
+    h225_pi=&pi_arr[pi_current];
+
 	/* Init struct for collecting h225_packet_info */
-	reset_h225_packet_info(&(h225_pi));
-	h225_pi.msg_type = H225_RAS;
+    reset_h225_packet_info(h225_pi);
+    h225_pi->msg_type = H225_RAS;
 
 	if (check_col(pinfo->cinfo, COL_PROTOCOL)){
 		col_set_str(pinfo->cinfo, COL_PROTOCOL, "H.225.0");
@@ -8888,12 +8953,13 @@
 
 	offset = dissect_h225_RasMessage(tvb, 0, pinfo,tr, hf_h225_RasMessage );
 
-	ras_call_matching(tvb, pinfo, tr, &(h225_pi));
+	ras_call_matching(tvb, pinfo, tr, h225_pi);
 
-	tap_queue_packet(h225_tap, pinfo, &h225_pi);
+	tap_queue_packet(h225_tap, pinfo, h225_pi);
 
 	return offset;
 }
+
 /*--- proto_register_h225 -------------------------------------------*/
 void proto_register_h225(void) {
 
@@ -12231,8 +12297,10 @@
 	pi->request_available = FALSE;
 	pi->is_faststart = FALSE;
 	pi->is_h245 = FALSE;
+	pi->is_h245Tunneling = FALSE;
 	pi->h245_address = 0;
 	pi->h245_port = 0;
+	pi->frame_label[0] = '\0';
 }
 
 /*
Index: epan/dissectors/packet-h225.h
===================================================================
--- epan/dissectors/packet-h225.h	(revision 13162)
+++ epan/dissectors/packet-h225.h	(working copy)
@@ -1,6 +1,6 @@
 /* Do not modify this file.                                                   */
 /* It is created automatically by the ASN.1 to Ethereal dissector compiler    */
-/* .\packet-h225.h                                                            */
+/* ./packet-h225.h                                                            */
 /* ../../tools/asn2eth.py -X -e -p h225 -c h225.cnf -s packet-h225-template h225.asn */
 
 /* Input file: packet-h225-template.h */
@@ -40,12 +40,20 @@
 } h225_msg_type;
 
 typedef enum _h225_cs_type {
-	H225_SETUP,
-	H225_CALL_PROCEDING,
-	H225_ALERTING,
-	H225_CONNECT,
-	H225_RELEASE_COMPLET,
-	H225_OTHER
+    H225_SETUP,
+    H225_CALL_PROCEDING,
+    H225_CONNECT,
+    H225_ALERTING,
+    H225_INFORMATION,
+    H225_RELEASE_COMPLET,
+    H225_FACILITY,
+    H225_PROGRESS,
+    H225_EMPTY,
+    H225_STATUS,
+    H225_STATUS_INQUIRY,
+    H225_SETUP_ACK,
+    H225_NOTIFY,
+    H225_OTHER
 } h225_cs_type;
 
 typedef struct _h225_packet_info {
@@ -61,8 +69,10 @@
 	/* added for h225 conversations analysis */
 	gboolean is_faststart;		/* true, if faststart field is included */
 	gboolean is_h245;
+	gboolean is_h245Tunneling;
 	guint32 h245_address;
 	guint16 h245_port;
+	gchar frame_label[50]; /* the Fram label used by graph_analysis, what is a abreviation of cinfo */
 } h225_packet_info;
 
 /*
Index: epan/dissectors/packet-q931.c
===================================================================
--- epan/dissectors/packet-q931.c	(revision 13162)
+++ epan/dissectors/packet-q931.c	(working copy)
@@ -33,6 +33,7 @@
 #include <glib.h>
 #include <string.h>
 #include <epan/packet.h>
+#include <epan/tap.h>
 #include <epan/strutil.h>
 #include "nlpid.h"
 #include "packet-q931.h"
@@ -54,6 +55,9 @@
  * http://www.andrews-arnold.co.uk/isdn/q931cause.html
  * http://www.tulatelecom.ru/staff/german/DSSHelp/MessList/InfEl/InfElList.html
  */
+static void reset_q931_packet_info(q931_packet_info *pi);
+static q931_packet_info q931_pi;
+static int q931_tap = -1;
 
 static int proto_q931 					= -1;
 static int hf_q931_discriminator			= -1;
@@ -1211,6 +1215,10 @@
 		return;
 	octet = tvb_get_guint8(tvb, offset);
 	cause_value = octet & 0x7F;
+
+    /* add cause value to packet info for use in tap */
+    q931_pi.cause_value = cause_value;
+
 	proto_tree_add_uint(tree, hf_cause_value, tvb, offset, 1, cause_value);
 	proto_tree_add_boolean(tree, hf_q931_extension_ind, tvb, offset, 1, octet);
 	offset += 1;
@@ -2112,6 +2120,11 @@
 		}
 	}
 
+    /* Collect q931_packet_info */
+    if ( e164_info.e164_number_type == CALLING_PARTY_NUMBER)
+          q931_pi.calling_number = tvb_get_string(tvb, offset, len);
+    if ( e164_info.e164_number_type == CALLED_PARTY_NUMBER)
+          q931_pi.called_number = tvb_get_string(tvb, offset, len);
 }
 
 /*
@@ -2352,6 +2365,9 @@
 	fragment_data *fd_head;
 	tvbuff_t *next_tvb = NULL;
 
+    /* Init struct for collecting q931_packet_info */
+    reset_q931_packet_info(&(q931_pi));
+
 	if (check_col(pinfo->cinfo, COL_PROTOCOL))
 		col_set_str(pinfo->cinfo, COL_PROTOCOL, "Q.931");
 
@@ -2382,6 +2398,10 @@
 			call_ref[0] &= 0x7F;
 			proto_tree_add_bytes(q931_tree, hf_q931_call_ref,
 			    tvb, offset, call_ref_len, call_ref);
+		} else
+        {       /* info for the tap */
+            call_ref[0] &= 0x7F;
+            g_memmove(&q931_pi.crv, call_ref, call_ref_len);
 		}
 		offset += call_ref_len;
 	}
@@ -2689,196 +2709,199 @@
 					proto_tree_add_text(q931_tree, tvb, offset + 4, tvb_reported_length_remaining(tvb, offset + 4), "Message segment");
 					info_element_len += tvb_reported_length_remaining(tvb, offset + 4);
 				}
-			} else if (q931_tree != NULL) {
-				switch ((codeset << 8) | info_element) {
+			} else {
+			    /* we move calling, called number and release cause to not check tree=NULL for the tap used in Voip Calls... */
+                switch ((codeset << 8) | info_element){
+                case CS0 | Q931_IE_CALLING_PARTY_NUMBER:
+	                e164_info.e164_number_type = CALLING_PARTY_NUMBER;
+					dissect_q931_number_ie(tvb,
+					offset + 2, info_element_len,
+					ie_tree,
+                    hf_q931_calling_party_number, e164_info);
+                    break;
+                case CS0 | Q931_IE_CALLED_PARTY_NUMBER:
+                    e164_info.e164_number_type = CALLED_PARTY_NUMBER;
+                    dissect_q931_number_ie(tvb,
+                    offset + 2, info_element_len,
+                    ie_tree,
+                    hf_q931_called_party_number, e164_info);
+                    break;
+                case CS0 | Q931_IE_CAUSE:
+                    dissect_q931_cause_ie(tvb,
+                    offset + 2, info_element_len,
+                    ie_tree,
+                    hf_q931_cause_value);
+                    break;
+                }
+				if (q931_tree != NULL) {
+					switch ((codeset << 8) | info_element) {
 
-				case CS0 | Q931_IE_BEARER_CAPABILITY:
-				case CS0 | Q931_IE_LOW_LAYER_COMPAT:
-					dissect_q931_bearer_capability_ie(tvb,
-					    offset + 2, info_element_len,
-					    ie_tree);
-					break;
+					case CS0 | Q931_IE_BEARER_CAPABILITY:
+					case CS0 | Q931_IE_LOW_LAYER_COMPAT:
+						dissect_q931_bearer_capability_ie(tvb,
+							offset + 2, info_element_len,
+							ie_tree);
+						break;
 
-				case CS0 | Q931_IE_CAUSE:
-					dissect_q931_cause_ie(tvb,
-					    offset + 2, info_element_len,
-					    ie_tree,
-					    hf_q931_cause_value);
-					break;
+					case CS0 | Q931_IE_CALL_STATE:
+						dissect_q931_call_state_ie(tvb,
+							offset + 2, info_element_len,
+							ie_tree);
+						break;
 
-				case CS0 | Q931_IE_CALL_STATE:
-					dissect_q931_call_state_ie(tvb,
-					    offset + 2, info_element_len,
-					    ie_tree);
-					break;
+					case CS0 | Q931_IE_CHANNEL_IDENTIFICATION:
+						dissect_q931_channel_identification_ie(
+							tvb, offset + 2, info_element_len,
+							ie_tree);
+						break;
 
-				case CS0 | Q931_IE_CHANNEL_IDENTIFICATION:
-					dissect_q931_channel_identification_ie(
-					    tvb, offset + 2, info_element_len,
-					    ie_tree);
-					break;
+					case CS0 | Q931_IE_PROGRESS_INDICATOR:
+						dissect_q931_progress_indicator_ie(tvb,
+							offset + 2, info_element_len,
+							ie_tree);
+						break;
 
-				case CS0 | Q931_IE_PROGRESS_INDICATOR:
-					dissect_q931_progress_indicator_ie(tvb,
-					    offset + 2, info_element_len,
-					    ie_tree);
-					break;
+					case CS0 | Q931_IE_NETWORK_SPECIFIC_FACIL:
+					case CS0 | Q931_IE_TRANSIT_NETWORK_SEL:
+						dissect_q931_ns_facilities_ie(tvb,
+							offset + 2, info_element_len,
+							ie_tree);
+						break;
 
-				case CS0 | Q931_IE_NETWORK_SPECIFIC_FACIL:
-				case CS0 | Q931_IE_TRANSIT_NETWORK_SEL:
-					dissect_q931_ns_facilities_ie(tvb,
-					    offset + 2, info_element_len,
-					    ie_tree);
-					break;
+					case CS0 | Q931_IE_NOTIFICATION_INDICATOR:
+						dissect_q931_notification_indicator_ie(
+							tvb, offset + 2, info_element_len,
+							ie_tree);
+						break;
 
-				case CS0 | Q931_IE_NOTIFICATION_INDICATOR:
-					dissect_q931_notification_indicator_ie(
-					    tvb, offset + 2, info_element_len,
-					    ie_tree);
-					break;
+					case CS0 | Q931_IE_DISPLAY:
+						dissect_q931_ia5_ie(tvb, offset + 2,
+							info_element_len, ie_tree,
+							"Display information");
+						break;
 
-				case CS0 | Q931_IE_DISPLAY:
-					dissect_q931_ia5_ie(tvb, offset + 2,
-					    info_element_len, ie_tree,
-					    "Display information");
-					break;
+					case CS0 | Q931_IE_DATE_TIME:
+						dissect_q931_date_time_ie(tvb,
+							offset + 2, info_element_len,
+							ie_tree);
+						break;
 
-				case CS0 | Q931_IE_DATE_TIME:
-					dissect_q931_date_time_ie(tvb,
-					    offset + 2, info_element_len,
-					    ie_tree);
-					break;
+					case CS0 | Q931_IE_KEYPAD_FACILITY:
+						dissect_q931_ia5_ie(tvb, offset + 2,
+							info_element_len, ie_tree,
+							"Keypad facility");
+						break;
 
-				case CS0 | Q931_IE_KEYPAD_FACILITY:
-					dissect_q931_ia5_ie(tvb, offset + 2,
-					    info_element_len, ie_tree,
-					    "Keypad facility");
-					break;
+					case CS0 | Q931_IE_SIGNAL:
+						dissect_q931_signal_ie(tvb,
+							offset + 2, info_element_len,
+							ie_tree);
+						break;
 
-				case CS0 | Q931_IE_SIGNAL:
-					dissect_q931_signal_ie(tvb,
-					    offset + 2, info_element_len,
-					    ie_tree);
-					break;
+					case CS0 | Q931_IE_INFORMATION_RATE:
+						dissect_q931_information_rate_ie(tvb,
+							offset + 2, info_element_len,
+							ie_tree);
+						break;
 
-				case CS0 | Q931_IE_INFORMATION_RATE:
-					dissect_q931_information_rate_ie(tvb,
-					    offset + 2, info_element_len,
-					    ie_tree);
-					break;
+					case CS0 | Q931_IE_E2E_TRANSIT_DELAY:
+						dissect_q931_e2e_transit_delay_ie(tvb,
+							offset + 2, info_element_len,
+							ie_tree);
+						break;
 
-				case CS0 | Q931_IE_E2E_TRANSIT_DELAY:
-					dissect_q931_e2e_transit_delay_ie(tvb,
-					    offset + 2, info_element_len,
-					    ie_tree);
-					break;
+					case CS0 | Q931_IE_TD_SELECTION_AND_INT:
+						dissect_q931_td_selection_and_int_ie(
+							tvb, offset + 2, info_element_len,
+							ie_tree);
+						break;
 
-				case CS0 | Q931_IE_TD_SELECTION_AND_INT:
-					dissect_q931_td_selection_and_int_ie(
-					    tvb, offset + 2, info_element_len,
-					    ie_tree);
-					break;
+					case CS0 | Q931_IE_PL_BINARY_PARAMETERS:
+						dissect_q931_pl_binary_parameters_ie(
+							tvb, offset + 2, info_element_len,
+							ie_tree);
+						break;
 
-				case CS0 | Q931_IE_PL_BINARY_PARAMETERS:
-					dissect_q931_pl_binary_parameters_ie(
-					    tvb, offset + 2, info_element_len,
-					    ie_tree);
-					break;
+					case CS0 | Q931_IE_PL_WINDOW_SIZE:
+						dissect_q931_pl_window_size_ie(tvb,
+							offset + 2, info_element_len,
+							ie_tree);
+						break;
 
-				case CS0 | Q931_IE_PL_WINDOW_SIZE:
-					dissect_q931_pl_window_size_ie(tvb,
-					    offset + 2, info_element_len,
-					    ie_tree);
-					break;
+					case CS0 | Q931_IE_PACKET_SIZE:
+						dissect_q931_packet_size_ie(tvb,
+							offset + 2, info_element_len,
+							ie_tree);
+						break;
 
-				case CS0 | Q931_IE_PACKET_SIZE:
-					dissect_q931_packet_size_ie(tvb,
-					    offset + 2, info_element_len,
-					    ie_tree);
-					break;
+					case CS0 | Q931_IE_CUG:
+						dissect_q931_cug_ie(tvb,
+							offset + 2, info_element_len,
+							ie_tree);
+						break;
 
-				case CS0 | Q931_IE_CUG:
-					dissect_q931_cug_ie(tvb,
-					    offset + 2, info_element_len,
-					    ie_tree);
-					break;
+					case CS0 | Q931_IE_REVERSE_CHARGE_IND:
+						dissect_q931_reverse_charge_ind_ie(tvb,
+							offset + 2, info_element_len,
+							ie_tree);
+						break;
 
-				case CS0 | Q931_IE_REVERSE_CHARGE_IND:
-					dissect_q931_reverse_charge_ind_ie(tvb,
-					    offset + 2, info_element_len,
-					    ie_tree);
-					break;
+					case CS0 | Q931_IE_CONNECTED_NUMBER_DEFAULT:
+						dissect_q931_number_ie(tvb,
+							offset + 2, info_element_len,
+							ie_tree,
+							hf_q931_connected_number, e164_info);
+						break;
 
-				case CS0 | Q931_IE_CALLING_PARTY_NUMBER:
-					e164_info.e164_number_type = CALLING_PARTY_NUMBER;
-					dissect_q931_number_ie(tvb,
-					    offset + 2, info_element_len,
-					    ie_tree,
-					    hf_q931_calling_party_number, e164_info);
-					break;
+					case CS0 | Q931_IE_REDIRECTING_NUMBER:
+						dissect_q931_number_ie(tvb,
+							offset + 2, info_element_len,
+							ie_tree,
+							hf_q931_redirecting_number, e164_info);
+						break;
 
-				case CS0 | Q931_IE_CONNECTED_NUMBER_DEFAULT:
-					dissect_q931_number_ie(tvb,
-					    offset + 2, info_element_len,
-					    ie_tree,
-					    hf_q931_connected_number, e164_info);
-					break;
+					case CS0 | Q931_IE_CALLING_PARTY_SUBADDR:
+					case CS0 | Q931_IE_CALLED_PARTY_SUBADDR:
+						dissect_q931_party_subaddr_ie(tvb,
+							offset + 2, info_element_len,
+							ie_tree);
+						break;
 
-				case CS0 | Q931_IE_CALLED_PARTY_NUMBER:
-					e164_info.e164_number_type = CALLED_PARTY_NUMBER;
-					dissect_q931_number_ie(tvb,
-					    offset + 2, info_element_len,
-					    ie_tree,
-					    hf_q931_called_party_number, e164_info);
-					break;
+					case CS0 | Q931_IE_RESTART_INDICATOR:
+						dissect_q931_restart_indicator_ie(tvb,
+							offset + 2, info_element_len,
+							ie_tree);
+						break;
 
-				case CS0 | Q931_IE_REDIRECTING_NUMBER:
-					dissect_q931_number_ie(tvb,
-					    offset + 2, info_element_len,
-					    ie_tree,
-					    hf_q931_redirecting_number, e164_info);
-					break;
+					case CS0 | Q931_IE_HIGH_LAYER_COMPAT:
+						dissect_q931_high_layer_compat_ie(tvb,
+							offset + 2, info_element_len,
+							ie_tree);
+						break;
 
-				case CS0 | Q931_IE_CALLING_PARTY_SUBADDR:
-				case CS0 | Q931_IE_CALLED_PARTY_SUBADDR:
-					dissect_q931_party_subaddr_ie(tvb,
-					    offset + 2, info_element_len,
-					    ie_tree);
-					break;
+					case CS0 | Q931_IE_USER_USER:
+						dissect_q931_user_user_ie(tvb,
+							offset + 2, info_element_len,
+							ie_tree);
+						break;
 
-				case CS0 | Q931_IE_RESTART_INDICATOR:
-					dissect_q931_restart_indicator_ie(tvb,
-					    offset + 2, info_element_len,
-					    ie_tree);
-					break;
-
-				case CS0 | Q931_IE_HIGH_LAYER_COMPAT:
-					dissect_q931_high_layer_compat_ie(tvb,
-					    offset + 2, info_element_len,
-					    ie_tree);
-					break;
-
-				case CS0 | Q931_IE_USER_USER:
-					dissect_q931_user_user_ie(tvb,
-					    offset + 2, info_element_len,
-					    ie_tree);
-					break;
-
-				default:
-					proto_tree_add_text(ie_tree, tvb,
-					    offset + 2, info_element_len,
-					    "Data: %s",
-					    bytes_to_str(
-					      tvb_get_ptr(tvb, offset + 2,
-					          info_element_len),
-						  info_element_len));
-					break;
+					default:
+						proto_tree_add_text(ie_tree, tvb,
+							offset + 2, info_element_len,
+							"Data: %s",
+							bytes_to_str(
+							  tvb_get_ptr(tvb, offset + 2,
+								  info_element_len),
+							  info_element_len));
+						break;
+					}
 				}
 			}
 			offset += 1 + 1 + info_element_len;
 		}
 		codeset = locked_codeset;
 	}
+	tap_queue_packet(q931_tap, pinfo, &q931_pi);
 }
 
 /*
@@ -3143,6 +3166,8 @@
 	    "Reassemble segmented Q.931 messages",
 	    "Reassemble segmented Q.931 messages (Q.931 - Annex H)",
 	    &q931_reassembly);
+       /* Register for tapping */
+       q931_tap = register_tap("q931");
 }
 
 void
@@ -3166,3 +3191,17 @@
 	 */
 	heur_dissector_add("tcp", dissect_q931_tpkt, proto_q931);
 }
+
+static void reset_q931_packet_info(q931_packet_info *pi)
+{
+    if(pi == NULL) {
+        return;
+    }
+
+    g_free(pi->calling_number);
+    g_free(pi->called_number);
+    pi->calling_number = NULL;
+    pi->called_number = NULL;
+    pi->cause_value = 0xFF;
+    pi->crv = -1;
+}
Index: epan/dissectors/packet-q931.h
===================================================================
--- epan/dissectors/packet-q931.h	(revision 13162)
+++ epan/dissectors/packet-q931.h	(working copy)
@@ -44,8 +44,20 @@
 
 extern const value_string q931_cause_location_vals[];
 
-extern const value_string q931_cause_code_vals[];
+typedef struct _q931_packet_info {
+       gchar *calling_number;
+       gchar *called_number;
+       guint8 cause_value;
+       gint32 crv;
+} q931_packet_info;
 
+/*
+ * the following allows TAP code access to the messages
+ * without having to duplicate it. With MSVC and a
+ * libethereal.dll, we need a special declaration.
+ */
+ETH_VAR_IMPORT const value_string q931_cause_code_vals[];
+
 extern const value_string q931_protocol_discriminator_vals[];
 
 #endif
Index: epan/dissectors/packet-sdp.c
===================================================================
--- epan/dissectors/packet-sdp.c	(revision 13162)
+++ epan/dissectors/packet-sdp.c	(working copy)
@@ -57,6 +57,9 @@
 #include <epan/conversation.h>
 #include <epan/strutil.h>
 
+#include "tap.h"
+#include "packet-sdp.h"
+
 #include "packet-rtp.h"
 #include "rtp_pt.h"
 #include "packet-rtcp.h"
@@ -68,6 +71,10 @@
 
 static dissector_handle_t t38_handle=NULL;
 
+static void reset_sdp_packet_info(sdp_packet_info *pi);
+static int sdp_tap = -1;
+static sdp_packet_info *sdp_pi;
+
 static int proto_sdp = -1;
 
 /* Top level fields */
@@ -213,6 +220,10 @@
     guint32 	ipaddr[4];
 	gint		n;
 
+    /* Initialise packet info for passing to tap */
+    sdp_pi = g_malloc(sizeof(sdp_packet_info));
+    sdp_pi->summary_str[0] = '\0';
+
 	/* Initialise RTP channel info */
 	transport_info.connection_address=NULL;
 	transport_info.connection_type=NULL;
@@ -436,6 +447,8 @@
 		proto_tree_add_text(sdp_tree, tvb, offset, datalen,
 		    "Data (%d bytes)", datalen);
 	}
+    /* Report this packet to the tap */
+    tap_queue_packet(sdp_tap, pinfo, sdp_pi);
 }
 
 static void
@@ -884,6 +897,7 @@
       media_format = tvb_get_string(tvb, offset, tokenlen);
       proto_tree_add_string(sdp_media_tree, hf_media_format, tvb, offset,
                              tokenlen, val_to_str(atol(media_format), rtp_payload_type_vals, "%u"));
+      g_snprintf(sdp_pi->summary_str, 50, "%s %s", sdp_pi->summary_str, val_to_str(atol(media_format), rtp_payload_type_short_vals, "%u"));
       g_free(media_format);
     } else {
       proto_tree_add_item(sdp_media_tree, hf_media_format, tvb,
@@ -1167,6 +1181,9 @@
    * on Windows without stuffing it into the Big Transfer Vector).
    */
   register_dissector("sdp", dissect_sdp, proto_sdp);
+
+  /* Register for tapping */
+  sdp_tap = register_tap("sdp");
 }
 
 void
Index: epan/dissectors/packet-sdp.h
===================================================================
--- epan/dissectors/packet-sdp.h	(revision 0)
+++ epan/dissectors/packet-sdp.h	(revision 0)
@@ -0,0 +1,31 @@
+/* packet-sdp.h
+ * Routines for SDP packet disassembly (RFC 2327)
+ *
+ * Jason Lango <jal@xxxxxxxxxx>
+ * Liberally copied from packet-http.c, by Guy Harris <guy@xxxxxxxxxxxx>
+ * 2005 Alejandro Vaquero <alejandro.vaquero@xxxxxxxxx>, add support for tap
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@xxxxxxxxxxxx>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+typedef struct _sdp_packet_info {
+		gchar summary_str[50];		/* SDP summary string for VoIP calls graph analysis */
+} sdp_packet_info;
Index: epan/dissectors/packet-h245.c
===================================================================
--- epan/dissectors/packet-h245.c	(revision 13162)
+++ epan/dissectors/packet-h245.c	(working copy)
@@ -1,6 +1,6 @@
 /* Do not modify this file.                                                   */
 /* It is created automatically by the ASN.1 to Ethereal dissector compiler    */
-/* .\packet-h245.c                                                            */
+/* ./packet-h245.c                                                            */
 /* ../../tools/asn2eth.py -X -e -p h245 -c h245.cnf -s packet-h245-template h245.asn */
 
 /* Input file: packet-h245-template.c */
@@ -77,7 +77,10 @@
 static int hf_h245Manufacturer = -1;
 static int h245_tap = -1;
 static int ett_h245 = -1;
-static h245_packet_info h245_pi;
+static int h245dg_tap = -1;
+static h245_packet_info pi_arr[5]; /* We assuming a maximum of 5 H245 messaages per packet */
+static int pi_current=0;
+h245_packet_info *h245_pi=NULL;
 
 static gboolean h245_reassembly = TRUE;
 static gboolean h245_shorttypes = FALSE;
@@ -171,6 +174,34 @@
 	{ 12,	"GC" },
 	{  0, NULL }
 };
+static const value_string h245_AudioCapability_short_vals[] = {
+        {  0, "nonStd" },
+        {  1, "g711A" },
+        {  2, "g711A56k" },
+        {  3, "g711U" },
+        {  4, "g711U56k" },
+        {  5, "g722-64k" },
+        {  6, "g722-56k" },
+        {  7, "g722-48k" },
+        {  8, "g7231" },
+        {  9, "g728" },
+        { 10, "g729" },
+        { 11, "g729A" },
+        { 12, "is11172" },
+        { 13, "is13818" },
+        { 14, "g729B" },
+        { 15, "g729AB" },
+        { 16, "g7231C" },
+        { 17, "gsmFR" },
+        { 18, "gsmHR" },
+        { 19, "gsmEFR" },
+        { 20, "generic" },
+        { 21, "g729Ext" },
+        { 22, "vbd" },
+        { 23, "audioTelEvent" },
+        { 24, "audioTone" },
+        {  0, NULL }
+};
 
 /* To put the codec type only in COL_INFO when
    an OLC is read */
@@ -2418,7 +2449,7 @@
                                 ett_h245_MasterSlaveDetermination, MasterSlaveDetermination_sequence);
 
 
-  h245_pi.msg_type = H245_MastSlvDet;
+  h245_pi->msg_type = H245_MastSlvDet;
   return offset;
 }
 static int dissect_masterSlaveDetermination(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
@@ -5460,6 +5491,7 @@
                               &value);
 
         codec_type = val_to_str(value, h245_Application_vals, "<unknown>");
+		if (h245_pi != NULL) g_snprintf(h245_pi->frame_label, 50, "%s %s", h245_pi->frame_label, codec_type);
 
   return offset;
 }
@@ -7226,7 +7258,9 @@
                               &value);
 
         codec_type = val_to_str(value, h245_VideoCapability_vals, "<unknown>");
+		if (h245_pi != NULL) g_snprintf(h245_pi->frame_label, 50, "%s %s", h245_pi->frame_label, codec_type);
 
+
   return offset;
 }
 
@@ -7595,8 +7629,10 @@
                               ett_h245_AudioCapability, AudioCapability_choice, "AudioCapability",
                               &value);
 
-        codec_type = val_to_str(value, h245_AudioCapability_vals, "<unknown>");
+        codec_type = val_to_str(value, h245_AudioCapability_short_vals, "<unknown>");
+		if (h245_pi != NULL) g_snprintf(h245_pi->frame_label, 50, "%s %s", h245_pi->frame_label, val_to_str(value, h245_AudioCapability_short_vals, "ukn"));
 
+
   return offset;
 }
 
@@ -8187,7 +8223,7 @@
                                 ett_h245_TerminalCapabilitySet, TerminalCapabilitySet_sequence);
 
 
-  h245_pi.msg_type = H245_TermCapSet;
+  h245_pi->msg_type = H245_TermCapSet;
   return offset;
 }
 static int dissect_terminalCapabilitySet(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
@@ -10089,7 +10125,7 @@
                                 ett_h245_OpenLogicalChannel, OpenLogicalChannel_sequence);
 
 
-  h245_pi.msg_type = H245_OpenLogChn;
+  if (h245_pi != NULL) h245_pi->msg_type = H245_OpenLogChn;
   return offset;
 }
 static int dissect_openLogicalChannel(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
@@ -10161,7 +10197,7 @@
                                 ett_h245_CloseLogicalChannel, CloseLogicalChannel_sequence);
 
 
-  h245_pi.msg_type = H245_CloseLogChn;
+  h245_pi->msg_type = H245_CloseLogChn;
   return offset;
 }
 static int dissect_closeLogicalChannel(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
@@ -12166,6 +12202,20 @@
 
         col_set_fence(pinfo->cinfo,COL_INFO);
 
+    /* Add to packet info */
+
+    /* if it is TCS*/
+    if ((codec_type != NULL) && ( value == 2))
+                g_snprintf(h245_pi->frame_label, 50, "%s (%s) ",val_to_str(value, h245_RequestMessage_short_vals, "UKN"), h245_pi->frame_label);
+    else
+                g_snprintf(h245_pi->frame_label, 50, "%s ", val_to_str(value, h245_RequestMessage_short_vals, "UKN"));
+
+    g_snprintf(h245_pi->comment, 50, "%s %s ", h245_pi->comment, val_to_str(value, h245_RequestMessage_vals, "<unknown>"));
+
+    /* if it is OLC or RM*/
+    if ((codec_type != NULL) && (( value == 3) || ( value == 8)))
+                g_snprintf(h245_pi->frame_label, 50, "%s (%s) ", h245_pi->frame_label, codec_type);
+
   return offset;
 }
 static int dissect_request(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
@@ -12208,7 +12258,7 @@
                                 ett_h245_MasterSlaveDeterminationAck, MasterSlaveDeterminationAck_sequence);
 
 
-  h245_pi.msg_type = H245_MastSlvDetAck;
+  h245_pi->msg_type = H245_MastSlvDetAck;
   return offset;
 }
 static int dissect_masterSlaveDeterminationAck(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
@@ -12249,7 +12299,7 @@
                                 ett_h245_MasterSlaveDeterminationReject, MasterSlaveDeterminationReject_sequence);
 
 
-  h245_pi.msg_type = H245_MastSlvDetRjc;
+  h245_pi->msg_type = H245_MastSlvDetRjc;
   return offset;
 }
 static int dissect_masterSlaveDeterminationReject(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
@@ -12267,7 +12317,7 @@
                                 ett_h245_TerminalCapabilitySetAck, TerminalCapabilitySetAck_sequence);
 
 
-  h245_pi.msg_type = H245_TermCapSetAck;
+  h245_pi->msg_type = H245_TermCapSetAck;
   return offset;
 }
 static int dissect_terminalCapabilitySetAck(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
@@ -12340,7 +12390,7 @@
                                 ett_h245_TerminalCapabilitySetReject, TerminalCapabilitySetReject_sequence);
 
 
-  h245_pi.msg_type = H245_TermCapSetRjc;
+  h245_pi->msg_type = H245_TermCapSetRjc;
   return offset;
 }
 static int dissect_terminalCapabilitySetReject(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
@@ -12510,7 +12560,7 @@
                                 ett_h245_OpenLogicalChannelAck, OpenLogicalChannelAck_sequence);
 
 
-  h245_pi.msg_type = H245_OpenLogChnAck;
+  h245_pi->msg_type = H245_OpenLogChnAck;
   return offset;
 }
 static int dissect_openLogicalChannelAck(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
@@ -12578,7 +12628,7 @@
                                 ett_h245_OpenLogicalChannelReject, OpenLogicalChannelReject_sequence);
 
 
-  h245_pi.msg_type = H245_OpenLogChnRjc;
+  h245_pi->msg_type = H245_OpenLogChnRjc;
   return offset;
 }
 static int dissect_openLogicalChannelReject(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
@@ -12596,7 +12646,7 @@
                                 ett_h245_CloseLogicalChannelAck, CloseLogicalChannelAck_sequence);
 
 
-  h245_pi.msg_type = H245_CloseLogChnAck;
+  h245_pi->msg_type = H245_CloseLogChnAck;
   return offset;
 }
 static int dissect_closeLogicalChannelAck(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
@@ -13867,6 +13917,10 @@
 
 	col_set_fence(pinfo->cinfo,COL_INFO);
 
+    /* Add to packet info */
+    g_snprintf(h245_pi->frame_label, 50, "%s %s ", h245_pi->frame_label, val_to_str(value, h245_ResponseMessage_short_vals, "UKN"));
+    g_snprintf(h245_pi->comment, 50, "%s %s ", h245_pi->comment, val_to_str(value, h245_ResponseMessage_vals, "<unknown>"));
+
   return offset;
 }
 static int dissect_response(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
@@ -15032,7 +15086,11 @@
 	}
 
 	col_set_fence(pinfo->cinfo,COL_INFO);
+    /* Add to packet info */
+    g_snprintf(h245_pi->frame_label, 50, "%s %s ", h245_pi->frame_label, val_to_str(value, h245_CommandMessage_short_vals, "UKN"));
+    g_snprintf(h245_pi->comment, 50, "%s %s ", h245_pi->comment, val_to_str(value, h245_CommandMessage_vals, "<unknown>"));
 
+
   return offset;
 }
 static int dissect_command(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
@@ -15076,7 +15134,7 @@
                                 ett_h245_MasterSlaveDeterminationRelease, MasterSlaveDeterminationRelease_sequence);
 
 
-  h245_pi.msg_type = H245_MastSlvDetRls;
+  h245_pi->msg_type = H245_MastSlvDetRls;
   return offset;
 }
 static int dissect_masterSlaveDeterminationRelease(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
@@ -15093,7 +15151,7 @@
                                 ett_h245_TerminalCapabilitySetRelease, TerminalCapabilitySetRelease_sequence);
 
 
-  h245_pi.msg_type = H245_TermCapSetRls;
+  h245_pi->msg_type = H245_TermCapSetRls;
   return offset;
 }
 static int dissect_terminalCapabilitySetRelease(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
@@ -15111,7 +15169,7 @@
                                 ett_h245_OpenLogicalChannelConfirm, OpenLogicalChannelConfirm_sequence);
 
 
-  h245_pi.msg_type = H245_OpenLogChnCnf;
+  h245_pi->msg_type = H245_OpenLogChnCnf;
   return offset;
 }
 static int dissect_openLogicalChannelConfirm(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
@@ -16193,6 +16251,9 @@
 	}
 
 	col_set_fence(pinfo->cinfo,COL_INFO);
+    /* Add to packet info */
+    g_snprintf(h245_pi->frame_label, 50, "%s %s ", h245_pi->frame_label, val_to_str(value, h245_IndicationMessage_short_vals, "UKN"));
+    g_snprintf(h245_pi->comment, 50, "%s %s ", h245_pi->comment, val_to_str(value, h245_IndicationMessage_vals, "<unknown>"));
 
   return offset;
 }
@@ -16255,12 +16316,18 @@
 void
 dissect_h245(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
 {
-	reset_h245_packet_info(&(h245_pi));
-        h245_pi.msg_type = H245_OTHER;
+    pi_current++;
+    if(pi_current==5){
+        pi_current=0;
+    }
+    h245_pi=&pi_arr[pi_current];
 
+    reset_h245_packet_info(h245_pi);
+       h245_pi->msg_type = H245_OTHER;
+
 	dissect_tpkt_encap(tvb, pinfo, parent_tree, h245_reassembly, MultimediaSystemControlMessage_handle);
 
-	tap_queue_packet(h245_tap, pinfo, &h245_pi);
+	tap_queue_packet(h245_tap, pinfo, h245_pi);
 }
 
 void
@@ -16270,7 +16337,15 @@
 	proto_tree *tr;
 	guint32 offset=0;
 
+    pi_current++;
+    if(pi_current==5){
+      pi_current=0;
+    }
+    h245_pi=&pi_arr[pi_current];
 
+    reset_h245_packet_info(h245_pi);
+    h245_pi->msg_type = H245_OTHER;
+
 	if (check_col(pinfo->cinfo, COL_PROTOCOL)){
 		col_set_str(pinfo->cinfo, COL_PROTOCOL, "H.245");
 	}
@@ -16278,9 +16353,24 @@
 	it=proto_tree_add_protocol_format(parent_tree, proto_h245, tvb, 0, tvb_length(tvb), "H.245");
 	tr=proto_item_add_subtree(it, ett_h245);
 	dissect_h245_MultimediaSystemControlMessage(tvb, offset, pinfo ,tr, hf_h245_pdu_type);
+	tap_queue_packet(h245dg_tap, pinfo, h245_pi);
 }
 
+int
+dissect_h245_OpenLogicalChannelCodec(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index, char *codec_str) {
+  offset = dissect_per_sequence(tvb, offset, pinfo, tree, hf_index,
+                                ett_h245_OpenLogicalChannel, OpenLogicalChannel_sequence);
 
+
+  if (h245_pi != NULL) h245_pi->msg_type = H245_OpenLogChn;
+
+  if (codec_str){
+        strcpy(codec_str, codec_type);
+  }
+
+  return offset;
+}
+
 /*--- proto_register_h245 -------------------------------------------*/
 void proto_register_h245(void) {
 
@@ -22148,6 +22238,7 @@
   nsp_object_dissector_table = register_dissector_table("h245.nsp.object", "H.245 NonStandardParameter (object)", FT_STRING, BASE_NONE);
   nsp_h221_dissector_table = register_dissector_table("h245.nsp.h221", "H.245 NonStandardParameter (h221)", FT_UINT32, BASE_HEX);
   h245_tap = register_tap("h245");
+  h245dg_tap = register_tap("h245dg");
 
   register_ber_oid_name("0.0.8.239.1.1","itu-t(0) recommendation(0) h(8) h239(239) generic-capabilities(1) h239ControlCapability(1)");
   register_ber_oid_name("0.0.8.239.1.2","itu-t(0) recommendation(0) h(8) h239(239) generic-capabilities(1) h239ExtendedVideoCapability(2)");
@@ -22187,5 +22278,7 @@
         }
 
         pi->msg_type = H245_OTHER;
+		pi->frame_label[0] = '\0';
+		sprintf(pi->comment, "H245 ");
 }
 
Index: epan/dissectors/packet-h245.h
===================================================================
--- epan/dissectors/packet-h245.h	(revision 13162)
+++ epan/dissectors/packet-h245.h	(working copy)
@@ -1,6 +1,6 @@
 /* Do not modify this file.                                                   */
 /* It is created automatically by the ASN.1 to Ethereal dissector compiler    */
-/* .\packet-h245.h                                                            */
+/* ./packet-h245.h                                                            */
 /* ../../tools/asn2eth.py -X -e -p h245 -c h245.cnf -s packet-h245-template h245.asn */
 
 /* Input file: packet-h245-template.h */
@@ -52,6 +52,8 @@
 
 typedef struct _h245_packet_info {
         h245_msg_type msg_type;         /* type of message */
+        gchar frame_label[50];          /* the Frame label used by graph_analysis, what is a abreviation of cinfo */
+        gchar comment[50];                      /* the Frame Comment used by graph_analysis, what is a message desc */
 } h245_packet_info;
 
 
@@ -65,7 +67,9 @@
 
 /*--- End of included file: packet-h245-exp.h ---*/
 
+int dissect_h245_OpenLogicalChannelCodec(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index, char *codec_str);
 
+
 #endif  /* PACKET_H245_H */
 
 
Index: epan/dissectors/packet-isup.c
===================================================================
--- epan/dissectors/packet-isup.c	(revision 13162)
+++ epan/dissectors/packet-isup.c	(working copy)
@@ -1315,6 +1315,10 @@
 static dissector_handle_t sdp_handle = NULL;
 static dissector_handle_t q931_ie_handle = NULL; 
 
+/* Info for the tap that must be passed between procedures */
+gchar *tap_called_number = NULL;
+gchar *tap_calling_number = NULL;
+
 /* ------------------------------------------------------------------
   Mapping number to ASCII-character
  ------------------------------------------------------------------ */
@@ -1461,6 +1465,7 @@
     proto_tree_add_string(address_digits_tree, hf_isup_called, parameter_tvb, 
 	  offset - length, length, called_number);
   }
+  tap_called_number = g_strdup(called_number);
 }
 /* ------------------------------------------------------------------
   Dissector Parameter  Subsequent number
@@ -2868,8 +2873,8 @@
   } else {
     proto_tree_add_string(address_digits_tree, hf_isup_calling, parameter_tvb,
 	  offset - length, length, calling_number);
-
   }
+  tap_calling_number = g_strdup(calling_number);
 }
 /* ------------------------------------------------------------------
   Dissector Parameter Original called  number
@@ -5143,9 +5148,9 @@
    offset +=  MESSAGE_TYPE_LENGTH;
 
    tap_rec.message_type = message_type;
+   tap_rec.calling_number = NULL;
+   tap_rec.called_number = NULL;
 
-   tap_queue_packet(isup_tap, pinfo, &tap_rec);
-
    parameter_tvb = tvb_new_subset(message_tvb, offset, -1, -1);
 
    /* distinguish between message types:*/
@@ -5359,7 +5364,11 @@
    }
    else if (message_type !=MESSAGE_TYPE_CHARGE_INFO)
      proto_tree_add_text(isup_tree, message_tvb, 0, 0, "No optional parameters are possible with this message type");
+   /* if there are calling/called number, we'll get them for the tap */
 
+   tap_rec.calling_number=tap_calling_number;
+   tap_rec.called_number=tap_called_number;
+   tap_queue_packet(isup_tap, pinfo, &tap_rec);
 }
 
 /* ------------------------------------------------------------------ */
Index: epan/dissectors/packet-isup.h
===================================================================
--- epan/dissectors/packet-isup.h	(revision 13162)
+++ epan/dissectors/packet-isup.h	(working copy)
@@ -28,6 +28,9 @@
 
 typedef struct _isup_tap_rec_t {
     guint8		message_type;
+    /* added for VoIP calls analysis, see gtk/voip_calls.c*/
+    gchar           *called_number;
+    gchar           *calling_number;
 } isup_tap_rec_t;
 
 
Index: epan/dissectors/packet-rtp.c
===================================================================
--- epan/dissectors/packet-rtp.c	(revision 13162)
+++ epan/dissectors/packet-rtp.c	(working copy)
@@ -190,6 +190,38 @@
 	{ 0,		NULL },
 };
 
+const value_string rtp_payload_type_short_vals[] =
+{
+       { PT_PCMU,      "g711U" },
+       { PT_1016,      "fs-1016" },
+       { PT_G721,      "g721" },
+       { PT_GSM,       "GSM" },
+       { PT_G723,      "g723" },
+       { PT_DVI4_8000, "DVI4 8k" },
+       { PT_DVI4_16000, "DVI4 16k" },
+       { PT_LPC,       "Exp. from Xerox PARC" },
+       { PT_PCMA,      "g711A" },
+       { PT_G722,      "g722" },
+       { PT_L16_STEREO, "16-bit audio, stereo" },
+       { PT_L16_MONO,  "16-bit audio, monaural" },
+       { PT_QCELP,     "Qualcomm" },
+       { PT_CN,        "CN" },
+       { PT_MPA,       "MPEG-I/II Audio"},
+       { PT_G728,      "g728" },
+       { PT_DVI4_11025, "DVI4 11k" },
+       { PT_DVI4_22050, "DVI4 22k" },
+       { PT_G729,      "g729" },
+       { PT_CN_OLD,    "CN(old)" },
+       { PT_CELB,      "CellB" },
+       { PT_JPEG,      "JPEG" },
+       { PT_NV,        "NV" },
+       { PT_H261,      "h261" },
+       { PT_MPV,       "MPEG-I/II Video"},
+       { PT_MP2T,      "MPEG-II streams"},
+       { PT_H263,      "h263" },
+       { 0,            NULL },
+};
+
 /* Set up an RTP conversation */
 void rtp_add_address(packet_info *pinfo,
                      address *addr, int port,
Index: epan/libethereal.def
===================================================================
--- epan/libethereal.def	(revision 13162)
+++ epan/libethereal.def	(working copy)
@@ -424,6 +424,7 @@
 proto_tree_get_parent
 p_add_proto_data
 p_get_proto_data
+q931_cause_code_vals           DATA
 range_convert_range
 range_convert_str
 range_copy
@@ -464,6 +465,7 @@
 rtcp_add_address
 rtp_add_address
 rtp_payload_type_vals           DATA
+rtp_payload_type_short_vals    DATA
 set_actual_length
 set_timestamp_setting
 show_fragment_seq_tree

JPEG image