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

Ethereal-dev: [Ethereal-dev] New H323 call analyser plugin

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

From: Miha Jemec <m.jemec@xxxxxxxxxxx>
Date: Wed, 29 Sep 2004 15:29:41 +0200
HI!

Doing the h323 call analysis daily, I missed the option to be able to
observe the h323 calls in a simple manner - something similar to rtp
analysis. So based on it I implemented a H323 call decoder. Using the
TAP system, it keeps track of each call, number of packets, setting
filter and a more detailed analysis of each call. Some pictures are
attached, so you can get the first impression. Currently there is no
connection of h323 signalization and associated rtp stream, this is one
functionality which should be added in first place. But in general, I
didn't want to mix signalization and rtp since it is possible to have
only one type of packets in the trace.

There are some new files, which should be putted in the gtk
 directory:

h323_analysis.c and .h
h323_conversations.c and .h
h323_conversations_dlg.c and .h

There are patches for h225_packet.c and .h and for packet-h245.c and .h
attached. And a patch for Makefile in gtk directory (I don't know how to
do it regular way with configure etc...) is included as well.

Instructions (for unfamiliar with configure scripts like me):
Put new files in the gtk directory, apply the pacthes for packet-*
files, run the configure script, then patch the Makefile in the gtk and
run the make command from the root. It should compile. The new option is
available in the statistics under H.323.

The whole source was done on the 0.10.5 release, but I think there were
no changes on this files in 0.10.6. The patches were made using diff -u
original_file my_file

Please try it, test it, comment it (hopefully once like it and checked
it in).  

Regards, Miha

ps: I have already some open questions/problems but I'll open them later
-- 
Miha Jemec <m.jemec@xxxxxxxxxxx>

Attachment: h323_analysis.png
Description: PNG image

--- packet-h225.c	2004-06-26 18:04:51.000000000 +0200
+++ my-packet-h225.c	2004-09-29 14:44:23.000000000 +0200
@@ -53,7 +53,7 @@
 static void reset_h225_packet_info(h225_packet_info *pi);
 static void ras_call_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, h225_packet_info *pi);
 
-static h225_packet_info h225_pi;
+static h225_packet_info h225_pi; 
 
 static dissector_handle_t h225ras_handle;
 static dissector_handle_t H323UserInformation_handle;
@@ -2809,6 +2809,11 @@
 
 	offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_h245Address, ett_h225_TransportAddress, TransportAddress_choice, "h245Address", NULL);
 
+	/* we need this info for TAPing */
+	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;
 		conversation_t *conv=NULL;
@@ -5223,8 +5228,8 @@
 					   PER dissectors, but the item length
 					   is in octets */
 	offset=dissect_h245_OpenLogicalChannel(tvb, offset, pinfo, tree);
-
 	contains_faststart = TRUE;
+	h225_pi.is_faststart = TRUE;
 
 	return newoffset;
 }
@@ -5638,6 +5643,9 @@
 dissect_h225_CallProceedingUUIE(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
 {
 	offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_CallProceedingUUIE, ett_h225_CallProceedingUUIE, CallProceedingUUIE_sequence);
+
+	h225_pi.cs_type = H225_CALL_PROCEDING;
+
 	return offset;
 }
 
@@ -6915,6 +6923,9 @@
 dissect_h225_AlertingUUIE(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
 {
 	offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_AlertingUUIE, ett_h225_AlertingUUIE, AlertingUUIE_sequence);
+
+	h225_pi.cs_type = H225_ALERTING;
+
 	return offset;
 }
 
@@ -6955,6 +6966,9 @@
 dissect_h225_ReleaseCompleteUUIE(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
 {
 	offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_ReleaseCompleteUUIE, ett_h225_ReleaseCompleteUUIE, ReleaseCompleteUUIE_sequence);
+
+	h225_pi.cs_type = H225_RELEASE_COMPLET;
+
 	return offset;
 }
 
@@ -7243,6 +7257,9 @@
 {
 	contains_faststart = FALSE;
 	offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_SetupUUIE, ett_h225_SetupUUIE, SetupUUIE_sequence);
+	
+	h225_pi.cs_type = H225_SETUP;
+
 	return offset;
 }
 
@@ -7299,6 +7316,9 @@
 dissect_h225_ConnectUUIE(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
 {
 	offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_ConnectUUIE, ett_h225_ConnectUUIE, ConnectUUIE_sequence);
+
+	h225_pi.cs_type = H225_CONNECT;
+
 	return offset;
 }
 
@@ -10548,12 +10568,17 @@
 	}
 
 	pi->msg_type = H225_OTHERS;
+	pi->cs_type = H225_OTHER;
 	pi->msg_tag = -1;
 	pi->reason = -1;
 	pi->requestSeqNum = 0;
 	memset(pi->guid,0,16);
 	pi->is_duplicate = FALSE;
 	pi->request_available = FALSE;
+	pi->is_faststart = FALSE;
+	pi->is_h245 = FALSE;
+	pi->h245_address = 0;
+	pi->h245_port = 0;
 }
 
 /*
--- packet-h245.c	2004-06-17 03:55:18.000000000 +0200
+++ my-packet-h245.c	2004-09-29 14:44:37.000000000 +0200
@@ -38,6 +38,9 @@
 #include <stdio.h>
 #include <string.h>
 
+#include "tap.h"
+#include "packet-h245.h"
+
 #include "prefs.h"
 #include "packet-tpkt.h"
 #include "packet-per.h"
@@ -51,6 +54,10 @@
 static dissector_handle_t h245_handle;
 static dissector_handle_t MultimediaSystemControlMessage_handle;
 
+static void reset_h245_packet_info(h245_packet_info *pi);
+static int h245_tap = -1;
+static h245_packet_info h245_pi;
+
 static int proto_h245 = -1;		/* h245 over tpkt */
 static int hf_h245_rfc_number = -1;
 static int hf_h245_pdu_type = -1;
@@ -1529,6 +1536,8 @@
 {
 	offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_MasterSlaveDeterminationAck, ett_h245_MasterSlaveDeterminationAck, MasterSlaveDeterminationAck_sequence);
 
+	h245_pi.msg_type = H245_MastSlvDetAck;
+
 	return offset;
 }
 
@@ -1562,6 +1571,8 @@
 {
 	offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_MasterSlaveDeterminationReject, ett_h245_MasterSlaveDeterminationReject, MasterSlaveDeterminationReject_sequence);
 
+	h245_pi.msg_type = H245_MastSlvDetRjc;
+
 	return offset;
 }
 
@@ -3327,6 +3338,8 @@
 {
 	offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_OpenLogicalChannelReject, ett_h245_OpenLogicalChannelReject, OpenLogicalChannelReject_sequence);
 
+	h245_pi.msg_type = H245_OpenLogChnRjc;
+
 	return offset;
 }
 
@@ -3347,6 +3360,8 @@
 {
 	offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_CloseLogicalChannel, ett_h245_CloseLogicalChannel, CloseLogicalChannel_sequence);
 
+	h245_pi.msg_type = H245_CloseLogChn;
+
 	return offset;
 }
 
@@ -3363,6 +3378,8 @@
 {
 	offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_CloseLogicalChannelAck, ett_h245_CloseLogicalChannelAck, CloseLogicalChannelAck_sequence);
 
+	h245_pi.msg_type = H245_CloseLogChnAck;
+
 	return offset;
 }
 
@@ -3509,6 +3526,8 @@
 {
 	offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_OpenLogicalChannelConfirm, ett_h245_OpenLogicalChannelConfirm, OpenLogicalChannelConfirm_sequence);
 
+	h245_pi.msg_type = H245_OpenLogChnCnf;
+
 	return offset;
 }
 
@@ -3524,6 +3543,8 @@
 {
 	offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_TerminalCapabilitySetAck, ett_h245_TerminalCapabilitySetAck, TerminalCapabilitySetAck_sequence);
 
+	h245_pi.msg_type = H245_TermCapSetAck;
+
 	return offset;
 }
 
@@ -7638,6 +7659,8 @@
 {
 	offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_MasterSlaveDetermination, ett_h245_MasterSlaveDetermination, MasterSlaveDetermination_sequence);
 
+	h245_pi.msg_type = H245_MastSlvDet;
+
 	return offset;
 }
 
@@ -7720,6 +7743,8 @@
 {
 	offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_TerminalCapabilitySetReject, ett_h245_TerminalCapabilitySetReject, TerminalCapabilitySetReject_sequence);
 
+	h245_pi.msg_type = H245_TermCapSetRjc;
+
 	return offset;
 }
 
@@ -12348,6 +12373,8 @@
 {
 	offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_MasterSlaveDeterminationRelease, ett_h245_MasterSlaveDeterminationRelease, MasterSlaveDeterminationRelease_sequence);
 
