aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--epan/camel-persistentdata.c798
-rw-r--r--epan/camel-persistentdata.h126
-rw-r--r--gtk/camel_counter.c233
-rw-r--r--gtk/camel_srt.c248
-rw-r--r--tap-camelcounter.c146
-rw-r--r--tap-camelsrt.c276
6 files changed, 1827 insertions, 0 deletions
diff --git a/epan/camel-persistentdata.c b/epan/camel-persistentdata.c
new file mode 100644
index 0000000000..ff3c06be7b
--- /dev/null
+++ b/epan/camel-persistentdata.c
@@ -0,0 +1,798 @@
+/*
+ * camel-persistentdata.c
+ * Source for lists and hash tables used in wireshark's camel dissector
+ * for calculation of delays in camel calls
+ * Copyright 2006 Florent Drouin
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * 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 <glib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <epan/emem.h>
+#include "epan/packet.h"
+#include "epan/conversation.h"
+#include "epan/camel-persistentdata.h"
+#include "epan/dissectors/packet-tcap.h"
+#include "epan/dissectors/packet-mtp3.h"
+
+static gint camelsrt_call_equal(gconstpointer k1, gconstpointer k2);
+static guint camelsrt_call_hash(gconstpointer k);
+static struct camelsrt_call_t * find_camelsrt_call(struct camelsrt_call_info_key_t * p_camelsrt_call_key,
+ packet_info *pinfo);
+static struct camelsrt_call_t * new_camelsrt_call(struct camelsrt_call_info_key_t * p_camelsrt_call_key,
+ packet_info *pinfo);
+
+static void update_camelsrt_call(struct camelsrt_call_t * p_camelsrt_call,
+ packet_info *pinfo,
+ guint msg_category _U_);
+
+static struct camelsrt_call_t * append_camelsrt_call(struct camelsrt_call_t * prev_call,
+ packet_info *pinfo);
+
+static void camelsrt_begin_call_matching(tvbuff_t *tvb,
+ packet_info * pinfo _U_,
+ proto_tree *tree,
+ struct camelsrt_info_t * p_camelsrt_info);
+
+static void camelsrt_request_call_matching(tvbuff_t *tvb,
+ packet_info * pinfo _U_,
+ proto_tree *tree,
+ struct camelsrt_info_t * p_camelsrt_info,
+ guint srt_type);
+
+static void camelsrt_report_call_matching(tvbuff_t *tvb,
+ packet_info * pinfo _U_,
+ proto_tree *tree,
+ struct camelsrt_info_t * p_camelsrt_info,
+ guint srt_type);
+
+static void camelsrt_close_call_matching(tvbuff_t *tvb,
+ packet_info * pinfo _U_,
+ proto_tree *tree,
+ struct camelsrt_info_t * p_camelsrt_info);
+
+static void camelsrt_display_DeltaTime(proto_tree *tree,
+ tvbuff_t *tvb,
+ nstime_t* value_ptr,
+ guint category);
+
+static void raz_camelsrt_call (struct camelsrt_call_t * p_camelsrt_call);
+
+void camelsrt_tcap_matching(tvbuff_t *tvb,
+ packet_info * pinfo _U_,
+ proto_tree *tree,
+ struct tcaphash_context_t * tcap_context);
+
+/* When several Camel components are received in a single TCAP message,
+ we have to use several buffers for the stored parameters
+ because else this data are erased during TAP dissector call */
+#define MAX_CAMEL_INSTANCE 10
+int camelsrt_global_current=0;
+struct camelsrt_info_t camelsrt_global_info[MAX_CAMEL_INSTANCE];
+
+/* Configuration parameters to enable or disable the Service Response Time */
+extern gboolean gcamel_HandleSRT;
+gboolean gcamel_PersistentSRT=FALSE;
+gboolean gcamel_DisplaySRT=FALSE;
+gboolean gcamel_StatSRT=FALSE;
+
+extern int camel_tap;
+
+extern int hf_camelsrt_SessionId;
+extern int hf_camelsrt_RequestNumber;
+extern int hf_camelsrt_Duplicate;
+extern int hf_camelsrt_RequestFrame;
+extern int hf_camelsrt_ResponseFrame;
+extern int hf_camelsrt_DeltaTime;
+extern int hf_camelsrt_SessionTime;
+extern int hf_camelsrt_DeltaTime31;
+extern int hf_camelsrt_DeltaTime75;
+extern int hf_camelsrt_DeltaTime65;
+extern int hf_camelsrt_DeltaTime22;
+extern int hf_camelsrt_DeltaTime35;
+extern int hf_camelsrt_DeltaTime80;
+
+/* Global hash tables*/
+static GHashTable *srt_calls = NULL;
+guint32 camelsrt_global_SessionId=1;
+
+/*
+ * DEBUG fonctions
+ */
+
+#undef DEBUG_CAMELSRT
+/* #define DEBUG_CAMELSRT */
+
+#ifdef DEBUG_CAMELSRT
+#include <stdio.h>
+#include <stdarg.h>
+static unsigned debug_level = 99;
+
+static void dbg(unsigned level, char* fmt, ...) {
+ va_list ap;
+
+ if (level > debug_level) return;
+ va_start(ap,fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+}
+#endif
+
+/*
+ * Functions needed for Hash-Table
+ */
+
+/* compare 2 keys */
+static gint camelsrt_call_equal(gconstpointer k1, gconstpointer k2)
+{
+ const struct camelsrt_call_info_key_t * key1 = (const struct camelsrt_call_info_key_t *) k1;
+ const struct camelsrt_call_info_key_t * key2 = (const struct camelsrt_call_info_key_t *) k2;
+
+ return (key1->SessionIdKey == key2->SessionIdKey) ;
+}
+
+/* calculate a hash key */
+static guint camelsrt_call_hash(gconstpointer k)
+{
+ const struct camelsrt_call_info_key_t * key = (const struct camelsrt_call_info_key_t *) k;
+ return key->SessionIdKey;
+}
+
+/*
+ * Find the dialog by Key and Time
+ */
+static struct camelsrt_call_t * find_camelsrt_call(struct camelsrt_call_info_key_t * p_camelsrt_call_key,
+ packet_info *pinfo)
+{
+ struct camelsrt_call_t * p_camelsrt_call = NULL;
+ p_camelsrt_call = (struct camelsrt_call_t *)g_hash_table_lookup(srt_calls, p_camelsrt_call_key);
+
+ if(p_camelsrt_call) {
+#ifdef DEBUG_CAMELSRT
+ dbg(10,"D%d ", p_camelsrt_call->session_id);
+#endif
+ } else {
+#ifdef DEBUG_CAMELSRT
+ dbg(23,"Not in hash ");
+#endif
+ }
+
+ return p_camelsrt_call;
+}
+
+/*
+ * New record to create, to identify a new transaction
+ */
+static struct camelsrt_call_t * new_camelsrt_call(struct camelsrt_call_info_key_t * p_camelsrt_call_key,
+ packet_info *pinfo)
+
+{
+ struct camelsrt_call_info_key_t * p_new_camelsrt_call_key;
+ struct camelsrt_call_t * p_new_camelsrt_call = NULL;
+
+ /* Register the transaction in the hash table
+ with the tcap transaction Id as main Key
+ Once created, this entry will be updated later */
+
+ p_new_camelsrt_call_key = se_alloc(sizeof(struct camelsrt_call_info_key_t));
+ p_new_camelsrt_call_key->SessionIdKey = p_camelsrt_call_key->SessionIdKey;
+ p_new_camelsrt_call = se_alloc(sizeof(struct camelsrt_call_t));
+ raz_camelsrt_call(p_new_camelsrt_call);
+ p_new_camelsrt_call->session_id = camelsrt_global_SessionId++;
+#ifdef DEBUG_CAMELSRT
+ dbg(10,"D%d ", p_new_camelsrt_call->session_id);
+#endif
+ /* store it */
+ g_hash_table_insert(srt_calls, p_new_camelsrt_call_key, p_new_camelsrt_call);
+ return p_new_camelsrt_call;
+}
+
+/*
+ * Update a record with the data of the Request
+ */
+static void update_camelsrt_call(struct camelsrt_call_t * p_camelsrt_call,
+ packet_info *pinfo,
+ guint msg_category _U_)
+{
+ p_camelsrt_call->category[msg_category].req_num = pinfo->fd->num;
+ p_camelsrt_call->category[msg_category].rsp_num = 0;
+ p_camelsrt_call->category[msg_category].responded = FALSE;
+ p_camelsrt_call->category[msg_category].req_time = pinfo->fd->abs_ts;
+}
+
+
+/*
+ * Routine called when the TAP is initialized.
+ * so hash table are (re)created
+ */
+void camelsrt_init_routine(void)
+{
+
+ /* free hash-tables and mem_chunks for SRT */
+ if (srt_calls != NULL) {
+#ifdef DEBUG_CAMELSRT
+ dbg(16,"Destroy hash ");
+#endif
+ g_hash_table_destroy(srt_calls);
+ }
+
+ /* create new hash-tables and mem_chunks for SRT */
+ srt_calls = g_hash_table_new(camelsrt_call_hash, camelsrt_call_equal);
+#ifdef DEBUG_CAMELSRT
+ dbg(16,"Create hash ");
+#endif
+ /* Reset the session counter */
+ camelsrt_global_SessionId=1;
+
+ /* The Display of SRT is enable
+ * 1) For wireshark only if Persistent Stat is enable
+ * 2) For Tshark, if the SRT handling is enable
+ */
+ gcamel_DisplaySRT=gcamel_PersistentSRT || gcamel_HandleSRT&gcamel_StatSRT;
+}
+
+/*
+ * Service Response Time analyze, called just after the camel dissector
+ * According to the camel operation, we
+ * - open/close a context for the camel session
+ * - look for a request, or look for the corresponding response
+ */
+void camelsrt_call_matching(tvbuff_t *tvb,
+ packet_info * pinfo _U_,
+ proto_tree *tree,
+ struct camelsrt_info_t * p_camelsrt_info)
+{
+
+#ifdef DEBUG_CAMELSRT
+ dbg(10,"tcap_session #%d ", p_camelsrt_info->tcap_session_id);
+#endif
+
+ switch (p_camelsrt_info->opcode) {
+
+ case 0: /*InitialDP*/
+ camelsrt_begin_call_matching(tvb, pinfo, tree, p_camelsrt_info);
+ camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
+ CAMELSRT_VOICE_INITIALDP);
+ break;
+ case 60: /*InitialDPSMS*/
+ camelsrt_begin_call_matching(tvb, pinfo, tree, p_camelsrt_info);
+ camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
+ CAMELSRT_SMS_INITIALDP);
+ break;
+ case 78: /*InitialDPGPRS*/
+ camelsrt_begin_call_matching(tvb, pinfo, tree, p_camelsrt_info);
+ camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
+ CAMELSRT_GPRS_INITIALDP);
+ break;
+
+ case 23: /*RequestReportBCSMEvent*/
+ break;
+
+ case 63: /*RequestReportSMSEvent*/
+ break;
+
+ case 81: /*RequestReportGPRSEvent*/
+ break;
+
+ case 24: /*EventReportBCSMEvent*/
+ camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
+ CAMELSRT_VOICE_DISC );
+ break;
+
+ case 64: /*EventReportSMS*/
+ /* Session has been explicity closed without TC_END */
+ camelsrt_close_call_matching(tvb, pinfo, tree, p_camelsrt_info);
+ tcapsrt_close(p_camelsrt_info->tcap_context, pinfo);
+ break;
+
+ case 80: /*EventReportGPRS*/
+ camelsrt_begin_call_matching(tvb, pinfo, tree, p_camelsrt_info);
+ camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
+ CAMELSRT_GPRS_REPORT);
+ break;
+
+ case 35: /*ApplyCharging*/
+ camelsrt_report_call_matching(tvb, pinfo, tree, p_camelsrt_info,
+ CAMELSRT_VOICE_ACR1 );
+ break;
+
+ case 71: /*ApplyChargingGPRS*/
+ break;
+
+ case 36: /*ApplyChargingReport*/
+ camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
+ CAMELSRT_VOICE_ACR1 );
+ break;
+
+ case 72: /*ApplyChargingReportGPRS*/
+ break;
+
+ case 31: /*Continue*/
+ camelsrt_report_call_matching(tvb, pinfo, tree, p_camelsrt_info,
+ CAMELSRT_VOICE_INITIALDP);
+ break;
+ case 65: /*ContinueSMS*/
+ camelsrt_report_call_matching(tvb, pinfo, tree, p_camelsrt_info,
+ CAMELSRT_SMS_INITIALDP);
+ break;
+ case 75: /*ContinueGPRS*/
+ camelsrt_report_call_matching(tvb, pinfo, tree, p_camelsrt_info,
+ CAMELSRT_GPRS_INITIALDP);
+ camelsrt_report_call_matching(tvb, pinfo, tree, p_camelsrt_info,
+ CAMELSRT_GPRS_REPORT);
+ break;
+
+ case 22: /*ReleaseCall*/
+ camelsrt_report_call_matching(tvb, pinfo, tree, p_camelsrt_info,
+ CAMELSRT_VOICE_DISC);
+ /* Session has been closed by Network */
+ camelsrt_close_call_matching(tvb, pinfo, tree, p_camelsrt_info);
+ break;
+
+ case 66: /*ReleaseSMS*/
+ /* Session has been closed by Network */
+ camelsrt_close_call_matching(tvb, pinfo, tree, p_camelsrt_info);
+ tcapsrt_close(p_camelsrt_info->tcap_context,pinfo);
+ break;
+
+ case 79: /*ReleaseGPRS*/
+ /* Session has been closed by Network */
+ camelsrt_close_call_matching(tvb, pinfo, tree, p_camelsrt_info);
+ break;
+ } /* switch opcode */
+}
+
+/*
+ * Callback function for the TCAP dissector
+ * This callback function is used to inform the camel layer, that the session
+ * has been Closed or Aborted by a TCAP message without Camel component
+ * So, we can close the context for camel session, and update the stats.
+ */
+void camelsrt_tcap_matching(tvbuff_t *tvb,
+ packet_info * pinfo _U_,
+ proto_tree *tree,
+ struct tcaphash_context_t * p_tcap_context)
+{
+ struct camelsrt_info_t * p_camelsrt_info;
+
+#ifdef DEBUG_CAMELSRT
+ dbg(11,"Camel_CallBack ");
+#endif
+ p_camelsrt_info=camelsrt_razinfo();
+
+ p_camelsrt_info->tcap_context=p_tcap_context;
+ if (p_tcap_context) {
+#ifdef DEBUG_CAMELSRT
+ dbg(11,"Close TCAP ");
+#endif
+ p_camelsrt_info->tcap_session_id = p_tcap_context->session_id;
+ camelsrt_close_call_matching(tvb, pinfo, tree, p_camelsrt_info);
+ tap_queue_packet(camel_tap, pinfo, p_camelsrt_info);
+ }
+}
+
+
+/*
+ * Create the record identifiying the Camel session
+ * As the Tcap session id given by the TCAP dissector is uniq, it will be
+ * used as main key.
+ */
+static void camelsrt_begin_call_matching(tvbuff_t *tvb,
+ packet_info * pinfo _U_,
+ proto_tree *tree,
+ struct camelsrt_info_t * p_camelsrt_info)
+{
+ struct camelsrt_call_t * p_camelsrt_call;
+ struct camelsrt_call_info_key_t camelsrt_call_key;
+
+ p_camelsrt_info->bool_msginfo[CAMELSRT_SESSION]=TRUE;
+
+ /* prepare the key data */
+ camelsrt_call_key.SessionIdKey = p_camelsrt_info->tcap_session_id;
+
+ /* look up the request */
+#ifdef DEBUG_CAMELSRT
+ dbg(10,"\n Session begin #%d\n", pinfo->fd->num);
+ dbg(11,"Search key %lu ",camelsrt_call_key.SessionIdKey);
+#endif
+ p_camelsrt_call = (struct camelsrt_call_t *)g_hash_table_lookup(srt_calls, &camelsrt_call_key);
+ if (p_camelsrt_call) {
+ /* We have seen this request before -> do nothing */
+#ifdef DEBUG_CAMELSRT
+ dbg(22,"Already seen ");
+#endif
+ } else { /* p_camelsrt_call has not been found */
+#ifdef DEBUG_CAMELSRT
+ dbg(10,"New key %lu ",camelsrt_call_key.SessionIdKey);
+#endif
+ p_camelsrt_call = new_camelsrt_call(&camelsrt_call_key, pinfo);
+ p_camelsrt_call->tcap_context=p_camelsrt_info->tcap_context;
+ update_camelsrt_call(p_camelsrt_call, pinfo,CAMELSRT_SESSION);
+
+#ifdef DEBUG_CAMELSRT
+ dbg(11,"Update Callback ");
+#endif
+ p_camelsrt_call->tcap_context->callback=camelsrt_tcap_matching;
+ }
+}
+
+/*
+ * Register the request, and try to find the response
+ *
+ */
+static void camelsrt_request_call_matching(tvbuff_t *tvb,
+ packet_info * pinfo _U_,
+ proto_tree *tree,
+ struct camelsrt_info_t * p_camelsrt_info,
+ guint srt_type )
+{
+ struct camelsrt_call_t * p_camelsrt_call;
+ struct camelsrt_call_info_key_t camelsrt_call_key;
+ proto_item *ti;
+
+#ifdef DEBUG_CAMELSRT
+ dbg(10,"\n %s #%d\n", val_to_str(srt_type, camelSRTtype_naming, "Unk"),pinfo->fd->num);
+#endif
+
+ /* look only for matching request, if matching conversation is available. */
+ camelsrt_call_key.SessionIdKey = p_camelsrt_info->tcap_session_id;
+
+#ifdef DEBUG_CAMELSRT
+ dbg(11,"Search key %lu ", camelsrt_call_key.SessionIdKey);
+#endif
+ p_camelsrt_call = find_camelsrt_call(&camelsrt_call_key, pinfo);
+ if(p_camelsrt_call) {
+#ifdef DEBUG_CAMELSRT
+ dbg(12,"Found ");
+#endif
+ if (gcamel_DisplaySRT)
+ proto_tree_add_uint(tree, hf_camelsrt_SessionId, tvb, 0,0, p_camelsrt_call->session_id);
+
+
+ /* Hmm.. As there are several slices ApplyChargingReport/ApplyCharging
+ * we will prepare the measurement for 3 slices with 3 categories */
+ if (srt_type==CAMELSRT_VOICE_ACR1) {
+ if (p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].req_num == 0) {
+ srt_type=CAMELSRT_VOICE_ACR1;
+ } else if ( (p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].req_num == 0)
+ && (p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].rsp_num != 0)
+ && (p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].rsp_num < pinfo->fd->num) ) {
+ srt_type=CAMELSRT_VOICE_ACR2;
+ } else if ( (p_camelsrt_call->category[CAMELSRT_VOICE_ACR3].req_num == 0)
+ && (p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].rsp_num != 0)
+ && (p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].rsp_num < pinfo->fd->num) ) {
+ srt_type=CAMELSRT_VOICE_ACR3;
+ } else if (p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].rsp_num != 0
+ && p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].rsp_num > pinfo->fd->num) {
+ srt_type=CAMELSRT_VOICE_ACR1;
+ } else if ( p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].rsp_num != 0
+ && p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].rsp_num > pinfo->fd->num) {
+ srt_type=CAMELSRT_VOICE_ACR2;
+ } else if (p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].rsp_num != 0
+ && p_camelsrt_call->category[CAMELSRT_VOICE_ACR3].rsp_num > pinfo->fd->num) {
+ srt_type=CAMELSRT_VOICE_ACR3;
+ }
+#ifdef DEBUG_CAMELSRT
+ dbg(70,"Request ACR %u ",srt_type);
+ dbg(70,"ACR1 %u %u",p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].req_num, p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].rsp_num);
+ dbg(70,"ACR2 %u %u",p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].req_num, p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].rsp_num);
+ dbg(70,"ACR3 %u %u",p_camelsrt_call->category[CAMELSRT_VOICE_ACR3].req_num, p_camelsrt_call->category[CAMELSRT_VOICE_ACR3].rsp_num);
+#endif
+ } /* not ACR */
+ p_camelsrt_info->bool_msginfo[srt_type]=TRUE;
+
+
+ if (p_camelsrt_call->category[srt_type].req_num == 0) {
+ /* We have not yet seen a request to that call, so this must be the first request
+ remember its frame number. */
+#ifdef DEBUG_CAMELSRT
+ dbg(5,"Set reqlink #%d ", pinfo->fd->num);
+#endif
+ update_camelsrt_call(p_camelsrt_call, pinfo, srt_type);
+ } else {
+ /* We have seen a request to this call - but was it *this* request? */
+ if (p_camelsrt_call->category[srt_type].req_num != pinfo->fd->num) {
+
+ if (srt_type!=CAMELSRT_VOICE_DISC) {
+ /* No, so it's a duplicate resquest. Mark it as such. */
+#ifdef DEBUG_CAMELSRT
+ dbg(21,"Display_duplicate with req %d ", p_camelsrt_call->category[srt_type].req_num);
+#endif
+ p_camelsrt_info->msginfo[srt_type].is_duplicate = TRUE;
+ if (gcamel_DisplaySRT)
+ proto_tree_add_uint_hidden(tree, hf_camelsrt_Duplicate, tvb, 0,0, 77);
+
+ } else {
+ /* Ignore duplicate frame */
+ if (pinfo->fd->num > p_camelsrt_call->category[srt_type].req_num) {
+ p_camelsrt_call->category[srt_type].req_num = pinfo->fd->num;
+#ifdef DEBUG_CAMELSRT
+ dbg(5,"DISC Set reqlink #%d ", pinfo->fd->num);
+#endif
+ update_camelsrt_call(p_camelsrt_call, pinfo, srt_type);
+ } /* greater frame */
+ } /* DISC */
+ } /* req_num already seen */
+ } /* req_num != 0 */
+
+ /* add link to response frame, if available */
+ if ( gcamel_DisplaySRT &&
+ (p_camelsrt_call->category[srt_type].rsp_num != 0) &&
+ (p_camelsrt_call->category[srt_type].req_num != 0) &&
+ (p_camelsrt_call->category[srt_type].req_num == pinfo->fd->num) ) {
+#ifdef DEBUG_CAMELSRT
+ dbg(20,"Display_framersplink %d ",p_camelsrt_call->category[srt_type].rsp_num);
+#endif
+ ti = proto_tree_add_uint_format(tree, hf_camelsrt_RequestFrame, tvb, 0, 0,
+ p_camelsrt_call->category[srt_type].rsp_num,
+ "Linked response %s in frame %u",
+ val_to_str(srt_type, camelSRTtype_naming, "Unk"),
+ p_camelsrt_call->category[srt_type].rsp_num);
+ PROTO_ITEM_SET_GENERATED(ti);
+ } /* frame valid */
+ }/* call reference */
+}
+
+
+/*
+ * Check if the received message is a response to a previous request
+ * registered is the camel session context.
+ */
+static void camelsrt_report_call_matching(tvbuff_t *tvb,
+ packet_info * pinfo _U_,
+ proto_tree *tree,
+ struct camelsrt_info_t * p_camelsrt_info,
+ guint srt_type )
+{
+ struct camelsrt_call_t * p_camelsrt_call;
+ struct camelsrt_call_info_key_t camelsrt_call_key;
+ nstime_t delta;
+ proto_item *ti;
+
+#ifdef DEBUG_CAMELSRT
+ dbg(10,"\n %s #%d\n", val_to_str(srt_type, camelSRTtype_naming, "Unk"),pinfo->fd->num);
+#endif
+ camelsrt_call_key.SessionIdKey = p_camelsrt_info->tcap_session_id;
+ /* look only for matching request, if matching conversation is available. */
+
+#ifdef DEBUG_CAMELSRT
+ dbg(11,"Search key %lu ",camelsrt_call_key.SessionIdKey);
+#endif
+ p_camelsrt_call = find_camelsrt_call(&camelsrt_call_key, pinfo);
+ if(p_camelsrt_call) {
+#ifdef DEBUG_CAMELSRT
+ dbg(12,"Found, req=%d ",p_camelsrt_call->category[srt_type].req_num);
+#endif
+ if ( gcamel_DisplaySRT )
+ proto_tree_add_uint(tree, hf_camelsrt_SessionId, tvb, 0,0, p_camelsrt_call->session_id);
+
+ if (srt_type==CAMELSRT_VOICE_ACR1) {
+ if (p_camelsrt_call->category[CAMELSRT_VOICE_ACR3].req_num != 0
+ && p_camelsrt_call->category[CAMELSRT_VOICE_ACR3].req_num < pinfo->fd->num) {
+ srt_type=CAMELSRT_VOICE_ACR1;
+ } else if ( p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].req_num != 0
+ && p_camelsrt_call->category[CAMELSRT_VOICE_ACR2].req_num < pinfo->fd->num) {
+ srt_type=CAMELSRT_VOICE_ACR2;
+ } else if (p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].req_num != 0
+ && p_camelsrt_call->category[CAMELSRT_VOICE_ACR1].req_num < pinfo->fd->num) {
+ srt_type=CAMELSRT_VOICE_ACR1;
+ }
+#ifdef DEBUG_CAMELSRT
+ dbg(70,"Report ACR %u ",srt_type);
+#endif
+ } /* not ACR */
+ p_camelsrt_info->bool_msginfo[srt_type]=TRUE;
+
+ if (p_camelsrt_call->category[srt_type].rsp_num == 0) {
+ if ( (p_camelsrt_call->category[srt_type].req_num != 0)
+ && (pinfo->fd->num > p_camelsrt_call->category[srt_type].req_num) ){
+ /* We have not yet seen a response to that call, so this must be the first response;
+ remember its frame number only if response comes after request */
+#ifdef DEBUG_CAMELSRT
+ dbg(14,"Set reslink #%d req %d ",pinfo->fd->num, p_camelsrt_call->category[srt_type].req_num);
+#endif
+ p_camelsrt_call->category[srt_type].rsp_num = pinfo->fd->num;
+
+ } else {
+#ifdef DEBUG_CAMELSRT
+ dbg(2,"badreslink #%d req %u ",pinfo->fd->num, p_camelsrt_call->category[srt_type].req_num);
+#endif
+ } /* req_num != 0 */
+ } else { /* rsp_num != 0 */
+ /* We have seen a response to this call - but was it *this* response? */
+ if (p_camelsrt_call->category[srt_type].rsp_num != pinfo->fd->num) {
+ /* No, so it's a duplicate response. Mark it as such. */
+#ifdef DEBUG_CAMELSRT
+ dbg(21,"Display_duplicate rsp=%d ", p_camelsrt_call->category[srt_type].rsp_num);
+#endif
+ p_camelsrt_info->msginfo[srt_type].is_duplicate = TRUE;
+ if ( gcamel_DisplaySRT )
+ proto_tree_add_uint_hidden(tree, hf_camelsrt_Duplicate, tvb, 0,0, 77);
+ }
+ } /* rsp_num != 0 */
+
+ if ( (p_camelsrt_call->category[srt_type].req_num != 0) &&
+ (p_camelsrt_call->category[srt_type].rsp_num != 0) &&
+ (p_camelsrt_call->category[srt_type].rsp_num == pinfo->fd->num) ) {
+
+ p_camelsrt_call->category[srt_type].responded = TRUE;
+ p_camelsrt_info->msginfo[srt_type].request_available = TRUE;
+#ifdef DEBUG_CAMELSRT
+ dbg(20,"Display_frameReqlink %d ",p_camelsrt_call->category[srt_type].req_num);
+#endif
+ /* Indicate the frame to which this is a reply. */
+ if ( gcamel_DisplaySRT ) {
+ ti = proto_tree_add_uint_format(tree, hf_camelsrt_ResponseFrame, tvb, 0, 0,
+ p_camelsrt_call->category[srt_type].req_num,
+ "Linked request %s in frame %u",
+ val_to_str(srt_type, camelSRTtype_naming, "Unk"),
+ p_camelsrt_call->category[srt_type].req_num);
+ PROTO_ITEM_SET_GENERATED(ti);
+ }
+ /* Calculate Service Response Time */
+ nstime_delta(&delta, &pinfo->fd->abs_ts, &p_camelsrt_call->category[srt_type].req_time);
+
+ p_camelsrt_info->msginfo[srt_type].is_delta_time = TRUE;
+ p_camelsrt_info->msginfo[srt_type].delta_time = delta; /* give it to tap */
+ p_camelsrt_info->msginfo[srt_type].req_time = p_camelsrt_call->category[srt_type].req_time;
+
+ /* display Service Response Time and make it filterable */
+ camelsrt_display_DeltaTime(tree, tvb, &delta, srt_type);
+
+ } /*req_num != 0 && not duplicate */
+ } /* call reference found */
+}
+
+/*
+ * Update the Camel session info, and close the session.
+ * Then remove the associated context, if we do not have persistentSRT enable
+ */
+static void camelsrt_close_call_matching(tvbuff_t *tvb,
+ packet_info * pinfo _U_,
+ proto_tree *tree,
+ struct camelsrt_info_t * p_camelsrt_info)
+{
+ struct camelsrt_call_t * p_camelsrt_call;
+ struct camelsrt_call_info_key_t camelsrt_call_key;
+ nstime_t delta;
+
+ p_camelsrt_info->bool_msginfo[CAMELSRT_SESSION]=TRUE;
+#ifdef DEBUG_CAMELSRT
+ dbg(10,"\n Session end #%d\n", pinfo->fd->num);
+#endif
+ /* look only for matching request, if matching conversation is available. */
+ camelsrt_call_key.SessionIdKey = p_camelsrt_info->tcap_session_id;
+
+#ifdef DEBUG_CAMELSRT
+ dbg(11,"Search key %lu ",camelsrt_call_key.SessionIdKey);
+#endif
+ p_camelsrt_call = find_camelsrt_call(&camelsrt_call_key, pinfo);
+ if(p_camelsrt_call) {
+#ifdef DEBUG_CAMELSRT
+ dbg(12,"Found ");
+#endif
+ /* Calculate Service Response Time */
+ nstime_delta(&delta, &pinfo->fd->abs_ts, &p_camelsrt_call->category[CAMELSRT_SESSION].req_time);
+ p_camelsrt_call->category[CAMELSRT_SESSION].responded = TRUE;
+ p_camelsrt_info->msginfo[CAMELSRT_SESSION].request_available = TRUE;
+ p_camelsrt_info->msginfo[CAMELSRT_SESSION].is_delta_time = TRUE;
+ p_camelsrt_info->msginfo[CAMELSRT_SESSION].delta_time = delta; /* give it to tap */
+ p_camelsrt_info->msginfo[CAMELSRT_SESSION].req_time = p_camelsrt_call->category[CAMELSRT_SESSION].req_time;
+
+ if ( !gcamel_PersistentSRT ) {
+ g_hash_table_remove(srt_calls, &camelsrt_call_key);
+#ifdef DEBUG_CAMELSRT
+ dbg(20,"remove hash ");
+#endif
+ } else {
+#ifdef DEBUG_CAMELSRT
+ dbg(20,"keep hash ");
+#endif
+ }
+ } /* call reference found */
+}
+
+/*
+ * Display the delta time between two messages in a field corresponding
+ * to the category (hf_camelsrt_DeltaTimexx).
+ */
+static void camelsrt_display_DeltaTime(proto_tree *tree,
+ tvbuff_t *tvb,
+ nstime_t* value_ptr,
+ guint category)
+{
+ proto_item *ti;
+
+ if ( gcamel_DisplaySRT ) {
+ switch(category) {
+ case CAMELSRT_VOICE_INITIALDP:
+ ti = proto_tree_add_time(tree, hf_camelsrt_DeltaTime31, tvb, 0, 0, value_ptr);
+ PROTO_ITEM_SET_GENERATED(ti);
+ break;
+
+ case CAMELSRT_VOICE_ACR1:
+ case CAMELSRT_VOICE_ACR2:
+ case CAMELSRT_VOICE_ACR3:
+ ti = proto_tree_add_time(tree, hf_camelsrt_DeltaTime22, tvb, 0, 0, value_ptr);
+ PROTO_ITEM_SET_GENERATED(ti);
+ break;
+
+ case CAMELSRT_VOICE_DISC:
+ ti = proto_tree_add_time(tree, hf_camelsrt_DeltaTime35, tvb, 0, 0, value_ptr);
+ PROTO_ITEM_SET_GENERATED(ti);
+ break;
+
+ case CAMELSRT_GPRS_INITIALDP:
+ ti = proto_tree_add_time(tree, hf_camelsrt_DeltaTime75, tvb, 0, 0, value_ptr);
+ PROTO_ITEM_SET_GENERATED(ti);
+ break;
+
+ case CAMELSRT_GPRS_REPORT:
+ ti = proto_tree_add_time(tree, hf_camelsrt_DeltaTime80, tvb, 0, 0, value_ptr);
+ PROTO_ITEM_SET_GENERATED(ti);
+ break;
+
+ case CAMELSRT_SMS_INITIALDP:
+ ti = proto_tree_add_time(tree, hf_camelsrt_DeltaTime65, tvb, 0, 0, value_ptr);
+ PROTO_ITEM_SET_GENERATED(ti);
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+/*
+ * Initialize the Message Info used by the main dissector
+ * Data are linked to a TCAP transaction
+ */
+struct camelsrt_info_t * camelsrt_razinfo(void)
+{
+ struct camelsrt_info_t * p_camelsrt_info ;
+
+ /* Global buffer for packet extraction */
+ camelsrt_global_current++;
+ if(camelsrt_global_current==MAX_CAMEL_INSTANCE){
+ camelsrt_global_current=0;
+ }
+
+ p_camelsrt_info=&camelsrt_global_info[camelsrt_global_current];
+ memset(p_camelsrt_info,0,sizeof(struct camelsrt_info_t));
+
+ p_camelsrt_info->opcode=255;
+
+ return p_camelsrt_info;
+}
+
+/*
+ * Initialize the data per call for the Service Response Time Statistics
+ * Data are linked to a Camel operation in a TCAP transaction
+ */
+static void raz_camelsrt_call (struct camelsrt_call_t * p_camelsrt_call)
+{
+ memset(p_camelsrt_call,0,sizeof(struct camelsrt_call_t));
+}
diff --git a/epan/camel-persistentdata.h b/epan/camel-persistentdata.h
new file mode 100644
index 0000000000..44147882dc
--- /dev/null
+++ b/epan/camel-persistentdata.h
@@ -0,0 +1,126 @@
+/*
+ * camel-persistentdata.h
+ * Definitions for lists and hash tables used in wireshark's camel dissector
+ * for calculation of delays in camel-transactions
+ * Copyright 2006 Florent Drouin
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * 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 __camelsrt_HASH__
+#define __camelsrt_HASH__
+
+#include "epan/packet.h"
+#include "epan/conversation.h"
+#include "epan/dissectors/packet-camel.h"
+#include "epan/tcap-persistentdata.h"
+
+#define NB_CAMELSRT_CATEGORY 9+1 /* Number of type of message */
+/* for example TC_BEGIN with InitalDP, and TC_CONT with RequestReportBCSMEvent
+ is a category, we want to measure the delay between the two messages */
+
+#define CAMELSRT_SESSION 1
+
+#define CAMELSRT_VOICE_INITIALDP 2
+#define CAMELSRT_VOICE_ACR1 3
+#define CAMELSRT_VOICE_ACR2 4
+#define CAMELSRT_VOICE_ACR3 5
+#define CAMELSRT_VOICE_DISC 6
+
+#define CAMELSRT_GPRS_INITIALDP 7
+#define CAMELSRT_GPRS_REPORT 8
+
+#define CAMELSRT_SMS_INITIALDP 9
+
+static const value_string camelSRTtype_naming[]= {
+ { CAMELSRT_SESSION, "TCAP_Session" },
+ { CAMELSRT_VOICE_INITIALDP, "InialDP/Continue" },
+ { CAMELSRT_VOICE_ACR1, "Slice1_ACR/ACH" },
+ { CAMELSRT_VOICE_ACR2, "Slice2_ACR/ACH" },
+ { CAMELSRT_VOICE_ACR3, "Slice3_ACR/ACH" },
+ { CAMELSRT_VOICE_DISC, "EvtRepBSCM/Release" },
+ { CAMELSRT_SMS_INITIALDP, "InitialDP/ContinueSMS" },
+ { CAMELSRT_GPRS_INITIALDP, "InitialDP/ContinueGPRS" },
+ { CAMELSRT_GPRS_REPORT, "EvtRepGPRS/ContinueGPRS" },
+ { 0,NULL}
+};
+
+/* If we have a request message and its response,
+ (eg: ApplyCharging, ApplyChargingReport)
+ the frames numbers are stored in this structure */
+
+struct camelsrt_category_t {
+ guint32 req_num; /* frame number request seen */
+ guint32 rsp_num; /* frame number response seen */
+ nstime_t req_time; /* arrival time of request */
+ gboolean responded; /* true, if request has been responded */
+};
+
+/* List of stored parameters for a Camel dialogue
+ All this parameters are linked to the hash table key below (use of Tid)
+ In case of same Tid reused, the Camel parameters are chained.
+ The right dialogue will be identified with the arrival time of the InitialDP */
+
+struct camelsrt_call_t {
+ guint32 session_id; /* Identify the session, with an internal number */
+ struct tcaphash_context_t * tcap_context;
+ struct camelsrt_category_t category[NB_CAMELSRT_CATEGORY];
+};
+
+
+/* The Key for the hash table is the TCAP origine transaction identifier
+ of the TC_BEGIN containing the InitialDP */
+
+struct camelsrt_call_info_key_t {
+ guint32 SessionIdKey;
+};
+
+/* Info for a couple of messages (or category)
+ The request must be available, not duplicated,
+ and once the corresponding response received,
+ we can deduce the Delta Time between Request/response */
+
+struct camelsrt_msginfo_t {
+ gboolean request_available;
+ gboolean is_duplicate;
+ gboolean is_delta_time;
+ nstime_t req_time;
+ nstime_t delta_time;
+};
+
+/* List of infos to store for the analyse */
+
+struct camelsrt_info_t {
+ guint32 tcap_session_id;
+ void * tcap_context;
+ guint8 opcode; /* operation code of message received */
+ guint8 bool_msginfo[NB_CAMELSRT_CATEGORY]; /* category for the received message */
+ struct camelsrt_msginfo_t msginfo[NB_CAMELSRT_CATEGORY];
+};
+
+void camelsrt_init_routine(void);
+
+struct camelsrt_info_t * camelsrt_razinfo(void);
+
+void camelsrt_call_matching(tvbuff_t *tvb,
+ packet_info * pinfo _U_,
+ proto_tree *tree,
+ struct camelsrt_info_t * p_camel_info);
+
+#endif /* __camelsrt_HASH__*/
diff --git a/gtk/camel_counter.c b/gtk/camel_counter.c
new file mode 100644
index 0000000000..600eac0e75
--- /dev/null
+++ b/gtk/camel_counter.c
@@ -0,0 +1,233 @@
+/* camel_counter.c
+ * camel message counter for Wireshark
+ * Copyright 2006 Florent Drouin (based on h225_counter.c from Lars Roland)
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * 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
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#include <string.h>
+#include <gtk/gtk.h>
+
+#include "epan/packet_info.h"
+#include "epan/epan.h"
+#include "epan/value_string.h"
+#include "epan/tap.h"
+
+#include "register.h"
+#include "timestats.h"
+#include "simple_dialog.h"
+#include "file.h"
+#include "globals.h"
+#include "stat_menu.h"
+#include "tap_dfilter_dlg.h"
+
+#include "gtk/main.h"
+#include "gtk/dlg_utils.h"
+#include "gtk/gui_utils.h"
+#include "gtk/gui_stat_util.h"
+#include "gtk/compat_macros.h"
+#include "epan/camel-persistentdata.h"
+
+static void gtk_camelcounter_reset(void *phs);
+static int gtk_camelcounter_packet(void *phs,
+ packet_info *pinfo _U_,
+ epan_dissect_t *edt _U_,
+ const void *phi);
+static void gtk_camelcounter_draw(void *phs);
+static void win_destroy_cb(GtkWindow *win _U_, gpointer data);
+static void gtk_camelcounter_init(const char *optarg, void *userdata _U_);
+void register_tap_listener_gtk_camelcounter(void);
+
+/* following values represent the size of their valuestring arrays */
+
+struct camelcounter_t {
+ GtkWidget *win;
+ GtkWidget *vbox;
+ char *filter;
+ GtkWidget *scrolled_window;
+ GtkCList *table;
+ guint32 camel_msg[camel_MAX_NUM_OPR_CODES];
+};
+
+static void gtk_camelcounter_reset(void *phs)
+{
+ struct camelcounter_t * p_counter= ( struct camelcounter_t *) phs;
+ int i;
+
+ /* Erase Message Type count */
+ for(i=0;i<camel_MAX_NUM_OPR_CODES;i++) {
+ p_counter->camel_msg[i]=0;
+ }
+}
+
+
+/*
+ * If there is a valid camel operation, increase the value in the array of counter
+ */
+static int gtk_camelcounter_packet(void *phs,
+ packet_info *pinfo _U_,
+ epan_dissect_t *edt _U_,
+ const void *phi)
+{
+ struct camelcounter_t * p_counter =(struct camelcounter_t *)phs;
+ const struct camelsrt_info_t * pi=phi;
+ if (pi->opcode != 255)
+ p_counter->camel_msg[pi->opcode]++;
+
+ return 1;
+}
+
+static void gtk_camelcounter_draw(void *phs)
+{
+ struct camelcounter_t *p_counter=(struct camelcounter_t *)phs;
+ int i;
+ char *str[2];
+
+ for(i=0;i<2;i++) {
+ str[i]=g_malloc(sizeof(char[256]));
+ }
+ /* Now print Message and Reason Counter Table */
+ /* clear list before printing */
+ gtk_clist_clear(p_counter->table);
+
+ for(i=0;i<camel_MAX_NUM_OPR_CODES;i++) {
+ /* Message counter */
+ if(p_counter->camel_msg[i]!=0) {
+ g_snprintf(str[0], sizeof(char[256]),
+ "Request %s", val_to_str(i,camel_opr_code_strings,"Unknown message "));
+ g_snprintf(str[1], sizeof(char[256]),
+ "%d", p_counter->camel_msg[i]);
+ gtk_clist_append(p_counter->table, str);
+ }
+ } /* Message Type */
+ gtk_widget_show(GTK_WIDGET(p_counter->table));
+}
+
+void protect_thread_critical_region(void);
+void unprotect_thread_critical_region(void);
+
+static void win_destroy_cb(GtkWindow *win _U_, gpointer data)
+{
+ struct camelcounter_t *hs=(struct camelcounter_t *)data;
+
+ protect_thread_critical_region();
+ remove_tap_listener(hs);
+ unprotect_thread_critical_region();
+
+ if(hs->filter){
+ g_free(hs->filter);
+ hs->filter=NULL;
+ }
+ g_free(hs);
+}
+
+static const gchar *titles[]={
+ "Message Type or Reason",
+ "Count" };
+
+static void gtk_camelcounter_init(const char *optarg, void *userdata _U_)
+{
+ struct camelcounter_t *p_camelcounter;
+ const char *filter=NULL;
+ const char *emptyfilter="";
+ GString *error_string;
+ GtkWidget *bbox;
+ GtkWidget *close_bt;
+
+ if(strncmp(optarg,"camel,counter,",14) == 0){
+ filter=optarg+14;
+ } else {
+ filter=NULL;
+ }
+
+ p_camelcounter=g_malloc(sizeof(struct camelcounter_t));
+ p_camelcounter->filter=g_strdup(filter);
+
+ gtk_camelcounter_reset(p_camelcounter);
+
+ p_camelcounter->win=window_new(GTK_WINDOW_TOPLEVEL, "Ethereal: CAMEL counters");
+ gtk_window_set_default_size(GTK_WINDOW(p_camelcounter->win), 500, 300);
+
+ p_camelcounter->vbox=gtk_vbox_new(FALSE, 3);
+ gtk_container_set_border_width(GTK_CONTAINER(p_camelcounter->vbox), 12);
+
+ init_main_stat_window(p_camelcounter->win, p_camelcounter->vbox, "CAMEL Messages Counters", filter);
+
+ /* init a scrolled window*/
+ p_camelcounter->scrolled_window = scrolled_window_new(NULL, NULL);
+
+ p_camelcounter->table = create_stat_table(p_camelcounter->scrolled_window, p_camelcounter->vbox, 2, titles);
+
+ if (filter) {
+ error_string=register_tap_listener("CAMEL", p_camelcounter, filter,
+ gtk_camelcounter_reset,
+ gtk_camelcounter_packet,
+ gtk_camelcounter_draw);
+ } else {
+ error_string=register_tap_listener("CAMEL", p_camelcounter, emptyfilter,
+ gtk_camelcounter_reset,
+ gtk_camelcounter_packet,
+ gtk_camelcounter_draw);
+ }
+
+ if(error_string){
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, error_string->str);
+ g_string_free(error_string, TRUE);
+ g_free(p_camelcounter);
+ return;
+ }
+
+ /* Button row. */
+ bbox = dlg_button_row_new(GTK_STOCK_CLOSE, NULL);
+ gtk_box_pack_end(GTK_BOX(p_camelcounter->vbox), bbox, FALSE, FALSE, 0);
+
+ close_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_CLOSE);
+ window_set_cancel_button(p_camelcounter->win, close_bt, window_cancel_button_cb);
+
+ SIGNAL_CONNECT(p_camelcounter->win, "delete_event", window_delete_event_cb, NULL);
+ SIGNAL_CONNECT(p_camelcounter->win, "destroy", win_destroy_cb, p_camelcounter);
+
+ gtk_widget_show_all(p_camelcounter->win);
+ window_present(p_camelcounter->win);
+
+ cf_retap_packets(&cfile, FALSE);
+}
+
+static tap_dfilter_dlg camel_counter_dlg = {
+ "CAMEL Messages and Response Status",
+ "camel,counter",
+ gtk_camelcounter_init,
+ -1
+};
+
+void /* Next line mandatory */
+register_tap_listener_gtk_camelcounter(void)
+{
+ register_dfilter_stat(&camel_counter_dlg, "GSM/CAMEL",
+ REGISTER_STAT_GROUP_TELEPHONY);
+
+}
diff --git a/gtk/camel_srt.c b/gtk/camel_srt.c
new file mode 100644
index 0000000000..fed4a8b1e0
--- /dev/null
+++ b/gtk/camel_srt.c
@@ -0,0 +1,248 @@
+/* camel_srt.c
+ * camel Service Response Time statistics for Wireshark
+ * Copyright 2006 Florent Drouin (based on h225_ras_srt.c from Lars Roland)
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * 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
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#include <string.h>
+#include <gtk/gtk.h>
+
+#include "epan/packet_info.h"
+#include "epan/epan.h"
+#include "epan/value_string.h"
+#include "epan/tap.h"
+
+#include "register.h"
+#include "timestats.h"
+#include "simple_dialog.h"
+#include "file.h"
+#include "globals.h"
+#include "stat_menu.h"
+#include "tap_dfilter_dlg.h"
+
+#include "gtk/main.h"
+#include "gtk/dlg_utils.h"
+#include "gtk/gui_utils.h"
+#include "gtk/gui_stat_util.h"
+#include "gtk/compat_macros.h"
+#include "gtk/service_response_time_table.h"
+
+#include "epan/camel-persistentdata.h"
+
+/* used to keep track of the statistics for an entire program interface */
+struct camelsrt_t {
+ GtkWidget *win;
+ srt_stat_table camel_srt_table;
+};
+
+static void camelsrt_set_title(struct camelsrt_t * p_camelsrt);
+static void camelsrt_reset(void *phs);
+static int camelsrt_packet(void *phs,
+ packet_info *pinfo _U_,
+ epan_dissect_t *edt _U_,
+ const void *phi);
+
+static void camelsrt_draw(void *phs);
+static void win_destroy_cb(GtkWindow *win _U_, gpointer data);
+static void gtk_camelsrt_init(const char *optarg, void *userdata _U_);
+void register_tap_listener_gtk_camelsrt(void);
+
+/*
+ *
+ */
+static void camelsrt_set_title(struct camelsrt_t * p_camelsrt)
+{
+ char * title;
+ title = g_strdup_printf("CAMEL Service Response Time statistics: %s",
+ cf_get_display_name(&cfile));
+ gtk_window_set_title(GTK_WINDOW(p_camelsrt->win), title);
+ g_free(title);
+}
+
+static void camelsrt_reset(void *phs)
+{
+ struct camelsrt_t *hs=(struct camelsrt_t *)phs;
+ reset_srt_table_data(&hs->camel_srt_table);
+ camelsrt_set_title(hs);
+}
+
+/*
+ * Count the delta time between Request and Response
+ * As we can make several measurement per message, we use a boolean array for the category
+ * Then, if the measurement is provided, check if it is valid, and update the table
+ */
+static int camelsrt_packet(void *phs,
+ packet_info *pinfo _U_,
+ epan_dissect_t *edt _U_,
+ const void *phi)
+{
+ struct camelsrt_t *hs=(struct camelsrt_t *)phs;
+ const struct camelsrt_info_t * pi=phi;
+ int i;
+
+ for (i=1; i<NB_CAMELSRT_CATEGORY; i++) {
+ if ( pi->bool_msginfo[i] &&
+ pi->msginfo[i].is_delta_time
+ && pi->msginfo[i].request_available
+ && !pi->msginfo[i].is_duplicate ) {
+
+ add_srt_table_data(&hs->camel_srt_table, i, &pi->msginfo[i].req_time, pinfo);
+
+ }
+ } /* category */
+ return 1;
+}
+
+
+static void camelsrt_draw(void *phs)
+{
+ struct camelsrt_t *hs=(struct camelsrt_t *)phs;
+ draw_srt_table_data(&hs->camel_srt_table);
+}
+
+/*
+ * Routine for Display
+ */
+static void win_destroy_cb(GtkWindow *win _U_, gpointer data)
+{
+ struct camelsrt_t *hs=(struct camelsrt_t *)data;
+
+ protect_thread_critical_region();
+ remove_tap_listener(hs);
+ unprotect_thread_critical_region();
+
+ free_srt_table_data(&hs->camel_srt_table);
+ g_free(hs);
+}
+
+static void gtk_camelsrt_init(const char *optarg, void *userdata _U_)
+{
+ struct camelsrt_t * p_camelsrt;
+ const char *filter=NULL;
+ const char *emptyfilter="";
+
+ GtkWidget *cmd_label;
+ GtkWidget *main_label;
+ GtkWidget *filter_label;
+ char filter_string[256];
+ GString *error_string;
+ GtkWidget *vbox;
+ GtkWidget *bbox;
+ GtkWidget *close_bt;
+ int i;
+
+ if(strncmp(optarg,"camel,srt,",10) == 0){
+ filter=optarg+10;
+ } else {
+ filter=NULL;
+ }
+
+ p_camelsrt=g_malloc(sizeof(struct camelsrt_t));
+
+ p_camelsrt->win=window_new(GTK_WINDOW_TOPLEVEL, "camel-srt");
+ gtk_window_set_default_size(GTK_WINDOW(p_camelsrt->win), 550, 400);
+ camelsrt_set_title(p_camelsrt);
+
+ vbox=gtk_vbox_new(FALSE, 3);
+ gtk_container_add(GTK_CONTAINER(p_camelsrt->win), vbox);
+ gtk_container_set_border_width(GTK_CONTAINER(vbox), 12);
+
+ main_label=gtk_label_new("CAMEL Service Response Time statistics");
+ gtk_box_pack_start(GTK_BOX(vbox), main_label, FALSE, FALSE, 0);
+ gtk_widget_show(main_label);
+
+ g_snprintf(filter_string,255,"Filter:%s",filter?filter:"");
+ filter_label=gtk_label_new(filter_string);
+ gtk_box_pack_start(GTK_BOX(vbox), filter_label, FALSE, FALSE, 0);
+ gtk_widget_show(filter_label);
+
+ cmd_label=gtk_label_new("CAMEL Commands");
+ gtk_box_pack_start(GTK_BOX(vbox), cmd_label, FALSE, FALSE, 0);
+ gtk_widget_show(cmd_label);
+
+ /* We must display TOP LEVEL Widget before calling init_srt_table() */
+ gtk_widget_show_all(p_camelsrt->win);
+
+ init_srt_table(&p_camelsrt->camel_srt_table, NB_CAMELSRT_CATEGORY, vbox, NULL);
+ for(i=0 ;i<NB_CAMELSRT_CATEGORY; i++) {
+ init_srt_table_row(&p_camelsrt->camel_srt_table, i,
+ val_to_str(i,camelSRTtype_naming,"Unknown"));
+ }
+
+ if (filter) {
+ error_string=register_tap_listener("CAMEL",
+ p_camelsrt,
+ filter,
+ camelsrt_reset,
+ camelsrt_packet,
+ camelsrt_draw);
+ } else {
+ error_string=register_tap_listener("CAMEL",
+ p_camelsrt,
+ emptyfilter,
+ camelsrt_reset,
+ camelsrt_packet,
+ camelsrt_draw);
+ }
+
+ if(error_string){
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, error_string->str);
+ g_string_free(error_string, TRUE);
+ g_free(p_camelsrt);
+ return;
+ }
+
+ /* Button row. */
+ bbox = dlg_button_row_new(GTK_STOCK_CLOSE, NULL);
+ gtk_box_pack_end(GTK_BOX(vbox), bbox, FALSE, FALSE, 0);
+
+ close_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_CLOSE);
+ window_set_cancel_button(p_camelsrt->win, close_bt, window_cancel_button_cb);
+
+ SIGNAL_CONNECT(p_camelsrt->win, "delete_event", window_delete_event_cb, NULL);
+ SIGNAL_CONNECT(p_camelsrt->win, "destroy", win_destroy_cb, p_camelsrt);
+
+ gtk_widget_show_all(p_camelsrt->win);
+ window_present(p_camelsrt->win);
+ cf_retap_packets(&cfile, FALSE);
+
+}
+
+static tap_dfilter_dlg camel_srt_dlg = {
+ "CAMEL Service Response Time",
+ "camel,srt",
+ gtk_camelsrt_init,
+ -1
+};
+
+void /* Next line mandatory */
+register_tap_listener_gtk_camelsrt(void)
+{
+ register_dfilter_stat(&camel_srt_dlg, "CAMEL",
+ REGISTER_STAT_GROUP_RESPONSE_TIME);
+}
diff --git a/tap-camelcounter.c b/tap-camelcounter.c
new file mode 100644
index 0000000000..b5ab177d15
--- /dev/null
+++ b/tap-camelcounter.c
@@ -0,0 +1,146 @@
+/* tap_camelcounter.c
+ * camel message counter for tshark
+ * Copyright 2006 Florent DROUIN
+ * This part of code is extracted from tap-h225counter.c from Lars Roland
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * 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 <stdio.h>
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#include <string.h>
+#include "epan/packet_info.h"
+#include "epan/tap.h"
+#include "epan/value_string.h"
+#include "register.h"
+#include "epan/stat_cmd_args.h"
+#include "epan/camel-persistentdata.h"
+
+void register_tap_listener_camelcounter(void);
+
+/* used to keep track of the statistics for an entire program interface */
+struct camelcounter_t {
+ char *filter;
+ guint32 camel_msg[camel_MAX_NUM_OPR_CODES];
+};
+
+
+static void camelcounter_reset(void *phs)
+{
+ struct camelcounter_t * p_counter= ( struct camelcounter_t *) phs;
+ memset(p_counter,0,sizeof(struct camelcounter_t));
+}
+
+static int camelcounter_packet(void *phs,
+ packet_info *pinfo _U_,
+ epan_dissect_t *edt _U_,
+ const void *phi)
+{
+ struct camelcounter_t * p_counter =(struct camelcounter_t *)phs;
+ const struct camelsrt_info_t * pi=phi;
+ if (pi->opcode != 255)
+ p_counter->camel_msg[pi->opcode]++;
+
+ return 1;
+}
+
+
+static void camelcounter_draw(void *phs)
+{
+ struct camelcounter_t * p_counter= (struct camelcounter_t *)phs;
+ int i;
+ printf("\n");
+ printf("CAMEL Message and Response Status Counter:\n");
+ printf("------------------------------------------\n");
+
+ for(i=0;i<camel_MAX_NUM_OPR_CODES;i++) {
+ /* Message counter */
+ if(p_counter->camel_msg[i]!=0) {
+ printf("%30s ", val_to_str(i,camel_opr_code_strings,"Unknown message "));
+ printf("%6d\n", p_counter->camel_msg[i]);
+ }
+ } /* Message Type */
+ printf("------------------------------------------\n");
+}
+
+static void camelcounter_init(const char *optarg, void* userdata _U_)
+{
+ struct camelcounter_t *p_camelcounter;
+ const char *filter=NULL;
+ const char *emptyfilter="";
+ GString *error_string;
+
+ if(!strncmp(optarg,"camel,counter,",13)){
+ filter=optarg+13;
+ } else {
+ filter=NULL;
+ }
+
+ p_camelcounter = g_malloc(sizeof(struct camelcounter_t));
+ if(filter){
+ p_camelcounter->filter=g_malloc(strlen(filter)+1);
+ strcpy(p_camelcounter->filter,filter);
+ } else {
+ p_camelcounter->filter=NULL;
+ }
+
+ camelcounter_reset(p_camelcounter);
+
+ if (filter) {
+ error_string=register_tap_listener("CAMEL",
+ p_camelcounter,
+ filter,
+ NULL,
+ camelcounter_packet,
+ camelcounter_draw);
+ } else {
+ error_string=register_tap_listener("CAMEL",
+ p_camelcounter,
+ emptyfilter,
+ NULL,
+ camelcounter_packet,
+ camelcounter_draw);
+ }
+
+ if(error_string){
+ /* error, we failed to attach to the tap. clean up */
+ g_free(p_camelcounter->filter);
+ g_free(p_camelcounter);
+
+ fprintf(stderr, "tshark: Couldn't register camel,counter tap: %s\n",
+ error_string->str);
+ g_string_free(error_string, TRUE);
+ exit(1);
+ }
+}
+
+
+void /* Next line mandatory */
+register_tap_listener_camelcounter(void)
+{
+ register_stat_cmd_arg("camel,counter", camelcounter_init, NULL);
+}
diff --git a/tap-camelsrt.c b/tap-camelsrt.c
new file mode 100644
index 0000000000..25387022a7
--- /dev/null
+++ b/tap-camelsrt.c
@@ -0,0 +1,276 @@
+/* tap_camelsrt.c
+ * CAMEL Service Response Time statistics for tshark
+ * Copyright 2006 Florent Drouin (based on tap_h225rassrt.c from Lars Roland)
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * 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 <stdio.h>
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#include <string.h>
+#include "epan/packet_info.h"
+#include <epan/tap.h>
+#include "epan/value_string.h"
+#include "register.h"
+#include "epan/dissectors/packet-camel.h"
+#include "epan/camel-persistentdata.h"
+#include "timestats.h"
+#include "epan/stat_cmd_args.h"
+
+#undef MIN
+#define MIN(x,y) ((x) < (y) ? (x) : (y))
+
+void register_tap_listener_camelsrt(void);
+
+/* Save the the first NUM_RAS_STATS stats in the array to calculate percentile */
+#define NUM_RAS_STATS 500000
+
+/* Number of couple message Request/Response to analyze*/
+#define NB_CRITERIA 7
+
+/* used to keep track of the statistics for an entire program interface */
+struct camelsrt_t {
+ char *filter;
+ guint32 count[NB_CAMELSRT_CATEGORY];
+ timestat_t stats[NB_CAMELSRT_CATEGORY];
+ nstime_t delta_time[NB_CAMELSRT_CATEGORY][NUM_RAS_STATS];
+};
+
+/* Check if we have to inhibit the display or not */
+extern gboolean gcamel_StatSRT;
+extern gboolean gtcap_StatSRT;
+
+/* Reset the counter */
+static void camelsrt_reset(void *phs)
+{
+ struct camelsrt_t *hs=(struct camelsrt_t *)phs;
+ memset(hs,0,sizeof(struct camelsrt_t));
+}
+
+
+static int camelsrt_packet(void *phs,
+ packet_info *pinfo _U_,
+ epan_dissect_t *edt _U_,
+ const void *phi)
+{
+ struct camelsrt_t *hs=(struct camelsrt_t *)phs;
+ const struct camelsrt_info_t * pi=phi;
+ int i;
+
+ for (i=0; i<NB_CAMELSRT_CATEGORY; i++) {
+ if (pi->bool_msginfo[i] &&
+ pi->msginfo[i].is_delta_time
+ && pi->msginfo[i].request_available
+ && !pi->msginfo[i].is_duplicate ) {
+
+ time_stat_update(&(hs->stats[i]),
+ &(pi->msginfo[i].delta_time),
+ pinfo);
+
+ if (hs->count[i] < NUM_RAS_STATS) {
+ hs->delta_time[i][hs->count[i]++]
+ = pi->msginfo[i].delta_time;
+ }
+ }
+ }
+ return 1;
+}
+
+
+static void camelsrt_draw(void *phs)
+{
+ struct camelsrt_t *hs=(struct camelsrt_t *)phs;
+ guint j,z;
+ guint32 li;
+ int somme,iteration=0;
+ timestat_t *rtd_temp;
+ double x,delay,delay_max,delay_min,delta;
+ double criteria[NB_CRITERIA]={ 5.0, 10.0, 75.0, 90.0, 95.0,99.0,99.90 };
+ double delay_criteria[NB_CRITERIA];
+
+ printf("\n");
+ printf("Camel Service Response Time (SRT) Statistics:\n");
+ printf("=================================================================================================\n");
+ printf("| Category | Measure | Min SRT | Max SRT | Avg SRT | Min frame | Max frame |\n");
+ printf("|-------------------------|---------|-----------|-----------|-----------|-----------|-----------|\n");
+
+ j=1;
+ printf("|%24s |%8u |%8.2f s |%8.2f s |%8.2f s |%10u |%10u |\n",
+ val_to_str(j,camelSRTtype_naming,"Unknown Message 0x%02x"),
+ hs->stats[j].num,
+ nstime_to_sec(&(hs->stats[j].min)),
+ nstime_to_sec(&(hs->stats[j].max)),
+ get_average(&(hs->stats[j].tot),hs->stats[j].num)/1000.0,
+ hs->stats[j].min_num,
+ hs->stats[j].max_num
+ );
+ for(j=2; j<NB_CAMELSRT_CATEGORY; j++) {
+ if(hs->stats[j].num==0){
+ printf("|%24s |%8u |%8.2f ms|%8.2f ms|%8.2f ms|%10u |%10u |\n",
+ val_to_str(j,camelSRTtype_naming,"Unknown Message 0x%02x"),
+ 0, 0.0, 0.0, 0.0, 0, 0);
+ continue;
+ }
+
+ printf("|%24s |%8u |%8.2f ms|%8.2f ms|%8.2f ms|%10u |%10u |\n",
+ val_to_str(j,camelSRTtype_naming,"Unknown Message 0x%02x"),
+ hs->stats[j].num,
+ MIN(9999,nstime_to_msec(&(hs->stats[j].min))),
+ MIN(9999,nstime_to_msec(&(hs->stats[j].max))),
+ MIN(9999,get_average(&(hs->stats[j].tot),hs->stats[j].num)),
+ hs->stats[j].min_num,
+ hs->stats[j].max_num
+ );
+ } /* j category */
+
+ printf("=================================================================================================\n");
+ /*
+ * Display 95%
+ */
+
+ printf("| Category/Criteria |");
+ for(z=0; z<NB_CRITERIA; z++) printf("%7.2f%% |", criteria[z]);
+ printf("\n");
+
+ printf("|-------------------------|");
+ for(z=0; z<NB_CRITERIA; z++) printf("---------|");
+ printf("\n");
+ /* calculate the delay max to have a given number of messages (in percentage) */
+ for(j=2;j<NB_CAMELSRT_CATEGORY;j++) {
+
+ rtd_temp = &(hs->stats[j]);
+
+ if (hs->count[j]>0) {
+ /* Calculate the delay to answer to p% of the MS */
+ for(z=0; z<NB_CRITERIA; z++) {
+ iteration=0;
+ delay_max=(double)rtd_temp->max.secs*1000 +(double)rtd_temp->max.nsecs/1000000;
+ delay_min=(double)rtd_temp->min.secs*1000 +(double)rtd_temp->min.nsecs/1000000;
+ delay=delay_min;
+ delta=delay_max-delay_min;
+ while( (delta > 0.001) && (iteration < 10000) ) {
+ somme=0;
+ iteration++;
+
+ for(li=0;li<hs->count[j];li++) {
+ x=hs->delta_time[j][li].secs*1000
+ + (double)hs->delta_time[j][li].nsecs/1000000;
+ if (x <= delay) somme++;
+ }
+ if ( somme*100 > hs->count[j]*criteria[z] ) { /* trop grand */
+ delay_max=delay;
+ delay=(delay_max+delay_min)/2;
+ delta=delay_max-delay_min;
+ } else { /* trop petit */
+ delay_min=delay;
+ delay=(delay_max+delay_min)/2;
+ delta=delay_max-delay_min;
+ }
+ } /* while */
+ delay_criteria[z]=delay;
+ } /* z criteria */
+ /* Append the result to the table */
+ printf("X%24s |", val_to_str(j, camelSRTtype_naming, "Unknown") );
+ for(z=0; z<NB_CRITERIA; z++) printf("%8.2f |", MIN(9999,delay_criteria[z]));
+ printf("\n");
+ } else { /* count */
+ printf("X%24s |", val_to_str(j, camelSRTtype_naming, "Unknown") );
+ for(z=0; z<NB_CRITERIA; z++) printf("%8.2f |", 0.0);
+ printf("\n");
+ } /* count */
+ }/* j category */
+ printf("===========================");
+ for(z=0; z<NB_CRITERIA; z++) printf("==========");
+ printf("\n");
+}
+
+static void camelsrt_init(const char *optarg, void* userdata _U_)
+{
+ struct camelsrt_t *p_camelsrt;
+ const char *filter=NULL;
+ const char *emptyfilter="";
+
+ GString *error_string;
+
+ if(!strncmp(optarg,"camel,srt,",9)){
+ filter=optarg+9;
+ } else {
+ filter=NULL;
+ }
+
+ p_camelsrt = g_malloc(sizeof(struct camelsrt_t));
+ if(filter){
+ p_camelsrt->filter=g_malloc(strlen(filter)+1);
+ strcpy(p_camelsrt->filter,filter);
+ } else {
+ p_camelsrt->filter=NULL;
+ }
+ camelsrt_reset(p_camelsrt);
+
+ if (filter) {
+ error_string=register_tap_listener("CAMEL",
+ p_camelsrt,
+ filter,
+ NULL,
+ camelsrt_packet,
+ camelsrt_draw);
+ } else {
+ error_string=register_tap_listener("CAMEL",
+ p_camelsrt,
+ emptyfilter,
+ NULL,
+ camelsrt_packet,
+ camelsrt_draw);
+ }
+
+ if(error_string){
+ /* error, we failed to attach to the tap. clean up */
+ g_free(p_camelsrt->filter);
+ g_free(p_camelsrt);
+
+ fprintf(stderr, "tshark: Couldn't register camel,srt tap: %s\n",
+ error_string->str);
+ g_string_free(error_string, TRUE);
+ exit(1);
+ }
+
+ /*
+ * If we are using tshark, we have to display the stats, even if the stats are not persistent
+ * As the frame are proceeded in the chronological order, we do not need persistent stats
+ * Whereas, with wireshark, it is not possible to have the correct display, if the stats are
+ * not saved along the analyze
+ */
+ gtcap_StatSRT=TRUE;
+ gcamel_StatSRT=TRUE;
+}
+
+
+void /* Next line mandatory */
+register_tap_listener_camelsrt(void)
+{
+ register_stat_cmd_arg("camel,srt", camelsrt_init, NULL);
+}