Huge thanks to our Platinum Members Endace and LiveAction,
and our Silver Member Veeam, for supporting the Wireshark Foundation and project.

Ethereal-dev: Re: [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: Fri, 04 Feb 2005 22:53:39 -0700
Hi All,
Attached a patch that to shows the RTP streams in the Graph. Now using an RTP tap (not using the rtp_stream).

Regards
Alejandro

Alejandro Vaquero wrote:

Hi Lars and All,
Thanks to test and add this. I'll work on get the RTP back using a tap for RTP.

Regards
Alejandro



Lars Roland wrote:

Hello all,

I've just patched the new VoIP call analysis feature from Alejandro Vaquero. It should work now reliable enough to add it to the distribution. I hope it compiles with GTK1.2, too. no problem with GTK 1.3 and GTK 2.4 on windows.

Unfortunately I had to disable support for showing rtp streams in call flows. The responsible function does not work in the current implementation. After all I am surprised that it worked at least partly before.

However I'd like to thank Alejandro for his excellent work.

IMO the buggy h323 conversation tap is obsolete now. It is surpassed by the VoIP Call Analysis.
Does anyone have any objections against removing it?

Regards,
Lars



_______________________________________________
Ethereal-dev mailing list
Ethereal-dev@xxxxxxxxxxxx
http://www.ethereal.com/mailman/listinfo/ethereal-dev


_______________________________________________
Ethereal-dev mailing list
Ethereal-dev@xxxxxxxxxxxx
http://www.ethereal.com/mailman/listinfo/ethereal-dev

Index: gtk/voip_calls_dlg.c
===================================================================
--- gtk/voip_calls_dlg.c	(revision 13232)
+++ gtk/voip_calls_dlg.c	(working copy)
@@ -174,6 +174,7 @@
 	remove_tap_listener_h245dg_calls();
 	remove_tap_listener_q931_calls();
 	remove_tap_listener_sdp_calls();
+	remove_tap_listener_rtp();
 }
 
 /****************************************************************************/
@@ -605,11 +606,6 @@
 	gchar label_text[256];
 
 	if (voip_calls_dlg != NULL) {
-
-		/* Add the RTP streams info for the graph */
-		/* deactivated for now */
-/*		add_rtp_streams_graph(); */
-
 		gtk_clist_clear(GTK_CLIST(clist));
 		calls_nb = 0;
 		calls_ns = 0;
@@ -674,6 +670,7 @@
 	h245dg_calls_init_tap();
 	q931_calls_init_tap();
 	sdp_calls_init_tap();
+	rtp_init_tap();
 	
 	/* init the Graph Analysys */
 	graph_analysis_data = graph_analysis_init();
Index: gtk/voip_calls.c
===================================================================
--- gtk/voip_calls.c	(revision 13232)
+++ gtk/voip_calls.c	(working copy)
@@ -92,8 +92,9 @@
 static voip_calls_tapinfo_t the_tapinfo_struct =
 	{0, NULL, 0, NULL, 0, 0, 0, 0, NULL, 0, 0, 0, 0, 0, 0, 0};
 
-/* static voip_calls_tapinfo_t the_tapinfo_struct;
-*/
+/* the one and only global voip_rtp_tapinfo_t structure */
+static voip_rtp_tapinfo_t the_tapinfo_rtp_struct =
+	{0, NULL, 0};
 
 /****************************************************************************/
 /* when there is a [re]reading of packet's */
@@ -173,81 +174,6 @@
 }
 
 /****************************************************************************/
-/* Add the RTP streams into the graph data */
-/** 
- * TODO: 
- * - reimplement this function
- * This function does not work with VoIP taps
- * which keep the window up to date.
- * Either make rtp_stream() work without redissection or
- * add an additional tap listener for rtp to this file.
- * The second solution is cleaner and probably easier to implement, 
- * leaving the current rtp analysis feature untouched.
- */
-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)
 {
@@ -317,6 +243,193 @@
 }
 
 /****************************************************************************/