+	h245_pi.msg_type = H245_MastSlvDetRls;
+
 	return offset;
 }
 
@@ -17487,6 +17514,8 @@
 {
 	offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_TerminalCapabilitySet, ett_h245_TerminalCapabilitySet, TerminalCapabilitySet_sequence);
 
+	h245_pi.msg_type = H245_TermCapSet;
+
 	return offset;
 }
 
@@ -18065,6 +18094,8 @@
 {
 	offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_TerminalCapabilitySetRelease, ett_h245_TerminalCapabilitySetRelease, TerminalCapabilitySetRelease_sequence);
 
+	h245_pi.msg_type = H245_TermCapSetRls;
+
 	return offset;
 }
 
@@ -18204,6 +18235,8 @@
 {
 	offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_OpenLogicalChannel, ett_h245_OpenLogicalChannel, OpenLogicalChannel_sequence);
 
+	h245_pi.msg_type = H245_OpenLogChn;
+
 	return offset;
 }
 
@@ -18228,6 +18261,8 @@
 {
 	offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_OpenLogicalChannelAck, ett_h245_OpenLogicalChannelAck, OpenLogicalChannelAck_sequence);
 
+	h245_pi.msg_type = H245_OpenLogChnAck;
+
 	return offset;
 }
 
@@ -19141,7 +19176,12 @@
 void
 dissect_h245(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 {
+	reset_h245_packet_info(&(h245_pi));
+        h245_pi.msg_type = H245_OTHER;
+
 	dissect_tpkt_encap(tvb, pinfo, tree, h245_reassembly, MultimediaSystemControlMessage_handle);
+
+	tap_queue_packet(h245_tap, pinfo, &h245_pi);
 }
 
 void
@@ -22443,6 +22483,8 @@
 
 	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");
 }
 
 void
@@ -22456,3 +22498,13 @@
 	MultimediaSystemControlMessage_handle=create_dissector_handle(dissect_h245_MultimediaSystemControlMessage, proto_h245);
 	dissector_add_handle("udp.port", MultimediaSystemControlMessage_handle);
 }
+
+static void reset_h245_packet_info(h245_packet_info *pi)
+{
+        if(pi == NULL) {
+                return;
+        }
+
+        pi->msg_type = H245_OTHER;
+}
+
--- packet-h245.h	2003-09-28 02:36:15.000000000 +0200
+++ my-packet-h245.h	2004-09-29 14:44:33.000000000 +0200
@@ -23,6 +23,29 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
+typedef enum _h245_msg_type {
+	H245_TermCapSet,
+	H245_TermCapSetAck,
+	H245_TermCapSetRjc,
+	H245_TermCapSetRls,
+	H245_OpenLogChn,
+	H245_OpenLogChnCnf,
+	H245_OpenLogChnAck,
+	H245_OpenLogChnRjc,	
+	H245_CloseLogChn,
+	H245_CloseLogChnAck,
+	H245_MastSlvDet,
+	H245_MastSlvDetAck,
+	H245_MastSlvDetRjc,
+	H245_MastSlvDetRls,
+        H245_OTHER
+} h245_msg_type;
+
+typedef struct _h245_packet_info {
+        h245_msg_type msg_type;         /* type of message */
+} h245_packet_info;
+
+
 extern void dissect_h245_MultimediaSystemControlMessage(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
 
 extern int dissect_h245_OpenLogicalChannel(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
--- packet-h225.h	2004-05-10 04:23:39.000000000 +0200
+++ my-packet-h225.h	2004-09-29 14:44:28.000000000 +0200
@@ -36,8 +36,18 @@
 	H225_OTHERS
 } h225_msg_type;
 
+typedef enum _h225_cs_type {
+	H225_SETUP,
+	H225_CALL_PROCEDING,
+	H225_ALERTING,
+	H225_CONNECT,
+	H225_RELEASE_COMPLET,
+	H225_OTHER
+} h225_cs_type;
+
 typedef struct _h225_packet_info {
 	h225_msg_type msg_type;		/* ras or cs message */
+	h225_cs_type cs_type;		/* cs message type */
 	gint msg_tag;			/* message tag*/
 	gint reason;			/* reason tag, if available */
 	guint requestSeqNum;		/* request sequence number of ras-message, if available */
@@ -45,6 +55,11 @@
 	gboolean is_duplicate;		/* true, if this is a repeated message */
 	gboolean request_available;	/* true, if response matches to a request */
 	nstime_t delta_time; 		/* this is the RAS response time delay */
+	/* added for h225 conversations analysis */
+	gboolean is_faststart;		/* true, if faststart field is included */
+	gboolean is_h245;
+	guint32 h245_address;
+	guint16 h245_port;
 } h225_packet_info;
 
 /*
/* h323_analysis.c
 * H323 analysis addition for ethereal
 *
 * Copyright 2004, Iskratel, Ltd, Kranj
 * By Miha Jemec <m.jemec@xxxxxxxxxxx>
 *
 * 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

/*do not define this symbol. will be added soon*/
/*#define USE_CONVERSATION_GRAPH 1*/

#include "h323_analysis.h"
#include "h323_conversations.h"
#include "h323_conversations_dlg.h"

#include <epan/epan_dissect.h>
#include <epan/filesystem.h>

#include "globals.h"

#include "util.h"
#include "tap.h"
#include "register.h"

#include "packet-h225.h"
#include "packet-h245.h"

/* in /gtk ... */
#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 <string.h>

/****************************************************************************/
/* structure that holds general information about the connection */
typedef struct _user_data_t {
        /* tap associated data*/
        guint32 ip_src;
        guint16 port_src;
        guint32 ip_dst;
        guint16 port_dst;
        guint32 ip_src_h245;
        guint16 port_src_h245;

	GtkWidget *window;
	GtkCList *clist1;
	GtkWidget *label_stats;
	GtkCList *selected_clist1;
	gint selected_row;

} user_data_t;

/* Column titles. */
static gchar *titles[7] =  {
	"Packet",
	"Time",
	"Delay",
	"             Side A",
	"Direction",
	"             Side B",
	"Comment"
};

typedef const guint8 * ip_addr_p;

static gint32 last_sec = 0, last_usec = 0;


/****************************************************************************/
/* TAP FUNCTIONS */

/****************************************************************************/
/* when there is a [re]reading of packet's */
static void
h225_reset(void *user_data_arg _U_)
{
	last_sec = 0;
	last_usec = 0;
	return;
}

/****************************************************************************/
/* here we can redraw the output */
/* not used yet */
static void h225_draw(void *prs _U_)
{
	return;
}


static const GdkColor COLOR_DEFAULT = {0, 0xffff, 0xffff, 0xffff};
static const GdkColor COLOR_ERROR = {0, 0xffff, 0xbfff, 0xbfff};
static const GdkColor COLOR_WARNING = {0, 0xffff, 0xdfff, 0xbfff};
static const GdkColor COLOR_CN = {0, 0xbfff, 0xbfff, 0xffff};

/****************************************************************************/
/* append a line to clist1 */
static void add_to_clist1(GtkCList *clist1, guint32 number, gchar *time,
                         double delay, gchar *sideA, gboolean direction, gchar *sideB,
                         gchar *comment, GdkColor *color)
{
        guint added_row;
        gchar *data[7];
        gchar field[7][32];

        data[0]=&field[0][0];
        data[1]=&field[1][0];
        data[2]=&field[2][0];
        data[3]=&field[3][0];
        data[4]=&field[4][0];
        data[5]=&field[5][0];
        data[6]=&field[6][0];

        g_snprintf(field[0], 32, "%u", number);
        g_snprintf(field[1], 32, "%s", time);
        g_snprintf(field[2], 32, "%f", delay);
        g_snprintf(field[3], 32, "%s", sideA);
        g_snprintf(field[4], 20, "%s", direction? "---->" : "<----");
        g_snprintf(field[5], 32, "%s", sideB);
        g_snprintf(field[6], 32, "%s", comment);

        added_row = gtk_clist_append(GTK_CLIST(clist1), data);
        gtk_clist_set_row_data(GTK_CLIST(clist1), added_row, GUINT_TO_POINTER(number));
        gtk_clist_set_background(GTK_CLIST(clist1), added_row, color);
}


/****************************************************************************/
/* whenever a h225 packet is seen by the tap listener */
static int h225_packet(void *user_data_arg, packet_info *pinfo, epan_dissect_t *edt _U_, void *h225info_arg)
{
	user_data_t *user_data = user_data_arg;
	h225_packet_info *h225ptr_info = h225info_arg;	
	GdkColor color = COLOR_DEFAULT;

        gchar timeStr[32];
        gchar message[32];
	guint32 src, dst;
	double delay;
	gint32 delay_sec, delay_usec;

	/* time since beginning of capture */
        g_snprintf(timeStr, sizeof(timeStr), "%d.%06d", pinfo->fd->rel_secs, pinfo->fd->rel_usecs);

	/* time since previous packet seen in tap listener */
	delay_sec = pinfo->fd->rel_secs - last_sec;
	delay_usec = pinfo->fd->rel_usecs - last_usec;
	
	delay = (double)delay_sec + ((double)delay_usec)/1000000;

	last_sec = pinfo->fd->rel_secs;
	last_usec = pinfo->fd->rel_usecs;

	switch (h225ptr_info->cs_type) {
		
		case H225_SETUP:
			g_snprintf(message, sizeof(message),"H225 Setup");
			break;
		case H225_CALL_PROCEDING:
			g_snprintf(message, sizeof(message),"H225 Call Proceding");
			break;
		case H225_ALERTING:
			g_snprintf(message, sizeof(message),"H225 Alerting");
			break;
		case H225_CONNECT:
			g_snprintf(message, sizeof(message),"H225 Connect");
			break;
		case H225_RELEASE_COMPLET:
			g_snprintf(message, sizeof(message),"H225 Release Complet");
			break;
		case H225_OTHER:
			g_snprintf(message, sizeof(message),"H225 Other");
		}

	g_memmove(&src, pinfo->src.data, 4);
        g_memmove(&dst, pinfo->dst.data, 4);

	if (src == user_data->ip_src)
		add_to_clist1(user_data->clist1,pinfo->fd->num,timeStr,delay,message, 1, "", "", &color);
	else
		add_to_clist1(user_data->clist1, pinfo->fd->num, timeStr,delay, "", 0, message, "", &color);

	return 0;
}


/****************************************************************************/
/* whenever a h245 packet is seen by the tap listener */
static int h245_packet(void *user_data_arg, packet_info *pinfo, epan_dissect_t *edt _U_, void *h245info_arg)
{

	user_data_t *user_data = user_data_arg;
	h245_packet_info *h245ptr_info = h245info_arg;	
	GdkColor color = COLOR_DEFAULT;

        gchar timeStr[32];
        gchar message[32];
	guint32 src, dst;
	double delay;
	gint32 delay_sec, delay_usec;

	/* time since beginning of capture */
        g_snprintf(timeStr, sizeof(timeStr), "%d.%06d", pinfo->fd->rel_secs, pinfo->fd->rel_usecs);

	/* time since previous packet seen in tap listener */
	delay_sec = pinfo->fd->rel_secs - last_sec;
	delay_usec = pinfo->fd->rel_usecs - last_usec;
	
	delay = (double)delay_sec + ((double)delay_usec)/1000000;

	last_sec = pinfo->fd->rel_secs;
	last_usec = pinfo->fd->rel_usecs;

	switch (h245ptr_info->msg_type) {
		
		case H245_TermCapSet:
			g_snprintf(message, sizeof(message),"H245 TermCapSet");
			break;
		case H245_TermCapSetAck:
			g_snprintf(message, sizeof(message),"H245_TermCapSetAck");
			break;
		case H245_TermCapSetRjc:
			g_snprintf(message, sizeof(message),"H245_TermCapSetRjc");
			break;
		case H245_TermCapSetRls:
			g_snprintf(message, sizeof(message),"H245_TermCapSetRls");
			break;
		case H245_OpenLogChn:
			g_snprintf(message, sizeof(message),"H245_OpenLogChn");
			break;
		case H245_OpenLogChnCnf:
			g_snprintf(message, sizeof(message),"H245_OpenLogChnCnf");
			break;
		case H245_OpenLogChnAck:
			g_snprintf(message, sizeof(message),"H245_OpenLogChnAck");
			break;
		case H245_OpenLogChnRjc:
			g_snprintf(message, sizeof(message),"H245_OpenLogChnRjc");
			break;
		case H245_CloseLogChn:
			g_snprintf(message, sizeof(message),"H245_CloseLogChn");
			break;
		case H245_CloseLogChnAck:
			g_snprintf(message, sizeof(message),"H245_CloseLogChnAck");
			break;
		case H245_MastSlvDet:
			g_snprintf(message, sizeof(message),"H245_MastSlvDet");
			break;
		case H245_MastSlvDetAck:
			g_snprintf(message, sizeof(message),"H245_MastSlvDetAck");
			break;
		case H245_MastSlvDetRjc:
			g_snprintf(message, sizeof(message),"H245_MastSlvDetRjc");
			break;
		case H245_MastSlvDetRls:
			g_snprintf(message, sizeof(message),"H245_MastSlvDetRls");
			break;
		case H245_OTHER:
			g_snprintf(message, sizeof(message),"H225 Other");
		}

	g_memmove(&src, pinfo->src.data, 4);
        g_memmove(&dst, pinfo->dst.data, 4);

	if (src == user_data->ip_src)
		add_to_clist1(user_data->clist1,pinfo->fd->num,timeStr,delay,message, 1, "", "", &color);
	else
		add_to_clist1(user_data->clist1, pinfo->fd->num, timeStr,delay, "", 0, message, "", &color);

	return 0;
}


/**************** Callbacks *************************************************/
/****************************************************************************/
/* XXX just copied from gtk/rpc_stat.c */
void protect_thread_critical_region(void);
void unprotect_thread_critical_region(void);


/****************************************************************************/
/* close the dialog window and remove the tap listener */
static void on_destroy(GtkWidget *win _U_, user_data_t *user_data _U_)
{
        g_free(user_data);
}

/****************************************************************************/
static void on_clist_select_row(GtkCList        *clist1 _U_,
                                gint             row _U_,
                                gint             column _U_,
                                GdkEvent        *event _U_,
                                user_data_t     *user_data _U_)
{
        user_data->selected_clist1 = clist1;
        user_data->selected_row = row;
}

/****************************************************************************/
static void on_goto_bt_clicked(GtkWidget *bt _U_, user_data_t *user_data _U_)
{
        guint fnumber;

        if (user_data->selected_clist1!=NULL) {
                fnumber = GPOINTER_TO_UINT(gtk_clist_get_row_data(
                        GTK_CLIST(user_data->selected_clist1), user_data->selected_row) );
               goto_frame(&cfile, fnumber);
        }
}


/****************************************************************************/
/* re-dissects all packets */
static void on_refresh_bt_clicked(GtkWidget *bt _U_, user_data_t *user_data _U_)
{
        gchar filter_text_h225[256];
        gchar filter_text_h245[256];
        /*gchar filter_text_rtp[256];*/
        dfilter_t *sfcode;
        GString *error_string;

        /* clear the dialog box clists */
        gtk_clist_clear(GTK_CLIST(user_data->clist1));

        /* try to compile the filter for h225 */
	g_snprintf(filter_text_h225,sizeof(filter_text_h225),
        "h225 && (( ip.src==%s && tcp.srcport==%u && ip.dst==%s && tcp.dstport==%u ) || ( ip.src==%s && tcp.srcport==%u && ip.dst==%s && tcp.dstport==%u ))",
                ip_to_str((ip_addr_p)&(user_data->ip_src)),
                user_data->port_src,
                ip_to_str((ip_addr_p)&(user_data->ip_dst)),
                user_data->port_dst,
                ip_to_str((ip_addr_p)&(user_data->ip_dst)),
                user_data->port_dst,
                ip_to_str((ip_addr_p)&(user_data->ip_src)),
                user_data->port_src
                );

        if (!dfilter_compile(filter_text_h225, &sfcode)) {
                simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, dfilter_error_msg);
                return;
        }

        /* try to compile the filter for h245 */
	g_snprintf(filter_text_h245,sizeof(filter_text_h245), 
        "h245 && (( ip.src==%s && tcp.srcport==%u ) || ( ip.dst==%s && tcp.dstport==%u ))",
                ip_to_str((ip_addr_p)&(user_data->ip_src_h245)),
                user_data->port_src_h245,
                ip_to_str((ip_addr_p)&(user_data->ip_src_h245)),
                user_data->port_src_h245
                );

        if (!dfilter_compile(filter_text_h245, &sfcode)) {
                simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, dfilter_error_msg);
                return;
        }

	/* register tap h225 listener */
        error_string = register_tap_listener("h225", user_data, filter_text_h225,
                h225_reset, h225_packet, h225_draw);
        if (error_string != NULL) {
                simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, error_string->str);
                        g_string_free(error_string, TRUE);
                return;
        }

	/* register tap h245 listener */
        error_string = register_tap_listener("h245", user_data, filter_text_h245,
                NULL, h245_packet, NULL);
        if (error_string != NULL) {
                simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, error_string->str);
                        g_string_free(error_string, TRUE);
                return;
        }

        /* retap all packets */
        retap_packets(&cfile);

        /* remove tap listener again */
        protect_thread_critical_region();
        remove_tap_listener(user_data);
        remove_tap_listener(user_data);
        unprotect_thread_critical_region();

}