+/* ***************************TAP for RTP **********************************/
+/****************************************************************************/
+
+/****************************************************************************/
+/* when there is a [re]reading of RTP packet's */
+void voip_rtp_reset(voip_rtp_tapinfo_t *tapinfo)
+{
+	GList* list;
+	/* free the data items first */
+	list = g_list_first(tapinfo->list);
+	while (list)
+	{
+		g_free(list->data);
+		list = g_list_next(list);
+	}
+	g_list_free(tapinfo->list);
+	tapinfo->list = NULL;
+	tapinfo->nstreams = 0;
+	return;
+}
+
+/****************************************************************************/
+/* whenever a RTP packet is seen by the tap listener */
+static int 
+RTP_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *RTPinfo)
+{
+	voip_rtp_tapinfo_t *tapinfo = &the_tapinfo_rtp_struct;
+	voip_rtp_stream_info_t *tmp_listinfo;
+	voip_rtp_stream_info_t *strinfo = NULL;
+	GList* list;
+
+	const struct _rtp_info *pi = RTPinfo;
+
+	/* do not consider RTP packets without a setup frame */
+	if (pi->info_setup_frame_num == 0){
+		return 0;
+	}
+
+	/* check wether we already have a RTP stream with this setup frame and ssrc in the list */
+	list = g_list_first(tapinfo->list);
+	while (list)
+	{
+		tmp_listinfo=list->data;
+		if ( (tmp_listinfo->setup_frame_number == pi->info_setup_frame_num) && (tmp_listinfo->ssrc == pi->info_sync_src) ){
+				strinfo = (voip_rtp_stream_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_rtp_stream_info_t));
+		COPY_ADDRESS(&(strinfo->src_addr), &(pinfo->src));
+		strinfo->src_port = pinfo->srcport;
+		COPY_ADDRESS(&(strinfo->dest_addr), &(pinfo->dst));
+		strinfo->dest_port = pinfo->destport;
+		strinfo->ssrc = pi->info_sync_src;
+		strinfo->pt = pi->info_payload_type;
+		strinfo->npackets = 0;
+		strinfo->first_frame_num = pinfo->fd->num;
+		strinfo->start_rel_sec = pinfo->fd->rel_secs;
+		strinfo->start_rel_usec = pinfo->fd->rel_usecs;
+		strinfo->setup_frame_number = pi->info_setup_frame_num;
+		tapinfo->list = g_list_append(tapinfo->list, strinfo);
+	}
+
+	if (strinfo!=NULL){
+		/* Add the info to the existing RTP stream */
+		strinfo->npackets++;
+		strinfo->stop_rel_sec = pinfo->fd->rel_secs;
+		strinfo->stop_rel_usec = pinfo->fd->rel_usecs;
+	}
+	return 1;
+}
+
+/****************************************************************************/
+/* whenever a redraw in the RTP tap listener */
+void RTP_packet_draw(void *prs _U_)
+{
+	voip_rtp_tapinfo_t *rtp_tapinfo = &the_tapinfo_rtp_struct;
+	GList* rtp_streams_list;
+	voip_rtp_stream_info_t *rtp_listinfo;
+	GList* voip_calls_graph_list;
+	guint item;
+	graph_analysis_item_t *gai;
+	graph_analysis_item_t *new_gai;
+	guint16 conv_num;
+	guint32 duration;
+
+	/* add each rtp stream to the graph */
+	rtp_streams_list = g_list_first(rtp_tapinfo->list);
+	while (rtp_streams_list)
+	{
+		rtp_listinfo = rtp_streams_list->data;
+
+		/* using the setup frame number of the RTP stream, we get the call number that it belongs */
+		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 we get the setup frame number, then get the time position to graph the RTP arrow */
+			if (rtp_listinfo->setup_frame_number == gai->frame_num){
+				while(voip_calls_graph_list){
+					gai = voip_calls_graph_list->data;
+					/* if RTP was already in the Graph, just update the comment information */
+					if (rtp_listinfo->first_frame_num == gai->frame_num){
+						duration = (rtp_listinfo->stop_rel_sec*1000000 + rtp_listinfo->stop_rel_usec) - (rtp_listinfo->start_rel_sec*1000000 + rtp_listinfo->start_rel_usec);
+						g_free(gai->comment);
+						gai->comment = g_strdup_printf("RTP Num packets:%d  Duration:%d.%03ds ssrc:%d", rtp_listinfo->npackets, duration/1000000,(duration%1000000)/1000, rtp_listinfo->ssrc);
+						break;
+					/* add the RTP item to the graph if was not there*/
+					} else if (rtp_listinfo->first_frame_num<gai->frame_num){
+						new_gai = g_malloc(sizeof(graph_analysis_item_t));
+						new_gai->frame_num = rtp_listinfo->first_frame_num;
+						new_gai->time = (double)rtp_listinfo->start_rel_sec + (double)rtp_listinfo->start_rel_usec/1000000;
+						g_memmove(&new_gai->ip_src, rtp_listinfo->src_addr.data, 4);
+						g_memmove(&new_gai->ip_dst, rtp_listinfo->dest_addr.data, 4);
+						new_gai->port_src = rtp_listinfo->src_port;
+						new_gai->port_dst = rtp_listinfo->dest_port;
+						duration = (rtp_listinfo->stop_rel_sec*1000000 + rtp_listinfo->stop_rel_usec) - (rtp_listinfo->start_rel_sec*1000000 + rtp_listinfo->start_rel_usec);
+						new_gai->frame_label = g_strdup_printf("RTP (%s)", val_to_str(rtp_listinfo->pt, rtp_payload_type_short_vals, "%u"));
+						new_gai->comment = g_strdup_printf("RTP Num packets:%d  Duration:%d.%03ds ssrc:%d", rtp_listinfo->npackets, duration/1000000,(duration%1000000)/1000, rtp_listinfo->ssrc);
+						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++;
+		}
+		rtp_streams_list = g_list_next(rtp_streams_list);
+	}
+}
+
+static gboolean have_RTP_tap_listener=FALSE;
+/****************************************************************************/
+void
+rtp_init_tap(void)
+{
+	GString *error_string;
+
+	if(have_RTP_tap_listener==FALSE)
+	{
+		/* don't register tap listener, if we have it already */
+		error_string = register_tap_listener("rtp", &(the_tapinfo_rtp_struct), NULL,
+			voip_rtp_reset, 
+			RTP_packet, 
+			RTP_packet_draw
+			);
+		if (error_string != NULL) {
+			simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+				      error_string->str);
+			g_string_free(error_string, TRUE);
+			exit(1);
+		}
+		have_RTP_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_rtp(void)
+{
+	protect_thread_critical_region();
+	remove_tap_listener(&(the_tapinfo_rtp_struct.rtp_dummy));
+	unprotect_thread_critical_region();
+
+	have_RTP_tap_listener=FALSE;
+}
+
+/****************************************************************************/
 /* ***************************TAP for SIP **********************************/
 /****************************************************************************/
 
Index: gtk/voip_calls.h
===================================================================
--- gtk/voip_calls.h	(revision 13232)
+++ gtk/voip_calls.h	(working copy)
@@ -38,6 +38,7 @@
 
 #include <glib.h>
 #include <stdio.h>
+#include <epan/address.h>
 
 /****************************************************************************/
 /* defines voip call state */
@@ -150,6 +151,33 @@
 } voip_calls_tapinfo_t;
 
 
+/* defines a RTP stream */
+typedef struct _voip_rtp_stream_info {
+	address src_addr;
+	guint16 src_port;
+	address dest_addr;
+	guint16 dest_port;
+	guint32 ssrc;
+	guint8  pt;
+	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_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 */
+} voip_rtp_stream_info_t;
+
+/* structure that holds the information about all RTP streams associated with the calls */
+/* struct holding all information of the RTP tap */
+typedef struct _voip_rtp_tapinfo {
+	int     nstreams;       /* number of rtp streams */
+	GList*  list;			/* list with the rtp streams */
+	int rtp_dummy;
+} voip_rtp_tapinfo_t;
+
 /****************************************************************************/
 /* INTERFACE */
 
@@ -167,6 +195,7 @@
 void h245dg_calls_init_tap(void);
 void q931_calls_init_tap(void);
 void sdp_calls_init_tap(void);
+void rtp_init_tap(void);
 
 
 /*
@@ -180,6 +209,7 @@
 void remove_tap_listener_h245dg_calls(void);
 void remove_tap_listener_q931_calls(void);
 void remove_tap_listener_sdp_calls(void);
+void remove_tap_listener_rtp(void);
 
 /*
 * Retrieves a constant reference to the unique info structure of the voip_calls tap listener.
Index: epan/dissectors/packet-rtp.c
===================================================================
--- epan/dissectors/packet-rtp.c	(revision 13232)
+++ epan/dissectors/packet-rtp.c	(working copy)
@@ -353,6 +353,8 @@
 		proto_tree_add_item( rtp_tree, hf_rtp_data, newtvb, 0, -1, FALSE );
 }
 
+static struct _rtp_info rtp_info;
+
 static void
 dissect_rtp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
 {
@@ -377,8 +379,6 @@
 	guint32     sync_src;
 	guint32     csrc_item;
 
-	static struct _rtp_info rtp_info;
-
 	/* Get the fields in the first octet */
 	octet1 = tvb_get_guint8( tvb, offset );
 	version = RTP_VERSION( octet1 );
@@ -430,6 +430,7 @@
 	rtp_info.info_seq_num = seq_num;
 	rtp_info.info_timestamp = timestamp;
 	rtp_info.info_sync_src = sync_src;
+	rtp_info.info_setup_frame_num = 0;
 
 	/*
 	 * Do we have all the data?
@@ -517,6 +518,7 @@
 		proto_tree_add_uint( rtp_tree, hf_rtp_ssrc, tvb, offset, 4, sync_src );
 		offset += 4;
 	} else {
+		show_setup_info(tvb, pinfo, NULL);
 		offset += 12;
 	}
 	/* CSRC list*/
@@ -653,7 +655,7 @@
 
 
 /* Look for conversation info and display any setup info found */
-void show_setup_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+static void show_setup_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 {
 	/* Conversation and current data */
 	conversation_t *p_conv = NULL;
@@ -705,6 +707,7 @@
 			                             tvb, 0, 0, p_conv_data->method);
 			PROTO_ITEM_SET_GENERATED(item);
 		}
+		rtp_info.info_setup_frame_num = p_conv_data->frame_number;
 	}
 }
 
Index: epan/dissectors/packet-rtp.h
===================================================================
--- epan/dissectors/packet-rtp.h	(revision 13232)
+++ epan/dissectors/packet-rtp.h	(working copy)
@@ -40,6 +40,7 @@
 	gboolean      info_all_data_present; /* FALSE if data is cut off */
 	guint         info_payload_offset; /* start of payload relative to info_data */
 	guint         info_payload_len;    /* length of payload (incl padding) */
+	guint32		  info_setup_frame_num; /* the frame num of the packet that set this RTP connection */
 	const guint8* info_data;           /* pointer to raw rtp data */
 	/*
 	* info_data: pointer to raw rtp data = header + payload incl. padding.