/************************************************************************************/
/************** Create the dialog box with all widgets ******************************/
void create_h225_dialog(user_data_t* user_data)
{
        GtkWidget *window = NULL;
        GtkWidget *clist_h225;
        GtkWidget *label_stats;

        GtkWidget *main_vb;
        GtkWidget *label;
        GtkWidget *scrolled_window;
        GtkWidget *box4, *goto_bt, *close_bt, *refresh_bt;

        gchar label_forward[150];

        gchar str_ip_src[16];
        gchar str_ip_dst[16];

	window = window_new(GTK_WINDOW_TOPLEVEL, "Ethereal: H.323 VoIP Analysis");
        gtk_window_set_default_size(GTK_WINDOW(window), 700, 350);

        /* Container for each row of widgets */
        main_vb = gtk_vbox_new(FALSE, 2);
        gtk_container_add(GTK_CONTAINER(window), main_vb);
        gtk_container_set_border_width(GTK_CONTAINER(main_vb), 2);
        gtk_widget_show(main_vb);

        strcpy(str_ip_src, ip_to_str((ip_addr_p)&user_data->ip_src));
        strcpy(str_ip_dst, ip_to_str((ip_addr_p)&user_data->ip_dst));

        g_snprintf(label_forward, 149,
                "\nAnalysing H.323 Call between  %s port %u (Side A) and  %s port %u (Side B)\n",
                str_ip_src, user_data->port_src, str_ip_dst, user_data->port_dst);

        /* label */
        label = gtk_label_new(label_forward);
        gtk_box_pack_start (GTK_BOX (main_vb), label, FALSE, FALSE, 0);

        /* scrolled window */
        scrolled_window = scrolled_window_new (NULL, NULL);
	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
                                        GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
        gtk_box_pack_start (GTK_BOX (main_vb), scrolled_window, TRUE, TRUE, 0);

        /* place for some statistics */
        /*label_stats = gtk_label_new("\n");*/
        /*gtk_box_pack_start(GTK_BOX(main_vb), label_stats, FALSE, FALSE, 0);*/

        /* packet clist */
	clist_h225 = gtk_clist_new_with_titles(7, titles);
        gtk_container_add(GTK_CONTAINER(scrolled_window), clist_h225);
        gtk_widget_show(clist_h225);
	SIGNAL_CONNECT(clist_h225, "select_row", on_clist_select_row, user_data);

        /* column widths and justification */
        gtk_clist_set_column_width(GTK_CLIST(clist_h225), 0, 45);
        gtk_clist_set_column_width(GTK_CLIST(clist_h225), 1, 90);
        gtk_clist_set_column_width(GTK_CLIST(clist_h225), 2, 90);
        gtk_clist_set_column_width(GTK_CLIST(clist_h225), 3, 140);
        gtk_clist_set_column_width(GTK_CLIST(clist_h225), 4, 60);
        gtk_clist_set_column_width(GTK_CLIST(clist_h225), 5, 140);
        gtk_clist_set_column_justification(GTK_CLIST(clist_h225), 0, GTK_JUSTIFY_CENTER);
        gtk_clist_set_column_justification(GTK_CLIST(clist_h225), 1, GTK_JUSTIFY_CENTER);
        gtk_clist_set_column_justification(GTK_CLIST(clist_h225), 2, GTK_JUSTIFY_CENTER);
        gtk_clist_set_column_justification(GTK_CLIST(clist_h225), 3, GTK_JUSTIFY_LEFT);
        gtk_clist_set_column_justification(GTK_CLIST(clist_h225), 4, GTK_JUSTIFY_CENTER);
        gtk_clist_set_column_justification(GTK_CLIST(clist_h225), 5, GTK_JUSTIFY_LEFT);
        gtk_clist_set_column_justification(GTK_CLIST(clist_h225), 6, GTK_JUSTIFY_CENTER);

        gtk_widget_show(scrolled_window);

        /* buttons */
        box4 = gtk_hbutton_box_new();
        gtk_box_pack_start(GTK_BOX(main_vb), box4, FALSE, FALSE, 0);
        gtk_container_set_border_width(GTK_CONTAINER(box4), 10);
        gtk_button_box_set_layout(GTK_BUTTON_BOX (box4), GTK_BUTTONBOX_END);
        gtk_button_box_set_spacing(GTK_BUTTON_BOX (box4), 10);
        gtk_button_box_set_child_ipadding(GTK_BUTTON_BOX (box4), 4, 0);
        gtk_widget_show(box4);

	refresh_bt = BUTTON_NEW_FROM_STOCK(GTK_STOCK_REFRESH);
        gtk_container_add(GTK_CONTAINER(box4), refresh_bt);
        gtk_widget_show(refresh_bt);
        SIGNAL_CONNECT(refresh_bt, "clicked", on_refresh_bt_clicked, user_data);

	goto_bt = BUTTON_NEW_FROM_STOCK(GTK_STOCK_JUMP_TO);
        gtk_container_add(GTK_CONTAINER(box4), goto_bt);
        gtk_widget_show(goto_bt);
        SIGNAL_CONNECT(goto_bt, "clicked", on_goto_bt_clicked, user_data);

        close_bt = BUTTON_NEW_FROM_STOCK(GTK_STOCK_CLOSE);
        gtk_container_add(GTK_CONTAINER(box4), close_bt);
	GTK_WIDGET_SET_FLAGS(close_bt, GTK_CAN_DEFAULT);
        gtk_widget_show(close_bt);
	window_set_cancel_button(window, close_bt, window_cancel_button_cb);

	SIGNAL_CONNECT(window, "delete_event", window_delete_event_cb, NULL);
        SIGNAL_CONNECT(window, "destroy", on_destroy, user_data);

	gtk_widget_show_all(window);
	window_present(window);

	/* some widget references need to be saved for outside use */
	user_data->window = window;
        user_data->clist1 = GTK_CLIST(clist_h225);
        user_data->label_stats = label;
        user_data->selected_clist1 = GTK_CLIST(clist_h225);
        user_data->selected_row = 0;
}


/****************************************************************************/
void h323_analysis(
                guint32 ip_src,
                guint16 port_src,
                guint32 ip_dst,
                guint16 port_dst,
                guint32 ip_src_h245,
                guint16 port_src_h245
                )
{
        user_data_t *user_data;

        /* init */
        user_data = g_malloc(sizeof(user_data_t));

        user_data->ip_src = ip_src;
        user_data->port_src = port_src;
        user_data->ip_dst = ip_dst;
        user_data->port_dst = port_dst;
        user_data->ip_src_h245 = ip_src_h245;
        user_data->port_src_h245 = port_src_h245;

	/* create the dialog box */
        create_h225_dialog(user_data);

	/* proceed as if the Refresh button would have been pressed */
        on_refresh_bt_clicked(NULL, user_data);
}


/* h323_analysis.h
 * H323 analysis addition for ethereal
 *
 * Copyright 2004, Iskratel, Ltd, Kranj
 * By Miha Jemec <m.jemec@xxxxxxxxxxx>
 *
 * 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 H323_ANALYSIS_H_INCLUDED
#define H323_ANALYSIS_H_INCLUDED

#include <glib.h>

/** @file
 *  ??? 
 *  @todo what's this?
 */

void h323_analysis(
		guint32 ip_src,  /* network-order IPv4 address */
		guint16 port_src,
		guint32 ip_dst,  /* network-order IPv4 address */
		guint16 port_dst,
		guint32 ip_src_h245,  /* network-order IPv4 address */
		guint16 port_src_h245
		);

#endif /* H323_ANALYSIS_H_INCLUDED*/
/* h323_conversations.c
 * H323 conversations summary addition for ethereal
 *
 * Copyright 2004, Iskratel, Ltd, Kranj
 * By Miha Jemec <m.jemec@xxxxxxxxxxx>
 *
 * based on rtp_stream.c
 * Copyright 2003, Alcatel Business Systems
 * By Lars Ruoff <lars.ruoff@xxxxxxx>
 *
 * 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 "h323_conversations.h"
#include "h323_conversations_dlg.h"

#include "globals.h"

#include "tap.h"
#include "register.h"
#include "packet-h225.h"
#include "packet-h245.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>

/****************************************************************************/
/* the one and only global h323conversations_tapinfo_t structure */
static h323conversations_tapinfo_t the_tapinfo_struct =
	{0, NULL, 0, NULL, 0, FALSE, FALSE, 0, 0, 0};

/****************************************************************************/
/* GCompareFunc style comparison function for _h323_conversations_info */
gint h323_conversations_info_cmp(gconstpointer aa, gconstpointer bb)
{
	const struct _h323_conversations_info* a = aa;
	const struct _h323_conversations_info* b = bb;

	if (a==b)
		return 0;
	if (a==NULL || b==NULL)
		return 1;
	if ((a->src_addr == b->src_addr)
		&& (a->src_port == b->src_port)
		&& (a->dest_addr == b->dest_addr)
		&& (a->dest_port == b->dest_port)
		)
		return 0;
	else if ((a->src_addr == b->dest_addr)
		&& (a->src_port == b->dest_port)
		&& (a->dest_addr == b->src_addr)
		&& (a->dest_port == b->src_port)
		)
		return 0;
	else
		return 1;
}


/****************************************************************************/
/* when there is a [re]reading of packet's */
void h225conversations_reset(h323conversations_tapinfo_t *tapinfo)
{
	GList* list;

	/* free the data items first */
	list = g_list_first(tapinfo->strinfo_list);
	while (list)
	{
		g_free(list->data);
		list = g_list_next(list);
	}
	g_list_free(tapinfo->strinfo_list);
	tapinfo->strinfo_list = NULL;
	tapinfo->nconversationss = 0;
	tapinfo->npackets = 0;
	tapinfo->setup_packets = 0;
        tapinfo->completed_calls = 0;
        tapinfo->rejected_calls = 0;

	++(tapinfo->launch_count);

	return;
}

/****************************************************************************/
/* redraw the output */
void h225conversations_draw(h323conversations_tapinfo_t *tapinfo _U_)
{
/* XXX: see h323conversations_on_update in h323_conversationss_dlg.c for comments
	gtk_signal_emit_by_name(top_level, "signal_h225conversations_update");
*/
	h323conversations_dlg_update(the_tapinfo_struct.strinfo_list);
	return;
}



/****************************************************************************/
/* whenever a H225 packet is seen by the tap listener */
int h225conversations_packet(h323conversations_tapinfo_t *tapinfo _U_, packet_info *pinfo, epan_dissect_t *edt _U_, void *h225info)
{
	h323_conversations_info_t tmp_strinfo;
	h323_conversations_info_t *strinfo = NULL;
	GList* list;

	h225_packet_info *pi = h225info;

	/* gather infos on the conversations this packet is part of */
	g_memmove(&(tmp_strinfo.src_addr), pinfo->src.data, 4);
	tmp_strinfo.src_port = pinfo->srcport;
	g_memmove(&(tmp_strinfo.dest_addr), pinfo->dst.data, 4);
	tmp_strinfo.dest_port = pinfo->destport;

		/* check wether we already have a conversations with these parameters in the list */
		list = g_list_first(tapinfo->strinfo_list);
		while (list)
		{
			if (h323_conversations_info_cmp(&tmp_strinfo, (h323_conversations_info_t*)(list->data))==0)
			{
				strinfo = (h323_conversations_info_t*)(list->data);  /*found!*/
				break;
			}
			list = g_list_next(list);
		}

		/* not in the list? then create a new entry */
		if (!strinfo) {
			tmp_strinfo.call_state = UNKNOWN;
			tmp_strinfo.npackets = 0;
			tmp_strinfo.h245packets = 0;
			tmp_strinfo.first_frame_num = pinfo->fd->num;
			tmp_strinfo.faststart = pi->is_faststart; 
			tmp_strinfo.is_h245 = pi->is_h245; 
			tmp_strinfo.h245address = pi->h245_address; 
			tmp_strinfo.h245port = pi->h245_port; 
			strinfo = g_malloc(sizeof(h323_conversations_info_t));
			*strinfo = tmp_strinfo;  /* memberwise copy of struct */
			tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);

		}
		/* ok, there is an entry, but is it also an entry for h.245 address.
		 * h.245 address can be provided in connect message, but entry for this conversation
		 * already exists at this point */
		else if (pi->is_h245) {
			strinfo->is_h245 = pi->is_h245; 
			strinfo->h245address = pi->h245_address; 
			strinfo->h245port = pi->h245_port; 
		}

		/* we check the faststart again in the connect message, if there is no
		 * faststart field in connect message, we asume, there is no faststart */
		if ((pi->cs_type == H225_CONNECT) && (pi->is_faststart == 0))
			strinfo->faststart = 0;

		/* in the list or not in the list, we want the status */
		/* we have four states: CALL SETUP, IN_CALL, COMPLETED, REJECTED 
		 * CALL_SETUP: if the setup, call proceding, alerting, 
		 * IN_CALL: connect 
		 * COMPLETED: release complete after connect
		 * REJECTED: release complete without connect
		 */
		switch (pi->cs_type) {

	                case H225_SETUP:
        			strinfo->call_state = CALL_SETUP;
				++(tapinfo->setup_packets);
        	                break;
        	        case H225_CALL_PROCEDING:
        			strinfo->call_state = CALL_SETUP;
        	                break;
			case H225_ALERTING:
        			strinfo->call_state = CALL_SETUP;
        	                break;
                	case H225_CONNECT:
        			strinfo->call_state = IN_CALL;
        	                break;
	                case H225_RELEASE_COMPLET:
				if (strinfo->call_state == IN_CALL) {
					strinfo->call_state = COMPLETED;
        				++(tapinfo->completed_calls);
				}
				else if (strinfo->call_state == CALL_SETUP) {
					strinfo->call_state = REJECTED;
        				++(tapinfo->rejected_calls);
				}
				else if (strinfo->call_state == COMPLETED)
					strinfo->call_state = COMPLETED;
				else if (strinfo->call_state == REJECTED)
					strinfo->call_state = REJECTED;
				else 
					strinfo->call_state = UNKNOWN;
	                case H225_OTHER:
				;
                }

		/* increment the packets counter for this conversations */
		++(strinfo->npackets);

		/* increment the packets counter of all conversationss */
		++(tapinfo->npackets);
		
		return 1;  /* refresh output */
}

/****************************************************************************/
/* scan for h323 conversationss */
void h323conversations_scan(void)
{
	gboolean was_h225_registered = the_tapinfo_struct.is_h225_registered;
	gboolean was_h245_registered = the_tapinfo_struct.is_h245_registered;

	if (!the_tapinfo_struct.is_h225_registered)
		register_tap_listener_h225_conversations();
	if (!the_tapinfo_struct.is_h245_registered)
		register_tap_listener_h245_conversations();

	retap_packets(&cfile);

	if (!was_h225_registered)
		remove_tap_listener_h225_conversations();
	if (!was_h245_registered)
		remove_tap_listener_h245_conversations();
}


/****************************************************************************/
const h323conversations_tapinfo_t* h323conversations_get_info(void)
{
	return &the_tapinfo_struct;
}


/****************************************************************************/
/* TAP INTERFACE */
/****************************************************************************/

/****************************************************************************/
static void
h225conversations_init_tap(char *dummy _U_)
{
	/* XXX: never called? */
}


/* 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_conversations(void)
{
	if (the_tapinfo_struct.is_h225_registered) {
		protect_thread_critical_region();
		remove_tap_listener(&the_tapinfo_struct);
		unprotect_thread_critical_region();

		the_tapinfo_struct.is_h225_registered = FALSE;
	}
}


/****************************************************************************/
void
register_tap_listener_h225_conversations(void)
{
	GString *error_string;

	if (!the_tapinfo_struct.is_h225_registered) {
		register_ethereal_tap("h225", h225conversations_init_tap);

		error_string = register_tap_listener("h225", &the_tapinfo_struct,
			NULL,
			(void*)h225conversations_reset, (void*)h225conversations_packet, (void*)h225conversations_draw);

		if (error_string != NULL) {
			simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
				      error_string->str);
			g_string_free(error_string, TRUE);
			exit(1);
		}

		the_tapinfo_struct.is_h225_registered = TRUE;
	}
}



/****************************************************************************/
/* ***************************TAP for h245 **********************************/
/****************************************************************************/

/****************************************************************************/
/* redraw the output */
void h245conversations_draw(h323conversations_tapinfo_t *tapinfo _U_)
{
	h323conversations_dlg_update(the_tapinfo_struct.strinfo_list);
	return;
}

/****************************************************************************/
/* whenever a H245 packet is seen by the tap listener */
int h245conversations_packet(h323conversations_tapinfo_t *tapinfo _U_, packet_info *pinfo, epan_dissect_t *edt _U_, void *h245info _U_)
{
	GList* list;
	struct _h323_conversations_info* a;
	guint32 src, dst;
	guint16 srcp, dstp;

	/* check wether this packet is a part of any H323 conversation in the list*/
	list = g_list_first(tapinfo->strinfo_list);
	while (list)
	{
		a = (h323_conversations_info_t*)(list->data);
		g_memmove(&src, pinfo->src.data, 4);
		g_memmove(&dst, pinfo->dst.data, 4);
		//src = *(pinfo->src.data);
		//dst = *(pinfo->dst.data);
		srcp = pinfo->srcport;
		dstp = pinfo->destport;
		if ( ((a->h245address == src) && (a->h245port == srcp) ) ||
				( (a->h245address == dst) && (a->h245port == dstp)) ) {
				/* in the list? increment packet number */
				++(a->h245packets);
			break;
		}
		list = g_list_next(list);
	}

	return 1;  /* refresh output */
}

/****************************************************************************/
static void
h245conversations_init_tap(char *dummy _U_)
{
	/* XXX: never called? */
}

/****************************************************************************/
void
remove_tap_listener_h245_conversations(void)
{
	if (the_tapinfo_struct.is_h245_registered) {
		protect_thread_critical_region();
		remove_tap_listener(&the_tapinfo_struct);
		unprotect_thread_critical_region();

		the_tapinfo_struct.is_h245_registered = FALSE;
	}
}


/****************************************************************************/
void
register_tap_listener_h245_conversations(void)
{
	GString *error_string;
	if (!the_tapinfo_struct.is_h245_registered) {
		register_ethereal_tap("h245", h245conversations_init_tap);

		error_string = register_tap_listener("h245", &the_tapinfo_struct,
			NULL,
			(void*)h245conversations_reset, (void*)h245conversations_packet, (void*)h245conversations_draw);

		if (error_string != NULL) {
			simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
				      error_string->str);
			g_string_free(error_string, TRUE);
			exit(1);
		}

		the_tapinfo_struct.is_h245_registered = TRUE;
	}
}


void h245conversations_reset(h323conversations_tapinfo_t *tapinfo _U_)
{
	return;
}

/* h323_conversations_dlg.c
 * H323 conversations summary addition for ethereal
 *
 * Copyright 2004, Iskratel, Ltd, Kranj
 * By Miha Jemec <m.jemec@xxxxxxxxxxx>
 *
 * based on rtp_stream_dlg.c
 * Copyright 2003, Alcatel Business Systems
 * By Lars Ruoff <lars.ruoff@xxxxxxx>
 *
 * 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 "h323_conversations_dlg.h"
#include "h323_conversations.h"
#include "h323_analysis.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 <string.h>


typedef const guint8 * ip_addr_p;

static const gchar FWD_LABEL_TEXT[] = "Select one conversation with left mouse button\n";

/****************************************************************************/
/* pointer to the one and only dialog window */
static GtkWidget *h323_conversations_dlg = NULL;

static GtkWidget *clist = NULL;
static GtkWidget *top_label = NULL;
static GtkWidget *status_label = NULL;
static GtkWidget *label_fwd = NULL;

static h323_conversations_info_t* selected_conversations_fwd = NULL;  /* current selection */
static GList *last_list = NULL;

static guint32 conversationss_nb = 0;     /* number of displayed conversationss */

/****************************************************************************/
/* append a line to clist */
static void add_to_clist(h323_conversations_info_t* strinfo)
{
	gchar label_text[256];
	gint added_row;
	gchar *data[8];
	gchar field[8][30];

	data[0]=&field[0][0];
	data[1]=&field[1][0];
	data[2]=&field[2][0];
	data[3]=&field[3][0];
	data[4]=&field[4][0];
	data[5]=&field[5][0];
	data[6]=&field[6][0];
	data[7]=&field[7][0];

	g_snprintf(field[0], 20, "%s", ip_to_str((const guint8*)&(strinfo->src_addr)));
	g_snprintf(field[1], 20, "%u", strinfo->src_port);
	g_snprintf(field[2], 20, "%s", ip_to_str((const guint8*)&(strinfo->dest_addr)));
	g_snprintf(field[3], 20, "%u", strinfo->dest_port);
        g_snprintf(field[4], 20, "%s", strinfo->faststart? "TRUE":"FALSE");
	g_snprintf(field[5], 20, "%u", strinfo->npackets);
        g_snprintf(field[6], 20, "%u", strinfo->h245packets);
	
	switch (strinfo->call_state) {

		case (CALL_SETUP):
			g_snprintf(field[7], 20, "%s", "CALL SETUP");
			break;
		case (IN_CALL):
			g_snprintf(field[7], 20, "%s", "IN CALL");
			break;
		case (COMPLETED):
			g_snprintf(field[7], 20, "%s", "COMPLETED");
			break;
		case (REJECTED):
			g_snprintf(field[7], 20, "%s", "REJECTED");
			break;
		case (UNKNOWN):
			g_snprintf(field[7], 20, "%s", "UNKNOWN");
	}

	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 conversationss */
	sprintf(label_text,
	        "Detected %d H323 Conversations. Choose one for analysis",
	        ++conversationss_nb);
	gtk_label_set(GTK_LABEL(top_label), label_text);

	/* Update the status label with the number of total messages */
        sprintf(label_text,
        	"Total Setup packets: %d   Completed calls: %d   Rejected calls: %d\n",
	                h323conversations_get_info()->setup_packets, 
			h323conversations_get_info()->completed_calls,
			h323conversations_get_info()->rejected_calls);
        gtk_label_set(GTK_LABEL(status_label), label_text);
}


/****************************************************************************/
/* CALLBACKS                                                                */
/****************************************************************************/
static void
h323conversations_on_destroy                      (GtkObject       *object _U_,
                                        gpointer         user_data _U_)
{
	/* Remove the conversations tap listener */
	remove_tap_listener_h225_conversations();
	remove_tap_listener_h245_conversations();

	/* Clean up memory used by conversations tap */
	h225conversations_reset((h323conversations_tapinfo_t*) h323conversations_get_info());

	/* Note that we no longer have a "H.323 Conversations" dialog box. */
	h323_conversations_dlg = NULL;
}


/****************************************************************************/
static void
h323conversations_on_unselect                  (GtkButton       *button _U_,
                                        gpointer         user_data _U_)
{
	selected_conversations_fwd = NULL;
	gtk_clist_unselect_all(GTK_CLIST(clist));
	gtk_label_set_text(GTK_LABEL(label_fwd), FWD_LABEL_TEXT);
}


/****************************************************************************/
static void
h323conversations_on_filter                    (GtkButton       *button _U_,
                                        gpointer         user_data _U_)
{
	gchar *filter_string = NULL;
	gchar *filter_string_fwd = NULL;

	if (selected_conversations_fwd==NULL)
		return;

	/* if also address for h245 packets is known */
	else if (selected_conversations_fwd->is_h245) {
		filter_string_fwd = g_strdup_printf(
				"((ip.addr==%s && tcp.port==%u && ip.addr==%s && tcp.port==%u) and h225) or ((ip.addr==%s && tcp.port==%u) and h245)",
				ip_to_str((const guint8*)&(selected_conversations_fwd->src_addr)),
				selected_conversations_fwd->src_port,
				ip_to_str((const guint8*)&(selected_conversations_fwd->dest_addr)),
				selected_conversations_fwd->dest_port,
				ip_to_str((const guint8*)&(selected_conversations_fwd->h245address)),
				selected_conversations_fwd->h245port);
	}
	/* else filter only h225 packets */
	else {
		filter_string_fwd = g_strdup_printf(
				"(ip.addr==%s && tcp.port==%u && ip.addr==%s && tcp.port==%u) and h225",
				ip_to_str((const guint8*)&(selected_conversations_fwd->src_addr)),
				selected_conversations_fwd->src_port,
				ip_to_str((const guint8*)&(selected_conversations_fwd->dest_addr)),
				selected_conversations_fwd->dest_port);
	}

        filter_string = filter_string_fwd;

	gtk_entry_set_text(GTK_ENTRY(main_display_filter_widget), filter_string);
	g_free(filter_string);
/*
	main_filter_packets(&cfile, filter_string, FALSE);
	h323conversations_dlg_update(h323conversations_get_info()->strinfo_list);
*/
}


/****************************************************************************/
static void
h323conversations_on_analyse                   (GtkButton       *button _U_,
                                        gpointer         user_data _U_)
{
	guint32 ip_src = 0;
        guint16 port_src = 0;
        guint32 ip_dst = 0;
        guint16 port_dst = 0;
        guint32 ip_src_h245 = 0;
        guint16 port_src_h245 = 0;

	if (selected_conversations_fwd) {
		ip_src = selected_conversations_fwd->src_addr;
		port_src = selected_conversations_fwd->src_port;
		ip_dst = selected_conversations_fwd->dest_addr;
		port_dst = selected_conversations_fwd->dest_port;
		ip_src_h245 = selected_conversations_fwd->h245address;
		port_src_h245 = selected_conversations_fwd->h245port;
	}

   	h323_analysis(
                ip_src,
                port_src,
                ip_dst,
                port_dst,
                ip_src_h245,
                port_src_h245
                );
}


/****************************************************************************/
/* when the user selects a row in the conversations list */
static void
h323conversations_on_select_row(GtkCList *clist,
                                            gint row _U_,
                                            gint column _U_,
                                            GdkEventButton *event _U_,
                                            gpointer user_data _U_)
{
	gchar label_text[80];

	selected_conversations_fwd = gtk_clist_get_row_data(GTK_CLIST(clist), row);
	g_snprintf(label_text, 80, "Conversation: %s:%u <---> %s:%u\n",
		ip_to_str((ip_addr_p)&selected_conversations_fwd->src_addr),
		selected_conversations_fwd->src_port,
		ip_to_str((ip_addr_p)&selected_conversations_fwd->dest_addr),
		selected_conversations_fwd->dest_port
	);
	gtk_label_set_text(GTK_LABEL(label_fwd), label_text);

/*
	gtk_widget_set_sensitive(save_bt, TRUE);
	gtk_widget_set_sensitive(filter_bt, TRUE);
	gtk_widget_set_sensitive(mark_bt, TRUE);
*/
	/* TODO: activate other buttons when implemented */
}


/****************************************************************************/
#define NUM_COLS 8

typedef struct column_arrows {
	GtkWidget *table;
	GtkWidget *ascend_pm;
	GtkWidget *descend_pm;
} column_arrows;


/****************************************************************************/
static void
h323conversations_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
h323conversations_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 2:
	case 5:
	case 7:
		return strcmp (text1, text2);
	case 1:
	case 3:
	case 4:
	case 6:
		i1=atoi(text1);
		i2=atoi(text2);
		return i1-i2;
	}
	g_assert_not_reached();
	return 0;
}


/****************************************************************************/
/* INTERFACE                                                                */
/****************************************************************************/

static void h323conversations_dlg_create (void)
{
	GtkWidget *h323conversations_dlg_w;
	GtkWidget *main_vb;
	GtkWidget *scrolledwindow;
	GtkWidget *hbuttonbox;
	GtkWidget *bt_unselect;
	GtkWidget *bt_filter;
	GtkWidget *bt_analyse;
	GtkWidget *bt_close;

	gchar *titles[8] =  {"Side A IP addr", "Side B port",  "Side B IP addr", "Side B port", "Faststart", "H225 pkts", "H245 pkts", "Status"};
	column_arrows *col_arrows;
	GtkWidget *column_lb;
	int i;

	h323conversations_dlg_w = dlg_window_new("Ethereal: H.323 Conversations");
	gtk_window_set_default_size(GTK_WINDOW(h323conversations_dlg_w), 700, 300);

	main_vb = gtk_vbox_new (FALSE, 0);
	gtk_container_add(GTK_CONTAINER(h323conversations_dlg_w), main_vb);
	gtk_container_set_border_width (GTK_CONTAINER (main_vb), 12);

	top_label = gtk_label_new ("Detected 0 H.323 Conversations. Choose one conversation for analysis");
	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, 100);
	gtk_clist_set_column_width (GTK_CLIST (clist), 1, 70);
	gtk_clist_set_column_width (GTK_CLIST (clist), 2, 100);
	gtk_clist_set_column_width (GTK_CLIST (clist), 3, 70);
	gtk_clist_set_column_width (GTK_CLIST (clist), 4, 60);
	gtk_clist_set_column_width (GTK_CLIST (clist), 5, 60);
	gtk_clist_set_column_width (GTK_CLIST (clist), 6, 60);
	gtk_clist_set_column_width (GTK_CLIST (clist), 7, 100);

	gtk_clist_set_column_justification(GTK_CLIST(clist), 0, GTK_JUSTIFY_CENTER);
	gtk_clist_set_column_justification(GTK_CLIST(clist), 1, GTK_JUSTIFY_CENTER);
	gtk_clist_set_column_justification(GTK_CLIST(clist), 2, GTK_JUSTIFY_CENTER);
	gtk_clist_set_column_justification(GTK_CLIST(clist), 3, GTK_JUSTIFY_CENTER);
	gtk_clist_set_column_justification(GTK_CLIST(clist), 4, GTK_JUSTIFY_CENTER);
	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_CENTER);

	gtk_clist_column_titles_show (GTK_CLIST (clist));

	gtk_clist_set_compare_func(GTK_CLIST(clist), h323conversations_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(h323conversations_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 src-ip 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", h323conversations_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 Setup packets: 0   Completed calls: 0   Rejected calls: 0\n");
	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);

	bt_filter = gtk_button_new_with_label ("Set filter");
	gtk_container_add (GTK_CONTAINER (hbuttonbox), bt_filter);

	bt_analyse = gtk_button_new_with_label ("Analyse");
	gtk_container_add (GTK_CONTAINER (hbuttonbox), bt_analyse);

	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);

	SIGNAL_CONNECT(clist, "select_row", h323conversations_on_select_row, NULL);
	SIGNAL_CONNECT(bt_unselect, "clicked", h323conversations_on_unselect, NULL);
	SIGNAL_CONNECT(bt_filter, "clicked", h323conversations_on_filter, NULL);
	SIGNAL_CONNECT(bt_analyse, "clicked", h323conversations_on_analyse, NULL);

	window_set_cancel_button(h323conversations_dlg_w, bt_close, window_cancel_button_cb);

	SIGNAL_CONNECT(h323conversations_dlg_w, "delete_event", window_delete_event_cb, NULL);
	SIGNAL_CONNECT(h323conversations_dlg_w, "destroy", h323conversations_on_destroy, NULL);

	gtk_widget_show_all(h323conversations_dlg_w);
	window_present(h323conversations_dlg_w);

	h323conversations_on_unselect(NULL, NULL);

	h323_conversations_dlg = h323conversations_dlg_w;
}


/****************************************************************************/
/* PUBLIC								    */
/****************************************************************************/

/****************************************************************************/
/* update the contents of the dialog box clist */
/* list: pointer to list of h323_conversations_info_t* */
void h323conversations_dlg_update(GList *list)
{
	gchar label_text[256];

	if (h323_conversations_dlg != NULL) {
		gtk_clist_clear(GTK_CLIST(clist));
		conversationss_nb = 0;
        	sprintf(label_text,
        		"Total Setup packets: %d   Completed calls: %d   Rejected calls: %d\n",
		                h323conversations_get_info()->setup_packets, 
				h323conversations_get_info()->completed_calls,
				h323conversations_get_info()->rejected_calls);
        	gtk_label_set(GTK_LABEL(status_label), label_text);

		list = g_list_first(list);
		while (list)
		{
			add_to_clist((h323_conversations_info_t*)(list->data));
			list = g_list_next(list);
		}

		h323conversations_on_unselect(NULL, NULL);
	}

	last_list = list;
}


/****************************************************************************/
/* update the contents of the dialog box clist */
/* list: pointer to list of h323_conversations_info_t* */
void h323conversations_dlg_show(GList *list)
{
	if (h323_conversations_dlg != NULL) {
		/* There's already a dialog box; reactivate it. */
		reactivate_window(h323_conversations_dlg);
		/* Another list since last call? */
		if (list != last_list) {
			h323conversations_dlg_update(list);
		}
	}
	else {
		/* Create and show the dialog box */
		h323conversations_dlg_create();
		h323conversations_dlg_update(list);
	}
}


/****************************************************************************/
/* entry point when called via the GTK menu */
void h323conversations_launch(GtkWidget *w _U_, gpointer data _U_)
{
	/* Register the tap listener */
	register_tap_listener_h225_conversations();
	register_tap_listener_h245_conversations();

	/* Scan for H323 conversations conversationss (redissect all packets) */
	h323conversations_scan();

	/* Show the dialog box with the list of conversationss */
	h323conversations_dlg_show(h323conversations_get_info()->strinfo_list);

	/* Tap listener will be removed and cleaned up in h323conversations_on_destroy */
}

/****************************************************************************/
void
register_tap_listener_h323_conversations_dlg(void)
{
	register_tap_menu_item("H.323/Show All H323 Conversations...", REGISTER_TAP_GROUP_NONE,
	    h323conversations_launch, NULL, NULL, NULL);
}
/* h323_conversations_dlg.h
 * H323 conversations addition for ethereal
 *
 * Copyright 2004, Iskratel, Ltd, Kranj
 * By Miha Jemec <m.jemec@xxxxxxxxxxx>
 *
 * based on rtp_stream_dlg.h
 * Copyright 2003, Alcatel Business Systems
 * By Lars Ruoff <lars.ruoff@xxxxxxx>
 *
 * 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 H323_STREAM_DLG_H_INCLUDED
#define H323_STREAM_DLG_H_INCLUDED

#include <gtk/gtk.h>

/**
 * Create or reactivate the h323 streams dialog box.
 *
 * @param list pointer to list of rtp_stream_info_t*
 */
void h323conversations_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 h323conversations_dlg_update(GList *list);

#endif /* H323_STREAM_DLG_H_INCLUDED*/
/* h323_conversations.h
 * H323 conversations summary addition for ethereal
 *
 * Copyright 2004, Iskratel, Ltd, Kranj
 * By Miha Jemec <m.jemec@xxxxxxxxxxx>
 *
 * based on rtp_stream.h
 * Copyright 2003, Alcatel Business Systems
 * By Lars Ruoff <lars.ruoff@xxxxxxx>
 *
 * 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 H323_STREAM_H_INCLUDED
#define H323_STREAM_H_INCLUDED

#include <glib.h>
#include <stdio.h>

/****************************************************************************/
/* defines h323 state */
typedef enum _h323_call_state {
        CALL_SETUP,
        IN_CALL,
        COMPLETED,
        REJECTED,
	UNKNOWN
} h323_call_state;

/* defines an h323 conversation */
typedef struct _h323_conversations_info {
	h323_call_state call_state;
	guint32 src_addr;
	guint16 src_port;
	guint32 dest_addr;
	guint16 dest_port;
	guint8  pt;
	guint32 npackets;
	gboolean faststart;
	/* if there are also h245 messages */
	gboolean is_h245;
	guint32 h245packets;
	guint32 h245address;
	guint16 h245port;

	guint32 first_frame_num; /* frame number of first frame */

} h323_conversations_info_t;

/* structure that holds the information about all detected conversationss */
/* struct holding all information of the tap */
typedef struct _h323conversations_tapinfo {
	int     nconversationss;       /* number of conversationss in the list */
	GList*  strinfo_list;   /* list with all conversationss */
	int     npackets;       /* total number of h323 packets of all conversationss */
	h323_conversations_info_t* filter_conversations_fwd;  /* used as filter in some tap modes */
	guint32 launch_count;   /* number of times the tap has been run */
	gboolean is_h225_registered; /* if the tap listener is currently registered or not */
	gboolean is_h245_registered; /* if the tap listener is currently registered or not */
	int setup_packets;
	int completed_calls;
	int rejected_calls;
} h323conversations_tapinfo_t;


/****************************************************************************/
/* INTERFACE */

/*
* Registers the h323_conversationss tap listener (if not already done).
* From that point on, the H323 conversationss list will be updated with every redissection.
* This function is also the entry point for the initialization routine of the tap system.
* So whenever h323_conversations.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 h323_conversationss and h323_analysis functions that need it.
*/
void register_tap_listener_h225_conversations(void);
void register_tap_listener_h245_conversations(void);

/*
* Removes the h323_conversationss tap listener (if not already done)
* From that point on, the H323 conversationss list won't be updated any more.
*/
void remove_tap_listener_h225_conversations(void);
void remove_tap_listener_h245_conversations(void);

/*
* Retrieves a constant reference to the unique info structure of the h323_conversationss tap listener.
* The user should not modify the data pointed to.
*/
const h323conversations_tapinfo_t* h323conversations_get_info(void);

/*
* Cleans up memory of h323 conversationss tap.
*/
void h225conversations_reset(h323conversations_tapinfo_t *tapinfo);
void h245conversations_reset(h323conversations_tapinfo_t *tapinfo);

/*
* Scans all packets for H225 conversationss and updates the H225 conversationss list.
* (redissects all packets)
*/
void h323conversations_scan(void);

/*
* Marks all packets belonging to conversations.
* (can be NULL)
* (redissects all packets)
*/
void h323conversations_mark(h323_conversations_info_t* conversations_fwd);


#endif /*H323_STREAM_H_INCLUDED*/
--- Makefile	2004-09-29 14:50:56.000000000 +0200
+++ my-Makefile	2004-09-29 14:55:42.000000000 +0200
@@ -86,10 +86,10 @@
 pkgincludedir = $(includedir)/ethereal
 top_builddir = ..
 
-ACLOCAL = ${SHELL} /home/miha/ethereal/tmp/ethereal-0.10.5/missing --run aclocal-1.6
-AUTOCONF = ${SHELL} /home/miha/ethereal/tmp/ethereal-0.10.5/missing --run autoconf
-AUTOMAKE = ${SHELL} /home/miha/ethereal/tmp/ethereal-0.10.5/missing --run automake-1.6
-AUTOHEADER = ${SHELL} /home/miha/ethereal/tmp/ethereal-0.10.5/missing --run autoheader
+ACLOCAL = ${SHELL} /home/miha/ethereal/ethereal-0.10.5/missing --run aclocal-1.6
+AUTOCONF = ${SHELL} /home/miha/ethereal/ethereal-0.10.5/missing --run autoconf
+AUTOMAKE = ${SHELL} /home/miha/ethereal/ethereal-0.10.5/missing --run automake-1.6
+AUTOHEADER = ${SHELL} /home/miha/ethereal/ethereal-0.10.5/missing --run autoheader
 
 am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
 INSTALL = /usr/bin/install -c
@@ -114,7 +114,7 @@
 OBJEXT = o
 PATH_SEPARATOR = :
 ADNS_LIBS = 
-AMTAR = ${SHELL} /home/miha/ethereal/tmp/ethereal-0.10.5/missing --run tar
+AMTAR = ${SHELL} /home/miha/ethereal/ethereal-0.10.5/missing --run tar
 AS = @AS@
 AWK = gawk
 CC = gcc
@@ -199,7 +199,7 @@
 etherealfilter_man = ethereal-filter.4
 idl2eth_bin = idl2eth
 idl2eth_man = idl2eth.1
-install_sh = /home/miha/ethereal/tmp/ethereal-0.10.5/install-sh
+install_sh = /home/miha/ethereal/ethereal-0.10.5/install-sh
 mergecap_bin = mergecap$(EXEEXT)
 mergecap_man = mergecap.1
 plugindir = /usr/local/lib/ethereal/plugins/0.10.5
@@ -257,6 +257,7 @@
 	range_utils.c \
 	recent.c	\
 	rtp_stream.c	\
+	h323_conversations.c	\
 	service_response_time_table.c	\
 	simple_dialog.c	\
 	stream_prefs.c	\
@@ -307,6 +308,8 @@
 	rpc_stat.c	\
 	rtp_analysis.c	\
 	rtp_stream_dlg.c	\
+	h323_analysis.c	\
+	h323_conversations_dlg.c	\
 	tcp_graph.c	\
 	sip_stat.c	\
 	smb_stat.c	\
@@ -365,6 +368,9 @@
 	rtp_analysis.h	\
 	rtp_stream.h	\
 	rtp_stream_dlg.h \
+	h323_analysis.h	\
+	h323_conversations.h	\
+	h323_conversations_dlg.h \
 	sat.h		\
 	service_response_time_table.h	\
 	stream_prefs.h	\
@@ -430,7 +436,7 @@
 	print_dlg.$(OBJEXT) print_prefs.$(OBJEXT) \
 	progress_dlg.$(OBJEXT) proto_dlg.$(OBJEXT) proto_draw.$(OBJEXT) \
 	proto_hier_stats_dlg.$(OBJEXT) range_utils.$(OBJEXT) \
-	recent.$(OBJEXT) rtp_stream.$(OBJEXT) \
+	recent.$(OBJEXT) rtp_stream.$(OBJEXT) h323_conversations.$(OBJEXT) \
 	service_response_time_table.$(OBJEXT) simple_dialog.$(OBJEXT) \
 	stream_prefs.$(OBJEXT) summary_dlg.$(OBJEXT) \
 	supported_protos_dlg.$(OBJEXT) tap_dfilter_dlg.$(OBJEXT) \
@@ -452,8 +458,8 @@
 	hostlist_udpip.$(OBJEXT) http_stat.$(OBJEXT) io_stat.$(OBJEXT) \
 	isup_stat.$(OBJEXT) ldap_stat.$(OBJEXT) mgcp_stat.$(OBJEXT) \
 	mtp3_stat.$(OBJEXT) mtp3_summary.$(OBJEXT) rpc_progs.$(OBJEXT) \
-	rpc_stat.$(OBJEXT) rtp_analysis.$(OBJEXT) \
-	rtp_stream_dlg.$(OBJEXT) tcp_graph.$(OBJEXT) sip_stat.$(OBJEXT) \
+	rpc_stat.$(OBJEXT) rtp_analysis.$(OBJEXT) h323_analysis.$(OBJEXT) \
+	rtp_stream_dlg.$(OBJEXT) h323_conversations_dlg.$(OBJEXT) tcp_graph.$(OBJEXT) sip_stat.$(OBJEXT) \
 	smb_stat.$(OBJEXT) wsp_stat.$(OBJEXT)
 am_libui_a_OBJECTS = $(am__objects_1) $(am__objects_2) \
 	$(am__objects_3)