Move tcap and camel "persistent data" functionality to the dissectors themselves...
authorMichael Mann <mmann78@netscape.net>
Mon, 30 Dec 2013 22:07:38 +0000 (22:07 -0000)
committerMichael Mann <mmann78@netscape.net>
Mon, 30 Dec 2013 22:07:38 +0000 (22:07 -0000)
svn path=/trunk/; revision=54499

20 files changed:
asn1/ansi_tcap/packet-ansi_tcap-template.c
asn1/camel/packet-camel-template.c
asn1/camel/packet-camel-template.h
asn1/tcap/packet-tcap-template.c
asn1/tcap/packet-tcap-template.h
epan/CMakeLists.txt
epan/Makefile.common
epan/camel-persistentdata.c [deleted file]
epan/camel-persistentdata.h [deleted file]
epan/dissectors/packet-ansi_tcap.c
epan/dissectors/packet-camel.c
epan/dissectors/packet-camel.h
epan/dissectors/packet-tcap.c
epan/dissectors/packet-tcap.h
epan/tcap-persistentdata.c [deleted file]
epan/tcap-persistentdata.h [deleted file]
ui/cli/tap-camelcounter.c
ui/cli/tap-camelsrt.c
ui/gtk/camel_counter.c
ui/gtk/camel_srt.c

index 3153afffee0797b21344584f000cbbaa949333a1..8f4c34df190557f633f91433377c51a580b03845 100644 (file)
@@ -38,7 +38,6 @@
 #include "packet-ber.h"
 #include "packet-tcap.h"
 #include "packet-ansi_tcap.h"
-#include <epan/tcap-persistentdata.h>
 
 #define PNAME  "ANSI Transaction Capabilities Application Part"
 #define PSNAME "ANSI_TCAP"
@@ -89,6 +88,13 @@ extern gboolean gtcap_PersistentSRT;
 extern guint gtcap_RepetitionTimeout;
 extern guint gtcap_LostTimeout;
 
+/* When several Tcap 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_TCAP_INSTANCE 10
+int tcapsrt_global_current=0;
+struct tcapsrt_info_t tcapsrt_global_info[MAX_TCAP_INSTANCE];
+
 static dissector_table_t ber_oid_dissector_table=NULL;
 static const char * cur_oid;
 static const char * tcapext_oid;
index 9acc33ce0c0bfcf0f64e8d7f52f547ce0d3b2546..ad7e9eacd6989c4a93e9f361cce9fd07da07cfe8 100644 (file)
@@ -55,8 +55,6 @@
 #include "packet-gsm_a_common.h"
 #include "packet-inap.h"
 #include "packet-tcap.h"
-#include <epan/camel-persistentdata.h>
-#include <epan/tcap-persistentdata.h>
 
 #define PNAME  "Camel"
 #define PSNAME "CAMEL"
@@ -70,6 +68,14 @@ int camel_tap = -1;
 static guint32 opcode=0;
 static guint32 errorCode=0;
 static guint32 camel_ver = 0;
+
+/* 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
+static int camelsrt_global_current=0;
+static struct camelsrt_info_t camelsrt_global_info[MAX_CAMEL_INSTANCE];
+
 /* ROSE context */
 static rose_ctx_t camel_rose_ctx;
 
@@ -91,20 +97,20 @@ static int hf_camel_CAMEL_SCIBillingChargingCharacteristics = -1;
 static int hf_camel_CAMEL_SCIGPRSBillingChargingCharacteristics = -1;
 static int hf_camel_CAMEL_CallResult = -1;
 
-/* Used by camel-persistentdata.c */
-int hf_camelsrt_SessionId=-1;
-int hf_camelsrt_RequestNumber=-1;
-int hf_camelsrt_Duplicate=-1;
-int hf_camelsrt_RequestFrame=-1;
-int hf_camelsrt_ResponseFrame=-1;
-int hf_camelsrt_DeltaTime=-1;
-int hf_camelsrt_SessionTime=-1;
-int hf_camelsrt_DeltaTime31=-1;
-int hf_camelsrt_DeltaTime75=-1;
-int hf_camelsrt_DeltaTime65=-1;
-int hf_camelsrt_DeltaTime22=-1;
-int hf_camelsrt_DeltaTime35=-1;
-int hf_camelsrt_DeltaTime80=-1;
+/* Used by persistent data */
+static int hf_camelsrt_SessionId=-1;
+static int hf_camelsrt_RequestNumber=-1;
+static int hf_camelsrt_Duplicate=-1;
+static int hf_camelsrt_RequestFrame=-1;
+static int hf_camelsrt_ResponseFrame=-1;
+static int hf_camelsrt_DeltaTime=-1;
+static int hf_camelsrt_SessionTime=-1;
+static int hf_camelsrt_DeltaTime31=-1;
+static int hf_camelsrt_DeltaTime75=-1;
+static int hf_camelsrt_DeltaTime65=-1;
+static int hf_camelsrt_DeltaTime22=-1;
+static int hf_camelsrt_DeltaTime35=-1;
+static int hf_camelsrt_DeltaTime80=-1;
 
 #include "packet-camel-hf.c"
 
@@ -118,9 +124,10 @@ static int dissect_camel_CAMEL_AChBillingChargingCharacteristics(gboolean implic
 static int dissect_camel_CAMEL_AChBillingChargingCharacteristicsV2(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
 static int dissect_camel_CAMEL_CallResult(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
 
-gboolean gcamel_HandleSRT=FALSE;
-extern gboolean gcamel_PersistentSRT;
-extern gboolean gcamel_DisplaySRT;
+static gboolean gcamel_HandleSRT=FALSE;
+static gboolean gcamel_PersistentSRT=FALSE;
+static gboolean gcamel_DisplaySRT=FALSE;
+static gboolean gcamel_StatSRT=FALSE;
 
 /* Initialize the subtree pointers */
 static gint ett_camel = -1;
@@ -155,6 +162,10 @@ static guint8 PDPTypeNumber;
 const char *camel_obj_id = NULL;
 gboolean is_ExtensionField =FALSE;
 
+/* Global hash tables*/
+static GHashTable *srt_calls = NULL;
+static guint32 camelsrt_global_SessionId=1;
+
 static int camel_opcode_type;
 #define CAMEL_OPCODE_INVOKE        1
 #define CAMEL_OPCODE_RETURN_RESULT 2
@@ -169,6 +180,19 @@ static const value_string camel_Component_vals[] = {
   { 0, NULL }
 };
 
+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 0
 static const true_false_string camel_extension_value = {
   "No Extension",
@@ -281,6 +305,28 @@ static const value_string camel_ectTreatmentIndicator_values[] = {
 
 #include "packet-camel-table.c"
 
+/*
+ * DEBUG fonctions
+ */
+
+#undef DEBUG_CAMELSRT
+/* #define DEBUG_CAMELSRT */
+
+#ifdef DEBUG_CAMELSRT
+#include <stdio.h>
+#include <stdarg.h>
+static guint debug_level = 99;
+
+static void dbg(guint level, char *fmt, ...) {
+  va_list ap;
+
+  if (level > debug_level) return;
+  va_start(ap,fmt);
+  vfprintf(stderr, fmt, ap);
+  va_end(ap);
+}
+#endif
+
 static char camel_number_to_char(int number)
 {
    if (number < 10)
@@ -330,6 +376,662 @@ static int dissect_camel_InitialDPArgExtensionV2(gboolean implicit_tag _U_, tvbu
 
 #include "packet-camel-table2.c"
 
+/*
+ * 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)
+{
+  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);
+
+#ifdef DEBUG_CAMELSRT
+  if(p_camelsrt_call) {
+    dbg(10,"D%d ", p_camelsrt_call->session_id);
+  } else {
+    dbg(23,"Not in hash ");
+  }
+#endif
+
+  return p_camelsrt_call;
+}
+
+/*
+ * 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));
+}
+
+/*
+ * 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)
+{
+  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_new(struct camelsrt_call_info_key_t);
+  p_new_camelsrt_call_key->SessionIdKey = p_camelsrt_call_key->SessionIdKey;
+  p_new_camelsrt_call = se_new(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;
+}
+
+/*
+ * Routine called when the TAP is initialized.
+ * so hash table are (re)created
+ */
+void
+camelsrt_init_routine(void)
+{
+
+  /* free hash-table for SRT */
+  if (srt_calls != NULL) {
+#ifdef DEBUG_CAMELSRT
+    dbg(16,"Destroy hash ");
+#endif
+    g_hash_table_destroy(srt_calls);
+  }
+
+  /* create new hash-table 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;
+}
+
+
+/*
+ * 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)
+{
+  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;
+}
+
+/*
+ * 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(packet_info *pinfo,
+                            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 #%u\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);
+  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 */
+}
+
+/*
+ * 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.
+ */
+static void
+camelsrt_tcap_matching(tvbuff_t *tvb _U_, packet_info *pinfo,
+                      proto_tree *tree _U_,
+                      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(pinfo, 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(packet_info *pinfo,
+                            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 #%u\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);
+    p_camelsrt_call->tcap_context=(struct tcaphash_context_t *)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,
+                              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, *hidden_item;
+
+#ifdef DEBUG_CAMELSRT
+  dbg(10,"\n %s #%u\n", val_to_str_const(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);
+  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 #%u ", 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){
+           hidden_item = proto_tree_add_uint(tree, hf_camelsrt_Duplicate, tvb, 0,0, 77);
+               PROTO_ITEM_SET_HIDDEN(hidden_item);
+         }
+
+       } 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 #%u ", 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_const(srt_type, camelSRTtype_naming, "Unk"),
+                                     p_camelsrt_call->category[srt_type].rsp_num);
+      PROTO_ITEM_SET_GENERATED(ti);
+    } /* frame valid */
+  } /* call reference */
+}
+
+/*
+ * 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;
+    }
+  }
+}
+
+/*
+ * 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,
+                             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, *hidden_item;
+
+#ifdef DEBUG_CAMELSRT
+  dbg(10,"\n %s #%u\n", val_to_str_const(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);
+  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 %u ",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 #%u 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 ){
+         hidden_item = proto_tree_add_uint(tree, hf_camelsrt_Duplicate, tvb, 0,0, 77);
+         PROTO_ITEM_SET_HIDDEN(hidden_item);
+       }
+      }
+    } /* 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_const(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 */
+}
+
+/*
+ * 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, 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(pinfo, p_camelsrt_info);
+    camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
+                                  CAMELSRT_VOICE_INITIALDP);
+    break;
+  case 60: /*InitialDPSMS*/
+    camelsrt_begin_call_matching(pinfo, p_camelsrt_info);
+    camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
+                                  CAMELSRT_SMS_INITIALDP);
+    break;
+  case 78: /*InitialDPGPRS*/
+    camelsrt_begin_call_matching(pinfo, 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(pinfo, p_camelsrt_info);
+    tcapsrt_close((struct tcaphash_context_t *)p_camelsrt_info->tcap_context, pinfo);
+    break;
+
+  case 80: /*EventReportGPRS*/
+    camelsrt_begin_call_matching(pinfo, 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(pinfo, p_camelsrt_info);
+    break;
+
+  case 66: /*ReleaseSMS*/
+    /* Session has been closed by Network */
+    camelsrt_close_call_matching(pinfo, p_camelsrt_info);
+    tcapsrt_close((struct tcaphash_context_t *)p_camelsrt_info->tcap_context,pinfo);
+    break;
+
+  case 79: /*ReleaseGPRS*/
+    /* Session has been closed by Network */
+    camelsrt_close_call_matching(pinfo, p_camelsrt_info);
+    break;
+  } /* switch opcode */
+}
+
+/*
+ * 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;
+}
+
 
 static guint8 camel_pdu_type = 0;
 static guint8 camel_pdu_size = 0;
index 5dd326b82efaa285b1ab89902e5e2503377be33c..ee40de3f55f90771fccd4d13fc96abd125b49767 100644 (file)
@@ -46,4 +46,103 @@ void proto_register_camel(void);
 WS_DLL_PUBLIC const value_string camel_opr_code_strings[];
 /* #include "packet-camel-exp.h"*/
 
+/** @file
+*/
+#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
+
+WS_DLL_PUBLIC const value_string  camelSRTtype_naming[];
+
+/** 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];
+};
+
+/**
+ * Routine called when the TAP is initialized.
+ * so hash table are (re)created
+ */
+void camelsrt_init_routine(void);
+
+/**
+ * Initialize the Message Info used by the main dissector
+ * Data are linked to a TCAP transaction
+ */
+struct camelsrt_info_t * camelsrt_razinfo(void);
+
+/**
+ * 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_camel_info);
+
+WS_DLL_PUBLIC gboolean gcamel_StatSRT;
+
 #endif  /* PACKET_camel_H */
index 869ac0f9c9c8f8700da6b86e2efd1926a1d09251..bc338ab08f9985443f06108dda9902023c85ae48 100644 (file)
@@ -39,7 +39,8 @@
 #include <string.h>
 #include "packet-ber.h"
 #include "packet-tcap.h"
-#include <epan/tcap-persistentdata.h>
+#include "packet-mtp3.h"
+
 
 #define PNAME  "Transaction Capabilities Application Part"
 #define PSNAME "TCAP"
@@ -76,16 +77,35 @@ static struct tcaphash_context_t * gp_tcap_context=NULL;
 
 #include "packet-tcap-ett.c"
 
+/* When several Tcap 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_TCAP_INSTANCE 10
+static int tcapsrt_global_current=0;
+static struct tcapsrt_info_t tcapsrt_global_info[MAX_TCAP_INSTANCE];
+
 #define MAX_SSN 254
 static range_t *global_ssn_range;
 static range_t *ssn_range;
 struct tcap_private_t tcap_private;
 
 gboolean gtcap_HandleSRT=FALSE;
-extern gboolean gtcap_PersistentSRT;
-extern gboolean gtcap_DisplaySRT;
-extern guint gtcap_RepetitionTimeout;
-extern guint gtcap_LostTimeout;
+/* These two timeout (in second) are used when some message are lost,
+   or when the same TCAP transcation identifier is reused */
+guint gtcap_RepetitionTimeout = 10;
+guint gtcap_LostTimeout = 30;
+gboolean gtcap_PersistentSRT=FALSE;
+gboolean gtcap_DisplaySRT=FALSE;
+gboolean gtcap_StatSRT=FALSE;
+
+/* Global hash tables*/
+static GHashTable *tcaphash_context = NULL;
+static GHashTable *tcaphash_begin = NULL;
+static GHashTable *tcaphash_cont = NULL;
+static GHashTable *tcaphash_end = NULL;
+static GHashTable *tcaphash_ansi = NULL;
+
+static guint32 tcapsrt_global_SessionId=1;
 
 static dissector_handle_t      tcap_handle = NULL;
 static dissector_table_t ber_oid_dissector_table;
@@ -135,11 +155,1817 @@ dissector_handle_t get_itu_tcap_subdissector(guint32 ssn) {
     return (dissector_handle_t)g_hash_table_lookup(itu_sub_dissectors,GUINT_TO_POINTER(ssn));
 }
 
+#include "packet-tcap-fn.c"
 
+/*
+ * DEBUG functions
+ */
+#undef MEM_TCAPSRT
+/* #define MEM_TCAPSRT */
 
-#include "packet-tcap-fn.c"
+#undef DEBUG_TCAPSRT
+/* #define DEBUG_TCAPSRT */
+
+#ifdef DEBUG_TCAPSRT
+#include <stdio.h>
+#include <stdarg.h>
+static guint debug_level = 99;
+
+static void
+dbg(guint level, char* fmt, ...)
+{
+  va_list ap;
+
+  if (level > debug_level) return;
+  va_start(ap,fmt);
+  vfprintf(stderr, fmt, ap);
+  va_end(ap);
+}
+#endif
+
+static gint
+tcaphash_context_equal(gconstpointer k1, gconstpointer k2)
+{
+  const struct tcaphash_context_key_t *key1 = (const struct tcaphash_context_key_t *) k1;
+  const struct tcaphash_context_key_t *key2 = (const struct tcaphash_context_key_t *) k2;
+
+  return (key1->session_id == key2->session_id);
+}
+
+/* calculate a hash key */
+static guint
+tcaphash_context_calchash(gconstpointer k)
+{
+  const struct tcaphash_context_key_t *key = (const struct tcaphash_context_key_t *) k;
+  return key->session_id;
+}
+
+
+static gint
+tcaphash_begin_equal(gconstpointer k1, gconstpointer k2)
+{
+  const struct tcaphash_begin_info_key_t *key1 = (const struct tcaphash_begin_info_key_t *) k1;
+  const struct tcaphash_begin_info_key_t *key2 = (const struct tcaphash_begin_info_key_t *) k2;
+
+  if (key1->hashKey == key2->hashKey) {
+
+    if ( ( (key1->opc_hash == key2->opc_hash) &&
+          (key1->dpc_hash == key2->dpc_hash) &&
+          (key1->tid == key2->tid) )
+        ||
+        ( (key1->opc_hash == key2->dpc_hash) &&
+          (key1->dpc_hash == key2->opc_hash) &&
+          (key1->tid == key2->tid) )
+        )
+      return TRUE;
+  }
+  return FALSE;
+}
+
+/* calculate a hash key */
+static guint
+tcaphash_begin_calchash(gconstpointer k)
+{
+  const struct tcaphash_begin_info_key_t *key = (const struct tcaphash_begin_info_key_t *) k;
+  guint hashkey;
+  /* hashkey = key->opc_hash<<16 + key->dpc_hash<<8 + key->src_tid; */
+  hashkey = key->tid;
+  return hashkey;
+}
+
+static gint
+tcaphash_cont_equal(gconstpointer k1, gconstpointer k2)
+{
+  const struct tcaphash_cont_info_key_t *key1 = (const struct tcaphash_cont_info_key_t *) k1;
+  const struct tcaphash_cont_info_key_t *key2 = (const struct tcaphash_cont_info_key_t *) k2;
+
+  if (key1->hashKey == key2->hashKey) {
+
+    if ( (key1->opc_hash == key2->opc_hash) &&
+        (key1->dpc_hash == key2->dpc_hash) &&
+        (key1->src_tid == key2->src_tid) &&
+        (key1->dst_tid == key2->dst_tid) ) {
+      return TRUE;
+    }
+    else if ( (key1->opc_hash == key2->dpc_hash) &&
+             (key1->dpc_hash == key2->opc_hash) &&
+             (key1->src_tid == key2->dst_tid) &&
+             (key1->dst_tid == key2->src_tid) ) {
+      return TRUE;
+    }
+  }
+  return FALSE;
+}
+
+/* calculate a hash key */
+static guint
+tcaphash_cont_calchash(gconstpointer k)
+{
+  const struct tcaphash_cont_info_key_t *key = (const struct tcaphash_cont_info_key_t *) k;
+  guint hashkey;
+  hashkey = key->src_tid + key->dst_tid;
+  return hashkey;
+}
+
+
+static gint
+tcaphash_end_equal(gconstpointer k1, gconstpointer k2)
+{
+  const struct tcaphash_end_info_key_t *key1 = (const struct tcaphash_end_info_key_t *) k1;
+  const struct tcaphash_end_info_key_t *key2 = (const struct tcaphash_end_info_key_t *) k2;
+
+  if (key1->hashKey == key2->hashKey) {
+    if ( ( (key1->opc_hash == key2->opc_hash) &&
+          (key1->dpc_hash == key2->dpc_hash) &&
+          (key1->tid == key2->tid) )
+        ||
+        ( (key1->opc_hash == key2->dpc_hash) &&
+          (key1->dpc_hash == key2->opc_hash) &&
+          (key1->tid == key2->tid) ) )
+      return TRUE;
+  }
+  return FALSE;
+}
+
+/* calculate a hash key */
+static guint
+tcaphash_end_calchash(gconstpointer k)
+{
+  const struct tcaphash_end_info_key_t *key = (const struct tcaphash_end_info_key_t *) k;
+  guint hashkey;
+  hashkey = key->tid;
+  return hashkey;
+}
+
+static gint
+tcaphash_ansi_equal(gconstpointer k1, gconstpointer k2)
+{
+  const struct tcaphash_ansi_info_key_t *key1 = (const struct tcaphash_ansi_info_key_t *) k1;
+  const struct tcaphash_ansi_info_key_t *key2 = (const struct tcaphash_ansi_info_key_t *) k2;
+
+  if (key1->hashKey == key2->hashKey) {
+
+    if ( ( (key1->opc_hash == key2->opc_hash) &&
+          (key1->dpc_hash == key2->dpc_hash) &&
+          (key1->tid == key2->tid) )
+        ||
+        ( (key1->opc_hash == key2->dpc_hash) &&
+          (key1->dpc_hash == key2->opc_hash) &&
+          (key1->tid == key2->tid) )
+        )
+      return TRUE;
+  }
+  return FALSE;
+}
+
+/* calculate a hash key */
+static guint
+tcaphash_ansi_calchash(gconstpointer k)
+{
+  const struct tcaphash_ansi_info_key_t *key = (const struct tcaphash_ansi_info_key_t *) k;
+  guint hashkey;
+  /* hashkey = key->opc_hash<<16 + key->dpc_hash<<8 + key->src_tid; */
+  hashkey = key->tid;
+  return hashkey;
+}
+
+/*
+ * Update a record with the data of the Request
+ */
+static void
+update_tcaphash_begincall(struct tcaphash_begincall_t *p_tcaphash_begincall,
+                         packet_info *pinfo)
+{
+  p_tcaphash_begincall->context->first_frame = pinfo->fd->num;
+  p_tcaphash_begincall->context->last_frame = 0;
+  p_tcaphash_begincall->context->responded = FALSE;
+  p_tcaphash_begincall->context->begin_time = pinfo->fd->abs_ts;
+}
+
+/*
+ * Append a new dialogue, using the same Key, to the chained list
+ * The time is stored too
+ */
+static struct tcaphash_begincall_t *
+append_tcaphash_begincall(struct tcaphash_begincall_t *prev_begincall,
+                         struct tcaphash_context_t *p_tcaphash_context,
+                         packet_info *pinfo)
+{
+  struct tcaphash_begincall_t *p_new_tcaphash_begincall = NULL;
+
+  /* Append the transaction to the list, when the same key is found
+     This should append when the tcap-transaction Id is reused  */
+
+#ifdef MEM_TCAPSRT
+  p_new_tcaphash_begincall = (struct tcaphash_begincall_t *)g_malloc0(sizeof(struct tcaphash_begincall_t));
+#else
+  p_new_tcaphash_begincall = se_new0(struct tcaphash_begincall_t);
+#endif
+  p_new_tcaphash_begincall->context=p_tcaphash_context;
+  p_tcaphash_context->begincall=p_new_tcaphash_begincall;
+  p_new_tcaphash_begincall->beginkey=prev_begincall->beginkey;
+  p_new_tcaphash_begincall->context->first_frame = pinfo->fd->num;
+  p_new_tcaphash_begincall->next_begincall=NULL;
+  p_new_tcaphash_begincall->previous_begincall=prev_begincall;
+  p_new_tcaphash_begincall->father=FALSE;
+
+#ifdef DEBUG_TCAPSRT
+  dbg(10,"+B%d ", p_new_tcaphash_begincall->context->session_id);
+#endif
+  /* Insert in the chained list */
+  prev_begincall->next_begincall = p_new_tcaphash_begincall;
+  if (prev_begincall->context->last_frame == 0) {
+#ifdef DEBUG_TCAPSRT
+    dbg(10,"last ");
+#endif
+    prev_begincall->context->last_frame = pinfo->fd->num-1;
+  }
+  return p_new_tcaphash_begincall;
+}
+
+/*
+ * Update a record with the data of the Request
+ */
+static void
+update_tcaphash_ansicall(struct tcaphash_ansicall_t *p_tcaphash_ansicall,
+                         packet_info *pinfo)
+{
+  p_tcaphash_ansicall->context->first_frame = pinfo->fd->num;
+  p_tcaphash_ansicall->context->last_frame = 0;
+  p_tcaphash_ansicall->context->responded = FALSE;
+  p_tcaphash_ansicall->context->begin_time = pinfo->fd->abs_ts;
+}
+
+/*
+ * Append a new dialogue, using the same Key, to the chained list
+ * The time is stored too
+ */
+static struct tcaphash_ansicall_t *
+append_tcaphash_ansicall(struct tcaphash_ansicall_t *prev_ansicall,
+                         struct tcaphash_context_t *p_tcaphash_context,
+                         packet_info *pinfo)
+{
+  struct tcaphash_ansicall_t *p_new_tcaphash_ansicall = NULL;
+
+  /* Append the transaction to the list, when the same key is found
+     This should append when the tcap-transaction Id is reused  */
+
+#ifdef MEM_TCAPSRT
+  p_new_tcaphash_ansicall = (struct tcaphash_ansicall_t *)g_malloc0(sizeof(struct tcaphash_ansicall_t));
+#else
+  p_new_tcaphash_ansicall = se_new0(struct tcaphash_ansicall_t);
+#endif
+  p_new_tcaphash_ansicall->context=p_tcaphash_context;
+  p_tcaphash_context->ansicall=p_new_tcaphash_ansicall;
+  p_new_tcaphash_ansicall->ansikey=prev_ansicall->ansikey;
+  p_new_tcaphash_ansicall->context->first_frame = pinfo->fd->num;
+  p_new_tcaphash_ansicall->next_ansicall=NULL;
+  p_new_tcaphash_ansicall->previous_ansicall=prev_ansicall;
+  p_new_tcaphash_ansicall->father=FALSE;
+
+#ifdef DEBUG_TCAPSRT
+  dbg(10,"+A%d ", p_new_tcaphash_ansicall->context->session_id);
+#endif
+  /* Insert in the chained list */
+  prev_ansicall->next_ansicall = p_new_tcaphash_ansicall;
+  if (prev_ansicall->context->last_frame == 0) {
+#ifdef DEBUG_TCAPSRT
+    dbg(10,"last ");
+#endif
+    prev_ansicall->context->last_frame = pinfo->fd->num-1;
+  }
+  return p_new_tcaphash_ansicall;
+}
+
+
+static struct tcaphash_contcall_t *
+append_tcaphash_contcall(struct tcaphash_contcall_t *prev_contcall,
+                        struct tcaphash_context_t *p_tcaphash_context)
+{
+  struct tcaphash_contcall_t *p_new_tcaphash_contcall = NULL;
+
+  /* Append the transaction to the list, when the same key is found
+     This should append when the tcap-transaction Id is reused  */
+
+#ifdef MEM_TCAPSRT
+  p_new_tcaphash_contcall = (struct tcaphash_contcall_t *)g_malloc0(sizeof(struct tcaphash_contcall_t));
+#else
+  p_new_tcaphash_contcall = se_new0(struct tcaphash_contcall_t);
+#endif
+  p_new_tcaphash_contcall->context=p_tcaphash_context;
+  p_tcaphash_context->contcall=p_new_tcaphash_contcall;
+  p_new_tcaphash_contcall->contkey=prev_contcall->contkey;
+  p_new_tcaphash_contcall->next_contcall=NULL;
+  p_new_tcaphash_contcall->previous_contcall=prev_contcall;
+  p_new_tcaphash_contcall->father=FALSE;
+
+#ifdef DEBUG_TCAPSRT
+  dbg(10,"+C%d ", p_new_tcaphash_contcall->context->session_id);
+#endif
+  /* Insert in the chained list */
+  prev_contcall->next_contcall = p_new_tcaphash_contcall;
+  return p_new_tcaphash_contcall;
+}
+
+
+static struct tcaphash_endcall_t *
+append_tcaphash_endcall(struct tcaphash_endcall_t *prev_endcall,
+                       struct tcaphash_context_t *p_tcaphash_context)
+{
+  struct tcaphash_endcall_t *p_new_tcaphash_endcall = NULL;
+
+  /* Append the transaction to the list, when the same key is found
+     This should append when the tcap-transaction Id is reused  */
+
+#ifdef MEM_TCAPSRT
+  p_new_tcaphash_endcall = (struct tcaphas_endcall_t *)g_malloc0(sizeof(struct tcaphash_endcall_t));
+#else
+  p_new_tcaphash_endcall = se_new0(struct tcaphash_endcall_t);
+#endif
+  p_new_tcaphash_endcall->context=p_tcaphash_context;
+  p_tcaphash_context->endcall=p_new_tcaphash_endcall;
+  p_new_tcaphash_endcall->endkey=prev_endcall->endkey;
+  p_new_tcaphash_endcall->next_endcall=NULL;
+  p_new_tcaphash_endcall->previous_endcall=prev_endcall;
+  p_new_tcaphash_endcall->father=FALSE;
+
+#ifdef DEBUG_TCAPSRT
+  dbg(10,"+E%d ", p_new_tcaphash_endcall->context->session_id);
+#endif
+  /* Insert in the chained list */
+  prev_endcall->next_endcall = p_new_tcaphash_endcall;
+  return p_new_tcaphash_endcall;
+}
+
+
+/*
+ * Find the dialog by Key and Time
+ */
+static struct tcaphash_begincall_t *
+find_tcaphash_begin(struct tcaphash_begin_info_key_t *p_tcaphash_begin_key,
+                   packet_info *pinfo, gboolean isBegin)
+{
+  struct tcaphash_begincall_t *p_tcaphash_begincall = NULL;
+  p_tcaphash_begincall = (struct tcaphash_begincall_t *)g_hash_table_lookup(tcaphash_begin, p_tcaphash_begin_key);
+
+  if(p_tcaphash_begincall) {
+    do {
+      if ( p_tcaphash_begincall->context ) {
+        if ( ( isBegin &&
+               pinfo->fd->num == p_tcaphash_begincall->context->first_frame )
+             ||
+             ( !isBegin &&
+               pinfo->fd->num >= p_tcaphash_begincall->context->first_frame &&
+               ( p_tcaphash_begincall->context->last_frame?pinfo->fd->num <= p_tcaphash_begincall->context->last_frame:1 )
+               )
+             ) {
+          /* We have a dialogue, with this key, opened before this request */
+#ifdef DEBUG_TCAPSRT
+          dbg(10,"B%d ", p_tcaphash_begincall->context->session_id);
+#endif
+          return p_tcaphash_begincall;
+        }
+#ifdef DEBUG_TCAPSRT
+      dbg(60,"[B%d] ", p_tcaphash_begincall->context->session_id);
+#endif
+      }
+      /* Break when list end is reached */
+      if(p_tcaphash_begincall->next_begincall == NULL) {
+#ifdef DEBUG_TCAPSRT
+        dbg(23,"End of Blist ");
+#endif
+        break;
+      }
+      p_tcaphash_begincall = p_tcaphash_begincall->next_begincall;
+    } while (p_tcaphash_begincall != NULL) ;
+  } else {
+#ifdef DEBUG_TCAPSRT
+    dbg(23,"Not in Bhash ");
+#endif
+  }
+  return NULL;
+}
+
+
+
+static struct tcaphash_contcall_t *
+find_tcaphash_cont(struct tcaphash_cont_info_key_t *p_tcaphash_cont_key,
+                  packet_info *pinfo)
+{
+  struct tcaphash_contcall_t *p_tcaphash_contcall = NULL;
+  p_tcaphash_contcall = (struct tcaphash_contcall_t *)g_hash_table_lookup(tcaphash_cont, p_tcaphash_cont_key);
+
+  if(p_tcaphash_contcall) {
+    do {
+      if ( p_tcaphash_contcall->context ) {
+       if (pinfo->fd->num >= p_tcaphash_contcall->context->first_frame &&
+           (p_tcaphash_contcall->context->last_frame?pinfo->fd->num <= p_tcaphash_contcall->context->last_frame:1) ) {
+         /* We have a dialogue, with this key, opened before this request */
+#ifdef DEBUG_TCAPSRT
+         dbg(10,"C%d ", p_tcaphash_contcall->context->session_id);
+#endif
+         return p_tcaphash_contcall;
+       }
+#ifdef DEBUG_TCAPSRT
+       dbg(60,"[C%d] ", p_tcaphash_contcall->context->session_id);
+#endif
+      }
+      /* Break when list end is reached */
+      if(p_tcaphash_contcall->next_contcall == NULL) {
+#ifdef DEBUG_TCAPSRT
+       dbg(23,"End of Clist ");
+#endif
+       break;
+      }
+      p_tcaphash_contcall = p_tcaphash_contcall->next_contcall;
+    } while (p_tcaphash_contcall != NULL) ;
+  } else {
+#ifdef DEBUG_TCAPSRT
+    dbg(23,"Not in Chash ");
+#endif
+  }
+  return NULL;
+}
+
+static struct tcaphash_endcall_t *
+find_tcaphash_end(struct tcaphash_end_info_key_t *p_tcaphash_end_key,
+                 packet_info *pinfo, gboolean isEnd)
+{
+  struct tcaphash_endcall_t *p_tcaphash_endcall = NULL;
+  p_tcaphash_endcall = (struct tcaphash_endcall_t *)g_hash_table_lookup(tcaphash_end, p_tcaphash_end_key);
+
+  if(p_tcaphash_endcall) {
+    do {
+      if ( p_tcaphash_endcall->context ) {
+       if ( ( isEnd &&
+              (p_tcaphash_endcall->context->last_frame?pinfo->fd->num == p_tcaphash_endcall->context->last_frame:1)
+              )
+            ||
+            ( !isEnd &&
+              pinfo->fd->num >= p_tcaphash_endcall->context->first_frame &&
+              (p_tcaphash_endcall->context->last_frame?pinfo->fd->num <= p_tcaphash_endcall->context->last_frame:1)
+              )
+            ) {
+         /* We have a dialogue, with this key, opened before this request */
+#ifdef DEBUG_TCAPSRT
+         dbg(10,"E%d ", p_tcaphash_endcall->context->session_id);
+#endif
+         return p_tcaphash_endcall;
+       }
+#ifdef DEBUG_TCAPSRT
+         dbg(60,"[E%d] ", p_tcaphash_endcall->context->session_id);
+#endif
+      }
+      /* Break when list end is reached */
+      if(p_tcaphash_endcall->next_endcall == NULL) {
+#ifdef DEBUG_TCAPSRT
+       dbg(23,"End of Elist ");
+#endif
+       break;
+      }
+      p_tcaphash_endcall = p_tcaphash_endcall->next_endcall;
+    } while (p_tcaphash_endcall != NULL) ;
+  } else {
+#ifdef DEBUG_TCAPSRT
+    dbg(23,"Not in Ehash ");
+#endif
+  }
+  return NULL;
+}
+
+/*
+ * New record to create, to identify a new transaction
+ */
+static struct tcaphash_context_t *
+new_tcaphash_context(struct tcaphash_context_key_t *p_tcaphash_context_key,
+                    packet_info *pinfo)
+{
+  struct tcaphash_context_key_t *p_new_tcaphash_context_key;
+  struct tcaphash_context_t *p_new_tcaphash_context = NULL;
+
+  /* Register the transaction in the hash table
+     with the tcap transaction Id as Main Key
+     Once created, this entry will be updated later */
+
+#ifdef MEM_TCAPSRT
+  p_new_tcaphash_context_key = (struct tcaphash_context_key_t *)g_malloc(sizeof(struct tcaphash_context_key_t));
+#else
+  p_new_tcaphash_context_key = se_new(struct tcaphash_context_key_t);
+#endif
+  p_new_tcaphash_context_key->session_id = p_tcaphash_context_key->session_id;
+
+#ifdef MEM_TCAPSRT
+  p_new_tcaphash_context = (struct tcaphash_context_t *)g_malloc0(sizeof(struct tcaphash_context_t));
+#else
+  p_new_tcaphash_context = se_new0(struct tcaphash_context_t);
+#endif
+  p_new_tcaphash_context->key = p_new_tcaphash_context_key;
+  p_new_tcaphash_context->session_id = p_tcaphash_context_key->session_id;
+  p_new_tcaphash_context->first_frame = pinfo->fd->num;
+#ifdef DEBUG_TCAPSRT
+  dbg(10,"S%d ", p_new_tcaphash_context->session_id);
+#endif
+  /* store it */
+  g_hash_table_insert(tcaphash_context, p_new_tcaphash_context_key, p_new_tcaphash_context);
+  return p_new_tcaphash_context;
+}
+
+/*
+ * New record to create, to identify a new transaction
+ */
+static struct tcaphash_begincall_t *
+new_tcaphash_begin(struct tcaphash_begin_info_key_t *p_tcaphash_begin_key,
+                  struct tcaphash_context_t *p_tcaphash_context)
+{
+  struct tcaphash_begin_info_key_t *p_new_tcaphash_begin_key;
+  struct tcaphash_begincall_t *p_new_tcaphash_begincall = NULL;
+
+  /* Register the transaction in the hash table
+     with the tcap transaction Id as Main Key
+     Once created, this entry will be updated later */
+
+#ifdef MEM_TCAPSRT
+  p_new_tcaphash_begin_key = (struct tcaphash_begin_info_key_t *)g_malloc(sizeof(struct tcaphash_begin_info_key_t));
+#else
+  p_new_tcaphash_begin_key = se_new(struct tcaphash_begin_info_key_t);
+#endif
+  p_new_tcaphash_begin_key->hashKey = p_tcaphash_begin_key->hashKey;
+  p_new_tcaphash_begin_key->tid = p_tcaphash_begin_key->tid;
+  p_new_tcaphash_begin_key->opc_hash = p_tcaphash_begin_key->opc_hash;
+  p_new_tcaphash_begin_key->dpc_hash = p_tcaphash_begin_key->dpc_hash;
+
+#ifdef MEM_TCAPSRT
+  p_new_tcaphash_begincall = (struct tcaphash_begincall_t *)g_malloc0(sizeof(struct tcaphash_begincall_t));
+#else
+ p_new_tcaphash_begincall = se_new0(struct tcaphash_begincall_t);
+#endif
+  p_new_tcaphash_begincall->beginkey=p_new_tcaphash_begin_key;
+  p_new_tcaphash_begincall->context=p_tcaphash_context;
+  p_tcaphash_context->begincall=p_new_tcaphash_begincall;
+  p_new_tcaphash_begincall->father=TRUE;
+  p_new_tcaphash_begincall->next_begincall=NULL;
+  p_new_tcaphash_begincall->previous_begincall=NULL;
+
+#ifdef DEBUG_TCAPSRT
+  dbg(10,"B%d ", p_new_tcaphash_begincall->context->session_id);
+#endif
+  /* store it */
+  g_hash_table_insert(tcaphash_begin, p_new_tcaphash_begin_key, p_new_tcaphash_begincall);
+  return p_new_tcaphash_begincall;
+}
+
+
+
+/*
+ * New record to create, to identify a new transaction
+ */
+static struct tcaphash_contcall_t *
+new_tcaphash_cont(struct tcaphash_cont_info_key_t *p_tcaphash_cont_key,
+                 struct tcaphash_context_t *p_tcaphash_context)
+{
+  struct tcaphash_cont_info_key_t *p_new_tcaphash_cont_key;
+  struct tcaphash_contcall_t *p_new_tcaphash_contcall = NULL;
+
+  /* Register the transaction in the hash table
+     with the tcap transaction Id as Main Key
+     Once created, this entry will be updated later */
+
+#ifdef MEM_TCAPSRT
+  p_new_tcaphash_cont_key = (struct tcaphash_cont_info_key_t *)g_malloc(sizeof(struct tcaphash_cont_info_key_t));
+#else
+  p_new_tcaphash_cont_key = se_new(struct tcaphash_cont_info_key_t);
+#endif
+  p_new_tcaphash_cont_key->hashKey = p_tcaphash_cont_key->hashKey;
+  p_new_tcaphash_cont_key->src_tid = p_tcaphash_cont_key->src_tid;
+  p_new_tcaphash_cont_key->dst_tid = p_tcaphash_cont_key->dst_tid;
+  p_new_tcaphash_cont_key->opc_hash = p_tcaphash_cont_key->opc_hash;
+  p_new_tcaphash_cont_key->dpc_hash = p_tcaphash_cont_key->dpc_hash;
+
+#ifdef MEM_TCAPSRT
+  p_new_tcaphash_contcall = (struct tcaphash_contcall_t *)g_malloc0(sizeof(struct tcaphash_contcall_t));
+#else
+  p_new_tcaphash_contcall = se_new0(struct tcaphash_contcall_t);
+#endif
+  p_new_tcaphash_contcall->contkey=p_new_tcaphash_cont_key;
+  p_new_tcaphash_contcall->context=p_tcaphash_context;
+  p_tcaphash_context->contcall=p_new_tcaphash_contcall;
+  p_new_tcaphash_contcall->father=TRUE;
+  p_new_tcaphash_contcall->next_contcall=NULL;
+  p_new_tcaphash_contcall->previous_contcall=NULL;
+
+#ifdef DEBUG_TCAPSRT
+  dbg(10,"C%d ", p_new_tcaphash_contcall->context->session_id);
+#endif
+  /* store it */
+  g_hash_table_insert(tcaphash_cont, p_new_tcaphash_cont_key, p_new_tcaphash_contcall);
+  return p_new_tcaphash_contcall;
+}
+
+
+/*
+ * New record to create, to identify a new transaction
+ */
+static struct tcaphash_endcall_t *
+new_tcaphash_end(struct tcaphash_end_info_key_t *p_tcaphash_end_key,
+                struct tcaphash_context_t *p_tcaphash_context)
+{
+  struct tcaphash_end_info_key_t *p_new_tcaphash_end_key;
+  struct tcaphash_endcall_t *p_new_tcaphash_endcall = NULL;
+
+  /* Register the transaction in the hash table
+     with the tcap transaction Id as Main Key
+     Once created, this entry will be updated later */
+
+#ifdef MEM_TCAPSRT
+  p_new_tcaphash_end_key = (struct tcaphash_end_info_key_t *)g_malloc(sizeof(struct tcaphash_end_info_key_t));
+#else
+  p_new_tcaphash_end_key = se_new(struct tcaphash_end_info_key_t);
+#endif
+  p_new_tcaphash_end_key->hashKey = p_tcaphash_end_key->hashKey;
+  p_new_tcaphash_end_key->tid = p_tcaphash_end_key->tid;
+  p_new_tcaphash_end_key->opc_hash = p_tcaphash_end_key->opc_hash;
+  p_new_tcaphash_end_key->dpc_hash = p_tcaphash_end_key->dpc_hash;
+
+#ifdef MEM_TCAPSRT
+  p_new_tcaphash_endcall = (struct tcaphash_endcall_t *)g_malloc0(sizeof(struct tcaphash_endcall_t));
+#else
+  p_new_tcaphash_endcall = se_new0(struct tcaphash_endcall_t);
+#endif
+  p_new_tcaphash_endcall->endkey=p_new_tcaphash_end_key;
+  p_new_tcaphash_endcall->context=p_tcaphash_context;
+  p_tcaphash_context->endcall=p_new_tcaphash_endcall;
+  p_new_tcaphash_endcall->father=TRUE;
+  p_new_tcaphash_endcall->next_endcall=NULL;
+  p_new_tcaphash_endcall->previous_endcall=NULL;
+
+#ifdef DEBUG_TCAPSRT
+  dbg(10,"E%d ", p_new_tcaphash_endcall->context->session_id);
+#endif
+  /* store it */
+  g_hash_table_insert(tcaphash_end, p_new_tcaphash_end_key, p_new_tcaphash_endcall);
+  return p_new_tcaphash_endcall;
+}
+/*
+ * New record to create, to identify a new transaction
+ */
+static struct tcaphash_ansicall_t *
+new_tcaphash_ansi(struct tcaphash_ansi_info_key_t *p_tcaphash_ansi_key,
+                  struct tcaphash_context_t *p_tcaphash_context)
+{
+  struct tcaphash_ansi_info_key_t *p_new_tcaphash_ansi_key;
+  struct tcaphash_ansicall_t *p_new_tcaphash_ansicall = NULL;
+
+  /* Register the transaction in the hash table
+     with the tcap transaction Id as Main Key
+     Once created, this entry will be updated later */
+
+#ifdef MEM_TCAPSRT
+  p_new_tcaphash_ansi_key = (struct tcaphash_ansi_info_key_t *)g_malloc(sizeof(struct tcaphash_ansi_info_key_t));
+#else
+  p_new_tcaphash_ansi_key = se_new(struct tcaphash_ansi_info_key_t);
+#endif
+  p_new_tcaphash_ansi_key->hashKey = p_tcaphash_ansi_key->hashKey;
+  p_new_tcaphash_ansi_key->tid = p_tcaphash_ansi_key->tid;
+  p_new_tcaphash_ansi_key->opc_hash = p_tcaphash_ansi_key->opc_hash;
+  p_new_tcaphash_ansi_key->dpc_hash = p_tcaphash_ansi_key->dpc_hash;
+
+#ifdef MEM_TCAPSRT
+  p_new_tcaphash_ansicall = (struct tcaphash_ansicall_t *)g_malloc0(sizeof(struct tcaphash_ansicall_t));
+#else
+  p_new_tcaphash_ansicall = se_new0(struct tcaphash_ansicall_t);
+#endif
+  p_new_tcaphash_ansicall->ansikey=p_new_tcaphash_ansi_key;
+  p_new_tcaphash_ansicall->context=p_tcaphash_context;
+  p_tcaphash_context->ansicall=p_new_tcaphash_ansicall;
+  p_new_tcaphash_ansicall->father=TRUE;
+  p_new_tcaphash_ansicall->next_ansicall=NULL;
+  p_new_tcaphash_ansicall->previous_ansicall=NULL;
+
+#ifdef DEBUG_TCAPSRT
+  dbg(10,"A%d ", p_new_tcaphash_ansicall->context->session_id);
+#endif
+  /* store it */
+  g_hash_table_insert(tcaphash_ansi, p_new_tcaphash_ansi_key, p_new_tcaphash_ansicall);
+  return p_new_tcaphash_ansicall;
+}
+
+static struct tcaphash_contcall_t *
+create_tcaphash_cont(struct tcaphash_cont_info_key_t *p_tcaphash_cont_key,
+                    struct tcaphash_context_t *p_tcaphash_context)
+{
+  struct tcaphash_contcall_t *p_tcaphash_contcall1 = NULL;
+  struct tcaphash_contcall_t *p_tcaphash_contcall = NULL;
+
+  p_tcaphash_contcall1 = (struct tcaphash_contcall_t *)
+    g_hash_table_lookup(tcaphash_cont, p_tcaphash_cont_key);
+
+  if (p_tcaphash_contcall1) {
+    /* Walk through list of transaction with identical keys */
+    /* go the the end to insert new record */
+    do {
+      if (!p_tcaphash_contcall1->next_contcall) {
+       p_tcaphash_contcall=append_tcaphash_contcall(p_tcaphash_contcall1,
+                                                    p_tcaphash_context);
+       break;
+      }
+      p_tcaphash_contcall1 = p_tcaphash_contcall1->next_contcall;
+    } while (p_tcaphash_contcall1 != NULL );
+  } else {
+    p_tcaphash_contcall = new_tcaphash_cont(p_tcaphash_cont_key,
+                                           p_tcaphash_context);
+  }
+  return p_tcaphash_contcall;
+}
+
+
+static struct tcaphash_endcall_t *
+create_tcaphash_end(struct tcaphash_end_info_key_t *p_tcaphash_end_key,
+                   struct tcaphash_context_t *p_tcaphash_context)
+{
+  struct tcaphash_endcall_t *p_tcaphash_endcall1 = NULL;
+  struct tcaphash_endcall_t *p_tcaphash_endcall = NULL;
+
+  p_tcaphash_endcall1 = (struct tcaphash_endcall_t *)
+    g_hash_table_lookup(tcaphash_end, p_tcaphash_end_key);
+
+  if (p_tcaphash_endcall1) {
+    /* Walk through list of transaction with identical keys */
+    /* go the the end to insert new record */
+    do {
+      if (!p_tcaphash_endcall1->next_endcall) {
+       p_tcaphash_endcall=append_tcaphash_endcall(p_tcaphash_endcall1,
+                                                  p_tcaphash_context);
+       break;
+      }
+      p_tcaphash_endcall1 = p_tcaphash_endcall1->next_endcall;
+    } while (p_tcaphash_endcall1 != NULL );
+  } else {
+    p_tcaphash_endcall = new_tcaphash_end(p_tcaphash_end_key,
+                                         p_tcaphash_context);
+  }
+  return p_tcaphash_endcall;
+}
+
+
+/*
+ * Routine called when the TAP is initialized.
+ * so hash table are (re)created
+ */
+void
+tcapsrt_init_routine(void)
+{
+
+  /* free hash-table for SRT */
+  if (tcaphash_context != NULL) {
+#ifdef DEBUG_TCAPSRT
+    dbg(16,"Destroy hash_context \n");
+#endif
+    g_hash_table_destroy(tcaphash_context);
+  }
+
+  if (tcaphash_begin != NULL) {
+#ifdef DEBUG_TCAPSRT
+    dbg(16,"Destroy hash_begin \n");
+#endif
+    g_hash_table_destroy(tcaphash_begin);
+  }
+
+  if (tcaphash_cont != NULL) {
+#ifdef DEBUG_TCAPSRT
+    dbg(16,"Destroy hash_cont \n");
+#endif
+    g_hash_table_destroy(tcaphash_cont);
+  }
+
+  if (tcaphash_end != NULL) {
+#ifdef DEBUG_TCAPSRT
+    dbg(16,"Destroy hash_end \n");
+#endif
+    g_hash_table_destroy(tcaphash_end);
+  }
+
+  if (tcaphash_ansi != NULL) {
+#ifdef DEBUG_TCAPSRT
+    dbg(16,"Destroy hash_ansi \n");
+#endif
+    g_hash_table_destroy(tcaphash_ansi);
+  }
+
+#ifdef DEBUG_TCAPSRT
+  dbg(16,"Create hash \n");
+#endif
+  /* create new hash-tables for SRT */
+  tcaphash_context = g_hash_table_new(tcaphash_context_calchash, tcaphash_context_equal);
+  tcaphash_begin   = g_hash_table_new(tcaphash_begin_calchash, tcaphash_begin_equal);
+  tcaphash_cont    = g_hash_table_new(tcaphash_cont_calchash, tcaphash_cont_equal);
+  tcaphash_end     = g_hash_table_new(tcaphash_end_calchash, tcaphash_end_equal);
+  tcaphash_ansi    = g_hash_table_new(tcaphash_ansi_calchash, tcaphash_ansi_equal);
+
+  /* Reset the session counter */
+  tcapsrt_global_SessionId=1;
+
+  /* Display of SRT only if Persistent Stat */
+  gtcap_DisplaySRT=gtcap_PersistentSRT || gtcap_HandleSRT&gtcap_StatSRT;
+}
+
+/*
+ * Create the record identifiying the TCAP transaction
+ * When the identifier for the transaction is reused, check
+ * the following criteria before to append a new record:
+ * - a timeout corresponding to a message retransmission is detected,
+ * - a message hast been lost
+ * - or the previous transaction has been  be closed
+ */
+static struct tcaphash_context_t *
+tcaphash_begin_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+                       struct tcapsrt_info_t *p_tcapsrt_info)
+{
+  struct tcaphash_context_t *p_tcaphash_context=NULL;
+  struct tcaphash_context_key_t tcaphash_context_key;
+  struct tcaphash_begincall_t *p_tcaphash_begincall, *p_new_tcaphash_begincall=NULL;
+  struct tcaphash_begin_info_key_t tcaphash_begin_key;
+  proto_item *pi;
+  proto_item *stat_item=NULL;
+  proto_tree *stat_tree=NULL;
+
+  /* prepare the key data */
+  tcaphash_begin_key.tid = p_tcapsrt_info->src_tid;
+  if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
+  {
+    /* We have MTP3 PCs (so we can safely do this cast) */
+    tcaphash_begin_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
+    tcaphash_begin_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
+  } else {
+    /* Don't have MTP3 PCs (maybe we're over SUA?) */
+    tcaphash_begin_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
+    tcaphash_begin_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
+  }
+  tcaphash_begin_key.hashKey=tcaphash_begin_calchash(&tcaphash_begin_key);
+
+  /* look up the request */
+#ifdef DEBUG_TCAPSRT
+  dbg(10,"\n Hbegin #%u ", pinfo->fd->num);
+  dbg(11,"key %lx ",tcaphash_begin_key.hashKey);
+  dbg(51,"PC %s %s ",ep_address_to_str(&pinfo->src), ep_address_to_str(&pinfo->dst));
+  dbg(51,"Tid %lx \n",tcaphash_begin_key.tid);
+#endif
+
+  p_tcaphash_begincall = (struct tcaphash_begincall_t *)
+  g_hash_table_lookup(tcaphash_begin, &tcaphash_begin_key);
+
+  if (p_tcaphash_begincall) {
+    /* Walk through list of transaction with identical keys */
+    do {
+      /* Check if the request with this reqSeqNum has been seen, with the same Message Type */
+      if (pinfo->fd->num == p_tcaphash_begincall->context->first_frame) {
+       /* We have seen this request before -> do nothing */
+#ifdef DEBUG_TCAPSRT
+       dbg(22,"Already seen ");
+#endif
+       p_tcaphash_context=p_tcaphash_begincall->context;
+       break;
+      }
+      /* If the last record for Tcap transaction with identifier has not been reached */
+      if (!p_tcaphash_begincall->next_begincall) {
+       /* check if we have to create a new record or not */
+       /* if last request has been responded (response number is known)
+          and this request appears after last response (has bigger frame number)
+          and last request occurred after the timeout for repetition,
+          or
+          if last request hasn't been responded (so number unknown)
+          and this request appears after last request (has bigger frame number)
+          and this request occurred after the timeout for message lost */
+       if ( ( p_tcaphash_begincall->context->last_frame != 0
+              && pinfo->fd->num > p_tcaphash_begincall->context->first_frame
+              && (guint) pinfo->fd->abs_ts.secs > (guint)(p_tcaphash_begincall->context->begin_time.secs + gtcap_RepetitionTimeout)
+              ) ||
+            ( p_tcaphash_begincall->context->last_frame == 0
+              && pinfo->fd->num > p_tcaphash_begincall->context->first_frame
+              && (guint)pinfo->fd->abs_ts.secs > (guint)(p_tcaphash_begincall->context->begin_time.secs + gtcap_LostTimeout)
+              )
+            )
+         {
+           /* we decide that we have a new request */
+           /* Append new record to the list */
+#ifdef DEBUG_TCAPSRT
+           dbg(12,"(timeout) Append key %lx ",tcaphash_begin_key.hashKey);
+           dbg(12,"Frame %u rsp %u ",pinfo->fd->num,p_tcaphash_begincall->context->last_frame );
+#endif
+           tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
+           p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
+
+           p_new_tcaphash_begincall = append_tcaphash_begincall(p_tcaphash_begincall,
+                                                                p_tcaphash_context,
+                                                                pinfo);
+#ifdef DEBUG_TCAPSRT
+           dbg(12,"Update key %lx ",tcaphash_begin_key.hashKey);
+#endif
+           update_tcaphash_begincall(p_new_tcaphash_begincall, pinfo);
+         } else { /* timeout or message lost */
+
+         /* If the Tid is reused for a closed Transaction */
+         /* Or if we received an TC_BEGIN for a Transaction marked as "closed" */
+         /* (this is the case, for pre-arranged END, the transaction is marked as closed */
+         /* by the upper layer, thank to a callback method close) */
+         if ( p_tcaphash_begincall->context->closed) {
+#ifdef DEBUG_TCAPSRT
+           dbg(12,"(closed) Append key %lu ",tcaphash_begin_key.hashKey);
+           dbg(12,"Frame %u rsp %u ",pinfo->fd->num,p_tcaphash_begincall->context->last_frame );
+#endif
+           tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
+           p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
+           p_new_tcaphash_begincall = append_tcaphash_begincall(p_tcaphash_begincall,
+                                                                p_tcaphash_context,
+                                                                pinfo);
+
+#ifdef DEBUG_TCAPSRT
+           dbg(12,"Update key %lu ",tcaphash_begin_key.hashKey);
+#endif
+           update_tcaphash_begincall(p_new_tcaphash_begincall, pinfo);
+
+         } else {
+           /* the TCAP session is not closed, so, either messages have been lost */
+           /* or it's a duplicate request. Mark it as such. */
+#ifdef DEBUG_TCAPSRT
+           dbg(21,"Display_duplicate %d ",p_tcaphash_begincall->context->first_frame);
+#endif
+           p_tcaphash_context=p_tcaphash_begincall->context;
+           if (gtcap_DisplaySRT && tree) {
+             stat_item = proto_tree_add_text(tree, tvb, 0, -1, "Stat");
+             PROTO_ITEM_SET_GENERATED(stat_item);
+             stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
+             pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_Duplicate, tvb, 0, 0,
+                                             p_tcaphash_context->first_frame,
+                                             "Duplicate with session %u in frame %u",
+                                             p_tcaphash_context->session_id,p_tcaphash_context->first_frame);
+             PROTO_ITEM_SET_GENERATED(pi);
+           }
+           return p_tcaphash_context;
+         } /* Previous session closed */
+       } /* test with Timeout or message Lost */
+       break;
+      } /* Next call is NULL */
+      /* Repeat the tests for the next record with the same transaction identifier */
+      p_tcaphash_begincall = p_tcaphash_begincall->next_begincall;
+    } while (p_tcaphash_begincall != NULL );
+    /*
+     * End of analyze for the list be TC_BEGIN with same transaction ID
+     */
+  } else { /* p_tcaphash_begincall has not been found */
+    /*
+     * Create a new TCAP context
+     */
+#ifdef DEBUG_TCAPSRT
+    dbg(10,"New key %lx ",tcaphash_begin_key.hashKey);
+#endif
+
+    tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
+    p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
+    p_tcaphash_begincall = new_tcaphash_begin(&tcaphash_begin_key, p_tcaphash_context);
+
+#ifdef DEBUG_TCAPSRT
+    dbg(11,"Update key %lx ",tcaphash_begin_key.hashKey);
+    dbg(11,"Frame reqlink #%u ", pinfo->fd->num);
+#endif
+    update_tcaphash_begincall(p_tcaphash_begincall, pinfo);
+  }
+
+  /* display tcap session, if available */
+  if ( gtcap_DisplaySRT && tree &&
+       p_tcaphash_context &&
+       p_tcaphash_context->session_id) {
+    stat_item = proto_tree_add_text(tree, tvb, 0, 0, "Stat");
+    PROTO_ITEM_SET_GENERATED(stat_item);
+    stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
+    pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
+    PROTO_ITEM_SET_GENERATED(pi);
+
+    /* add link to response frame, if available */
+    /* p_tcaphash_begincall->context->last_frame) */
+    if( p_tcaphash_context->last_frame != 0 ){
+#ifdef DEBUG_TCAPSRT
+      dbg(20,"Display_frameRsplink %d ",p_tcaphash_context->last_frame);
+#endif
+      pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_BeginSession, tvb, 0, 0,
+                                     p_tcaphash_context->last_frame,
+                                     "End of session in frame %u",
+                                     p_tcaphash_context->last_frame);
+      PROTO_ITEM_SET_GENERATED(pi);
+    }
+  }
+  return p_tcaphash_context;
+}
+
+/*
+* Try to find a TCAP session according to the source and destination
+* Identifier given in the TC_CONT
+* If nothing is found, it is probably a session in opening state, so try to find
+* a tcap session registered with a TC_BEGIN "key", matching the destination Id of the TC_CONT
+* Then associate the TC_CONT "key" to the TCAP context, and create a TC_END "key"
+* and display the available info for the TCAP context
+*/
+static struct tcaphash_context_t *
+tcaphash_cont_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+                      struct tcapsrt_info_t *p_tcapsrt_info)
+{
+  struct tcaphash_context_t *p_tcaphash_context=NULL;
+  struct tcaphash_contcall_t *p_tcaphash_contcall;
+  struct tcaphash_cont_info_key_t tcaphash_cont_key;
+  struct tcaphash_begin_info_key_t tcaphash_begin_key;
+  struct tcaphash_begincall_t *p_tcaphash_begincall;
+  struct tcaphash_end_info_key_t tcaphash_end_key;
+  proto_item *pi;
+  proto_item *stat_item=NULL;
+  proto_tree *stat_tree=NULL;
+
+#ifdef DEBUG_TCAPSRT
+  dbg(10,"\n Hcont #%u ", pinfo->fd->num);
+#endif
+
+  /* look only for matching request, if matching conversation is available. */
+  tcaphash_cont_key.src_tid = p_tcapsrt_info->src_tid;
+  tcaphash_cont_key.dst_tid = p_tcapsrt_info->dst_tid;
+  if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
+  {
+    /* We have MTP3 PCs (so we can safely do this cast) */
+    tcaphash_cont_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
+    tcaphash_cont_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
+  } else {
+    /* Don't have MTP3 PCs (maybe we're over SUA?) */
+    tcaphash_cont_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
+    tcaphash_cont_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
+  }
+  tcaphash_cont_key.hashKey=tcaphash_cont_calchash(&tcaphash_cont_key);
+
+#ifdef DEBUG_TCAPSRT
+  dbg(11,"Ckey %lx ", tcaphash_cont_key.hashKey);
+  dbg(51,"PC %s %s ",ep_address_to_str(&pinfo->src), ep_address_to_str(&pinfo->dst));
+  dbg(51,"Tid %lx %lx \n",tcaphash_cont_key.src_tid, tcaphash_cont_key.dst_tid);
+#endif
+  p_tcaphash_contcall = find_tcaphash_cont(&tcaphash_cont_key, pinfo);
+  if(p_tcaphash_contcall) {
+#ifdef DEBUG_TCAPSRT
+    dbg(12,"CFound ");
+#endif
+    p_tcaphash_context=p_tcaphash_contcall->context;
+  } else { /* cont not found */
+#ifdef DEBUG_TCAPSRT
+    dbg(12,"CnotFound ");
+#endif
+    /* Find the TCAP transaction according to the TC_BEGIN */
+    tcaphash_begin_key.tid = p_tcapsrt_info->dst_tid;
+    if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
+    {
+      /* We have MTP3 PCs (so we can safely do this cast) */
+      tcaphash_begin_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
+      tcaphash_begin_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
+    } else {
+      /* Don't have MTP3 PCs (maybe we're over SUA?) */
+      tcaphash_begin_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
+      tcaphash_begin_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
+    }
+    tcaphash_begin_key.hashKey=tcaphash_begin_calchash(&tcaphash_begin_key);
+
+#ifdef DEBUG_TCAPSRT
+    dbg(11,"Bkey %lx ", tcaphash_begin_key.hashKey);
+    dbg(51,"PC %s %s ",ep_address_to_str(&pinfo->src), ep_address_to_str(&pinfo->dst));
+    dbg(51,"Tid %lx \n",tcaphash_begin_key.tid);
+#endif
+    p_tcaphash_begincall = find_tcaphash_begin(&tcaphash_begin_key, pinfo, FALSE);
+    if(!p_tcaphash_begincall){
+        /* Do we have a continue from the same source? */
+        tcaphash_begin_key.tid = p_tcapsrt_info->src_tid;
+        tcaphash_begin_key.hashKey=tcaphash_begin_calchash(&tcaphash_begin_key);
+        p_tcaphash_begincall = find_tcaphash_begin(&tcaphash_begin_key, pinfo,FALSE);
+    }
+    if(p_tcaphash_begincall &&
+       !p_tcaphash_begincall->context->contcall ) {
+#ifdef DEBUG_TCAPSRT
+      dbg(12,"BFound \n");
+#endif
+      p_tcaphash_context=p_tcaphash_begincall->context;
+      p_tcaphash_context->responded=TRUE;
+
+#ifdef DEBUG_TCAPSRT
+      dbg(10,"New Ckey %lx ",tcaphash_cont_key.hashKey);
+      dbg(11,"Frame reqlink #%u \n", pinfo->fd->num);
+#endif
+      create_tcaphash_cont(&tcaphash_cont_key,
+                           p_tcaphash_begincall->context);
+
+      tcaphash_end_key.tid = p_tcapsrt_info->src_tid;
+      if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
+      {
+        /* We have MTP3 PCs (so we can safely do this cast) */
+        tcaphash_end_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
+        tcaphash_end_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
+      } else {
+        /* Don't have MTP3 PCs (maybe we're over SUA?) */
+        tcaphash_end_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
+        tcaphash_end_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
+      }
+      tcaphash_end_key.hashKey=tcaphash_end_calchash(&tcaphash_end_key);
+
+#ifdef DEBUG_TCAPSRT
+      dbg(10,"New Ekey %lx ",tcaphash_end_key.hashKey);
+      dbg(11,"Frame reqlink #%u ", pinfo->fd->num);
+#endif
+      create_tcaphash_end(&tcaphash_end_key,
+                          p_tcaphash_begincall->context);
+
+    } else { /* Begin not found */
+#ifdef DEBUG_TCAPSRT
+      dbg(12,"BnotFound ");
+#endif
+    } /* begin found */
+  } /* cont found */
+    /* display tcap session, if available */
+  if (gtcap_DisplaySRT && tree &&
+      p_tcaphash_context &&
+      p_tcaphash_context->session_id) {
+    stat_item = proto_tree_add_text(tree, tvb, 0, -1, "Stat");
+    PROTO_ITEM_SET_GENERATED(stat_item);
+    stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
+    pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
+    PROTO_ITEM_SET_GENERATED(pi);
+  }
+
+  return p_tcaphash_context;
+}
+
+/*
+* Try to find a TCAP session according to the destination Identifier given in the TC_END/TC_ABORT
+* If nothing is found,
+* - either it is a session in opening state,
+* - or the session is closed/aborted by the remote, ( so we switch the src and dst tid )
+* so try to find a tcap session registered with a TC_BEGIN "key",
+* matching the destination Id of the TC_END
+* Then associate the TC_CONT "key" to the TCAP context
+* and display the available info for the TCAP context
+*/
+
+static struct tcaphash_context_t *
+tcaphash_end_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+                     struct tcapsrt_info_t *p_tcapsrt_info)
+{
+  struct tcaphash_context_t *p_tcaphash_context=NULL;
+
+  struct tcaphash_end_info_key_t tcaphash_end_key;
+  struct tcaphash_endcall_t *p_tcaphash_endcall=NULL;
+
+  struct tcaphash_begin_info_key_t tcaphash_begin_key;
+  struct tcaphash_begincall_t *p_tcaphash_begincall=NULL;
+  proto_item *pi;
+  nstime_t delta;
+  proto_item *stat_item=NULL;
+  proto_tree *stat_tree=NULL;
+
+#ifdef DEBUG_TCAPSRT
+  dbg(10,"\n Hend #%u ", pinfo->fd->num);
+#endif
+  /* look only for matching request, if matching conversation is available. */
+  tcaphash_end_key.tid = p_tcapsrt_info->dst_tid;
+  if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
+  {
+    /* We have MTP3 PCs (so we can safely do this cast) */
+    tcaphash_end_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
+    tcaphash_end_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
+  } else {
+    /* Don't have MTP3 PCs (maybe we're over SUA?) */
+    tcaphash_end_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
+    tcaphash_end_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
+  }
+  tcaphash_end_key.hashKey=tcaphash_end_calchash(&tcaphash_end_key);
+
+#ifdef DEBUG_TCAPSRT
+  dbg(11,"Ekey %lx ",tcaphash_end_key.hashKey);
+  dbg(11,"PC %s %s ",ep_address_to_str(&pinfo->src), ep_address_to_str(&pinfo->dst));
+  dbg(51,"Tid %lx ",tcaphash_end_key.tid);
+#endif
+  p_tcaphash_endcall = find_tcaphash_end(&tcaphash_end_key, pinfo,TRUE);
+
+  if(!p_tcaphash_endcall) {
+#ifdef DEBUG_TCAPSRT
+    dbg(12,"EnotFound ");
+#endif
+    tcaphash_begin_key.tid = p_tcapsrt_info->dst_tid;
+    if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
+    {
+      /* We have MTP3 PCs (so we can safely do this cast) */
+      tcaphash_begin_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
+      tcaphash_begin_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
+    } else {
+      /* Don't have MTP3 PCs (maybe we're over SUA?) */
+      tcaphash_begin_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
+      tcaphash_begin_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
+    }
+    tcaphash_begin_key.hashKey=tcaphash_begin_calchash(&tcaphash_begin_key);
+
+#ifdef DEBUG_TCAPSRT
+    dbg(11,"Bkey %lx ", tcaphash_begin_key.hashKey);
+    dbg(51,"PC %s %s ",ep_address_to_str(&pinfo->src), ep_address_to_str(&pinfo->dst));
+    dbg(51,"Tid %lx ",tcaphash_begin_key.tid);
+#endif
+    p_tcaphash_begincall = find_tcaphash_begin(&tcaphash_begin_key, pinfo,FALSE);
+    if(!p_tcaphash_begincall) {
+#ifdef DEBUG_TCAPSRT
+      dbg(12,"BnotFound ");
+#endif
+    }
+  }
+  if (p_tcaphash_endcall) {
+    /* Use the TC_BEGIN Destination reference */
+    p_tcaphash_context=p_tcaphash_endcall->context;
+  } else if (p_tcaphash_begincall) {
+    /* Use the TC_BEGIN Source reference */
+    p_tcaphash_context=p_tcaphash_begincall->context;
+  }
+
+  if (p_tcaphash_context) {
+
+#ifdef DEBUG_TCAPSRT
+    dbg(12,"Found, req=%d ",p_tcaphash_context->first_frame);
+#endif
+    if (gtcap_DisplaySRT && tree) {
+      stat_item = proto_tree_add_text(tree, tvb, 0, -1, "Stat");
+      PROTO_ITEM_SET_GENERATED(stat_item);
+      stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
+
+      pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
+      PROTO_ITEM_SET_GENERATED(pi);
+    }
+
+#ifdef DEBUG_TCAPSRT
+    dbg(20,"Display framereqlink %d ",p_tcaphash_context->first_frame);
+#endif
+    /* Indicate the frame to which this is a reply. */
+    if (gtcap_DisplaySRT && stat_tree) {
+      pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_EndSession, tvb, 0, 0,
+                                     p_tcaphash_context->first_frame,
+                                     "Begin of session in frame %u",
+                                     p_tcaphash_context->first_frame);
+      PROTO_ITEM_SET_GENERATED(pi);
+      /* Calculate Service Response Time */
+      nstime_delta(&delta, &pinfo->fd->abs_ts, &p_tcaphash_context->begin_time);
+
+      /* display Service Response Time and make it filterable */
+      pi = proto_tree_add_time(stat_tree, hf_tcapsrt_SessionTime, tvb, 0, 0, &delta);
+      PROTO_ITEM_SET_GENERATED(pi);
+    }
+    /* Close the context and remove it (if needed) */
+    tcapsrt_close(p_tcaphash_context,pinfo);
+
+  } else {/* context present */
+#ifdef DEBUG_TCAPSRT
+    dbg(12,"Context notFound ");
+#endif
+  }
+  return p_tcaphash_context;
+}
 
+/*
+ * ANSI PART
+ * Create the record identifiying the TCAP transaction
+ * When the identifier for the transaction is reused, check
+ * the following criteria before to append a new record:
+ * - a timeout corresponding to a message retransmission is detected,
+ * - a message hast been lost
+ * - or the previous transaction has been  be closed
+ */
+static struct tcaphash_context_t *
+tcaphash_ansi_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+                      struct tcapsrt_info_t *p_tcapsrt_info)
+{
+  struct tcaphash_context_t *p_tcaphash_context=NULL;
+  struct tcaphash_context_key_t tcaphash_context_key;
+  struct tcaphash_ansicall_t *p_tcaphash_ansicall, *p_new_tcaphash_ansicall;
+  struct tcaphash_ansi_info_key_t tcaphash_ansi_key;
+  proto_item *pi;
+  nstime_t delta;
+  gboolean isResponse=FALSE;
+  proto_tree * stat_tree=NULL;
+  proto_item * stat_item=NULL;
+
+  /* prepare the key data */
+  tcaphash_ansi_key.tid = p_tcapsrt_info->src_tid;
+  if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
+  {
+    /* We have MTP3 PCs (so we can safely do this cast) */
+    tcaphash_ansi_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
+    tcaphash_ansi_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
+  } else {
+    /* Don't have MTP3 PCs (maybe we're over SUA?) */
+    tcaphash_ansi_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
+    tcaphash_ansi_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
+  }
+  tcaphash_ansi_key.hashKey=tcaphash_ansi_calchash(&tcaphash_ansi_key);
+
+  /* look up the request */
+#ifdef DEBUG_TCAPSRT
+  dbg(10,"\n Hansi #%u ", pinfo->fd->num);
+  dbg(11,"key %lx ",tcaphash_ansi_key.hashKey);
+  dbg(51,"PC %s %s ",ep_address_to_str(&pinfo->src), ep_address_to_str(&pinfo->dst));
+  dbg(51,"Tid %lx ",tcaphash_ansi_key.tid);
+#endif
+  p_tcaphash_ansicall = (struct tcaphash_ansicall_t *)
+    g_hash_table_lookup(tcaphash_ansi, &tcaphash_ansi_key);
+
+  if (p_tcaphash_ansicall) {
+    /* Walk through list of transaction with identical keys */
+    do {
+      /* Check if the request with this reqSeqNum has been seen */
+      if (pinfo->fd->num == p_tcaphash_ansicall->context->first_frame) {
+       /* We have seen this request before -> do nothing */
+#ifdef DEBUG_TCAPSRT
+       dbg(22,"Request already seen ");
+#endif
+       isResponse=FALSE;
+       p_tcaphash_context=p_tcaphash_ansicall->context;
+       break;
+      }
+
+      /* Check if the reponse with this reqSeqNum has been seen */
+      if (pinfo->fd->num == p_tcaphash_ansicall->context->last_frame) {
+       /* We have seen this response before -> do nothing */
+#ifdef DEBUG_TCAPSRT
+       dbg(22,"Response already seen ");
+#endif
+       isResponse=TRUE;
+       p_tcaphash_context=p_tcaphash_ansicall->context;
+       break;
+      }
+
+      /* Check for the first Request without Response
+       received before this frame */
+      if ( pinfo->fd->num > p_tcaphash_ansicall->context->first_frame &&
+          p_tcaphash_ansicall->context->last_frame==0 ) {
+       /* Take it, and update the context */
+
+#ifdef DEBUG_TCAPSRT
+       dbg(12,"Update key %lx ",tcaphash_ansi_key.hashKey);
+#endif
+       p_tcaphash_ansicall->context->last_frame = pinfo->fd->num;
+       p_tcaphash_ansicall->context->responded = TRUE;
+       p_tcaphash_ansicall->context->closed = TRUE;
+       p_tcaphash_context=p_tcaphash_ansicall->context;
+       isResponse=TRUE;
+
+       if (gtcap_DisplaySRT && tree) {
+         stat_item = proto_tree_add_text(tree, tvb, 0, -1, "Stat");
+         PROTO_ITEM_SET_GENERATED(stat_item);
+         stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
+
+         pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
+         PROTO_ITEM_SET_GENERATED(pi);
+
+#ifdef DEBUG_TCAPSRT
+         dbg(20,"Display framereqlink %d ",p_tcaphash_context->first_frame);
+#endif
+         /* Indicate the frame to which this is a reply. */
+         pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_EndSession, tvb, 0, 0,
+                                         p_tcaphash_context->first_frame,
+                                         "Begin of session in frame %u",
+                                         p_tcaphash_context->first_frame);
+         PROTO_ITEM_SET_GENERATED(pi);
+         /* Calculate Service Response Time */
+         nstime_delta(&delta, &pinfo->fd->abs_ts, &p_tcaphash_context->begin_time);
+
+         /* display Service Response Time and make it filterable */
+         pi = proto_tree_add_time(stat_tree, hf_tcapsrt_SessionTime, tvb, 0, 0, &delta);
+         PROTO_ITEM_SET_GENERATED(pi);
+       }
+       break;
+      } /* Lastframe=0, so take it */
+
+
+      /* If the last record for Tcap transaction with identifier has been reached */
+      if (!p_tcaphash_ansicall->next_ansicall) {
+       /* check if we have to create a new record or not */
+       /* if last request has been responded (response number in known)
+          and this request appears after last response (has bigger frame number)
+          and last request occurred after the timeout for repetition,
+          or
+          if last request hasn't been responded (so number unknown)
+          and this request appears after last request (has bigger frame number)
+          and this request occurred after the timeout for message lost */
+       if ( ( p_tcaphash_ansicall->context->last_frame != 0
+              && pinfo->fd->num > p_tcaphash_ansicall->context->first_frame
+              && (guint) pinfo->fd->abs_ts.secs > (guint)(p_tcaphash_ansicall->context->begin_time.secs + gtcap_RepetitionTimeout)
+              ) ||
+            ( p_tcaphash_ansicall->context->last_frame == 0
+              && pinfo->fd->num > p_tcaphash_ansicall->context->first_frame
+              && (guint)pinfo->fd->abs_ts.secs > (guint)(p_tcaphash_ansicall->context->begin_time.secs + gtcap_LostTimeout)
+              )
+            )
+         {
+           /* we decide that we have a new request */
+           /* Append new record to the list */
+#ifdef DEBUG_TCAPSRT
+           dbg(12,"(timeout) Append key %lx ",tcaphash_ansi_key.hashKey);
+           dbg(12,"Frame %u rsp %u ",pinfo->fd->num,p_tcaphash_ansicall->context->last_frame );
+#endif
+           tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
+           p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
+           p_new_tcaphash_ansicall = append_tcaphash_ansicall(p_tcaphash_ansicall,
+                                                                p_tcaphash_context,
+                                                                pinfo);
+
+#ifdef DEBUG_TCAPSRT
+           dbg(12,"Update key %lx ",tcaphash_ansi_key.hashKey);
+#endif
+           update_tcaphash_ansicall(p_new_tcaphash_ansicall, pinfo);
+           p_tcaphash_ansicall=p_new_tcaphash_ansicall;
+         } else {
+
+         /* If the Tid is reused for a closed Transaction */
+         if ( p_tcaphash_ansicall->context->closed) {
+#ifdef DEBUG_TCAPSRT
+           dbg(12,"(closed) Append key %lu ",tcaphash_ansi_key.hashKey);
+           dbg(12,"Frame %u rsp %u ",pinfo->fd->num,p_tcaphash_ansicall->context->last_frame );
+#endif
+           tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
+           p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
+           p_new_tcaphash_ansicall = append_tcaphash_ansicall(p_tcaphash_ansicall,
+                                                                p_tcaphash_context,
+                                                                pinfo);
+
+#ifdef DEBUG_TCAPSRT
+           dbg(12,"Update key %lu ",tcaphash_ansi_key.hashKey);
+#endif
+           update_tcaphash_ansicall(p_new_tcaphash_ansicall, pinfo);
+           p_tcaphash_ansicall=p_new_tcaphash_ansicall;
+
+         } else {
+           /* the Tid is reused for an opened Transaction */
+           /* so, this is the reply to the request of our context */
+           p_tcaphash_context=p_tcaphash_ansicall->context;
+#ifdef DEBUG_TCAPSRT
+           dbg(12,"Found, req=%d ",p_tcaphash_context->first_frame);
+#endif
+
+           if (gtcap_DisplaySRT && tree) {
+             stat_item = proto_tree_add_text(tree, tvb, 0, -1, "Stat");
+             PROTO_ITEM_SET_GENERATED(stat_item);
+             stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
+
+             pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
+             PROTO_ITEM_SET_GENERATED(pi);
+
+#ifdef DEBUG_TCAPSRT
+             dbg(20,"Display framereqlink %d ",p_tcaphash_context->first_frame);
+#endif
+             /* Indicate the frame to which this is a reply. */
+             pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_EndSession, tvb, 0, 0,
+                                             p_tcaphash_context->first_frame,
+                                             "Begin of session in frame %u",
+                                             p_tcaphash_context->first_frame);
+             PROTO_ITEM_SET_GENERATED(pi);
+             /* Calculate Service Response Time */
+             nstime_delta(&delta, &pinfo->fd->abs_ts, &p_tcaphash_context->begin_time);
+
+             /* display Service Response Time and make it filterable */
+             pi = proto_tree_add_time(stat_tree, hf_tcapsrt_SessionTime, tvb, 0, 0, &delta);
+             PROTO_ITEM_SET_GENERATED(pi);
+           }
+           p_tcaphash_context=p_tcaphash_ansicall->context;
+         } /* test with Timeout */
+       } /* closed */
+       break;
+      } /* Next call is NULL */
+      p_tcaphash_ansicall = p_tcaphash_ansicall->next_ansicall;
+    } while (p_tcaphash_ansicall != NULL );
+    /*
+     * New TCAP context
+     */
+  } else { /* p_tcaphash_ansicall has not been found */
+#ifdef DEBUG_TCAPSRT
+    dbg(10,"New key %lx ",tcaphash_ansi_key.hashKey);
+#endif
+
+    tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
+    p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
+    p_tcaphash_ansicall = new_tcaphash_ansi(&tcaphash_ansi_key, p_tcaphash_context);
 
+#ifdef DEBUG_TCAPSRT
+    dbg(11,"Update key %lx ",tcaphash_ansi_key.hashKey);
+    dbg(11,"Frame reqlink #%u ", pinfo->fd->num);
+#endif
+    update_tcaphash_ansicall(p_tcaphash_ansicall, pinfo);
+  }
+
+  /* display tcap session, if available */
+  if ( gtcap_DisplaySRT && tree &&
+       p_tcaphash_context &&
+       p_tcaphash_context->session_id) {
+    stat_item = proto_tree_add_text(tree, tvb, 0, -1, "Stat");
+    PROTO_ITEM_SET_GENERATED(stat_item);
+    stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
+    pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
+    PROTO_ITEM_SET_GENERATED(pi);
+  }
+
+
+  /* add link to response frame, if available */
+  if( gtcap_DisplaySRT && stat_tree &&
+      p_tcaphash_ansicall->context->last_frame != 0){
+    if (!isResponse) { /* Request */
+#ifdef DEBUG_TCAPSRT
+      dbg(20,"Display_frameRsplink %d ",p_tcaphash_ansicall->context->last_frame);
+#endif
+      pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_BeginSession, tvb, 0, 0,
+                                     p_tcaphash_ansicall->context->last_frame,
+                                     "End of session in frame %u",
+                                     p_tcaphash_ansicall->context->last_frame);
+      PROTO_ITEM_SET_GENERATED(pi);
+    } else { /* Response */
+#ifdef DEBUG_TCAPSRT
+      dbg(20,"Display framereqlink %d ",p_tcaphash_context->first_frame);
+#endif
+      /* Indicate the frame to which this is a reply. */
+      if (gtcap_DisplaySRT) {
+       pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_EndSession, tvb, 0, 0,
+                                       p_tcaphash_context->first_frame,
+                                       "Begin of session in frame %u",
+                                       p_tcaphash_context->first_frame);
+       PROTO_ITEM_SET_GENERATED(pi);
+       /* Calculate Service Response Time */
+       nstime_delta(&delta, &pinfo->fd->abs_ts, &p_tcaphash_context->begin_time);
+
+       /* display Service Response Time and make it filterable */
+       pi = proto_tree_add_time(stat_tree, hf_tcapsrt_SessionTime, tvb, 0, 0, &delta);
+       PROTO_ITEM_SET_GENERATED(pi);
+      }
+    } /* Request or Response */
+  }
+  return p_tcaphash_context;
+}
+
+/*
+ * Service Response Time analyze
+ * Called just after dissector call
+ * Associate a TCAP context to a tcap session and display session related infomations
+ * like the first frame, the last, the session duration,
+ * and a uniq session identifier for the filtering
+ *
+ * For ETSI tcap, the TCAP context can be reached through three keys
+ * - a key (BEGIN) identifying the session according to the tcap source identifier
+ * - a key (CONT) identifying the established session (src_id and dst_id)
+ * - a key (END) identifying the session according to the tcap destination identifier
+ *
+ * For ANSI tcap, the TCAP context is reached through a uniq key
+ * - a key (ANSI) identifying the session according to the tcap identifier
+*/
+struct tcaphash_context_t *
+tcapsrt_call_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+                     struct tcapsrt_info_t *p_tcapsrt_info)
+{
+  struct tcaphash_context_t *tcap_context=NULL;
+
+  /* if this packet isn't loaded because of a read filter, don't output anything */
+  if(pinfo == NULL || pinfo->fd->num == 0) {
+    return NULL;
+  }
+
+  switch (p_tcapsrt_info->ope) {
+
+  case TC_BEGIN:
+#ifdef DEBUG_TCAPSRT
+    dbg(1,"\nTC_BEGIN ");
+#endif
+    tcap_context=tcaphash_begin_matching(tvb, pinfo, tree, p_tcapsrt_info);
+    break;
+
+  case TC_CONT:
+#ifdef DEBUG_TCAPSRT
+    dbg(1,"\nTC_CONT ");
+#endif
+    tcap_context=tcaphash_cont_matching(tvb, pinfo, tree, p_tcapsrt_info);
+    break;
+
+  case TC_ABORT:
+#ifdef DEBUG_TCAPSRT
+    dbg(1,"\nTC_ABORT ");
+#endif
+    tcap_context=tcaphash_end_matching(tvb, pinfo, tree, p_tcapsrt_info);
+    break;
+
+  case TC_END:
+#ifdef DEBUG_TCAPSRT
+    dbg(1,"\nTC_END ");
+#endif
+    tcap_context=tcaphash_end_matching(tvb, pinfo, tree, p_tcapsrt_info);
+    break;
+
+  case TC_ANSI_ALL:
+  case TC_ANSI_ABORT:
+#ifdef DEBUG_TCAPSRT
+    dbg(1,"\nTC_ANSI ");
+#endif
+    tcap_context=tcaphash_ansi_matching(tvb, pinfo, tree, p_tcapsrt_info);
+    break;
+
+  default:
+#ifdef DEBUG_TCAPSRT
+    dbg(1,"\nUnknown %d ", p_tcapsrt_info->ope);
+#endif
+    break;
+  } /* switch tcapop */
+#ifdef DEBUG_TCAPSRT
+  if (tcap_context)
+    dbg(1,"session %d ", tcap_context->session_id);
+#endif
+  return tcap_context;
+}
+
+/*
+ * Initialize the Message Info used by the main dissector
+ * Data are linked to a TCAP transaction
+ */
+struct tcapsrt_info_t *
+tcapsrt_razinfo(void)
+{
+  struct tcapsrt_info_t *p_tcapsrt_info ;
+
+  /* Global buffer for packet extraction */
+  tcapsrt_global_current++;
+  if(tcapsrt_global_current==MAX_TCAP_INSTANCE){
+    tcapsrt_global_current=0;
+  }
+
+  p_tcapsrt_info=&tcapsrt_global_info[tcapsrt_global_current];
+  memset(p_tcapsrt_info,0,sizeof(struct tcapsrt_info_t));
+
+  return p_tcapsrt_info;
+}
+
+void
+tcapsrt_close(struct tcaphash_context_t *p_tcaphash_context,
+             packet_info *pinfo)
+{
+#ifdef DEBUG_TCAPSRT
+  dbg(60,"Force close ");
+#endif
+  if (p_tcaphash_context) {
+    p_tcaphash_context->responded=TRUE;
+    p_tcaphash_context->last_frame = pinfo->fd->num;
+    p_tcaphash_context->end_time = pinfo->fd->abs_ts;
+    p_tcaphash_context->closed=TRUE;
+
+    /* If the endkey is present */
+    if (p_tcaphash_context->endcall
+       && !gtcap_PersistentSRT) {
+      if (p_tcaphash_context->endcall->next_endcall) {
+       if (p_tcaphash_context->endcall->previous_endcall ) {
+#ifdef DEBUG_TCAPSRT
+         dbg(20,"deplace Ehash ");
+#endif
+         p_tcaphash_context->endcall->previous_endcall->next_endcall
+           = p_tcaphash_context->endcall->next_endcall;
+         p_tcaphash_context->endcall->next_endcall->previous_endcall
+           = p_tcaphash_context->endcall->previous_endcall;
+         g_hash_table_remove(tcaphash_end, p_tcaphash_context->endcall->endkey);
+#ifdef MEM_TCAPSRT
+         g_free(p_tcaphash_context->endcall);
+#endif
+       } else {
+         /* cannot remove the father */
+#ifdef DEBUG_TCAPSRT
+         dbg(20,"father Ehash ");
+#endif
+       } /* no previous link, so father */
+      } else if (!gtcap_PersistentSRT) {
+#ifdef DEBUG_TCAPSRT
+       dbg(20,"remove Ehash ");
+#endif
+       g_hash_table_remove(tcaphash_end, p_tcaphash_context->endcall->endkey);
+#ifdef MEM_TCAPSRT
+       g_free(p_tcaphash_context->endcall->endkey);
+       g_free(p_tcaphash_context->endcall);
+#endif
+
+      } /* endcall without chained string */
+    } /* no endcall */
+
+
+    /* If the contkey is present */
+    if (p_tcaphash_context->contcall
+       && !gtcap_PersistentSRT) {
+      if (p_tcaphash_context->contcall->next_contcall) {
+       if (p_tcaphash_context->contcall->previous_contcall ) {
+#ifdef DEBUG_TCAPSRT
+         dbg(20,"deplace Chash ");
+#endif
+         p_tcaphash_context->contcall->previous_contcall->next_contcall
+           = p_tcaphash_context->contcall->next_contcall;
+         p_tcaphash_context->contcall->next_contcall->previous_contcall
+           = p_tcaphash_context->contcall->previous_contcall;
+         g_hash_table_remove(tcaphash_cont, p_tcaphash_context->contcall->contkey);
+#ifdef MEM_TCAPSRT
+         g_free(p_tcaphash_context->contcall);
+#endif
+       } else {
+         /* cannot remove the father */
+#ifdef DEBUG_TCAPSRT
+         dbg(20,"father Chash ");
+#endif
+       } /* no previous link, so father */
+      } else if (!gtcap_PersistentSRT) {
+#ifdef DEBUG_TCAPSRT
+       dbg(20,"remove Chash ");
+#endif
+       g_hash_table_remove(tcaphash_cont, p_tcaphash_context->contcall->contkey);
+#ifdef MEM_TCAPSRT
+       g_free(p_tcaphash_context->contcall->contkey);
+       g_free(p_tcaphash_context->contcall);
+#endif
+      } /* contcall without chained string */
+    } /* no contcall */
+
+
+    /* If the beginkey is present */
+    if (p_tcaphash_context->begincall
+       && !gtcap_PersistentSRT) {
+      if (p_tcaphash_context->begincall->next_begincall) {
+       if (p_tcaphash_context->begincall->previous_begincall ) {
+#ifdef DEBUG_TCAPSRT
+         dbg(20,"deplace Bhash ");
+#endif
+         p_tcaphash_context->begincall->previous_begincall->next_begincall
+           = p_tcaphash_context->begincall->next_begincall;
+         p_tcaphash_context->begincall->next_begincall->previous_begincall
+           = p_tcaphash_context->begincall->previous_begincall;
+         g_hash_table_remove(tcaphash_begin, p_tcaphash_context->begincall->beginkey);
+#ifdef MEM_TCAPSRT
+         g_free(p_tcaphash_context->begincall);
+#endif
+       } else {
+         /* cannot remove the father */
+#ifdef DEBUG_TCAPSRT
+         dbg(20,"father Bhash ");
+#endif
+       }
+      } else  if (!gtcap_PersistentSRT) {
+#ifdef DEBUG_TCAPSRT
+       dbg(20,"remove Bhash ");
+#endif
+       g_hash_table_remove(tcaphash_begin, p_tcaphash_context->begincall->beginkey);
+#ifdef MEM_TCAPSRT
+       g_free(p_tcaphash_context->begincall->beginkey);
+       g_free(p_tcaphash_context->begincall);
+#endif
+      } /* begincall without chained string */
+    } /* no begincall */
+
+    /* If the ansikey is present */
+    if (p_tcaphash_context->ansicall
+       && !gtcap_PersistentSRT) {
+      if (p_tcaphash_context->ansicall->next_ansicall) {
+       if (p_tcaphash_context->ansicall->previous_ansicall ) {
+#ifdef DEBUG_TCAPSRT
+         dbg(20,"deplace Ahash ");
+#endif
+         p_tcaphash_context->ansicall->previous_ansicall->next_ansicall
+           = p_tcaphash_context->ansicall->next_ansicall;
+         p_tcaphash_context->ansicall->next_ansicall->previous_ansicall
+           = p_tcaphash_context->ansicall->previous_ansicall;
+         g_hash_table_remove(tcaphash_ansi, p_tcaphash_context->ansicall->ansikey);
+#ifdef MEM_TCAPSRT
+         g_free(p_tcaphash_context->ansicall);
+#endif
+       } else {
+         /* cannot remove the father */
+#ifdef DEBUG_TCAPSRT
+         dbg(20,"father Ahash ");
+#endif
+       }
+      } else  if (!gtcap_PersistentSRT) {
+#ifdef DEBUG_TCAPSRT
+       dbg(20,"remove Ahash ");
+#endif
+       g_hash_table_remove(tcaphash_ansi, p_tcaphash_context->ansicall->ansikey);
+#ifdef MEM_TCAPSRT
+       g_free(p_tcaphash_context->ansicall->ansikey);
+       g_free(p_tcaphash_context->ansicall);
+#endif
+      } /* ansicall without chained string */
+    } /* no ansicall */
+
+    if (!gtcap_PersistentSRT) {
+#ifdef DEBUG_TCAPSRT
+      dbg(20,"remove context ");
+#endif
+      g_hash_table_remove(tcaphash_context, p_tcaphash_context->key);
+#ifdef MEM_TCAPSRT
+      g_free(p_tcaphash_context->key);
+      g_free(p_tcaphash_context);
+#endif
+    }
+  } else { /* no context */
+#ifdef DEBUG_TCAPSRT
+    dbg(20,"No context to remove ");
+#endif
+  }
+}
 
 const value_string tcap_component_type_str[] = {
     { TCAP_COMP_INVOKE,                "Invoke" },
index 8d057c3713ef57d21bb01cdacb322f1f590bc2d7..fe0ab464cf5120843251761f8ff1b3dff209b53a 100644 (file)
@@ -70,6 +70,147 @@ struct tcap_private_t {
   gchar *TransactionID_str;
 };
 
+/** @file
+ * lists and hash tables used in wireshark's tcap dissector
+ * for calculation of delays in tcap-calls
+ */
+
+#define LENGTH_OID 23
+struct tcaphash_context_t {
+  struct tcaphash_context_key_t * key;
+  guint32 session_id;
+  guint32 first_frame;
+  guint32 last_frame;
+  nstime_t begin_time; /**< time of arrival of TC_BEGIN */
+  nstime_t end_time;   /**< time of closing message */
+  gboolean responded;  /**< true, if request has been responded */
+  gboolean closed;
+  gboolean upper_dissector;
+  gboolean oid_present;
+  gchar oid[LENGTH_OID+1];
+  gboolean subdissector_present;
+  dissector_handle_t subdissector_handle;
+  void (* callback) (tvbuff_t *,packet_info *, proto_tree *, struct tcaphash_context_t *);
+  struct tcaphash_begincall_t * begincall;
+  struct tcaphash_contcall_t * contcall;
+  struct tcaphash_endcall_t * endcall;
+  struct tcaphash_ansicall_t * ansicall;
+};
+
+struct tcaphash_begincall_t {
+  struct tcaphash_begin_info_key_t * beginkey;
+  struct tcaphash_context_t * context;
+  gboolean father;
+  struct tcaphash_begincall_t * next_begincall;
+  struct tcaphash_begincall_t * previous_begincall;
+};
+
+struct tcaphash_contcall_t {
+  struct tcaphash_cont_info_key_t * contkey;
+  struct tcaphash_context_t * context;
+  gboolean father;
+  struct tcaphash_contcall_t * next_contcall;
+  struct tcaphash_contcall_t * previous_contcall;
+};
+
+struct tcaphash_endcall_t {
+  struct tcaphash_end_info_key_t * endkey;
+  struct tcaphash_context_t * context;
+  gboolean father;
+  struct tcaphash_endcall_t * next_endcall;
+  struct tcaphash_endcall_t * previous_endcall;
+};
+
+struct tcaphash_ansicall_t {
+  struct tcaphash_ansi_info_key_t * ansikey;
+  struct tcaphash_context_t * context;
+  gboolean father;
+  struct tcaphash_ansicall_t * next_ansicall;
+  struct tcaphash_ansicall_t * previous_ansicall;
+};
+
+/** The Key for the hash table is the TCAP origine transaction identifier
+   of the TC_BEGIN containing the InitialDP */
+
+struct tcaphash_context_key_t {
+  guint32 session_id;
+};
+
+struct tcaphash_begin_info_key_t {
+  guint32 hashKey;
+  guint32 tid;
+  guint32 opc_hash;
+  guint32 dpc_hash;
+};
+
+struct tcaphash_cont_info_key_t {
+  guint32 hashKey;
+  guint32 src_tid;
+  guint32 dst_tid;
+  guint32 opc_hash;
+  guint32 dpc_hash;
+};
+
+struct tcaphash_end_info_key_t {
+  guint32 hashKey;
+  guint32 tid;
+  guint32 opc_hash;
+  guint32 dpc_hash;
+};
+
+struct tcaphash_ansi_info_key_t {
+  guint32 hashKey;
+  guint32 tid;
+  guint32 opc_hash;
+  guint32 dpc_hash;
+};
+
+
+/** List of infos to store for the analyse */
+struct tcapsrt_info_t {
+  guint32 tcap_session_id;
+  guint32 src_tid;
+  guint32 dst_tid;
+  guint8 ope;
+};
+
+/**
+ * Routine called when the TAP is initialized.
+ * so hash table are (re)created
+ */
+void tcapsrt_init_routine(void);
+
+/**
+ * Initialize the Message Info used by the main dissector
+ * Data are linked to a TCAP transaction
+ */
+struct tcapsrt_info_t * tcapsrt_razinfo(void);
+
+void tcapsrt_close(struct tcaphash_context_t * p_tcaphash_context,
+                  packet_info * pinfo _U_);
+
+/**
+ * Service Response Time analyze
+ * Called just after dissector call
+ * Associate a TCAP context to a tcap session and display session related infomations
+ * like the first frame, the last, the session duration,
+ * and a uniq session identifier for the filtering
+ *
+ * For ETSI tcap, the TCAP context can be reached through three keys
+ * - a key (BEGIN) identifying the session according to the tcap source identifier
+ * - a key (CONT) identifying the established session (src_id and dst_id)
+ * - a key (END) identifying the session according to the tcap destination identifier
+ *
+ * For ANSI tcap, the TCAP context is reached through a uniq key
+ * - a key (ANSI) identifying the session according to the tcap identifier
+*/
+struct tcaphash_context_t * tcapsrt_call_matching(tvbuff_t *tvb,
+                                                 packet_info * pinfo _U_,
+                                                 proto_tree *tree,
+                                                 struct tcapsrt_info_t * p_tcap_info);
+
+WS_DLL_PUBLIC gboolean gtcap_StatSRT;
+
 extern gint tcap_standard;
 
 extern const value_string tcap_component_type_str[];
index caaa97bf0fd1e5957397b133199185537cc96511..66a7cf4e4a885d162f2c7c9b68242c3a72c63a91 100644 (file)
@@ -1476,7 +1476,6 @@ set(LIBWIRESHARK_FILES
        app_mem_usage.c
        asn1.c
        atalk-utils.c
-       camel-persistentdata.c
        charsets.c
        circuit.c
        column.c
@@ -1534,7 +1533,6 @@ set(LIBWIRESHARK_FILES
        stream.c
        t35.c
        tap.c
-       tcap-persistentdata.c
        timestamp.c
        timestats.c
        tfs.c
index 69b7f6d811ebac36104c3793f9c8ca7f82f46e2c..5505e1ac9bf099953d9c11207b8a8996c7b48361 100644 (file)
@@ -32,7 +32,6 @@ LIBWIRESHARK_SRC =            \
        app_mem_usage.c         \
        asn1.c                  \
        atalk-utils.c           \
-       camel-persistentdata.c  \
        charsets.c              \
        circuit.c               \
        column.c                \
@@ -89,7 +88,6 @@ LIBWIRESHARK_SRC =            \
        stream.c                \
        t35.c                   \
        tap.c                   \
-       tcap-persistentdata.c   \
        timestamp.c             \
        timestats.c             \
        tfs.c                   \
@@ -158,7 +156,6 @@ LIBWIRESHARK_INCLUDES =             \
        atalk-utils.h           \
        ax25_pids.h             \
        bridged_pids.h          \
-       camel-persistentdata.h  \
        charsets.h              \
        chdlctypes.h            \
        circuit.h               \
@@ -246,7 +243,6 @@ LIBWIRESHARK_INCLUDES =             \
        t35.h                   \
        tap.h                   \
        tap-voip.h              \
-       tcap-persistentdata.h   \
        timestamp.h             \
        timestats.h             \
        tfs.h                   \
diff --git a/epan/camel-persistentdata.c b/epan/camel-persistentdata.c
deleted file mode 100644 (file)
index 7f269a4..0000000
+++ /dev/null
@@ -1,798 +0,0 @@
-/*
- * 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
- *
- * $Id$
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include "config.h"
-
-#include <glib.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <epan/emem.h>
-#include <epan/packet.h>
-#include <epan/tap.h>
-#include <epan/asn1.h>
-#include <epan/camel-persistentdata.h>
-#include <epan/dissectors/packet-tcap.h>
-#include <epan/dissectors/packet-mtp3.h>
-
-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}
-};
-
-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);
-static struct camelsrt_call_t *new_camelsrt_call(struct camelsrt_call_info_key_t *p_camelsrt_call_key);
-
-static void update_camelsrt_call(struct camelsrt_call_t *p_camelsrt_call,
-                                packet_info *pinfo, guint msg_category);
-
-static void camelsrt_begin_call_matching(packet_info *pinfo,
-                                        struct camelsrt_info_t *p_camelsrt_info);
-
-static void camelsrt_request_call_matching(tvbuff_t *tvb, packet_info *pinfo,
-                                          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,
-                                         proto_tree *tree,
-                                         struct camelsrt_info_t *p_camelsrt_info,
-                                         guint srt_type);
-
-static void camelsrt_close_call_matching(packet_info *pinfo,
-                                        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, 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 guint debug_level = 99;
-
-static void dbg(guint 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)
-{
-  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);
-
-#ifdef DEBUG_CAMELSRT
-  if(p_camelsrt_call) {
-    dbg(10,"D%d ", p_camelsrt_call->session_id);
-  } else {
-    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)
-{
-  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_new(struct camelsrt_call_info_key_t);
-  p_new_camelsrt_call_key->SessionIdKey = p_camelsrt_call_key->SessionIdKey;
-  p_new_camelsrt_call = se_new(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)
-{
-  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-table for SRT */
-  if (srt_calls != NULL) {
-#ifdef DEBUG_CAMELSRT
-    dbg(16,"Destroy hash ");
-#endif
-    g_hash_table_destroy(srt_calls);
-  }
-
-  /* create new hash-table 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, 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(pinfo, p_camelsrt_info);
-    camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
-                                  CAMELSRT_VOICE_INITIALDP);
-    break;
-  case 60: /*InitialDPSMS*/
-    camelsrt_begin_call_matching(pinfo, p_camelsrt_info);
-    camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
-                                  CAMELSRT_SMS_INITIALDP);
-    break;
-  case 78: /*InitialDPGPRS*/
-    camelsrt_begin_call_matching(pinfo, 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(pinfo, p_camelsrt_info);
-    tcapsrt_close((struct tcaphash_context_t *)p_camelsrt_info->tcap_context, pinfo);
-    break;
-
-  case 80: /*EventReportGPRS*/
-    camelsrt_begin_call_matching(pinfo, 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(pinfo, p_camelsrt_info);
-    break;
-
-  case 66: /*ReleaseSMS*/
-    /* Session has been closed by Network */
-    camelsrt_close_call_matching(pinfo, p_camelsrt_info);
-    tcapsrt_close((struct tcaphash_context_t *)p_camelsrt_info->tcap_context,pinfo);
-    break;
-
-  case 79: /*ReleaseGPRS*/
-    /* Session has been closed by Network */
-    camelsrt_close_call_matching(pinfo, 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 _U_, packet_info *pinfo,
-                      proto_tree *tree _U_,
-                      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(pinfo, 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(packet_info *pinfo,
-                            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 #%u\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);
-    p_camelsrt_call->tcap_context=(struct tcaphash_context_t *)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,
-                              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, *hidden_item;
-
-#ifdef DEBUG_CAMELSRT
-  dbg(10,"\n %s #%u\n", val_to_str_const(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);
-  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 #%u ", 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){
-           hidden_item = proto_tree_add_uint(tree, hf_camelsrt_Duplicate, tvb, 0,0, 77);
-               PROTO_ITEM_SET_HIDDEN(hidden_item);
-         }
-
-       } 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 #%u ", 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_const(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,
-                             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, *hidden_item;
-
-#ifdef DEBUG_CAMELSRT
-  dbg(10,"\n %s #%u\n", val_to_str_const(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);
-  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 %u ",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 #%u 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 ){
-         hidden_item = proto_tree_add_uint(tree, hf_camelsrt_Duplicate, tvb, 0,0, 77);
-         PROTO_ITEM_SET_HIDDEN(hidden_item);
-       }
-      }
-    } /* 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_const(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(packet_info *pinfo,
-                            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 #%u\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);
-  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
deleted file mode 100644 (file)
index 3573485..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * 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
- *
- * $Id$
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef __CAMEL_PERSISTENTDATA_H__
-#define __CAMEL_PERSISTENTDATA_H__
-
-#include <epan/packet.h>
-#include <epan/conversation.h>
-#include <epan/dissectors/packet-camel.h>
-#include <epan/tcap-persistentdata.h>
-#include "ws_symbol_export.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-/** @file
-*/
-#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
-
-WS_DLL_PUBLIC const value_string  camelSRTtype_naming[];
-
-/** 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];
-};
-
-/**
- * Routine called when the TAP is initialized.
- * so hash table are (re)created
- */
-void camelsrt_init_routine(void);
-
-/**
- * Initialize the Message Info used by the main dissector
- * Data are linked to a TCAP transaction
- */
-struct camelsrt_info_t * camelsrt_razinfo(void);
-
-/**
- * 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_camel_info);
-
-WS_DLL_PUBLIC gboolean gcamel_StatSRT;
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* camel-persistentdata.h */
index efe18a3093a507db0f9dd9772f250efed949752c..f35d223d1abe8b4cc4532573fb8b550e3966042f 100644 (file)
@@ -46,7 +46,6 @@
 #include "packet-ber.h"
 #include "packet-tcap.h"
 #include "packet-ansi_tcap.h"
-#include <epan/tcap-persistentdata.h>
 
 #define PNAME  "ANSI Transaction Capabilities Application Part"
 #define PSNAME "ANSI_TCAP"
@@ -126,7 +125,7 @@ static int hf_ansi_tcap_paramSequence = -1;       /* T_paramSequence */
 static int hf_ansi_tcap_paramSet = -1;            /* T_paramSet */
 
 /*--- End of included file: packet-ansi_tcap-hf.c ---*/
-#line 66 "../../asn1/ansi_tcap/packet-ansi_tcap-template.c"
+#line 65 "../../asn1/ansi_tcap/packet-ansi_tcap-template.c"
 
 /* Initialize the subtree pointers */
 static gint ett_tcap = -1;
@@ -172,7 +171,7 @@ static gint ett_ansi_tcap_T_paramSequence = -1;
 static gint ett_ansi_tcap_T_paramSet = -1;
 
 /*--- End of included file: packet-ansi_tcap-ett.c ---*/
-#line 85 "../../asn1/ansi_tcap/packet-ansi_tcap-template.c"
+#line 84 "../../asn1/ansi_tcap/packet-ansi_tcap-template.c"
 
 #define MAX_SSN 254
 
@@ -1395,7 +1394,7 @@ dissect_ansi_tcap_PackageType(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int
 
 
 /*--- End of included file: packet-ansi_tcap-fn.c ---*/
-#line 353 "../../asn1/ansi_tcap/packet-ansi_tcap-template.c"
+#line 352 "../../asn1/ansi_tcap/packet-ansi_tcap-template.c"
 
 
 
@@ -1740,7 +1739,7 @@ proto_register_ansi_tcap(void)
         NULL, HFILL }},
 
 /*--- End of included file: packet-ansi_tcap-hfarr.c ---*/
-#line 489 "../../asn1/ansi_tcap/packet-ansi_tcap-template.c"
+#line 488 "../../asn1/ansi_tcap/packet-ansi_tcap-template.c"
     };
 
 /* Setup protocol subtree array */
@@ -1778,7 +1777,7 @@ proto_register_ansi_tcap(void)
     &ett_ansi_tcap_T_paramSet,
 
 /*--- End of included file: packet-ansi_tcap-ettarr.c ---*/
-#line 500 "../../asn1/ansi_tcap/packet-ansi_tcap-template.c"
+#line 499 "../../asn1/ansi_tcap/packet-ansi_tcap-template.c"
     };
 
     static const enum_val_t ansi_tcap_response_matching_type_values[] = {
index bca870f7fb11ff4d7693f3e60028e336cebd25dd..a08c6b36d0b110c34ea621bce3f2c6ec0a811b8c 100644 (file)
@@ -63,8 +63,6 @@
 #include "packet-gsm_a_common.h"
 #include "packet-inap.h"
 #include "packet-tcap.h"
-#include <epan/camel-persistentdata.h>
-#include <epan/tcap-persistentdata.h>
 
 #define PNAME  "Camel"
 #define PSNAME "CAMEL"
@@ -78,6 +76,14 @@ int camel_tap = -1;
 static guint32 opcode=0;
 static guint32 errorCode=0;
 static guint32 camel_ver = 0;
+
+/* 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
+static int camelsrt_global_current=0;
+static struct camelsrt_info_t camelsrt_global_info[MAX_CAMEL_INSTANCE];
+
 /* ROSE context */
 static rose_ctx_t camel_rose_ctx;
 
@@ -99,20 +105,20 @@ static int hf_camel_CAMEL_SCIBillingChargingCharacteristics = -1;
 static int hf_camel_CAMEL_SCIGPRSBillingChargingCharacteristics = -1;
 static int hf_camel_CAMEL_CallResult = -1;
 
-/* Used by camel-persistentdata.c */
-int hf_camelsrt_SessionId=-1;
-int hf_camelsrt_RequestNumber=-1;
-int hf_camelsrt_Duplicate=-1;
-int hf_camelsrt_RequestFrame=-1;
-int hf_camelsrt_ResponseFrame=-1;
-int hf_camelsrt_DeltaTime=-1;
-int hf_camelsrt_SessionTime=-1;
-int hf_camelsrt_DeltaTime31=-1;
-int hf_camelsrt_DeltaTime75=-1;
-int hf_camelsrt_DeltaTime65=-1;
-int hf_camelsrt_DeltaTime22=-1;
-int hf_camelsrt_DeltaTime35=-1;
-int hf_camelsrt_DeltaTime80=-1;
+/* Used by persistent data */
+static int hf_camelsrt_SessionId=-1;
+static int hf_camelsrt_RequestNumber=-1;
+static int hf_camelsrt_Duplicate=-1;
+static int hf_camelsrt_RequestFrame=-1;
+static int hf_camelsrt_ResponseFrame=-1;
+static int hf_camelsrt_DeltaTime=-1;
+static int hf_camelsrt_SessionTime=-1;
+static int hf_camelsrt_DeltaTime31=-1;
+static int hf_camelsrt_DeltaTime75=-1;
+static int hf_camelsrt_DeltaTime65=-1;
+static int hf_camelsrt_DeltaTime22=-1;
+static int hf_camelsrt_DeltaTime35=-1;
+static int hf_camelsrt_DeltaTime80=-1;
 
 
 /*--- Included file: packet-camel-hf.c ---*/
@@ -603,7 +609,7 @@ static int hf_camel_present = -1;                 /* INTEGER */
 static int hf_camel_InvokeId_present = -1;        /* InvokeId_present */
 
 /*--- End of included file: packet-camel-hf.c ---*/
-#line 110 "../../asn1/camel/packet-camel-template.c"
+#line 116 "../../asn1/camel/packet-camel-template.c"
 
 static struct camelsrt_info_t * gp_camelsrt_info;
 
@@ -615,9 +621,10 @@ static int dissect_camel_CAMEL_AChBillingChargingCharacteristics(gboolean implic
 static int dissect_camel_CAMEL_AChBillingChargingCharacteristicsV2(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
 static int dissect_camel_CAMEL_CallResult(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
 
-gboolean gcamel_HandleSRT=FALSE;
-extern gboolean gcamel_PersistentSRT;
-extern gboolean gcamel_DisplaySRT;
+static gboolean gcamel_HandleSRT=FALSE;
+static gboolean gcamel_PersistentSRT=FALSE;
+static gboolean gcamel_DisplaySRT=FALSE;
+static gboolean gcamel_StatSRT=FALSE;
 
 /* Initialize the subtree pointers */
 static gint ett_camel = -1;
@@ -830,7 +837,7 @@ static gint ett_camel_T_problem = -1;
 static gint ett_camel_InvokeId = -1;
 
 /*--- End of included file: packet-camel-ett.c ---*/
-#line 138 "../../asn1/camel/packet-camel-template.c"
+#line 145 "../../asn1/camel/packet-camel-template.c"
 
 static expert_field ei_camel_unknown_invokeData = EI_INIT;
 static expert_field ei_camel_unknown_returnResultData = EI_INIT;
@@ -851,6 +858,10 @@ static guint8 PDPTypeNumber;
 const char *camel_obj_id = NULL;
 gboolean is_ExtensionField =FALSE;
 
+/* Global hash tables*/
+static GHashTable *srt_calls = NULL;
+static guint32 camelsrt_global_SessionId=1;
+
 static int camel_opcode_type;
 #define CAMEL_OPCODE_INVOKE        1
 #define CAMEL_OPCODE_RETURN_RESULT 2
@@ -865,6 +876,19 @@ static const value_string camel_Component_vals[] = {
   { 0, NULL }
 };
 
+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 0
 static const true_false_string camel_extension_value = {
   "No Extension",
@@ -1158,7 +1182,7 @@ static const value_string camel_ectTreatmentIndicator_values[] = {
 #define noInvokeId                     NULL
 
 /*--- End of included file: packet-camel-val.h ---*/
-#line 281 "../../asn1/camel/packet-camel-template.c"
+#line 305 "../../asn1/camel/packet-camel-template.c"
 
 
 /*--- Included file: packet-camel-table.c ---*/
@@ -1248,7 +1272,29 @@ static const value_string camel_err_code_string_vals[] = {
 
 
 /*--- End of included file: packet-camel-table.c ---*/
-#line 283 "../../asn1/camel/packet-camel-template.c"
+#line 307 "../../asn1/camel/packet-camel-template.c"
+
+/*
+ * DEBUG fonctions
+ */
+
+#undef DEBUG_CAMELSRT
+/* #define DEBUG_CAMELSRT */
+
+#ifdef DEBUG_CAMELSRT
+#include <stdio.h>
+#include <stdarg.h>
+static guint debug_level = 99;
+
+static void dbg(guint level, char *fmt, ...) {
+  va_list ap;
+
+  if (level > debug_level) return;
+  va_start(ap,fmt);
+  vfprintf(stderr, fmt, ap);
+  va_end(ap);
+}
+#endif
 
 static char camel_number_to_char(int number)
 {
@@ -7011,7 +7057,7 @@ static void dissect_CAP_U_ABORT_REASON_PDU(tvbuff_t *tvb _U_, packet_info *pinfo
 
 
 /*--- End of included file: packet-camel-fn.c ---*/
-#line 330 "../../asn1/camel/packet-camel-template.c"
+#line 376 "../../asn1/camel/packet-camel-template.c"
 
 
 /*--- Included file: packet-camel-table2.c ---*/
@@ -7218,7 +7264,663 @@ static int dissect_returnErrorData(proto_tree *tree, tvbuff_t *tvb, int offset,a
 
 
 /*--- End of included file: packet-camel-table2.c ---*/
-#line 332 "../../asn1/camel/packet-camel-template.c"
+#line 378 "../../asn1/camel/packet-camel-template.c"
+
+/*
+ * 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)
+{
+  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);
+
+#ifdef DEBUG_CAMELSRT
+  if(p_camelsrt_call) {
+    dbg(10,"D%d ", p_camelsrt_call->session_id);
+  } else {
+    dbg(23,"Not in hash ");
+  }
+#endif
+
+  return p_camelsrt_call;
+}
+
+/*
+ * 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));
+}
+
+/*
+ * 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)
+{
+  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_new(struct camelsrt_call_info_key_t);
+  p_new_camelsrt_call_key->SessionIdKey = p_camelsrt_call_key->SessionIdKey;
+  p_new_camelsrt_call = se_new(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;
+}
+
+/*
+ * Routine called when the TAP is initialized.
+ * so hash table are (re)created
+ */
+void
+camelsrt_init_routine(void)
+{
+
+  /* free hash-table for SRT */
+  if (srt_calls != NULL) {
+#ifdef DEBUG_CAMELSRT
+    dbg(16,"Destroy hash ");
+#endif
+    g_hash_table_destroy(srt_calls);
+  }
+
+  /* create new hash-table 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;
+}
+
+
+/*
+ * 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)
+{
+  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;
+}
+
+/*
+ * 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(packet_info *pinfo,
+                            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 #%u\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);
+  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 */
+}
+
+/*
+ * 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.
+ */
+static void
+camelsrt_tcap_matching(tvbuff_t *tvb _U_, packet_info *pinfo,
+                      proto_tree *tree _U_,
+                      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(pinfo, 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(packet_info *pinfo,
+                            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 #%u\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);
+    p_camelsrt_call->tcap_context=(struct tcaphash_context_t *)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,
+                              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, *hidden_item;
+
+#ifdef DEBUG_CAMELSRT
+  dbg(10,"\n %s #%u\n", val_to_str_const(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);
+  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 #%u ", 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){
+           hidden_item = proto_tree_add_uint(tree, hf_camelsrt_Duplicate, tvb, 0,0, 77);
+               PROTO_ITEM_SET_HIDDEN(hidden_item);
+         }
+
+       } 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 #%u ", 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_const(srt_type, camelSRTtype_naming, "Unk"),
+                                     p_camelsrt_call->category[srt_type].rsp_num);
+      PROTO_ITEM_SET_GENERATED(ti);
+    } /* frame valid */
+  } /* call reference */
+}
+
+/*
+ * 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;
+    }
+  }
+}
+
+/*
+ * 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,
+                             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, *hidden_item;
+
+#ifdef DEBUG_CAMELSRT
+  dbg(10,"\n %s #%u\n", val_to_str_const(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);
+  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 %u ",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 #%u 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 ){
+         hidden_item = proto_tree_add_uint(tree, hf_camelsrt_Duplicate, tvb, 0,0, 77);
+         PROTO_ITEM_SET_HIDDEN(hidden_item);
+       }
+      }
+    } /* 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_const(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 */
+}
+
+/*
+ * 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, 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(pinfo, p_camelsrt_info);
+    camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
+                                  CAMELSRT_VOICE_INITIALDP);
+    break;
+  case 60: /*InitialDPSMS*/
+    camelsrt_begin_call_matching(pinfo, p_camelsrt_info);
+    camelsrt_request_call_matching(tvb, pinfo, tree, p_camelsrt_info,
+                                  CAMELSRT_SMS_INITIALDP);
+    break;
+  case 78: /*InitialDPGPRS*/
+    camelsrt_begin_call_matching(pinfo, 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(pinfo, p_camelsrt_info);
+    tcapsrt_close((struct tcaphash_context_t *)p_camelsrt_info->tcap_context, pinfo);
+    break;
+
+  case 80: /*EventReportGPRS*/
+    camelsrt_begin_call_matching(pinfo, 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(pinfo, p_camelsrt_info);
+    break;
+
+  case 66: /*ReleaseSMS*/
+    /* Session has been closed by Network */
+    camelsrt_close_call_matching(pinfo, p_camelsrt_info);
+    tcapsrt_close((struct tcaphash_context_t *)p_camelsrt_info->tcap_context,pinfo);
+    break;
+
+  case 79: /*ReleaseGPRS*/
+    /* Session has been closed by Network */
+    camelsrt_close_call_matching(pinfo, p_camelsrt_info);
+    break;
+  } /* switch opcode */
+}
+
+/*
+ * 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;
+}
 
 
 static guint8 camel_pdu_type = 0;
@@ -7417,7 +8119,7 @@ void proto_reg_handoff_camel(void) {
 
 
 /*--- End of included file: packet-camel-dis-tab.c ---*/
-#line 523 "../../asn1/camel/packet-camel-template.c"
+#line 1225 "../../asn1/camel/packet-camel-template.c"
   } else {
     range_foreach(ssn_range, range_delete_callback);
     g_free(ssn_range);
@@ -9531,7 +10233,7 @@ void proto_register_camel(void) {
         "InvokeId_present", HFILL }},
 
 /*--- End of included file: packet-camel-hfarr.c ---*/
-#line 696 "../../asn1/camel/packet-camel-template.c"
+#line 1398 "../../asn1/camel/packet-camel-template.c"
   };
 
   /* List of subtrees */
@@ -9746,7 +10448,7 @@ void proto_register_camel(void) {
     &ett_camel_InvokeId,
 
 /*--- End of included file: packet-camel-ettarr.c ---*/
-#line 712 "../../asn1/camel/packet-camel-template.c"
+#line 1414 "../../asn1/camel/packet-camel-template.c"
   };
 
   static ei_register_info ei[] = {
index 973058cf89dd9566891d778da133bb1f2a4edbab..5e1eaa5c35d6bb81d73301ecae0ed32d74c068fd 100644 (file)
@@ -54,4 +54,103 @@ void proto_register_camel(void);
 WS_DLL_PUBLIC const value_string camel_opr_code_strings[];
 /* #include "packet-camel-exp.h"*/
 
+/** @file
+*/
+#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
+
+WS_DLL_PUBLIC const value_string  camelSRTtype_naming[];
+
+/** 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];
+};
+
+/**
+ * Routine called when the TAP is initialized.
+ * so hash table are (re)created
+ */
+void camelsrt_init_routine(void);
+
+/**
+ * Initialize the Message Info used by the main dissector
+ * Data are linked to a TCAP transaction
+ */
+struct camelsrt_info_t * camelsrt_razinfo(void);
+
+/**
+ * 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_camel_info);
+
+WS_DLL_PUBLIC gboolean gcamel_StatSRT;
+
 #endif  /* PACKET_camel_H */
index 84ae484c70fc0662bba86c7d950dc7c11d70157e..39234a7d7c8ba48390fba4c15a5b79860cdad643 100644 (file)
@@ -47,7 +47,8 @@
 #include <string.h>
 #include "packet-ber.h"
 #include "packet-tcap.h"
-#include <epan/tcap-persistentdata.h>
+#include "packet-mtp3.h"
+
 
 #define PNAME  "Transaction Capabilities Application Part"
 #define PSNAME "TCAP"
@@ -138,7 +139,7 @@ static int hf_tcap_AARQ_protocol_version_version1 = -1;
 static int hf_tcap_AARE_protocol_version_version1 = -1;
 
 /*--- End of included file: packet-tcap-hf.c ---*/
-#line 62 "../../asn1/tcap/packet-tcap-template.c"
+#line 63 "../../asn1/tcap/packet-tcap-template.c"
 
 /* Initialize the subtree pointers */
 static gint ett_tcap = -1;
@@ -193,7 +194,14 @@ static gint ett_tcap_ABRT_user_information = -1;
 static gint ett_tcap_Associate_source_diagnostic = -1;
 
 /*--- End of included file: packet-tcap-ett.c ---*/
-#line 78 "../../asn1/tcap/packet-tcap-template.c"
+#line 79 "../../asn1/tcap/packet-tcap-template.c"
+
+/* When several Tcap 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_TCAP_INSTANCE 10
+static int tcapsrt_global_current=0;
+static struct tcapsrt_info_t tcapsrt_global_info[MAX_TCAP_INSTANCE];
 
 #define MAX_SSN 254
 static range_t *global_ssn_range;
@@ -201,10 +209,22 @@ static range_t *ssn_range;
 struct tcap_private_t tcap_private;
 
 gboolean gtcap_HandleSRT=FALSE;
-extern gboolean gtcap_PersistentSRT;
-extern gboolean gtcap_DisplaySRT;
-extern guint gtcap_RepetitionTimeout;
-extern guint gtcap_LostTimeout;
+/* These two timeout (in second) are used when some message are lost,
+   or when the same TCAP transcation identifier is reused */
+guint gtcap_RepetitionTimeout = 10;
+guint gtcap_LostTimeout = 30;
+gboolean gtcap_PersistentSRT=FALSE;
+gboolean gtcap_DisplaySRT=FALSE;
+gboolean gtcap_StatSRT=FALSE;
+
+/* Global hash tables*/
+static GHashTable *tcaphash_context = NULL;
+static GHashTable *tcaphash_begin = NULL;
+static GHashTable *tcaphash_cont = NULL;
+static GHashTable *tcaphash_end = NULL;
+static GHashTable *tcaphash_ansi = NULL;
+
+static guint32 tcapsrt_global_SessionId=1;
 
 static dissector_handle_t      tcap_handle = NULL;
 static dissector_table_t ber_oid_dissector_table;
@@ -255,8 +275,6 @@ dissector_handle_t get_itu_tcap_subdissector(guint32 ssn) {
 }
 
 
-
-
 /*--- Included file: packet-tcap-fn.c ---*/
 #line 1 "../../asn1/tcap/packet-tcap-fn.c"
 
@@ -1423,9 +1441,1817 @@ static void dissect_DialoguePDU_PDU(tvbuff_t *tvb _U_, packet_info *pinfo _U_, p
 
 
 /*--- End of included file: packet-tcap-fn.c ---*/
-#line 141 "../../asn1/tcap/packet-tcap-template.c"
+#line 159 "../../asn1/tcap/packet-tcap-template.c"
+
+/*
+ * DEBUG functions
+ */
+#undef MEM_TCAPSRT
+/* #define MEM_TCAPSRT */
+
+#undef DEBUG_TCAPSRT
+/* #define DEBUG_TCAPSRT */
+
+#ifdef DEBUG_TCAPSRT
+#include <stdio.h>
+#include <stdarg.h>
+static guint debug_level = 99;
+
+static void
+dbg(guint level, char* fmt, ...)
+{
+  va_list ap;
+
+  if (level > debug_level) return;
+  va_start(ap,fmt);
+  vfprintf(stderr, fmt, ap);
+  va_end(ap);
+}
+#endif
+
+static gint
+tcaphash_context_equal(gconstpointer k1, gconstpointer k2)
+{
+  const struct tcaphash_context_key_t *key1 = (const struct tcaphash_context_key_t *) k1;
+  const struct tcaphash_context_key_t *key2 = (const struct tcaphash_context_key_t *) k2;
+
+  return (key1->session_id == key2->session_id);
+}
+
+/* calculate a hash key */
+static guint
+tcaphash_context_calchash(gconstpointer k)
+{
+  const struct tcaphash_context_key_t *key = (const struct tcaphash_context_key_t *) k;
+  return key->session_id;
+}
+
+
+static gint
+tcaphash_begin_equal(gconstpointer k1, gconstpointer k2)
+{
+  const struct tcaphash_begin_info_key_t *key1 = (const struct tcaphash_begin_info_key_t *) k1;
+  const struct tcaphash_begin_info_key_t *key2 = (const struct tcaphash_begin_info_key_t *) k2;
+
+  if (key1->hashKey == key2->hashKey) {
+
+    if ( ( (key1->opc_hash == key2->opc_hash) &&
+          (key1->dpc_hash == key2->dpc_hash) &&
+          (key1->tid == key2->tid) )
+        ||
+        ( (key1->opc_hash == key2->dpc_hash) &&
+          (key1->dpc_hash == key2->opc_hash) &&
+          (key1->tid == key2->tid) )
+        )
+      return TRUE;
+  }
+  return FALSE;
+}
+
+/* calculate a hash key */
+static guint
+tcaphash_begin_calchash(gconstpointer k)
+{
+  const struct tcaphash_begin_info_key_t *key = (const struct tcaphash_begin_info_key_t *) k;
+  guint hashkey;
+  /* hashkey = key->opc_hash<<16 + key->dpc_hash<<8 + key->src_tid; */
+  hashkey = key->tid;
+  return hashkey;
+}
+
+static gint
+tcaphash_cont_equal(gconstpointer k1, gconstpointer k2)
+{
+  const struct tcaphash_cont_info_key_t *key1 = (const struct tcaphash_cont_info_key_t *) k1;
+  const struct tcaphash_cont_info_key_t *key2 = (const struct tcaphash_cont_info_key_t *) k2;
+
+  if (key1->hashKey == key2->hashKey) {
+
+    if ( (key1->opc_hash == key2->opc_hash) &&
+        (key1->dpc_hash == key2->dpc_hash) &&
+        (key1->src_tid == key2->src_tid) &&
+        (key1->dst_tid == key2->dst_tid) ) {
+      return TRUE;
+    }
+    else if ( (key1->opc_hash == key2->dpc_hash) &&
+             (key1->dpc_hash == key2->opc_hash) &&
+             (key1->src_tid == key2->dst_tid) &&
+             (key1->dst_tid == key2->src_tid) ) {
+      return TRUE;
+    }
+  }
+  return FALSE;
+}
+
+/* calculate a hash key */
+static guint
+tcaphash_cont_calchash(gconstpointer k)
+{
+  const struct tcaphash_cont_info_key_t *key = (const struct tcaphash_cont_info_key_t *) k;
+  guint hashkey;
+  hashkey = key->src_tid + key->dst_tid;
+  return hashkey;
+}
+
+
+static gint
+tcaphash_end_equal(gconstpointer k1, gconstpointer k2)
+{
+  const struct tcaphash_end_info_key_t *key1 = (const struct tcaphash_end_info_key_t *) k1;
+  const struct tcaphash_end_info_key_t *key2 = (const struct tcaphash_end_info_key_t *) k2;
+
+  if (key1->hashKey == key2->hashKey) {
+    if ( ( (key1->opc_hash == key2->opc_hash) &&
+          (key1->dpc_hash == key2->dpc_hash) &&
+          (key1->tid == key2->tid) )
+        ||
+        ( (key1->opc_hash == key2->dpc_hash) &&
+          (key1->dpc_hash == key2->opc_hash) &&
+          (key1->tid == key2->tid) ) )
+      return TRUE;
+  }
+  return FALSE;
+}
+
+/* calculate a hash key */
+static guint
+tcaphash_end_calchash(gconstpointer k)
+{
+  const struct tcaphash_end_info_key_t *key = (const struct tcaphash_end_info_key_t *) k;
+  guint hashkey;
+  hashkey = key->tid;
+  return hashkey;
+}
+
+static gint
+tcaphash_ansi_equal(gconstpointer k1, gconstpointer k2)
+{
+  const struct tcaphash_ansi_info_key_t *key1 = (const struct tcaphash_ansi_info_key_t *) k1;
+  const struct tcaphash_ansi_info_key_t *key2 = (const struct tcaphash_ansi_info_key_t *) k2;
+
+  if (key1->hashKey == key2->hashKey) {
+
+    if ( ( (key1->opc_hash == key2->opc_hash) &&
+          (key1->dpc_hash == key2->dpc_hash) &&
+          (key1->tid == key2->tid) )
+        ||
+        ( (key1->opc_hash == key2->dpc_hash) &&
+          (key1->dpc_hash == key2->opc_hash) &&
+          (key1->tid == key2->tid) )
+        )
+      return TRUE;
+  }
+  return FALSE;
+}
+
+/* calculate a hash key */
+static guint
+tcaphash_ansi_calchash(gconstpointer k)
+{
+  const struct tcaphash_ansi_info_key_t *key = (const struct tcaphash_ansi_info_key_t *) k;
+  guint hashkey;
+  /* hashkey = key->opc_hash<<16 + key->dpc_hash<<8 + key->src_tid; */
+  hashkey = key->tid;
+  return hashkey;
+}
+
+/*
+ * Update a record with the data of the Request
+ */
+static void
+update_tcaphash_begincall(struct tcaphash_begincall_t *p_tcaphash_begincall,
+                         packet_info *pinfo)
+{
+  p_tcaphash_begincall->context->first_frame = pinfo->fd->num;
+  p_tcaphash_begincall->context->last_frame = 0;
+  p_tcaphash_begincall->context->responded = FALSE;
+  p_tcaphash_begincall->context->begin_time = pinfo->fd->abs_ts;
+}
+
+/*
+ * Append a new dialogue, using the same Key, to the chained list
+ * The time is stored too
+ */
+static struct tcaphash_begincall_t *
+append_tcaphash_begincall(struct tcaphash_begincall_t *prev_begincall,
+                         struct tcaphash_context_t *p_tcaphash_context,
+                         packet_info *pinfo)
+{
+  struct tcaphash_begincall_t *p_new_tcaphash_begincall = NULL;
+
+  /* Append the transaction to the list, when the same key is found
+     This should append when the tcap-transaction Id is reused  */
+
+#ifdef MEM_TCAPSRT
+  p_new_tcaphash_begincall = (struct tcaphash_begincall_t *)g_malloc0(sizeof(struct tcaphash_begincall_t));
+#else
+  p_new_tcaphash_begincall = se_new0(struct tcaphash_begincall_t);
+#endif
+  p_new_tcaphash_begincall->context=p_tcaphash_context;
+  p_tcaphash_context->begincall=p_new_tcaphash_begincall;
+  p_new_tcaphash_begincall->beginkey=prev_begincall->beginkey;
+  p_new_tcaphash_begincall->context->first_frame = pinfo->fd->num;
+  p_new_tcaphash_begincall->next_begincall=NULL;
+  p_new_tcaphash_begincall->previous_begincall=prev_begincall;
+  p_new_tcaphash_begincall->father=FALSE;
+
+#ifdef DEBUG_TCAPSRT
+  dbg(10,"+B%d ", p_new_tcaphash_begincall->context->session_id);
+#endif
+  /* Insert in the chained list */
+  prev_begincall->next_begincall = p_new_tcaphash_begincall;
+  if (prev_begincall->context->last_frame == 0) {
+#ifdef DEBUG_TCAPSRT
+    dbg(10,"last ");
+#endif
+    prev_begincall->context->last_frame = pinfo->fd->num-1;
+  }
+  return p_new_tcaphash_begincall;
+}
+
+/*
+ * Update a record with the data of the Request
+ */
+static void
+update_tcaphash_ansicall(struct tcaphash_ansicall_t *p_tcaphash_ansicall,
+                         packet_info *pinfo)
+{
+  p_tcaphash_ansicall->context->first_frame = pinfo->fd->num;
+  p_tcaphash_ansicall->context->last_frame = 0;
+  p_tcaphash_ansicall->context->responded = FALSE;
+  p_tcaphash_ansicall->context->begin_time = pinfo->fd->abs_ts;
+}
+
+/*
+ * Append a new dialogue, using the same Key, to the chained list
+ * The time is stored too
+ */
+static struct tcaphash_ansicall_t *
+append_tcaphash_ansicall(struct tcaphash_ansicall_t *prev_ansicall,
+                         struct tcaphash_context_t *p_tcaphash_context,
+                         packet_info *pinfo)
+{
+  struct tcaphash_ansicall_t *p_new_tcaphash_ansicall = NULL;
+
+  /* Append the transaction to the list, when the same key is found
+     This should append when the tcap-transaction Id is reused  */
+
+#ifdef MEM_TCAPSRT
+  p_new_tcaphash_ansicall = (struct tcaphash_ansicall_t *)g_malloc0(sizeof(struct tcaphash_ansicall_t));
+#else
+  p_new_tcaphash_ansicall = se_new0(struct tcaphash_ansicall_t);
+#endif
+  p_new_tcaphash_ansicall->context=p_tcaphash_context;
+  p_tcaphash_context->ansicall=p_new_tcaphash_ansicall;
+  p_new_tcaphash_ansicall->ansikey=prev_ansicall->ansikey;
+  p_new_tcaphash_ansicall->context->first_frame = pinfo->fd->num;
+  p_new_tcaphash_ansicall->next_ansicall=NULL;
+  p_new_tcaphash_ansicall->previous_ansicall=prev_ansicall;
+  p_new_tcaphash_ansicall->father=FALSE;
+
+#ifdef DEBUG_TCAPSRT
+  dbg(10,"+A%d ", p_new_tcaphash_ansicall->context->session_id);
+#endif
+  /* Insert in the chained list */
+  prev_ansicall->next_ansicall = p_new_tcaphash_ansicall;
+  if (prev_ansicall->context->last_frame == 0) {
+#ifdef DEBUG_TCAPSRT
+    dbg(10,"last ");
+#endif
+    prev_ansicall->context->last_frame = pinfo->fd->num-1;
+  }
+  return p_new_tcaphash_ansicall;
+}
+
+
+static struct tcaphash_contcall_t *
+append_tcaphash_contcall(struct tcaphash_contcall_t *prev_contcall,
+                        struct tcaphash_context_t *p_tcaphash_context)
+{
+  struct tcaphash_contcall_t *p_new_tcaphash_contcall = NULL;
+
+  /* Append the transaction to the list, when the same key is found
+     This should append when the tcap-transaction Id is reused  */
+
+#ifdef MEM_TCAPSRT
+  p_new_tcaphash_contcall = (struct tcaphash_contcall_t *)g_malloc0(sizeof(struct tcaphash_contcall_t));
+#else
+  p_new_tcaphash_contcall = se_new0(struct tcaphash_contcall_t);
+#endif
+  p_new_tcaphash_contcall->context=p_tcaphash_context;
+  p_tcaphash_context->contcall=p_new_tcaphash_contcall;
+  p_new_tcaphash_contcall->contkey=prev_contcall->contkey;
+  p_new_tcaphash_contcall->next_contcall=NULL;
+  p_new_tcaphash_contcall->previous_contcall=prev_contcall;
+  p_new_tcaphash_contcall->father=FALSE;
+
+#ifdef DEBUG_TCAPSRT
+  dbg(10,"+C%d ", p_new_tcaphash_contcall->context->session_id);
+#endif
+  /* Insert in the chained list */
+  prev_contcall->next_contcall = p_new_tcaphash_contcall;
+  return p_new_tcaphash_contcall;
+}
+
+
+static struct tcaphash_endcall_t *
+append_tcaphash_endcall(struct tcaphash_endcall_t *prev_endcall,
+                       struct tcaphash_context_t *p_tcaphash_context)
+{
+  struct tcaphash_endcall_t *p_new_tcaphash_endcall = NULL;
+
+  /* Append the transaction to the list, when the same key is found
+     This should append when the tcap-transaction Id is reused  */
+
+#ifdef MEM_TCAPSRT
+  p_new_tcaphash_endcall = (struct tcaphas_endcall_t *)g_malloc0(sizeof(struct tcaphash_endcall_t));
+#else
+  p_new_tcaphash_endcall = se_new0(struct tcaphash_endcall_t);
+#endif
+  p_new_tcaphash_endcall->context=p_tcaphash_context;
+  p_tcaphash_context->endcall=p_new_tcaphash_endcall;
+  p_new_tcaphash_endcall->endkey=prev_endcall->endkey;
+  p_new_tcaphash_endcall->next_endcall=NULL;
+  p_new_tcaphash_endcall->previous_endcall=prev_endcall;
+  p_new_tcaphash_endcall->father=FALSE;
+
+#ifdef DEBUG_TCAPSRT
+  dbg(10,"+E%d ", p_new_tcaphash_endcall->context->session_id);
+#endif
+  /* Insert in the chained list */
+  prev_endcall->next_endcall = p_new_tcaphash_endcall;
+  return p_new_tcaphash_endcall;
+}
+
+
+/*
+ * Find the dialog by Key and Time
+ */
+static struct tcaphash_begincall_t *
+find_tcaphash_begin(struct tcaphash_begin_info_key_t *p_tcaphash_begin_key,
+                   packet_info *pinfo, gboolean isBegin)
+{
+  struct tcaphash_begincall_t *p_tcaphash_begincall = NULL;
+  p_tcaphash_begincall = (struct tcaphash_begincall_t *)g_hash_table_lookup(tcaphash_begin, p_tcaphash_begin_key);
+
+  if(p_tcaphash_begincall) {
+    do {
+      if ( p_tcaphash_begincall->context ) {
+        if ( ( isBegin &&
+               pinfo->fd->num == p_tcaphash_begincall->context->first_frame )
+             ||
+             ( !isBegin &&
+               pinfo->fd->num >= p_tcaphash_begincall->context->first_frame &&
+               ( p_tcaphash_begincall->context->last_frame?pinfo->fd->num <= p_tcaphash_begincall->context->last_frame:1 )
+               )
+             ) {
+          /* We have a dialogue, with this key, opened before this request */
+#ifdef DEBUG_TCAPSRT
+          dbg(10,"B%d ", p_tcaphash_begincall->context->session_id);
+#endif
+          return p_tcaphash_begincall;
+        }
+#ifdef DEBUG_TCAPSRT
+      dbg(60,"[B%d] ", p_tcaphash_begincall->context->session_id);
+#endif
+      }
+      /* Break when list end is reached */
+      if(p_tcaphash_begincall->next_begincall == NULL) {
+#ifdef DEBUG_TCAPSRT
+        dbg(23,"End of Blist ");
+#endif
+        break;
+      }
+      p_tcaphash_begincall = p_tcaphash_begincall->next_begincall;
+    } while (p_tcaphash_begincall != NULL) ;
+  } else {
+#ifdef DEBUG_TCAPSRT
+    dbg(23,"Not in Bhash ");
+#endif
+  }
+  return NULL;
+}
+
+
+
+static struct tcaphash_contcall_t *
+find_tcaphash_cont(struct tcaphash_cont_info_key_t *p_tcaphash_cont_key,
+                  packet_info *pinfo)
+{
+  struct tcaphash_contcall_t *p_tcaphash_contcall = NULL;
+  p_tcaphash_contcall = (struct tcaphash_contcall_t *)g_hash_table_lookup(tcaphash_cont, p_tcaphash_cont_key);
+
+  if(p_tcaphash_contcall) {
+    do {
+      if ( p_tcaphash_contcall->context ) {
+       if (pinfo->fd->num >= p_tcaphash_contcall->context->first_frame &&
+           (p_tcaphash_contcall->context->last_frame?pinfo->fd->num <= p_tcaphash_contcall->context->last_frame:1) ) {
+         /* We have a dialogue, with this key, opened before this request */
+#ifdef DEBUG_TCAPSRT
+         dbg(10,"C%d ", p_tcaphash_contcall->context->session_id);
+#endif
+         return p_tcaphash_contcall;
+       }
+#ifdef DEBUG_TCAPSRT
+       dbg(60,"[C%d] ", p_tcaphash_contcall->context->session_id);
+#endif
+      }
+      /* Break when list end is reached */
+      if(p_tcaphash_contcall->next_contcall == NULL) {
+#ifdef DEBUG_TCAPSRT
+       dbg(23,"End of Clist ");
+#endif
+       break;
+      }
+      p_tcaphash_contcall = p_tcaphash_contcall->next_contcall;
+    } while (p_tcaphash_contcall != NULL) ;
+  } else {
+#ifdef DEBUG_TCAPSRT
+    dbg(23,"Not in Chash ");
+#endif
+  }
+  return NULL;
+}
+
+static struct tcaphash_endcall_t *
+find_tcaphash_end(struct tcaphash_end_info_key_t *p_tcaphash_end_key,
+                 packet_info *pinfo, gboolean isEnd)
+{
+  struct tcaphash_endcall_t *p_tcaphash_endcall = NULL;
+  p_tcaphash_endcall = (struct tcaphash_endcall_t *)g_hash_table_lookup(tcaphash_end, p_tcaphash_end_key);
+
+  if(p_tcaphash_endcall) {
+    do {
+      if ( p_tcaphash_endcall->context ) {
+       if ( ( isEnd &&
+              (p_tcaphash_endcall->context->last_frame?pinfo->fd->num == p_tcaphash_endcall->context->last_frame:1)
+              )
+            ||
+            ( !isEnd &&
+              pinfo->fd->num >= p_tcaphash_endcall->context->first_frame &&
+              (p_tcaphash_endcall->context->last_frame?pinfo->fd->num <= p_tcaphash_endcall->context->last_frame:1)
+              )
+            ) {
+         /* We have a dialogue, with this key, opened before this request */
+#ifdef DEBUG_TCAPSRT
+         dbg(10,"E%d ", p_tcaphash_endcall->context->session_id);
+#endif
+         return p_tcaphash_endcall;
+       }
+#ifdef DEBUG_TCAPSRT
+         dbg(60,"[E%d] ", p_tcaphash_endcall->context->session_id);
+#endif
+      }
+      /* Break when list end is reached */
+      if(p_tcaphash_endcall->next_endcall == NULL) {
+#ifdef DEBUG_TCAPSRT
+       dbg(23,"End of Elist ");
+#endif
+       break;
+      }
+      p_tcaphash_endcall = p_tcaphash_endcall->next_endcall;
+    } while (p_tcaphash_endcall != NULL) ;
+  } else {
+#ifdef DEBUG_TCAPSRT
+    dbg(23,"Not in Ehash ");
+#endif
+  }
+  return NULL;
+}
+
+/*
+ * New record to create, to identify a new transaction
+ */
+static struct tcaphash_context_t *
+new_tcaphash_context(struct tcaphash_context_key_t *p_tcaphash_context_key,
+                    packet_info *pinfo)
+{
+  struct tcaphash_context_key_t *p_new_tcaphash_context_key;
+  struct tcaphash_context_t *p_new_tcaphash_context = NULL;
+
+  /* Register the transaction in the hash table
+     with the tcap transaction Id as Main Key
+     Once created, this entry will be updated later */
+
+#ifdef MEM_TCAPSRT
+  p_new_tcaphash_context_key = (struct tcaphash_context_key_t *)g_malloc(sizeof(struct tcaphash_context_key_t));
+#else
+  p_new_tcaphash_context_key = se_new(struct tcaphash_context_key_t);
+#endif
+  p_new_tcaphash_context_key->session_id = p_tcaphash_context_key->session_id;
+
+#ifdef MEM_TCAPSRT
+  p_new_tcaphash_context = (struct tcaphash_context_t *)g_malloc0(sizeof(struct tcaphash_context_t));
+#else
+  p_new_tcaphash_context = se_new0(struct tcaphash_context_t);
+#endif
+  p_new_tcaphash_context->key = p_new_tcaphash_context_key;
+  p_new_tcaphash_context->session_id = p_tcaphash_context_key->session_id;
+  p_new_tcaphash_context->first_frame = pinfo->fd->num;
+#ifdef DEBUG_TCAPSRT
+  dbg(10,"S%d ", p_new_tcaphash_context->session_id);
+#endif
+  /* store it */
+  g_hash_table_insert(tcaphash_context, p_new_tcaphash_context_key, p_new_tcaphash_context);
+  return p_new_tcaphash_context;
+}
+
+/*
+ * New record to create, to identify a new transaction
+ */
+static struct tcaphash_begincall_t *
+new_tcaphash_begin(struct tcaphash_begin_info_key_t *p_tcaphash_begin_key,
+                  struct tcaphash_context_t *p_tcaphash_context)
+{
+  struct tcaphash_begin_info_key_t *p_new_tcaphash_begin_key;
+  struct tcaphash_begincall_t *p_new_tcaphash_begincall = NULL;
+
+  /* Register the transaction in the hash table
+     with the tcap transaction Id as Main Key
+     Once created, this entry will be updated later */
+
+#ifdef MEM_TCAPSRT
+  p_new_tcaphash_begin_key = (struct tcaphash_begin_info_key_t *)g_malloc(sizeof(struct tcaphash_begin_info_key_t));
+#else
+  p_new_tcaphash_begin_key = se_new(struct tcaphash_begin_info_key_t);
+#endif
+  p_new_tcaphash_begin_key->hashKey = p_tcaphash_begin_key->hashKey;
+  p_new_tcaphash_begin_key->tid = p_tcaphash_begin_key->tid;
+  p_new_tcaphash_begin_key->opc_hash = p_tcaphash_begin_key->opc_hash;
+  p_new_tcaphash_begin_key->dpc_hash = p_tcaphash_begin_key->dpc_hash;
+
+#ifdef MEM_TCAPSRT
+  p_new_tcaphash_begincall = (struct tcaphash_begincall_t *)g_malloc0(sizeof(struct tcaphash_begincall_t));
+#else
+ p_new_tcaphash_begincall = se_new0(struct tcaphash_begincall_t);
+#endif
+  p_new_tcaphash_begincall->beginkey=p_new_tcaphash_begin_key;
+  p_new_tcaphash_begincall->context=p_tcaphash_context;
+  p_tcaphash_context->begincall=p_new_tcaphash_begincall;
+  p_new_tcaphash_begincall->father=TRUE;
+  p_new_tcaphash_begincall->next_begincall=NULL;
+  p_new_tcaphash_begincall->previous_begincall=NULL;
+
+#ifdef DEBUG_TCAPSRT
+  dbg(10,"B%d ", p_new_tcaphash_begincall->context->session_id);
+#endif
+  /* store it */
+  g_hash_table_insert(tcaphash_begin, p_new_tcaphash_begin_key, p_new_tcaphash_begincall);
+  return p_new_tcaphash_begincall;
+}
+
+
+
+/*
+ * New record to create, to identify a new transaction
+ */
+static struct tcaphash_contcall_t *
+new_tcaphash_cont(struct tcaphash_cont_info_key_t *p_tcaphash_cont_key,
+                 struct tcaphash_context_t *p_tcaphash_context)
+{
+  struct tcaphash_cont_info_key_t *p_new_tcaphash_cont_key;
+  struct tcaphash_contcall_t *p_new_tcaphash_contcall = NULL;
+
+  /* Register the transaction in the hash table
+     with the tcap transaction Id as Main Key
+     Once created, this entry will be updated later */
+
+#ifdef MEM_TCAPSRT
+  p_new_tcaphash_cont_key = (struct tcaphash_cont_info_key_t *)g_malloc(sizeof(struct tcaphash_cont_info_key_t));
+#else
+  p_new_tcaphash_cont_key = se_new(struct tcaphash_cont_info_key_t);
+#endif
+  p_new_tcaphash_cont_key->hashKey = p_tcaphash_cont_key->hashKey;
+  p_new_tcaphash_cont_key->src_tid = p_tcaphash_cont_key->src_tid;
+  p_new_tcaphash_cont_key->dst_tid = p_tcaphash_cont_key->dst_tid;
+  p_new_tcaphash_cont_key->opc_hash = p_tcaphash_cont_key->opc_hash;
+  p_new_tcaphash_cont_key->dpc_hash = p_tcaphash_cont_key->dpc_hash;
+
+#ifdef MEM_TCAPSRT
+  p_new_tcaphash_contcall = (struct tcaphash_contcall_t *)g_malloc0(sizeof(struct tcaphash_contcall_t));
+#else
+  p_new_tcaphash_contcall = se_new0(struct tcaphash_contcall_t);
+#endif
+  p_new_tcaphash_contcall->contkey=p_new_tcaphash_cont_key;
+  p_new_tcaphash_contcall->context=p_tcaphash_context;
+  p_tcaphash_context->contcall=p_new_tcaphash_contcall;
+  p_new_tcaphash_contcall->father=TRUE;
+  p_new_tcaphash_contcall->next_contcall=NULL;
+  p_new_tcaphash_contcall->previous_contcall=NULL;
+
+#ifdef DEBUG_TCAPSRT
+  dbg(10,"C%d ", p_new_tcaphash_contcall->context->session_id);
+#endif
+  /* store it */
+  g_hash_table_insert(tcaphash_cont, p_new_tcaphash_cont_key, p_new_tcaphash_contcall);
+  return p_new_tcaphash_contcall;
+}
+
+
+/*
+ * New record to create, to identify a new transaction
+ */
+static struct tcaphash_endcall_t *
+new_tcaphash_end(struct tcaphash_end_info_key_t *p_tcaphash_end_key,
+                struct tcaphash_context_t *p_tcaphash_context)
+{
+  struct tcaphash_end_info_key_t *p_new_tcaphash_end_key;
+  struct tcaphash_endcall_t *p_new_tcaphash_endcall = NULL;
+
+  /* Register the transaction in the hash table
+     with the tcap transaction Id as Main Key
+     Once created, this entry will be updated later */
+
+#ifdef MEM_TCAPSRT
+  p_new_tcaphash_end_key = (struct tcaphash_end_info_key_t *)g_malloc(sizeof(struct tcaphash_end_info_key_t));
+#else
+  p_new_tcaphash_end_key = se_new(struct tcaphash_end_info_key_t);
+#endif
+  p_new_tcaphash_end_key->hashKey = p_tcaphash_end_key->hashKey;
+  p_new_tcaphash_end_key->tid = p_tcaphash_end_key->tid;
+  p_new_tcaphash_end_key->opc_hash = p_tcaphash_end_key->opc_hash;
+  p_new_tcaphash_end_key->dpc_hash = p_tcaphash_end_key->dpc_hash;
+
+#ifdef MEM_TCAPSRT
+  p_new_tcaphash_endcall = (struct tcaphash_endcall_t *)g_malloc0(sizeof(struct tcaphash_endcall_t));
+#else
+  p_new_tcaphash_endcall = se_new0(struct tcaphash_endcall_t);
+#endif
+  p_new_tcaphash_endcall->endkey=p_new_tcaphash_end_key;
+  p_new_tcaphash_endcall->context=p_tcaphash_context;
+  p_tcaphash_context->endcall=p_new_tcaphash_endcall;
+  p_new_tcaphash_endcall->father=TRUE;
+  p_new_tcaphash_endcall->next_endcall=NULL;
+  p_new_tcaphash_endcall->previous_endcall=NULL;
+
+#ifdef DEBUG_TCAPSRT
+  dbg(10,"E%d ", p_new_tcaphash_endcall->context->session_id);
+#endif
+  /* store it */
+  g_hash_table_insert(tcaphash_end, p_new_tcaphash_end_key, p_new_tcaphash_endcall);
+  return p_new_tcaphash_endcall;
+}
+/*
+ * New record to create, to identify a new transaction
+ */
+static struct tcaphash_ansicall_t *
+new_tcaphash_ansi(struct tcaphash_ansi_info_key_t *p_tcaphash_ansi_key,
+                  struct tcaphash_context_t *p_tcaphash_context)
+{
+  struct tcaphash_ansi_info_key_t *p_new_tcaphash_ansi_key;
+  struct tcaphash_ansicall_t *p_new_tcaphash_ansicall = NULL;
+
+  /* Register the transaction in the hash table
+     with the tcap transaction Id as Main Key
+     Once created, this entry will be updated later */
+
+#ifdef MEM_TCAPSRT
+  p_new_tcaphash_ansi_key = (struct tcaphash_ansi_info_key_t *)g_malloc(sizeof(struct tcaphash_ansi_info_key_t));
+#else
+  p_new_tcaphash_ansi_key = se_new(struct tcaphash_ansi_info_key_t);
+#endif
+  p_new_tcaphash_ansi_key->hashKey = p_tcaphash_ansi_key->hashKey;
+  p_new_tcaphash_ansi_key->tid = p_tcaphash_ansi_key->tid;
+  p_new_tcaphash_ansi_key->opc_hash = p_tcaphash_ansi_key->opc_hash;
+  p_new_tcaphash_ansi_key->dpc_hash = p_tcaphash_ansi_key->dpc_hash;
+
+#ifdef MEM_TCAPSRT
+  p_new_tcaphash_ansicall = (struct tcaphash_ansicall_t *)g_malloc0(sizeof(struct tcaphash_ansicall_t));
+#else
+  p_new_tcaphash_ansicall = se_new0(struct tcaphash_ansicall_t);
+#endif
+  p_new_tcaphash_ansicall->ansikey=p_new_tcaphash_ansi_key;
+  p_new_tcaphash_ansicall->context=p_tcaphash_context;
+  p_tcaphash_context->ansicall=p_new_tcaphash_ansicall;
+  p_new_tcaphash_ansicall->father=TRUE;
+  p_new_tcaphash_ansicall->next_ansicall=NULL;
+  p_new_tcaphash_ansicall->previous_ansicall=NULL;
+
+#ifdef DEBUG_TCAPSRT
+  dbg(10,"A%d ", p_new_tcaphash_ansicall->context->session_id);
+#endif
+  /* store it */
+  g_hash_table_insert(tcaphash_ansi, p_new_tcaphash_ansi_key, p_new_tcaphash_ansicall);
+  return p_new_tcaphash_ansicall;
+}
+
+static struct tcaphash_contcall_t *
+create_tcaphash_cont(struct tcaphash_cont_info_key_t *p_tcaphash_cont_key,
+                    struct tcaphash_context_t *p_tcaphash_context)
+{
+  struct tcaphash_contcall_t *p_tcaphash_contcall1 = NULL;
+  struct tcaphash_contcall_t *p_tcaphash_contcall = NULL;
+
+  p_tcaphash_contcall1 = (struct tcaphash_contcall_t *)
+    g_hash_table_lookup(tcaphash_cont, p_tcaphash_cont_key);
+
+  if (p_tcaphash_contcall1) {
+    /* Walk through list of transaction with identical keys */
+    /* go the the end to insert new record */
+    do {
+      if (!p_tcaphash_contcall1->next_contcall) {
+       p_tcaphash_contcall=append_tcaphash_contcall(p_tcaphash_contcall1,
+                                                    p_tcaphash_context);
+       break;
+      }
+      p_tcaphash_contcall1 = p_tcaphash_contcall1->next_contcall;
+    } while (p_tcaphash_contcall1 != NULL );
+  } else {
+    p_tcaphash_contcall = new_tcaphash_cont(p_tcaphash_cont_key,
+                                           p_tcaphash_context);
+  }
+  return p_tcaphash_contcall;
+}
+
+
+static struct tcaphash_endcall_t *
+create_tcaphash_end(struct tcaphash_end_info_key_t *p_tcaphash_end_key,
+                   struct tcaphash_context_t *p_tcaphash_context)
+{
+  struct tcaphash_endcall_t *p_tcaphash_endcall1 = NULL;
+  struct tcaphash_endcall_t *p_tcaphash_endcall = NULL;
+
+  p_tcaphash_endcall1 = (struct tcaphash_endcall_t *)
+    g_hash_table_lookup(tcaphash_end, p_tcaphash_end_key);
+
+  if (p_tcaphash_endcall1) {
+    /* Walk through list of transaction with identical keys */
+    /* go the the end to insert new record */
+    do {
+      if (!p_tcaphash_endcall1->next_endcall) {
+       p_tcaphash_endcall=append_tcaphash_endcall(p_tcaphash_endcall1,
+                                                  p_tcaphash_context);
+       break;
+      }
+      p_tcaphash_endcall1 = p_tcaphash_endcall1->next_endcall;
+    } while (p_tcaphash_endcall1 != NULL );
+  } else {
+    p_tcaphash_endcall = new_tcaphash_end(p_tcaphash_end_key,
+                                         p_tcaphash_context);
+  }
+  return p_tcaphash_endcall;
+}
+
+
+/*
+ * Routine called when the TAP is initialized.
+ * so hash table are (re)created
+ */
+void
+tcapsrt_init_routine(void)
+{
+
+  /* free hash-table for SRT */
+  if (tcaphash_context != NULL) {
+#ifdef DEBUG_TCAPSRT
+    dbg(16,"Destroy hash_context \n");
+#endif
+    g_hash_table_destroy(tcaphash_context);
+  }
+
+  if (tcaphash_begin != NULL) {
+#ifdef DEBUG_TCAPSRT
+    dbg(16,"Destroy hash_begin \n");
+#endif
+    g_hash_table_destroy(tcaphash_begin);
+  }
+
+  if (tcaphash_cont != NULL) {
+#ifdef DEBUG_TCAPSRT
+    dbg(16,"Destroy hash_cont \n");
+#endif
+    g_hash_table_destroy(tcaphash_cont);
+  }
+
+  if (tcaphash_end != NULL) {
+#ifdef DEBUG_TCAPSRT
+    dbg(16,"Destroy hash_end \n");
+#endif
+    g_hash_table_destroy(tcaphash_end);
+  }
+
+  if (tcaphash_ansi != NULL) {
+#ifdef DEBUG_TCAPSRT
+    dbg(16,"Destroy hash_ansi \n");
+#endif
+    g_hash_table_destroy(tcaphash_ansi);
+  }
+
+#ifdef DEBUG_TCAPSRT
+  dbg(16,"Create hash \n");
+#endif
+  /* create new hash-tables for SRT */
+  tcaphash_context = g_hash_table_new(tcaphash_context_calchash, tcaphash_context_equal);
+  tcaphash_begin   = g_hash_table_new(tcaphash_begin_calchash, tcaphash_begin_equal);
+  tcaphash_cont    = g_hash_table_new(tcaphash_cont_calchash, tcaphash_cont_equal);
+  tcaphash_end     = g_hash_table_new(tcaphash_end_calchash, tcaphash_end_equal);
+  tcaphash_ansi    = g_hash_table_new(tcaphash_ansi_calchash, tcaphash_ansi_equal);
+
+  /* Reset the session counter */
+  tcapsrt_global_SessionId=1;
+
+  /* Display of SRT only if Persistent Stat */
+  gtcap_DisplaySRT=gtcap_PersistentSRT || gtcap_HandleSRT&gtcap_StatSRT;
+}
+
+/*
+ * Create the record identifiying the TCAP transaction
+ * When the identifier for the transaction is reused, check
+ * the following criteria before to append a new record:
+ * - a timeout corresponding to a message retransmission is detected,
+ * - a message hast been lost
+ * - or the previous transaction has been  be closed
+ */
+static struct tcaphash_context_t *
+tcaphash_begin_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+                       struct tcapsrt_info_t *p_tcapsrt_info)
+{
+  struct tcaphash_context_t *p_tcaphash_context=NULL;
+  struct tcaphash_context_key_t tcaphash_context_key;
+  struct tcaphash_begincall_t *p_tcaphash_begincall, *p_new_tcaphash_begincall=NULL;
+  struct tcaphash_begin_info_key_t tcaphash_begin_key;
+  proto_item *pi;
+  proto_item *stat_item=NULL;
+  proto_tree *stat_tree=NULL;
+
+  /* prepare the key data */
+  tcaphash_begin_key.tid = p_tcapsrt_info->src_tid;
+  if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
+  {
+    /* We have MTP3 PCs (so we can safely do this cast) */
+    tcaphash_begin_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
+    tcaphash_begin_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
+  } else {
+    /* Don't have MTP3 PCs (maybe we're over SUA?) */
+    tcaphash_begin_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
+    tcaphash_begin_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
+  }
+  tcaphash_begin_key.hashKey=tcaphash_begin_calchash(&tcaphash_begin_key);
+
+  /* look up the request */
+#ifdef DEBUG_TCAPSRT
+  dbg(10,"\n Hbegin #%u ", pinfo->fd->num);
+  dbg(11,"key %lx ",tcaphash_begin_key.hashKey);
+  dbg(51,"PC %s %s ",ep_address_to_str(&pinfo->src), ep_address_to_str(&pinfo->dst));
+  dbg(51,"Tid %lx \n",tcaphash_begin_key.tid);
+#endif
+
+  p_tcaphash_begincall = (struct tcaphash_begincall_t *)
+  g_hash_table_lookup(tcaphash_begin, &tcaphash_begin_key);
+
+  if (p_tcaphash_begincall) {
+    /* Walk through list of transaction with identical keys */
+    do {
+      /* Check if the request with this reqSeqNum has been seen, with the same Message Type */
+      if (pinfo->fd->num == p_tcaphash_begincall->context->first_frame) {
+       /* We have seen this request before -> do nothing */
+#ifdef DEBUG_TCAPSRT
+       dbg(22,"Already seen ");
+#endif
+       p_tcaphash_context=p_tcaphash_begincall->context;
+       break;
+      }
+      /* If the last record for Tcap transaction with identifier has not been reached */
+      if (!p_tcaphash_begincall->next_begincall) {
+       /* check if we have to create a new record or not */
+       /* if last request has been responded (response number is known)
+          and this request appears after last response (has bigger frame number)
+          and last request occurred after the timeout for repetition,
+          or
+          if last request hasn't been responded (so number unknown)
+          and this request appears after last request (has bigger frame number)
+          and this request occurred after the timeout for message lost */
+       if ( ( p_tcaphash_begincall->context->last_frame != 0
+              && pinfo->fd->num > p_tcaphash_begincall->context->first_frame
+              && (guint) pinfo->fd->abs_ts.secs > (guint)(p_tcaphash_begincall->context->begin_time.secs + gtcap_RepetitionTimeout)
+              ) ||
+            ( p_tcaphash_begincall->context->last_frame == 0
+              && pinfo->fd->num > p_tcaphash_begincall->context->first_frame
+              && (guint)pinfo->fd->abs_ts.secs > (guint)(p_tcaphash_begincall->context->begin_time.secs + gtcap_LostTimeout)
+              )
+            )
+         {
+           /* we decide that we have a new request */
+           /* Append new record to the list */
+#ifdef DEBUG_TCAPSRT
+           dbg(12,"(timeout) Append key %lx ",tcaphash_begin_key.hashKey);
+           dbg(12,"Frame %u rsp %u ",pinfo->fd->num,p_tcaphash_begincall->context->last_frame );
+#endif
+           tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
+           p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
+
+           p_new_tcaphash_begincall = append_tcaphash_begincall(p_tcaphash_begincall,
+                                                                p_tcaphash_context,
+                                                                pinfo);
+#ifdef DEBUG_TCAPSRT
+           dbg(12,"Update key %lx ",tcaphash_begin_key.hashKey);
+#endif
+           update_tcaphash_begincall(p_new_tcaphash_begincall, pinfo);
+         } else { /* timeout or message lost */
+
+         /* If the Tid is reused for a closed Transaction */
+         /* Or if we received an TC_BEGIN for a Transaction marked as "closed" */
+         /* (this is the case, for pre-arranged END, the transaction is marked as closed */
+         /* by the upper layer, thank to a callback method close) */
+         if ( p_tcaphash_begincall->context->closed) {
+#ifdef DEBUG_TCAPSRT
+           dbg(12,"(closed) Append key %lu ",tcaphash_begin_key.hashKey);
+           dbg(12,"Frame %u rsp %u ",pinfo->fd->num,p_tcaphash_begincall->context->last_frame );
+#endif
+           tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
+           p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
+           p_new_tcaphash_begincall = append_tcaphash_begincall(p_tcaphash_begincall,
+                                                                p_tcaphash_context,
+                                                                pinfo);
+
+#ifdef DEBUG_TCAPSRT
+           dbg(12,"Update key %lu ",tcaphash_begin_key.hashKey);
+#endif
+           update_tcaphash_begincall(p_new_tcaphash_begincall, pinfo);
+
+         } else {
+           /* the TCAP session is not closed, so, either messages have been lost */
+           /* or it's a duplicate request. Mark it as such. */
+#ifdef DEBUG_TCAPSRT
+           dbg(21,"Display_duplicate %d ",p_tcaphash_begincall->context->first_frame);
+#endif
+           p_tcaphash_context=p_tcaphash_begincall->context;
+           if (gtcap_DisplaySRT && tree) {
+             stat_item = proto_tree_add_text(tree, tvb, 0, -1, "Stat");
+             PROTO_ITEM_SET_GENERATED(stat_item);
+             stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
+             pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_Duplicate, tvb, 0, 0,
+                                             p_tcaphash_context->first_frame,
+                                             "Duplicate with session %u in frame %u",
+                                             p_tcaphash_context->session_id,p_tcaphash_context->first_frame);
+             PROTO_ITEM_SET_GENERATED(pi);
+           }
+           return p_tcaphash_context;
+         } /* Previous session closed */
+       } /* test with Timeout or message Lost */
+       break;
+      } /* Next call is NULL */
+      /* Repeat the tests for the next record with the same transaction identifier */
+      p_tcaphash_begincall = p_tcaphash_begincall->next_begincall;
+    } while (p_tcaphash_begincall != NULL );
+    /*
+     * End of analyze for the list be TC_BEGIN with same transaction ID
+     */
+  } else { /* p_tcaphash_begincall has not been found */
+    /*
+     * Create a new TCAP context
+     */
+#ifdef DEBUG_TCAPSRT
+    dbg(10,"New key %lx ",tcaphash_begin_key.hashKey);
+#endif
+
+    tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
+    p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
+    p_tcaphash_begincall = new_tcaphash_begin(&tcaphash_begin_key, p_tcaphash_context);
+
+#ifdef DEBUG_TCAPSRT
+    dbg(11,"Update key %lx ",tcaphash_begin_key.hashKey);
+    dbg(11,"Frame reqlink #%u ", pinfo->fd->num);
+#endif
+    update_tcaphash_begincall(p_tcaphash_begincall, pinfo);
+  }
+
+  /* display tcap session, if available */
+  if ( gtcap_DisplaySRT && tree &&
+       p_tcaphash_context &&
+       p_tcaphash_context->session_id) {
+    stat_item = proto_tree_add_text(tree, tvb, 0, 0, "Stat");
+    PROTO_ITEM_SET_GENERATED(stat_item);
+    stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
+    pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
+    PROTO_ITEM_SET_GENERATED(pi);
+
+    /* add link to response frame, if available */
+    /* p_tcaphash_begincall->context->last_frame) */
+    if( p_tcaphash_context->last_frame != 0 ){
+#ifdef DEBUG_TCAPSRT
+      dbg(20,"Display_frameRsplink %d ",p_tcaphash_context->last_frame);
+#endif
+      pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_BeginSession, tvb, 0, 0,
+                                     p_tcaphash_context->last_frame,
+                                     "End of session in frame %u",
+                                     p_tcaphash_context->last_frame);
+      PROTO_ITEM_SET_GENERATED(pi);
+    }
+  }
+  return p_tcaphash_context;
+}
+
+/*
+* Try to find a TCAP session according to the source and destination
+* Identifier given in the TC_CONT
+* If nothing is found, it is probably a session in opening state, so try to find
+* a tcap session registered with a TC_BEGIN "key", matching the destination Id of the TC_CONT
+* Then associate the TC_CONT "key" to the TCAP context, and create a TC_END "key"
+* and display the available info for the TCAP context
+*/
+static struct tcaphash_context_t *
+tcaphash_cont_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+                      struct tcapsrt_info_t *p_tcapsrt_info)
+{
+  struct tcaphash_context_t *p_tcaphash_context=NULL;
+  struct tcaphash_contcall_t *p_tcaphash_contcall;
+  struct tcaphash_cont_info_key_t tcaphash_cont_key;
+  struct tcaphash_begin_info_key_t tcaphash_begin_key;
+  struct tcaphash_begincall_t *p_tcaphash_begincall;
+  struct tcaphash_end_info_key_t tcaphash_end_key;
+  proto_item *pi;
+  proto_item *stat_item=NULL;
+  proto_tree *stat_tree=NULL;
+
+#ifdef DEBUG_TCAPSRT
+  dbg(10,"\n Hcont #%u ", pinfo->fd->num);
+#endif
+
+  /* look only for matching request, if matching conversation is available. */
+  tcaphash_cont_key.src_tid = p_tcapsrt_info->src_tid;
+  tcaphash_cont_key.dst_tid = p_tcapsrt_info->dst_tid;
+  if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
+  {
+    /* We have MTP3 PCs (so we can safely do this cast) */
+    tcaphash_cont_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
+    tcaphash_cont_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
+  } else {
+    /* Don't have MTP3 PCs (maybe we're over SUA?) */
+    tcaphash_cont_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
+    tcaphash_cont_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
+  }
+  tcaphash_cont_key.hashKey=tcaphash_cont_calchash(&tcaphash_cont_key);
+
+#ifdef DEBUG_TCAPSRT
+  dbg(11,"Ckey %lx ", tcaphash_cont_key.hashKey);
+  dbg(51,"PC %s %s ",ep_address_to_str(&pinfo->src), ep_address_to_str(&pinfo->dst));
+  dbg(51,"Tid %lx %lx \n",tcaphash_cont_key.src_tid, tcaphash_cont_key.dst_tid);
+#endif
+  p_tcaphash_contcall = find_tcaphash_cont(&tcaphash_cont_key, pinfo);
+  if(p_tcaphash_contcall) {
+#ifdef DEBUG_TCAPSRT
+    dbg(12,"CFound ");
+#endif
+    p_tcaphash_context=p_tcaphash_contcall->context;
+  } else { /* cont not found */
+#ifdef DEBUG_TCAPSRT
+    dbg(12,"CnotFound ");
+#endif
+    /* Find the TCAP transaction according to the TC_BEGIN */
+    tcaphash_begin_key.tid = p_tcapsrt_info->dst_tid;
+    if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
+    {
+      /* We have MTP3 PCs (so we can safely do this cast) */
+      tcaphash_begin_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
+      tcaphash_begin_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
+    } else {
+      /* Don't have MTP3 PCs (maybe we're over SUA?) */
+      tcaphash_begin_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
+      tcaphash_begin_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
+    }
+    tcaphash_begin_key.hashKey=tcaphash_begin_calchash(&tcaphash_begin_key);
+
+#ifdef DEBUG_TCAPSRT
+    dbg(11,"Bkey %lx ", tcaphash_begin_key.hashKey);
+    dbg(51,"PC %s %s ",ep_address_to_str(&pinfo->src), ep_address_to_str(&pinfo->dst));
+    dbg(51,"Tid %lx \n",tcaphash_begin_key.tid);
+#endif
+    p_tcaphash_begincall = find_tcaphash_begin(&tcaphash_begin_key, pinfo, FALSE);
+    if(!p_tcaphash_begincall){
+        /* Do we have a continue from the same source? */
+        tcaphash_begin_key.tid = p_tcapsrt_info->src_tid;
+        tcaphash_begin_key.hashKey=tcaphash_begin_calchash(&tcaphash_begin_key);
+        p_tcaphash_begincall = find_tcaphash_begin(&tcaphash_begin_key, pinfo,FALSE);
+    }
+    if(p_tcaphash_begincall &&
+       !p_tcaphash_begincall->context->contcall ) {
+#ifdef DEBUG_TCAPSRT
+      dbg(12,"BFound \n");
+#endif
+      p_tcaphash_context=p_tcaphash_begincall->context;
+      p_tcaphash_context->responded=TRUE;
+
+#ifdef DEBUG_TCAPSRT
+      dbg(10,"New Ckey %lx ",tcaphash_cont_key.hashKey);
+      dbg(11,"Frame reqlink #%u \n", pinfo->fd->num);
+#endif
+      create_tcaphash_cont(&tcaphash_cont_key,
+                           p_tcaphash_begincall->context);
+
+      tcaphash_end_key.tid = p_tcapsrt_info->src_tid;
+      if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
+      {
+        /* We have MTP3 PCs (so we can safely do this cast) */
+        tcaphash_end_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
+        tcaphash_end_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
+      } else {
+        /* Don't have MTP3 PCs (maybe we're over SUA?) */
+        tcaphash_end_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
+        tcaphash_end_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
+      }
+      tcaphash_end_key.hashKey=tcaphash_end_calchash(&tcaphash_end_key);
+
+#ifdef DEBUG_TCAPSRT
+      dbg(10,"New Ekey %lx ",tcaphash_end_key.hashKey);
+      dbg(11,"Frame reqlink #%u ", pinfo->fd->num);
+#endif
+      create_tcaphash_end(&tcaphash_end_key,
+                          p_tcaphash_begincall->context);
+
+    } else { /* Begin not found */
+#ifdef DEBUG_TCAPSRT
+      dbg(12,"BnotFound ");
+#endif
+    } /* begin found */
+  } /* cont found */
+    /* display tcap session, if available */
+  if (gtcap_DisplaySRT && tree &&
+      p_tcaphash_context &&
+      p_tcaphash_context->session_id) {
+    stat_item = proto_tree_add_text(tree, tvb, 0, -1, "Stat");
+    PROTO_ITEM_SET_GENERATED(stat_item);
+    stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
+    pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
+    PROTO_ITEM_SET_GENERATED(pi);
+  }
+
+  return p_tcaphash_context;
+}
+
+/*
+* Try to find a TCAP session according to the destination Identifier given in the TC_END/TC_ABORT
+* If nothing is found,
+* - either it is a session in opening state,
+* - or the session is closed/aborted by the remote, ( so we switch the src and dst tid )
+* so try to find a tcap session registered with a TC_BEGIN "key",
+* matching the destination Id of the TC_END
+* Then associate the TC_CONT "key" to the TCAP context
+* and display the available info for the TCAP context
+*/
+
+static struct tcaphash_context_t *
+tcaphash_end_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+                     struct tcapsrt_info_t *p_tcapsrt_info)
+{
+  struct tcaphash_context_t *p_tcaphash_context=NULL;
+
+  struct tcaphash_end_info_key_t tcaphash_end_key;
+  struct tcaphash_endcall_t *p_tcaphash_endcall=NULL;
+
+  struct tcaphash_begin_info_key_t tcaphash_begin_key;
+  struct tcaphash_begincall_t *p_tcaphash_begincall=NULL;
+  proto_item *pi;
+  nstime_t delta;
+  proto_item *stat_item=NULL;
+  proto_tree *stat_tree=NULL;
+
+#ifdef DEBUG_TCAPSRT
+  dbg(10,"\n Hend #%u ", pinfo->fd->num);
+#endif
+  /* look only for matching request, if matching conversation is available. */
+  tcaphash_end_key.tid = p_tcapsrt_info->dst_tid;
+  if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
+  {
+    /* We have MTP3 PCs (so we can safely do this cast) */
+    tcaphash_end_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
+    tcaphash_end_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
+  } else {
+    /* Don't have MTP3 PCs (maybe we're over SUA?) */
+    tcaphash_end_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
+    tcaphash_end_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
+  }
+  tcaphash_end_key.hashKey=tcaphash_end_calchash(&tcaphash_end_key);
+
+#ifdef DEBUG_TCAPSRT
+  dbg(11,"Ekey %lx ",tcaphash_end_key.hashKey);
+  dbg(11,"PC %s %s ",ep_address_to_str(&pinfo->src), ep_address_to_str(&pinfo->dst));
+  dbg(51,"Tid %lx ",tcaphash_end_key.tid);
+#endif
+  p_tcaphash_endcall = find_tcaphash_end(&tcaphash_end_key, pinfo,TRUE);
+
+  if(!p_tcaphash_endcall) {
+#ifdef DEBUG_TCAPSRT
+    dbg(12,"EnotFound ");
+#endif
+    tcaphash_begin_key.tid = p_tcapsrt_info->dst_tid;
+    if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
+    {
+      /* We have MTP3 PCs (so we can safely do this cast) */
+      tcaphash_begin_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
+      tcaphash_begin_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
+    } else {
+      /* Don't have MTP3 PCs (maybe we're over SUA?) */
+      tcaphash_begin_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
+      tcaphash_begin_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
+    }
+    tcaphash_begin_key.hashKey=tcaphash_begin_calchash(&tcaphash_begin_key);
+
+#ifdef DEBUG_TCAPSRT
+    dbg(11,"Bkey %lx ", tcaphash_begin_key.hashKey);
+    dbg(51,"PC %s %s ",ep_address_to_str(&pinfo->src), ep_address_to_str(&pinfo->dst));
+    dbg(51,"Tid %lx ",tcaphash_begin_key.tid);
+#endif
+    p_tcaphash_begincall = find_tcaphash_begin(&tcaphash_begin_key, pinfo,FALSE);
+    if(!p_tcaphash_begincall) {
+#ifdef DEBUG_TCAPSRT
+      dbg(12,"BnotFound ");
+#endif
+    }
+  }
+  if (p_tcaphash_endcall) {
+    /* Use the TC_BEGIN Destination reference */
+    p_tcaphash_context=p_tcaphash_endcall->context;
+  } else if (p_tcaphash_begincall) {
+    /* Use the TC_BEGIN Source reference */
+    p_tcaphash_context=p_tcaphash_begincall->context;
+  }
+
+  if (p_tcaphash_context) {
+
+#ifdef DEBUG_TCAPSRT
+    dbg(12,"Found, req=%d ",p_tcaphash_context->first_frame);
+#endif
+    if (gtcap_DisplaySRT && tree) {
+      stat_item = proto_tree_add_text(tree, tvb, 0, -1, "Stat");
+      PROTO_ITEM_SET_GENERATED(stat_item);
+      stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
+
+      pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
+      PROTO_ITEM_SET_GENERATED(pi);
+    }
+
+#ifdef DEBUG_TCAPSRT
+    dbg(20,"Display framereqlink %d ",p_tcaphash_context->first_frame);
+#endif
+    /* Indicate the frame to which this is a reply. */
+    if (gtcap_DisplaySRT && stat_tree) {
+      pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_EndSession, tvb, 0, 0,
+                                     p_tcaphash_context->first_frame,
+                                     "Begin of session in frame %u",
+                                     p_tcaphash_context->first_frame);
+      PROTO_ITEM_SET_GENERATED(pi);
+      /* Calculate Service Response Time */
+      nstime_delta(&delta, &pinfo->fd->abs_ts, &p_tcaphash_context->begin_time);
+
+      /* display Service Response Time and make it filterable */
+      pi = proto_tree_add_time(stat_tree, hf_tcapsrt_SessionTime, tvb, 0, 0, &delta);
+      PROTO_ITEM_SET_GENERATED(pi);
+    }
+    /* Close the context and remove it (if needed) */
+    tcapsrt_close(p_tcaphash_context,pinfo);
+
+  } else {/* context present */
+#ifdef DEBUG_TCAPSRT
+    dbg(12,"Context notFound ");
+#endif
+  }
+  return p_tcaphash_context;
+}
+
+/*
+ * ANSI PART
+ * Create the record identifiying the TCAP transaction
+ * When the identifier for the transaction is reused, check
+ * the following criteria before to append a new record:
+ * - a timeout corresponding to a message retransmission is detected,
+ * - a message hast been lost
+ * - or the previous transaction has been  be closed
+ */
+static struct tcaphash_context_t *
+tcaphash_ansi_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+                      struct tcapsrt_info_t *p_tcapsrt_info)
+{
+  struct tcaphash_context_t *p_tcaphash_context=NULL;
+  struct tcaphash_context_key_t tcaphash_context_key;
+  struct tcaphash_ansicall_t *p_tcaphash_ansicall, *p_new_tcaphash_ansicall;
+  struct tcaphash_ansi_info_key_t tcaphash_ansi_key;
+  proto_item *pi;
+  nstime_t delta;
+  gboolean isResponse=FALSE;
+  proto_tree * stat_tree=NULL;
+  proto_item * stat_item=NULL;
+
+  /* prepare the key data */
+  tcaphash_ansi_key.tid = p_tcapsrt_info->src_tid;
+  if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
+  {
+    /* We have MTP3 PCs (so we can safely do this cast) */
+    tcaphash_ansi_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
+    tcaphash_ansi_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
+  } else {
+    /* Don't have MTP3 PCs (maybe we're over SUA?) */
+    tcaphash_ansi_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
+    tcaphash_ansi_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
+  }
+  tcaphash_ansi_key.hashKey=tcaphash_ansi_calchash(&tcaphash_ansi_key);
+
+  /* look up the request */
+#ifdef DEBUG_TCAPSRT
+  dbg(10,"\n Hansi #%u ", pinfo->fd->num);
+  dbg(11,"key %lx ",tcaphash_ansi_key.hashKey);
+  dbg(51,"PC %s %s ",ep_address_to_str(&pinfo->src), ep_address_to_str(&pinfo->dst));
+  dbg(51,"Tid %lx ",tcaphash_ansi_key.tid);
+#endif
+  p_tcaphash_ansicall = (struct tcaphash_ansicall_t *)
+    g_hash_table_lookup(tcaphash_ansi, &tcaphash_ansi_key);
+
+  if (p_tcaphash_ansicall) {
+    /* Walk through list of transaction with identical keys */
+    do {
+      /* Check if the request with this reqSeqNum has been seen */
+      if (pinfo->fd->num == p_tcaphash_ansicall->context->first_frame) {
+       /* We have seen this request before -> do nothing */
+#ifdef DEBUG_TCAPSRT
+       dbg(22,"Request already seen ");
+#endif
+       isResponse=FALSE;
+       p_tcaphash_context=p_tcaphash_ansicall->context;
+       break;
+      }
+
+      /* Check if the reponse with this reqSeqNum has been seen */
+      if (pinfo->fd->num == p_tcaphash_ansicall->context->last_frame) {
+       /* We have seen this response before -> do nothing */
+#ifdef DEBUG_TCAPSRT
+       dbg(22,"Response already seen ");
+#endif
+       isResponse=TRUE;
+       p_tcaphash_context=p_tcaphash_ansicall->context;
+       break;
+      }
+
+      /* Check for the first Request without Response
+       received before this frame */
+      if ( pinfo->fd->num > p_tcaphash_ansicall->context->first_frame &&
+          p_tcaphash_ansicall->context->last_frame==0 ) {
+       /* Take it, and update the context */
+
+#ifdef DEBUG_TCAPSRT
+       dbg(12,"Update key %lx ",tcaphash_ansi_key.hashKey);
+#endif
+       p_tcaphash_ansicall->context->last_frame = pinfo->fd->num;
+       p_tcaphash_ansicall->context->responded = TRUE;
+       p_tcaphash_ansicall->context->closed = TRUE;
+       p_tcaphash_context=p_tcaphash_ansicall->context;
+       isResponse=TRUE;
+
+       if (gtcap_DisplaySRT && tree) {
+         stat_item = proto_tree_add_text(tree, tvb, 0, -1, "Stat");
+         PROTO_ITEM_SET_GENERATED(stat_item);
+         stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
+
+         pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
+         PROTO_ITEM_SET_GENERATED(pi);
+
+#ifdef DEBUG_TCAPSRT
+         dbg(20,"Display framereqlink %d ",p_tcaphash_context->first_frame);
+#endif
+         /* Indicate the frame to which this is a reply. */
+         pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_EndSession, tvb, 0, 0,
+                                         p_tcaphash_context->first_frame,
+                                         "Begin of session in frame %u",
+                                         p_tcaphash_context->first_frame);
+         PROTO_ITEM_SET_GENERATED(pi);
+         /* Calculate Service Response Time */
+         nstime_delta(&delta, &pinfo->fd->abs_ts, &p_tcaphash_context->begin_time);
+
+         /* display Service Response Time and make it filterable */
+         pi = proto_tree_add_time(stat_tree, hf_tcapsrt_SessionTime, tvb, 0, 0, &delta);
+         PROTO_ITEM_SET_GENERATED(pi);
+       }
+       break;
+      } /* Lastframe=0, so take it */
+
+
+      /* If the last record for Tcap transaction with identifier has been reached */
+      if (!p_tcaphash_ansicall->next_ansicall) {
+       /* check if we have to create a new record or not */
+       /* if last request has been responded (response number in known)
+          and this request appears after last response (has bigger frame number)
+          and last request occurred after the timeout for repetition,
+          or
+          if last request hasn't been responded (so number unknown)
+          and this request appears after last request (has bigger frame number)
+          and this request occurred after the timeout for message lost */
+       if ( ( p_tcaphash_ansicall->context->last_frame != 0
+              && pinfo->fd->num > p_tcaphash_ansicall->context->first_frame
+              && (guint) pinfo->fd->abs_ts.secs > (guint)(p_tcaphash_ansicall->context->begin_time.secs + gtcap_RepetitionTimeout)
+              ) ||
+            ( p_tcaphash_ansicall->context->last_frame == 0
+              && pinfo->fd->num > p_tcaphash_ansicall->context->first_frame
+              && (guint)pinfo->fd->abs_ts.secs > (guint)(p_tcaphash_ansicall->context->begin_time.secs + gtcap_LostTimeout)
+              )
+            )
+         {
+           /* we decide that we have a new request */
+           /* Append new record to the list */
+#ifdef DEBUG_TCAPSRT
+           dbg(12,"(timeout) Append key %lx ",tcaphash_ansi_key.hashKey);
+           dbg(12,"Frame %u rsp %u ",pinfo->fd->num,p_tcaphash_ansicall->context->last_frame );
+#endif
+           tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
+           p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
+           p_new_tcaphash_ansicall = append_tcaphash_ansicall(p_tcaphash_ansicall,
+                                                                p_tcaphash_context,
+                                                                pinfo);
+
+#ifdef DEBUG_TCAPSRT
+           dbg(12,"Update key %lx ",tcaphash_ansi_key.hashKey);
+#endif
+           update_tcaphash_ansicall(p_new_tcaphash_ansicall, pinfo);
+           p_tcaphash_ansicall=p_new_tcaphash_ansicall;
+         } else {
+
+         /* If the Tid is reused for a closed Transaction */
+         if ( p_tcaphash_ansicall->context->closed) {
+#ifdef DEBUG_TCAPSRT
+           dbg(12,"(closed) Append key %lu ",tcaphash_ansi_key.hashKey);
+           dbg(12,"Frame %u rsp %u ",pinfo->fd->num,p_tcaphash_ansicall->context->last_frame );
+#endif
+           tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
+           p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
+           p_new_tcaphash_ansicall = append_tcaphash_ansicall(p_tcaphash_ansicall,
+                                                                p_tcaphash_context,
+                                                                pinfo);
+
+#ifdef DEBUG_TCAPSRT
+           dbg(12,"Update key %lu ",tcaphash_ansi_key.hashKey);
+#endif
+           update_tcaphash_ansicall(p_new_tcaphash_ansicall, pinfo);
+           p_tcaphash_ansicall=p_new_tcaphash_ansicall;
+
+         } else {
+           /* the Tid is reused for an opened Transaction */
+           /* so, this is the reply to the request of our context */
+           p_tcaphash_context=p_tcaphash_ansicall->context;
+#ifdef DEBUG_TCAPSRT
+           dbg(12,"Found, req=%d ",p_tcaphash_context->first_frame);
+#endif
+
+           if (gtcap_DisplaySRT && tree) {
+             stat_item = proto_tree_add_text(tree, tvb, 0, -1, "Stat");
+             PROTO_ITEM_SET_GENERATED(stat_item);
+             stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
+
+             pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
+             PROTO_ITEM_SET_GENERATED(pi);
+
+#ifdef DEBUG_TCAPSRT
+             dbg(20,"Display framereqlink %d ",p_tcaphash_context->first_frame);
+#endif
+             /* Indicate the frame to which this is a reply. */
+             pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_EndSession, tvb, 0, 0,
+                                             p_tcaphash_context->first_frame,
+                                             "Begin of session in frame %u",
+                                             p_tcaphash_context->first_frame);
+             PROTO_ITEM_SET_GENERATED(pi);
+             /* Calculate Service Response Time */
+             nstime_delta(&delta, &pinfo->fd->abs_ts, &p_tcaphash_context->begin_time);
+
+             /* display Service Response Time and make it filterable */
+             pi = proto_tree_add_time(stat_tree, hf_tcapsrt_SessionTime, tvb, 0, 0, &delta);
+             PROTO_ITEM_SET_GENERATED(pi);
+           }
+           p_tcaphash_context=p_tcaphash_ansicall->context;
+         } /* test with Timeout */
+       } /* closed */
+       break;
+      } /* Next call is NULL */
+      p_tcaphash_ansicall = p_tcaphash_ansicall->next_ansicall;
+    } while (p_tcaphash_ansicall != NULL );
+    /*
+     * New TCAP context
+     */
+  } else { /* p_tcaphash_ansicall has not been found */
+#ifdef DEBUG_TCAPSRT
+    dbg(10,"New key %lx ",tcaphash_ansi_key.hashKey);
+#endif
+
+    tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
+    p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
+    p_tcaphash_ansicall = new_tcaphash_ansi(&tcaphash_ansi_key, p_tcaphash_context);
+
+#ifdef DEBUG_TCAPSRT
+    dbg(11,"Update key %lx ",tcaphash_ansi_key.hashKey);
+    dbg(11,"Frame reqlink #%u ", pinfo->fd->num);
+#endif
+    update_tcaphash_ansicall(p_tcaphash_ansicall, pinfo);
+  }
+
+  /* display tcap session, if available */
+  if ( gtcap_DisplaySRT && tree &&
+       p_tcaphash_context &&
+       p_tcaphash_context->session_id) {
+    stat_item = proto_tree_add_text(tree, tvb, 0, -1, "Stat");
+    PROTO_ITEM_SET_GENERATED(stat_item);
+    stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
+    pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
+    PROTO_ITEM_SET_GENERATED(pi);
+  }
+
+
+  /* add link to response frame, if available */
+  if( gtcap_DisplaySRT && stat_tree &&
+      p_tcaphash_ansicall->context->last_frame != 0){
+    if (!isResponse) { /* Request */
+#ifdef DEBUG_TCAPSRT
+      dbg(20,"Display_frameRsplink %d ",p_tcaphash_ansicall->context->last_frame);
+#endif
+      pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_BeginSession, tvb, 0, 0,
+                                     p_tcaphash_ansicall->context->last_frame,
+                                     "End of session in frame %u",
+                                     p_tcaphash_ansicall->context->last_frame);
+      PROTO_ITEM_SET_GENERATED(pi);
+    } else { /* Response */
+#ifdef DEBUG_TCAPSRT
+      dbg(20,"Display framereqlink %d ",p_tcaphash_context->first_frame);
+#endif
+      /* Indicate the frame to which this is a reply. */
+      if (gtcap_DisplaySRT) {
+       pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_EndSession, tvb, 0, 0,
+                                       p_tcaphash_context->first_frame,
+                                       "Begin of session in frame %u",
+                                       p_tcaphash_context->first_frame);
+       PROTO_ITEM_SET_GENERATED(pi);
+       /* Calculate Service Response Time */
+       nstime_delta(&delta, &pinfo->fd->abs_ts, &p_tcaphash_context->begin_time);
+
+       /* display Service Response Time and make it filterable */
+       pi = proto_tree_add_time(stat_tree, hf_tcapsrt_SessionTime, tvb, 0, 0, &delta);
+       PROTO_ITEM_SET_GENERATED(pi);
+      }
+    } /* Request or Response */
+  }
+  return p_tcaphash_context;
+}
+
+/*
+ * Service Response Time analyze
+ * Called just after dissector call
+ * Associate a TCAP context to a tcap session and display session related infomations
+ * like the first frame, the last, the session duration,
+ * and a uniq session identifier for the filtering
+ *
+ * For ETSI tcap, the TCAP context can be reached through three keys
+ * - a key (BEGIN) identifying the session according to the tcap source identifier
+ * - a key (CONT) identifying the established session (src_id and dst_id)
+ * - a key (END) identifying the session according to the tcap destination identifier
+ *
+ * For ANSI tcap, the TCAP context is reached through a uniq key
+ * - a key (ANSI) identifying the session according to the tcap identifier
+*/
+struct tcaphash_context_t *
+tcapsrt_call_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+                     struct tcapsrt_info_t *p_tcapsrt_info)
+{
+  struct tcaphash_context_t *tcap_context=NULL;
+
+  /* if this packet isn't loaded because of a read filter, don't output anything */
+  if(pinfo == NULL || pinfo->fd->num == 0) {
+    return NULL;
+  }
+
+  switch (p_tcapsrt_info->ope) {
+
+  case TC_BEGIN:
+#ifdef DEBUG_TCAPSRT
+    dbg(1,"\nTC_BEGIN ");
+#endif
+    tcap_context=tcaphash_begin_matching(tvb, pinfo, tree, p_tcapsrt_info);
+    break;
+
+  case TC_CONT:
+#ifdef DEBUG_TCAPSRT
+    dbg(1,"\nTC_CONT ");
+#endif
+    tcap_context=tcaphash_cont_matching(tvb, pinfo, tree, p_tcapsrt_info);
+    break;
+
+  case TC_ABORT:
+#ifdef DEBUG_TCAPSRT
+    dbg(1,"\nTC_ABORT ");
+#endif
+    tcap_context=tcaphash_end_matching(tvb, pinfo, tree, p_tcapsrt_info);
+    break;
+
+  case TC_END:
+#ifdef DEBUG_TCAPSRT
+    dbg(1,"\nTC_END ");
+#endif
+    tcap_context=tcaphash_end_matching(tvb, pinfo, tree, p_tcapsrt_info);
+    break;
+
+  case TC_ANSI_ALL:
+  case TC_ANSI_ABORT:
+#ifdef DEBUG_TCAPSRT
+    dbg(1,"\nTC_ANSI ");
+#endif
+    tcap_context=tcaphash_ansi_matching(tvb, pinfo, tree, p_tcapsrt_info);
+    break;
+
+  default:
+#ifdef DEBUG_TCAPSRT
+    dbg(1,"\nUnknown %d ", p_tcapsrt_info->ope);
+#endif
+    break;
+  } /* switch tcapop */
+#ifdef DEBUG_TCAPSRT
+  if (tcap_context)
+    dbg(1,"session %d ", tcap_context->session_id);
+#endif
+  return tcap_context;
+}
+
+/*
+ * Initialize the Message Info used by the main dissector
+ * Data are linked to a TCAP transaction
+ */
+struct tcapsrt_info_t *
+tcapsrt_razinfo(void)
+{
+  struct tcapsrt_info_t *p_tcapsrt_info ;
+
+  /* Global buffer for packet extraction */
+  tcapsrt_global_current++;
+  if(tcapsrt_global_current==MAX_TCAP_INSTANCE){
+    tcapsrt_global_current=0;
+  }
+
+  p_tcapsrt_info=&tcapsrt_global_info[tcapsrt_global_current];
+  memset(p_tcapsrt_info,0,sizeof(struct tcapsrt_info_t));
+
+  return p_tcapsrt_info;
+}
+
+void
+tcapsrt_close(struct tcaphash_context_t *p_tcaphash_context,
+             packet_info *pinfo)
+{
+#ifdef DEBUG_TCAPSRT
+  dbg(60,"Force close ");
+#endif
+  if (p_tcaphash_context) {
+    p_tcaphash_context->responded=TRUE;
+    p_tcaphash_context->last_frame = pinfo->fd->num;
+    p_tcaphash_context->end_time = pinfo->fd->abs_ts;
+    p_tcaphash_context->closed=TRUE;
+
+    /* If the endkey is present */
+    if (p_tcaphash_context->endcall
+       && !gtcap_PersistentSRT) {
+      if (p_tcaphash_context->endcall->next_endcall) {
+       if (p_tcaphash_context->endcall->previous_endcall ) {
+#ifdef DEBUG_TCAPSRT
+         dbg(20,"deplace Ehash ");
+#endif
+         p_tcaphash_context->endcall->previous_endcall->next_endcall
+           = p_tcaphash_context->endcall->next_endcall;
+         p_tcaphash_context->endcall->next_endcall->previous_endcall
+           = p_tcaphash_context->endcall->previous_endcall;
+         g_hash_table_remove(tcaphash_end, p_tcaphash_context->endcall->endkey);
+#ifdef MEM_TCAPSRT
+         g_free(p_tcaphash_context->endcall);
+#endif
+       } else {
+         /* cannot remove the father */
+#ifdef DEBUG_TCAPSRT
+         dbg(20,"father Ehash ");
+#endif
+       } /* no previous link, so father */
+      } else if (!gtcap_PersistentSRT) {
+#ifdef DEBUG_TCAPSRT
+       dbg(20,"remove Ehash ");
+#endif
+       g_hash_table_remove(tcaphash_end, p_tcaphash_context->endcall->endkey);
+#ifdef MEM_TCAPSRT
+       g_free(p_tcaphash_context->endcall->endkey);
+       g_free(p_tcaphash_context->endcall);
+#endif
+
+      } /* endcall without chained string */
+    } /* no endcall */
+
 
+    /* If the contkey is present */
+    if (p_tcaphash_context->contcall
+       && !gtcap_PersistentSRT) {
+      if (p_tcaphash_context->contcall->next_contcall) {
+       if (p_tcaphash_context->contcall->previous_contcall ) {
+#ifdef DEBUG_TCAPSRT
+         dbg(20,"deplace Chash ");
+#endif
+         p_tcaphash_context->contcall->previous_contcall->next_contcall
+           = p_tcaphash_context->contcall->next_contcall;
+         p_tcaphash_context->contcall->next_contcall->previous_contcall
+           = p_tcaphash_context->contcall->previous_contcall;
+         g_hash_table_remove(tcaphash_cont, p_tcaphash_context->contcall->contkey);
+#ifdef MEM_TCAPSRT
+         g_free(p_tcaphash_context->contcall);
+#endif
+       } else {
+         /* cannot remove the father */
+#ifdef DEBUG_TCAPSRT
+         dbg(20,"father Chash ");
+#endif
+       } /* no previous link, so father */
+      } else if (!gtcap_PersistentSRT) {
+#ifdef DEBUG_TCAPSRT
+       dbg(20,"remove Chash ");
+#endif
+       g_hash_table_remove(tcaphash_cont, p_tcaphash_context->contcall->contkey);
+#ifdef MEM_TCAPSRT
+       g_free(p_tcaphash_context->contcall->contkey);
+       g_free(p_tcaphash_context->contcall);
+#endif
+      } /* contcall without chained string */
+    } /* no contcall */
+
+
+    /* If the beginkey is present */
+    if (p_tcaphash_context->begincall
+       && !gtcap_PersistentSRT) {
+      if (p_tcaphash_context->begincall->next_begincall) {
+       if (p_tcaphash_context->begincall->previous_begincall ) {
+#ifdef DEBUG_TCAPSRT
+         dbg(20,"deplace Bhash ");
+#endif
+         p_tcaphash_context->begincall->previous_begincall->next_begincall
+           = p_tcaphash_context->begincall->next_begincall;
+         p_tcaphash_context->begincall->next_begincall->previous_begincall
+           = p_tcaphash_context->begincall->previous_begincall;
+         g_hash_table_remove(tcaphash_begin, p_tcaphash_context->begincall->beginkey);
+#ifdef MEM_TCAPSRT
+         g_free(p_tcaphash_context->begincall);
+#endif
+       } else {
+         /* cannot remove the father */
+#ifdef DEBUG_TCAPSRT
+         dbg(20,"father Bhash ");
+#endif
+       }
+      } else  if (!gtcap_PersistentSRT) {
+#ifdef DEBUG_TCAPSRT
+       dbg(20,"remove Bhash ");
+#endif
+       g_hash_table_remove(tcaphash_begin, p_tcaphash_context->begincall->beginkey);
+#ifdef MEM_TCAPSRT
+       g_free(p_tcaphash_context->begincall->beginkey);
+       g_free(p_tcaphash_context->begincall);
+#endif
+      } /* begincall without chained string */
+    } /* no begincall */
+
+    /* If the ansikey is present */
+    if (p_tcaphash_context->ansicall
+       && !gtcap_PersistentSRT) {
+      if (p_tcaphash_context->ansicall->next_ansicall) {
+       if (p_tcaphash_context->ansicall->previous_ansicall ) {
+#ifdef DEBUG_TCAPSRT
+         dbg(20,"deplace Ahash ");
+#endif
+         p_tcaphash_context->ansicall->previous_ansicall->next_ansicall
+           = p_tcaphash_context->ansicall->next_ansicall;
+         p_tcaphash_context->ansicall->next_ansicall->previous_ansicall
+           = p_tcaphash_context->ansicall->previous_ansicall;
+         g_hash_table_remove(tcaphash_ansi, p_tcaphash_context->ansicall->ansikey);
+#ifdef MEM_TCAPSRT
+         g_free(p_tcaphash_context->ansicall);
+#endif
+       } else {
+         /* cannot remove the father */
+#ifdef DEBUG_TCAPSRT
+         dbg(20,"father Ahash ");
+#endif
+       }
+      } else  if (!gtcap_PersistentSRT) {
+#ifdef DEBUG_TCAPSRT
+       dbg(20,"remove Ahash ");
+#endif
+       g_hash_table_remove(tcaphash_ansi, p_tcaphash_context->ansicall->ansikey);
+#ifdef MEM_TCAPSRT
+       g_free(p_tcaphash_context->ansicall->ansikey);
+       g_free(p_tcaphash_context->ansicall);
+#endif
+      } /* ansicall without chained string */
+    } /* no ansicall */
 
+    if (!gtcap_PersistentSRT) {
+#ifdef DEBUG_TCAPSRT
+      dbg(20,"remove context ");
+#endif
+      g_hash_table_remove(tcaphash_context, p_tcaphash_context->key);
+#ifdef MEM_TCAPSRT
+      g_free(p_tcaphash_context->key);
+      g_free(p_tcaphash_context);
+#endif
+    }
+  } else { /* no context */
+#ifdef DEBUG_TCAPSRT
+    dbg(20,"No context to remove ");
+#endif
+  }
+}
 
 const value_string tcap_component_type_str[] = {
     { TCAP_COMP_INVOKE,                "Invoke" },
@@ -1543,7 +3369,7 @@ proto_reg_handoff_tcap(void)
 
 
 /*--- End of included file: packet-tcap-dis-tab.c ---*/
-#line 253 "../../asn1/tcap/packet-tcap-template.c"
+#line 2079 "../../asn1/tcap/packet-tcap-template.c"
 }
 
 static void init_tcap(void);
@@ -1874,7 +3700,7 @@ proto_register_tcap(void)
         NULL, HFILL }},
 
 /*--- End of included file: packet-tcap-hfarr.c ---*/
-#line 315 "../../asn1/tcap/packet-tcap-template.c"
+#line 2141 "../../asn1/tcap/packet-tcap-template.c"
     };
 
 /* Setup protocol subtree array */
@@ -1923,7 +3749,7 @@ proto_register_tcap(void)
     &ett_tcap_Associate_source_diagnostic,
 
 /*--- End of included file: packet-tcap-ettarr.c ---*/
-#line 325 "../../asn1/tcap/packet-tcap-template.c"
+#line 2151 "../../asn1/tcap/packet-tcap-template.c"
     };
 
     /*static enum_val_t tcap_options[] = {
index d28b5158f08d4dda59a157e00407f626fefef234..1faba2fc4172d45977d0490825ab21c2d8fdf1e4 100644 (file)
@@ -78,6 +78,147 @@ struct tcap_private_t {
   gchar *TransactionID_str;
 };
 
+/** @file
+ * lists and hash tables used in wireshark's tcap dissector
+ * for calculation of delays in tcap-calls
+ */
+
+#define LENGTH_OID 23
+struct tcaphash_context_t {
+  struct tcaphash_context_key_t * key;
+  guint32 session_id;
+  guint32 first_frame;
+  guint32 last_frame;
+  nstime_t begin_time; /**< time of arrival of TC_BEGIN */
+  nstime_t end_time;   /**< time of closing message */
+  gboolean responded;  /**< true, if request has been responded */
+  gboolean closed;
+  gboolean upper_dissector;
+  gboolean oid_present;
+  gchar oid[LENGTH_OID+1];
+  gboolean subdissector_present;
+  dissector_handle_t subdissector_handle;
+  void (* callback) (tvbuff_t *,packet_info *, proto_tree *, struct tcaphash_context_t *);
+  struct tcaphash_begincall_t * begincall;
+  struct tcaphash_contcall_t * contcall;
+  struct tcaphash_endcall_t * endcall;
+  struct tcaphash_ansicall_t * ansicall;
+};
+
+struct tcaphash_begincall_t {
+  struct tcaphash_begin_info_key_t * beginkey;
+  struct tcaphash_context_t * context;
+  gboolean father;
+  struct tcaphash_begincall_t * next_begincall;
+  struct tcaphash_begincall_t * previous_begincall;
+};
+
+struct tcaphash_contcall_t {
+  struct tcaphash_cont_info_key_t * contkey;
+  struct tcaphash_context_t * context;
+  gboolean father;
+  struct tcaphash_contcall_t * next_contcall;
+  struct tcaphash_contcall_t * previous_contcall;
+};
+
+struct tcaphash_endcall_t {
+  struct tcaphash_end_info_key_t * endkey;
+  struct tcaphash_context_t * context;
+  gboolean father;
+  struct tcaphash_endcall_t * next_endcall;
+  struct tcaphash_endcall_t * previous_endcall;
+};
+
+struct tcaphash_ansicall_t {
+  struct tcaphash_ansi_info_key_t * ansikey;
+  struct tcaphash_context_t * context;
+  gboolean father;
+  struct tcaphash_ansicall_t * next_ansicall;
+  struct tcaphash_ansicall_t * previous_ansicall;
+};
+
+/** The Key for the hash table is the TCAP origine transaction identifier
+   of the TC_BEGIN containing the InitialDP */
+
+struct tcaphash_context_key_t {
+  guint32 session_id;
+};
+
+struct tcaphash_begin_info_key_t {
+  guint32 hashKey;
+  guint32 tid;
+  guint32 opc_hash;
+  guint32 dpc_hash;
+};
+
+struct tcaphash_cont_info_key_t {
+  guint32 hashKey;
+  guint32 src_tid;
+  guint32 dst_tid;
+  guint32 opc_hash;
+  guint32 dpc_hash;
+};
+
+struct tcaphash_end_info_key_t {
+  guint32 hashKey;
+  guint32 tid;
+  guint32 opc_hash;
+  guint32 dpc_hash;
+};
+
+struct tcaphash_ansi_info_key_t {
+  guint32 hashKey;
+  guint32 tid;
+  guint32 opc_hash;
+  guint32 dpc_hash;
+};
+
+
+/** List of infos to store for the analyse */
+struct tcapsrt_info_t {
+  guint32 tcap_session_id;
+  guint32 src_tid;
+  guint32 dst_tid;
+  guint8 ope;
+};
+
+/**
+ * Routine called when the TAP is initialized.
+ * so hash table are (re)created
+ */
+void tcapsrt_init_routine(void);
+
+/**
+ * Initialize the Message Info used by the main dissector
+ * Data are linked to a TCAP transaction
+ */
+struct tcapsrt_info_t * tcapsrt_razinfo(void);
+
+void tcapsrt_close(struct tcaphash_context_t * p_tcaphash_context,
+                  packet_info * pinfo _U_);
+
+/**
+ * Service Response Time analyze
+ * Called just after dissector call
+ * Associate a TCAP context to a tcap session and display session related infomations
+ * like the first frame, the last, the session duration,
+ * and a uniq session identifier for the filtering
+ *
+ * For ETSI tcap, the TCAP context can be reached through three keys
+ * - a key (BEGIN) identifying the session according to the tcap source identifier
+ * - a key (CONT) identifying the established session (src_id and dst_id)
+ * - a key (END) identifying the session according to the tcap destination identifier
+ *
+ * For ANSI tcap, the TCAP context is reached through a uniq key
+ * - a key (ANSI) identifying the session according to the tcap identifier
+*/
+struct tcaphash_context_t * tcapsrt_call_matching(tvbuff_t *tvb,
+                                                 packet_info * pinfo _U_,
+                                                 proto_tree *tree,
+                                                 struct tcapsrt_info_t * p_tcap_info);
+
+WS_DLL_PUBLIC gboolean gtcap_StatSRT;
+
 extern gint tcap_standard;
 
 extern const value_string tcap_component_type_str[];
@@ -104,6 +245,6 @@ int dissect_tcap_UniDialoguePDU(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, in
 int dissect_tcap_DialoguePDU(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
 
 /*--- End of included file: packet-tcap-exp.h ---*/
-#line 91 "../../asn1/tcap/packet-tcap-template.h"
+#line 232 "../../asn1/tcap/packet-tcap-template.h"
 
 #endif  /* PACKET_tcap_H */
diff --git a/epan/tcap-persistentdata.c b/epan/tcap-persistentdata.c
deleted file mode 100644 (file)
index 7e84f5e..0000000
+++ /dev/null
@@ -1,1940 +0,0 @@
-/*
- * tcap-persistentdata.c
- * Source for lists and hash tables used in wireshark's tcap dissector
- * for calculation of delays in tcap-calls
- * Copyright 2006 Florent Drouin (based on h225-persistentdata.c from Lars Roland)
- *
- * Wireshark - Network traffic analyzer
- * By Gerald Combs <gerald@wireshark.org>
- * Copyright 1998 Gerald Combs
- *
- * $Id$
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include "config.h"
-
-#include <glib.h>
-#include <string.h>
-
-#include <epan/emem.h>
-#include <epan/packet.h>
-#include <epan/to_str.h>
-#include <epan/asn1.h>
-#include <epan/tcap-persistentdata.h>
-#include <epan/dissectors/packet-tcap.h>
-#include <epan/dissectors/packet-mtp3.h>
-
-static gint tcaphash_context_equal(gconstpointer k1, gconstpointer k2);
-static guint tcaphash_context_calchash(gconstpointer k);
-static gint tcaphash_begin_equal(gconstpointer k1, gconstpointer k2);
-static guint tcaphash_begin_calchash(gconstpointer k);
-static gint tcaphash_cont_equal(gconstpointer k1, gconstpointer k2);
-static guint tcaphash_cont_calchash(gconstpointer k);
-static gint tcaphash_end_equal(gconstpointer k1, gconstpointer k2);
-static guint tcaphash_end_calchash(gconstpointer k);
-static gint tcaphash_ansi_equal(gconstpointer k1, gconstpointer k2);
-static guint tcaphash_ansi_calchash(gconstpointer k);
-
-static void update_tcaphash_begincall(struct tcaphash_begincall_t *p_tcaphash_begincall,
-                                     packet_info *pinfo );
-
-static struct tcaphash_begincall_t *append_tcaphash_begincall(struct tcaphash_begincall_t *prev_begincall,
-                                                             struct tcaphash_context_t *p_tcaphash_context,
-                                                             packet_info *pinfo);
-
-
-static struct tcaphash_begincall_t *find_tcaphash_begin(struct tcaphash_begin_info_key_t *p_tcaphash_begin_key,
-                                                       packet_info *pinfo,
-                                                       gboolean isBegin);
-
-
-static struct tcaphash_contcall_t *find_tcaphash_cont(struct tcaphash_cont_info_key_t *p_tcaphash_cont_key,
-                                                     packet_info *pinfo);
-
-static struct tcaphash_endcall_t *find_tcaphash_end(struct tcaphash_end_info_key_t *p_tcaphash_end_key,
-                                                   packet_info *pinfo,
-                                                   gboolean isEnd);
-/* new key */
-static struct tcaphash_context_t *new_tcaphash_context(struct tcaphash_context_key_t *p_tcaphash_context_key,
-                                                      packet_info *pinfo);
-
-static struct tcaphash_begincall_t *new_tcaphash_begin(struct tcaphash_begin_info_key_t *p_tcaphash_begin_key,
-                                                      struct tcaphash_context_t *p_tcaphash_context);
-
-static struct tcaphash_contcall_t *new_tcaphash_cont(struct tcaphash_cont_info_key_t *p_tcaphash_cont_key,
-                                                    struct tcaphash_context_t *p_tcaphash_context);
-
-static struct tcaphash_endcall_t *new_tcaphash_end(struct tcaphash_end_info_key_t *p_tcaphash_end_key,
-                                                  struct tcaphash_context_t *p_tcaphash_context);
-
-static struct tcaphash_context_t *tcaphash_begin_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
-                                                         struct tcapsrt_info_t *p_tcapsrt_info);
-
-static struct tcaphash_context_t *tcaphash_cont_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
-                                                        struct tcapsrt_info_t *p_tcapsrt_info);
-
-static struct tcaphash_context_t *tcaphash_end_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
-                                                       struct tcapsrt_info_t *p_tcapsrt_info);
-
-static struct tcaphash_context_t *tcaphash_ansi_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
-                                                        struct tcapsrt_info_t *p_tcapsrt_info);
-
-/* When several Tcap 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_TCAP_INSTANCE 10
-int tcapsrt_global_current=0;
-struct tcapsrt_info_t tcapsrt_global_info[MAX_TCAP_INSTANCE];
-
-/* These two timeout (in second) are used when some message are lost,
-   or when the same TCAP transcation identifier is reused */
-guint gtcap_RepetitionTimeout = 10;
-guint gtcap_LostTimeout = 30;
-extern gboolean gtcap_HandleSRT;
-gboolean gtcap_PersistentSRT=FALSE;
-gboolean gtcap_DisplaySRT=FALSE;
-gboolean gtcap_StatSRT=FALSE;
-
-extern gint ett_tcap_stat;
-
-extern int hf_tcapsrt_SessionId;
-extern int hf_tcapsrt_Duplicate;
-extern int hf_tcapsrt_BeginSession;
-extern int hf_tcapsrt_EndSession;
-extern int hf_tcapsrt_SessionTime;
-
-/* Global hash tables*/
-static GHashTable *tcaphash_context = NULL;
-static GHashTable *tcaphash_begin = NULL;
-static GHashTable *tcaphash_cont = NULL;
-static GHashTable *tcaphash_end = NULL;
-static GHashTable *tcaphash_ansi = NULL;
-
-guint32 tcapsrt_global_SessionId=1;
-
-/*
- * DEBUG functions
- */
-#undef MEM_TCAPSRT
-/* #define MEM_TCAPSRT */
-
-#undef DEBUG_TCAPSRT
-/* #define DEBUG_TCAPSRT */
-
-#ifdef DEBUG_TCAPSRT
-#include <stdio.h>
-#include <stdarg.h>
-static guint debug_level = 99;
-
-static void
-dbg(guint level, char* fmt, ...)
-{
-  va_list ap;
-
-  if (level > debug_level) return;
-  va_start(ap,fmt);
-  vfprintf(stderr, fmt, ap);
-  va_end(ap);
-}
-#endif
-
-static gint
-tcaphash_context_equal(gconstpointer k1, gconstpointer k2)
-{
-  const struct tcaphash_context_key_t *key1 = (const struct tcaphash_context_key_t *) k1;
-  const struct tcaphash_context_key_t *key2 = (const struct tcaphash_context_key_t *) k2;
-
-  return (key1->session_id == key2->session_id);
-}
-
-/* calculate a hash key */
-static guint
-tcaphash_context_calchash(gconstpointer k)
-{
-  const struct tcaphash_context_key_t *key = (const struct tcaphash_context_key_t *) k;
-  return key->session_id;
-}
-
-
-static gint
-tcaphash_begin_equal(gconstpointer k1, gconstpointer k2)
-{
-  const struct tcaphash_begin_info_key_t *key1 = (const struct tcaphash_begin_info_key_t *) k1;
-  const struct tcaphash_begin_info_key_t *key2 = (const struct tcaphash_begin_info_key_t *) k2;
-
-  if (key1->hashKey == key2->hashKey) {
-
-    if ( ( (key1->opc_hash == key2->opc_hash) &&
-          (key1->dpc_hash == key2->dpc_hash) &&
-          (key1->tid == key2->tid) )
-        ||
-        ( (key1->opc_hash == key2->dpc_hash) &&
-          (key1->dpc_hash == key2->opc_hash) &&
-          (key1->tid == key2->tid) )
-        )
-      return TRUE;
-  }
-  return FALSE;
-}
-
-/* calculate a hash key */
-static guint
-tcaphash_begin_calchash(gconstpointer k)
-{
-  const struct tcaphash_begin_info_key_t *key = (const struct tcaphash_begin_info_key_t *) k;
-  guint hashkey;
-  /* hashkey = key->opc_hash<<16 + key->dpc_hash<<8 + key->src_tid; */
-  hashkey = key->tid;
-  return hashkey;
-}
-
-static gint
-tcaphash_cont_equal(gconstpointer k1, gconstpointer k2)
-{
-  const struct tcaphash_cont_info_key_t *key1 = (const struct tcaphash_cont_info_key_t *) k1;
-  const struct tcaphash_cont_info_key_t *key2 = (const struct tcaphash_cont_info_key_t *) k2;
-
-  if (key1->hashKey == key2->hashKey) {
-
-    if ( (key1->opc_hash == key2->opc_hash) &&
-        (key1->dpc_hash == key2->dpc_hash) &&
-        (key1->src_tid == key2->src_tid) &&
-        (key1->dst_tid == key2->dst_tid) ) {
-      return TRUE;
-    }
-    else if ( (key1->opc_hash == key2->dpc_hash) &&
-             (key1->dpc_hash == key2->opc_hash) &&
-             (key1->src_tid == key2->dst_tid) &&
-             (key1->dst_tid == key2->src_tid) ) {
-      return TRUE;
-    }
-  }
-  return FALSE;
-}
-
-/* calculate a hash key */
-static guint
-tcaphash_cont_calchash(gconstpointer k)
-{
-  const struct tcaphash_cont_info_key_t *key = (const struct tcaphash_cont_info_key_t *) k;
-  guint hashkey;
-  hashkey = key->src_tid + key->dst_tid;
-  return hashkey;
-}
-
-
-static gint
-tcaphash_end_equal(gconstpointer k1, gconstpointer k2)
-{
-  const struct tcaphash_end_info_key_t *key1 = (const struct tcaphash_end_info_key_t *) k1;
-  const struct tcaphash_end_info_key_t *key2 = (const struct tcaphash_end_info_key_t *) k2;
-
-  if (key1->hashKey == key2->hashKey) {
-    if ( ( (key1->opc_hash == key2->opc_hash) &&
-          (key1->dpc_hash == key2->dpc_hash) &&
-          (key1->tid == key2->tid) )
-        ||
-        ( (key1->opc_hash == key2->dpc_hash) &&
-          (key1->dpc_hash == key2->opc_hash) &&
-          (key1->tid == key2->tid) ) )
-      return TRUE;
-  }
-  return FALSE;
-}
-
-/* calculate a hash key */
-static guint
-tcaphash_end_calchash(gconstpointer k)
-{
-  const struct tcaphash_end_info_key_t *key = (const struct tcaphash_end_info_key_t *) k;
-  guint hashkey;
-  hashkey = key->tid;
-  return hashkey;
-}
-
-static gint
-tcaphash_ansi_equal(gconstpointer k1, gconstpointer k2)
-{
-  const struct tcaphash_ansi_info_key_t *key1 = (const struct tcaphash_ansi_info_key_t *) k1;
-  const struct tcaphash_ansi_info_key_t *key2 = (const struct tcaphash_ansi_info_key_t *) k2;
-
-  if (key1->hashKey == key2->hashKey) {
-
-    if ( ( (key1->opc_hash == key2->opc_hash) &&
-          (key1->dpc_hash == key2->dpc_hash) &&
-          (key1->tid == key2->tid) )
-        ||
-        ( (key1->opc_hash == key2->dpc_hash) &&
-          (key1->dpc_hash == key2->opc_hash) &&
-          (key1->tid == key2->tid) )
-        )
-      return TRUE;
-  }
-  return FALSE;
-}
-
-/* calculate a hash key */
-static guint
-tcaphash_ansi_calchash(gconstpointer k)
-{
-  const struct tcaphash_ansi_info_key_t *key = (const struct tcaphash_ansi_info_key_t *) k;
-  guint hashkey;
-  /* hashkey = key->opc_hash<<16 + key->dpc_hash<<8 + key->src_tid; */
-  hashkey = key->tid;
-  return hashkey;
-}
-
-/*
- * Update a record with the data of the Request
- */
-static void
-update_tcaphash_begincall(struct tcaphash_begincall_t *p_tcaphash_begincall,
-                         packet_info *pinfo)
-{
-  p_tcaphash_begincall->context->first_frame = pinfo->fd->num;
-  p_tcaphash_begincall->context->last_frame = 0;
-  p_tcaphash_begincall->context->responded = FALSE;
-  p_tcaphash_begincall->context->begin_time = pinfo->fd->abs_ts;
-}
-
-/*
- * Append a new dialogue, using the same Key, to the chained list
- * The time is stored too
- */
-static struct tcaphash_begincall_t *
-append_tcaphash_begincall(struct tcaphash_begincall_t *prev_begincall,
-                         struct tcaphash_context_t *p_tcaphash_context,
-                         packet_info *pinfo)
-{
-  struct tcaphash_begincall_t *p_new_tcaphash_begincall = NULL;
-
-  /* Append the transaction to the list, when the same key is found
-     This should append when the tcap-transaction Id is reused  */
-
-#ifdef MEM_TCAPSRT
-  p_new_tcaphash_begincall = (struct tcaphash_begincall_t *)g_malloc0(sizeof(struct tcaphash_begincall_t));
-#else
-  p_new_tcaphash_begincall = se_new0(struct tcaphash_begincall_t);
-#endif
-  p_new_tcaphash_begincall->context=p_tcaphash_context;
-  p_tcaphash_context->begincall=p_new_tcaphash_begincall;
-  p_new_tcaphash_begincall->beginkey=prev_begincall->beginkey;
-  p_new_tcaphash_begincall->context->first_frame = pinfo->fd->num;
-  p_new_tcaphash_begincall->next_begincall=NULL;
-  p_new_tcaphash_begincall->previous_begincall=prev_begincall;
-  p_new_tcaphash_begincall->father=FALSE;
-
-#ifdef DEBUG_TCAPSRT
-  dbg(10,"+B%d ", p_new_tcaphash_begincall->context->session_id);
-#endif
-  /* Insert in the chained list */
-  prev_begincall->next_begincall = p_new_tcaphash_begincall;
-  if (prev_begincall->context->last_frame == 0) {
-#ifdef DEBUG_TCAPSRT
-    dbg(10,"last ");
-#endif
-    prev_begincall->context->last_frame = pinfo->fd->num-1;
-  }
-  return p_new_tcaphash_begincall;
-}
-
-/*
- * Update a record with the data of the Request
- */
-static void
-update_tcaphash_ansicall(struct tcaphash_ansicall_t *p_tcaphash_ansicall,
-                         packet_info *pinfo)
-{
-  p_tcaphash_ansicall->context->first_frame = pinfo->fd->num;
-  p_tcaphash_ansicall->context->last_frame = 0;
-  p_tcaphash_ansicall->context->responded = FALSE;
-  p_tcaphash_ansicall->context->begin_time = pinfo->fd->abs_ts;
-}
-
-/*
- * Append a new dialogue, using the same Key, to the chained list
- * The time is stored too
- */
-static struct tcaphash_ansicall_t *
-append_tcaphash_ansicall(struct tcaphash_ansicall_t *prev_ansicall,
-                         struct tcaphash_context_t *p_tcaphash_context,
-                         packet_info *pinfo)
-{
-  struct tcaphash_ansicall_t *p_new_tcaphash_ansicall = NULL;
-
-  /* Append the transaction to the list, when the same key is found
-     This should append when the tcap-transaction Id is reused  */
-
-#ifdef MEM_TCAPSRT
-  p_new_tcaphash_ansicall = (struct tcaphash_ansicall_t *)g_malloc0(sizeof(struct tcaphash_ansicall_t));
-#else
-  p_new_tcaphash_ansicall = se_new0(struct tcaphash_ansicall_t);
-#endif
-  p_new_tcaphash_ansicall->context=p_tcaphash_context;
-  p_tcaphash_context->ansicall=p_new_tcaphash_ansicall;
-  p_new_tcaphash_ansicall->ansikey=prev_ansicall->ansikey;
-  p_new_tcaphash_ansicall->context->first_frame = pinfo->fd->num;
-  p_new_tcaphash_ansicall->next_ansicall=NULL;
-  p_new_tcaphash_ansicall->previous_ansicall=prev_ansicall;
-  p_new_tcaphash_ansicall->father=FALSE;
-
-#ifdef DEBUG_TCAPSRT
-  dbg(10,"+A%d ", p_new_tcaphash_ansicall->context->session_id);
-#endif
-  /* Insert in the chained list */
-  prev_ansicall->next_ansicall = p_new_tcaphash_ansicall;
-  if (prev_ansicall->context->last_frame == 0) {
-#ifdef DEBUG_TCAPSRT
-    dbg(10,"last ");
-#endif
-    prev_ansicall->context->last_frame = pinfo->fd->num-1;
-  }
-  return p_new_tcaphash_ansicall;
-}
-
-
-static struct tcaphash_contcall_t *
-append_tcaphash_contcall(struct tcaphash_contcall_t *prev_contcall,
-                        struct tcaphash_context_t *p_tcaphash_context)
-{
-  struct tcaphash_contcall_t *p_new_tcaphash_contcall = NULL;
-
-  /* Append the transaction to the list, when the same key is found
-     This should append when the tcap-transaction Id is reused  */
-
-#ifdef MEM_TCAPSRT
-  p_new_tcaphash_contcall = (struct tcaphash_contcall_t *)g_malloc0(sizeof(struct tcaphash_contcall_t));
-#else
-  p_new_tcaphash_contcall = se_new0(struct tcaphash_contcall_t);
-#endif
-  p_new_tcaphash_contcall->context=p_tcaphash_context;
-  p_tcaphash_context->contcall=p_new_tcaphash_contcall;
-  p_new_tcaphash_contcall->contkey=prev_contcall->contkey;
-  p_new_tcaphash_contcall->next_contcall=NULL;
-  p_new_tcaphash_contcall->previous_contcall=prev_contcall;
-  p_new_tcaphash_contcall->father=FALSE;
-
-#ifdef DEBUG_TCAPSRT
-  dbg(10,"+C%d ", p_new_tcaphash_contcall->context->session_id);
-#endif
-  /* Insert in the chained list */
-  prev_contcall->next_contcall = p_new_tcaphash_contcall;
-  return p_new_tcaphash_contcall;
-}
-
-
-static struct tcaphash_endcall_t *
-append_tcaphash_endcall(struct tcaphash_endcall_t *prev_endcall,
-                       struct tcaphash_context_t *p_tcaphash_context)
-{
-  struct tcaphash_endcall_t *p_new_tcaphash_endcall = NULL;
-
-  /* Append the transaction to the list, when the same key is found
-     This should append when the tcap-transaction Id is reused  */
-
-#ifdef MEM_TCAPSRT
-  p_new_tcaphash_endcall = (struct tcaphas_endcall_t *)g_malloc0(sizeof(struct tcaphash_endcall_t));
-#else
-  p_new_tcaphash_endcall = se_new0(struct tcaphash_endcall_t);
-#endif
-  p_new_tcaphash_endcall->context=p_tcaphash_context;
-  p_tcaphash_context->endcall=p_new_tcaphash_endcall;
-  p_new_tcaphash_endcall->endkey=prev_endcall->endkey;
-  p_new_tcaphash_endcall->next_endcall=NULL;
-  p_new_tcaphash_endcall->previous_endcall=prev_endcall;
-  p_new_tcaphash_endcall->father=FALSE;
-
-#ifdef DEBUG_TCAPSRT
-  dbg(10,"+E%d ", p_new_tcaphash_endcall->context->session_id);
-#endif
-  /* Insert in the chained list */
-  prev_endcall->next_endcall = p_new_tcaphash_endcall;
-  return p_new_tcaphash_endcall;
-}
-
-
-/*
- * Find the dialog by Key and Time
- */
-static struct tcaphash_begincall_t *
-find_tcaphash_begin(struct tcaphash_begin_info_key_t *p_tcaphash_begin_key,
-                   packet_info *pinfo, gboolean isBegin)
-{
-  struct tcaphash_begincall_t *p_tcaphash_begincall = NULL;
-  p_tcaphash_begincall = (struct tcaphash_begincall_t *)g_hash_table_lookup(tcaphash_begin, p_tcaphash_begin_key);
-
-  if(p_tcaphash_begincall) {
-    do {
-      if ( p_tcaphash_begincall->context ) {
-        if ( ( isBegin &&
-               pinfo->fd->num == p_tcaphash_begincall->context->first_frame )
-             ||
-             ( !isBegin &&
-               pinfo->fd->num >= p_tcaphash_begincall->context->first_frame &&
-               ( p_tcaphash_begincall->context->last_frame?pinfo->fd->num <= p_tcaphash_begincall->context->last_frame:1 )
-               )
-             ) {
-          /* We have a dialogue, with this key, opened before this request */
-#ifdef DEBUG_TCAPSRT
-          dbg(10,"B%d ", p_tcaphash_begincall->context->session_id);
-#endif
-          return p_tcaphash_begincall;
-        }
-#ifdef DEBUG_TCAPSRT
-      dbg(60,"[B%d] ", p_tcaphash_begincall->context->session_id);
-#endif
-      }
-      /* Break when list end is reached */
-      if(p_tcaphash_begincall->next_begincall == NULL) {
-#ifdef DEBUG_TCAPSRT
-        dbg(23,"End of Blist ");
-#endif
-        break;
-      }
-      p_tcaphash_begincall = p_tcaphash_begincall->next_begincall;
-    } while (p_tcaphash_begincall != NULL) ;
-  } else {
-#ifdef DEBUG_TCAPSRT
-    dbg(23,"Not in Bhash ");
-#endif
-  }
-  return NULL;
-}
-
-
-
-static struct tcaphash_contcall_t *
-find_tcaphash_cont(struct tcaphash_cont_info_key_t *p_tcaphash_cont_key,
-                  packet_info *pinfo)
-{
-  struct tcaphash_contcall_t *p_tcaphash_contcall = NULL;
-  p_tcaphash_contcall = (struct tcaphash_contcall_t *)g_hash_table_lookup(tcaphash_cont, p_tcaphash_cont_key);
-
-  if(p_tcaphash_contcall) {
-    do {
-      if ( p_tcaphash_contcall->context ) {
-       if (pinfo->fd->num >= p_tcaphash_contcall->context->first_frame &&
-           (p_tcaphash_contcall->context->last_frame?pinfo->fd->num <= p_tcaphash_contcall->context->last_frame:1) ) {
-         /* We have a dialogue, with this key, opened before this request */
-#ifdef DEBUG_TCAPSRT
-         dbg(10,"C%d ", p_tcaphash_contcall->context->session_id);
-#endif
-         return p_tcaphash_contcall;
-       }
-#ifdef DEBUG_TCAPSRT
-       dbg(60,"[C%d] ", p_tcaphash_contcall->context->session_id);
-#endif
-      }
-      /* Break when list end is reached */
-      if(p_tcaphash_contcall->next_contcall == NULL) {
-#ifdef DEBUG_TCAPSRT
-       dbg(23,"End of Clist ");
-#endif
-       break;
-      }
-      p_tcaphash_contcall = p_tcaphash_contcall->next_contcall;
-    } while (p_tcaphash_contcall != NULL) ;
-  } else {
-#ifdef DEBUG_TCAPSRT
-    dbg(23,"Not in Chash ");
-#endif
-  }
-  return NULL;
-}
-
-static struct tcaphash_endcall_t *
-find_tcaphash_end(struct tcaphash_end_info_key_t *p_tcaphash_end_key,
-                 packet_info *pinfo, gboolean isEnd)
-{
-  struct tcaphash_endcall_t *p_tcaphash_endcall = NULL;
-  p_tcaphash_endcall = (struct tcaphash_endcall_t *)g_hash_table_lookup(tcaphash_end, p_tcaphash_end_key);
-
-  if(p_tcaphash_endcall) {
-    do {
-      if ( p_tcaphash_endcall->context ) {
-       if ( ( isEnd &&
-              (p_tcaphash_endcall->context->last_frame?pinfo->fd->num == p_tcaphash_endcall->context->last_frame:1)
-              )
-            ||
-            ( !isEnd &&
-              pinfo->fd->num >= p_tcaphash_endcall->context->first_frame &&
-              (p_tcaphash_endcall->context->last_frame?pinfo->fd->num <= p_tcaphash_endcall->context->last_frame:1)
-              )
-            ) {
-         /* We have a dialogue, with this key, opened before this request */
-#ifdef DEBUG_TCAPSRT
-         dbg(10,"E%d ", p_tcaphash_endcall->context->session_id);
-#endif
-         return p_tcaphash_endcall;
-       }
-#ifdef DEBUG_TCAPSRT
-         dbg(60,"[E%d] ", p_tcaphash_endcall->context->session_id);
-#endif
-      }
-      /* Break when list end is reached */
-      if(p_tcaphash_endcall->next_endcall == NULL) {
-#ifdef DEBUG_TCAPSRT
-       dbg(23,"End of Elist ");
-#endif
-       break;
-      }
-      p_tcaphash_endcall = p_tcaphash_endcall->next_endcall;
-    } while (p_tcaphash_endcall != NULL) ;
-  } else {
-#ifdef DEBUG_TCAPSRT
-    dbg(23,"Not in Ehash ");
-#endif
-  }
-  return NULL;
-}
-
-/*
- * New record to create, to identify a new transaction
- */
-static struct tcaphash_context_t *
-new_tcaphash_context(struct tcaphash_context_key_t *p_tcaphash_context_key,
-                    packet_info *pinfo)
-{
-  struct tcaphash_context_key_t *p_new_tcaphash_context_key;
-  struct tcaphash_context_t *p_new_tcaphash_context = NULL;
-
-  /* Register the transaction in the hash table
-     with the tcap transaction Id as Main Key
-     Once created, this entry will be updated later */
-
-#ifdef MEM_TCAPSRT
-  p_new_tcaphash_context_key = (struct tcaphash_context_key_t *)g_malloc(sizeof(struct tcaphash_context_key_t));
-#else
-  p_new_tcaphash_context_key = se_new(struct tcaphash_context_key_t);
-#endif
-  p_new_tcaphash_context_key->session_id = p_tcaphash_context_key->session_id;
-
-#ifdef MEM_TCAPSRT
-  p_new_tcaphash_context = (struct tcaphash_context_t *)g_malloc0(sizeof(struct tcaphash_context_t));
-#else
-  p_new_tcaphash_context = se_new0(struct tcaphash_context_t);
-#endif
-  p_new_tcaphash_context->key = p_new_tcaphash_context_key;
-  p_new_tcaphash_context->session_id = p_tcaphash_context_key->session_id;
-  p_new_tcaphash_context->first_frame = pinfo->fd->num;
-#ifdef DEBUG_TCAPSRT
-  dbg(10,"S%d ", p_new_tcaphash_context->session_id);
-#endif
-  /* store it */
-  g_hash_table_insert(tcaphash_context, p_new_tcaphash_context_key, p_new_tcaphash_context);
-  return p_new_tcaphash_context;
-}
-
-/*
- * New record to create, to identify a new transaction
- */
-static struct tcaphash_begincall_t *
-new_tcaphash_begin(struct tcaphash_begin_info_key_t *p_tcaphash_begin_key,
-                  struct tcaphash_context_t *p_tcaphash_context)
-{
-  struct tcaphash_begin_info_key_t *p_new_tcaphash_begin_key;
-  struct tcaphash_begincall_t *p_new_tcaphash_begincall = NULL;
-
-  /* Register the transaction in the hash table
-     with the tcap transaction Id as Main Key
-     Once created, this entry will be updated later */
-
-#ifdef MEM_TCAPSRT
-  p_new_tcaphash_begin_key = (struct tcaphash_begin_info_key_t *)g_malloc(sizeof(struct tcaphash_begin_info_key_t));
-#else
-  p_new_tcaphash_begin_key = se_new(struct tcaphash_begin_info_key_t);
-#endif
-  p_new_tcaphash_begin_key->hashKey = p_tcaphash_begin_key->hashKey;
-  p_new_tcaphash_begin_key->tid = p_tcaphash_begin_key->tid;
-  p_new_tcaphash_begin_key->opc_hash = p_tcaphash_begin_key->opc_hash;
-  p_new_tcaphash_begin_key->dpc_hash = p_tcaphash_begin_key->dpc_hash;
-
-#ifdef MEM_TCAPSRT
-  p_new_tcaphash_begincall = (struct tcaphash_begincall_t *)g_malloc0(sizeof(struct tcaphash_begincall_t));
-#else
- p_new_tcaphash_begincall = se_new0(struct tcaphash_begincall_t);
-#endif
-  p_new_tcaphash_begincall->beginkey=p_new_tcaphash_begin_key;
-  p_new_tcaphash_begincall->context=p_tcaphash_context;
-  p_tcaphash_context->begincall=p_new_tcaphash_begincall;
-  p_new_tcaphash_begincall->father=TRUE;
-  p_new_tcaphash_begincall->next_begincall=NULL;
-  p_new_tcaphash_begincall->previous_begincall=NULL;
-
-#ifdef DEBUG_TCAPSRT
-  dbg(10,"B%d ", p_new_tcaphash_begincall->context->session_id);
-#endif
-  /* store it */
-  g_hash_table_insert(tcaphash_begin, p_new_tcaphash_begin_key, p_new_tcaphash_begincall);
-  return p_new_tcaphash_begincall;
-}
-
-
-
-/*
- * New record to create, to identify a new transaction
- */
-static struct tcaphash_contcall_t *
-new_tcaphash_cont(struct tcaphash_cont_info_key_t *p_tcaphash_cont_key,
-                 struct tcaphash_context_t *p_tcaphash_context)
-{
-  struct tcaphash_cont_info_key_t *p_new_tcaphash_cont_key;
-  struct tcaphash_contcall_t *p_new_tcaphash_contcall = NULL;
-
-  /* Register the transaction in the hash table
-     with the tcap transaction Id as Main Key
-     Once created, this entry will be updated later */
-
-#ifdef MEM_TCAPSRT
-  p_new_tcaphash_cont_key = (struct tcaphash_cont_info_key_t *)g_malloc(sizeof(struct tcaphash_cont_info_key_t));
-#else
-  p_new_tcaphash_cont_key = se_new(struct tcaphash_cont_info_key_t);
-#endif
-  p_new_tcaphash_cont_key->hashKey = p_tcaphash_cont_key->hashKey;
-  p_new_tcaphash_cont_key->src_tid = p_tcaphash_cont_key->src_tid;
-  p_new_tcaphash_cont_key->dst_tid = p_tcaphash_cont_key->dst_tid;
-  p_new_tcaphash_cont_key->opc_hash = p_tcaphash_cont_key->opc_hash;
-  p_new_tcaphash_cont_key->dpc_hash = p_tcaphash_cont_key->dpc_hash;
-
-#ifdef MEM_TCAPSRT
-  p_new_tcaphash_contcall = (struct tcaphash_contcall_t *)g_malloc0(sizeof(struct tcaphash_contcall_t));
-#else
-  p_new_tcaphash_contcall = se_new0(struct tcaphash_contcall_t);
-#endif
-  p_new_tcaphash_contcall->contkey=p_new_tcaphash_cont_key;
-  p_new_tcaphash_contcall->context=p_tcaphash_context;
-  p_tcaphash_context->contcall=p_new_tcaphash_contcall;
-  p_new_tcaphash_contcall->father=TRUE;
-  p_new_tcaphash_contcall->next_contcall=NULL;
-  p_new_tcaphash_contcall->previous_contcall=NULL;
-
-#ifdef DEBUG_TCAPSRT
-  dbg(10,"C%d ", p_new_tcaphash_contcall->context->session_id);
-#endif
-  /* store it */
-  g_hash_table_insert(tcaphash_cont, p_new_tcaphash_cont_key, p_new_tcaphash_contcall);
-  return p_new_tcaphash_contcall;
-}
-
-
-/*
- * New record to create, to identify a new transaction
- */
-static struct tcaphash_endcall_t *
-new_tcaphash_end(struct tcaphash_end_info_key_t *p_tcaphash_end_key,
-                struct tcaphash_context_t *p_tcaphash_context)
-{
-  struct tcaphash_end_info_key_t *p_new_tcaphash_end_key;
-  struct tcaphash_endcall_t *p_new_tcaphash_endcall = NULL;
-
-  /* Register the transaction in the hash table
-     with the tcap transaction Id as Main Key
-     Once created, this entry will be updated later */
-
-#ifdef MEM_TCAPSRT
-  p_new_tcaphash_end_key = (struct tcaphash_end_info_key_t *)g_malloc(sizeof(struct tcaphash_end_info_key_t));
-#else
-  p_new_tcaphash_end_key = se_new(struct tcaphash_end_info_key_t);
-#endif
-  p_new_tcaphash_end_key->hashKey = p_tcaphash_end_key->hashKey;
-  p_new_tcaphash_end_key->tid = p_tcaphash_end_key->tid;
-  p_new_tcaphash_end_key->opc_hash = p_tcaphash_end_key->opc_hash;
-  p_new_tcaphash_end_key->dpc_hash = p_tcaphash_end_key->dpc_hash;
-
-#ifdef MEM_TCAPSRT
-  p_new_tcaphash_endcall = (struct tcaphash_endcall_t *)g_malloc0(sizeof(struct tcaphash_endcall_t));
-#else
-  p_new_tcaphash_endcall = se_new0(struct tcaphash_endcall_t);
-#endif
-  p_new_tcaphash_endcall->endkey=p_new_tcaphash_end_key;
-  p_new_tcaphash_endcall->context=p_tcaphash_context;
-  p_tcaphash_context->endcall=p_new_tcaphash_endcall;
-  p_new_tcaphash_endcall->father=TRUE;
-  p_new_tcaphash_endcall->next_endcall=NULL;
-  p_new_tcaphash_endcall->previous_endcall=NULL;
-
-#ifdef DEBUG_TCAPSRT
-  dbg(10,"E%d ", p_new_tcaphash_endcall->context->session_id);
-#endif
-  /* store it */
-  g_hash_table_insert(tcaphash_end, p_new_tcaphash_end_key, p_new_tcaphash_endcall);
-  return p_new_tcaphash_endcall;
-}
-/*
- * New record to create, to identify a new transaction
- */
-static struct tcaphash_ansicall_t *
-new_tcaphash_ansi(struct tcaphash_ansi_info_key_t *p_tcaphash_ansi_key,
-                  struct tcaphash_context_t *p_tcaphash_context)
-{
-  struct tcaphash_ansi_info_key_t *p_new_tcaphash_ansi_key;
-  struct tcaphash_ansicall_t *p_new_tcaphash_ansicall = NULL;
-
-  /* Register the transaction in the hash table
-     with the tcap transaction Id as Main Key
-     Once created, this entry will be updated later */
-
-#ifdef MEM_TCAPSRT
-  p_new_tcaphash_ansi_key = (struct tcaphash_ansi_info_key_t *)g_malloc(sizeof(struct tcaphash_ansi_info_key_t));
-#else
-  p_new_tcaphash_ansi_key = se_new(struct tcaphash_ansi_info_key_t);
-#endif
-  p_new_tcaphash_ansi_key->hashKey = p_tcaphash_ansi_key->hashKey;
-  p_new_tcaphash_ansi_key->tid = p_tcaphash_ansi_key->tid;
-  p_new_tcaphash_ansi_key->opc_hash = p_tcaphash_ansi_key->opc_hash;
-  p_new_tcaphash_ansi_key->dpc_hash = p_tcaphash_ansi_key->dpc_hash;
-
-#ifdef MEM_TCAPSRT
-  p_new_tcaphash_ansicall = (struct tcaphash_ansicall_t *)g_malloc0(sizeof(struct tcaphash_ansicall_t));
-#else
-  p_new_tcaphash_ansicall = se_new0(struct tcaphash_ansicall_t);
-#endif
-  p_new_tcaphash_ansicall->ansikey=p_new_tcaphash_ansi_key;
-  p_new_tcaphash_ansicall->context=p_tcaphash_context;
-  p_tcaphash_context->ansicall=p_new_tcaphash_ansicall;
-  p_new_tcaphash_ansicall->father=TRUE;
-  p_new_tcaphash_ansicall->next_ansicall=NULL;
-  p_new_tcaphash_ansicall->previous_ansicall=NULL;
-
-#ifdef DEBUG_TCAPSRT
-  dbg(10,"A%d ", p_new_tcaphash_ansicall->context->session_id);
-#endif
-  /* store it */
-  g_hash_table_insert(tcaphash_ansi, p_new_tcaphash_ansi_key, p_new_tcaphash_ansicall);
-  return p_new_tcaphash_ansicall;
-}
-
-static struct tcaphash_contcall_t *
-create_tcaphash_cont(struct tcaphash_cont_info_key_t *p_tcaphash_cont_key,
-                    struct tcaphash_context_t *p_tcaphash_context)
-{
-  struct tcaphash_contcall_t *p_tcaphash_contcall1 = NULL;
-  struct tcaphash_contcall_t *p_tcaphash_contcall = NULL;
-
-  p_tcaphash_contcall1 = (struct tcaphash_contcall_t *)
-    g_hash_table_lookup(tcaphash_cont, p_tcaphash_cont_key);
-
-  if (p_tcaphash_contcall1) {
-    /* Walk through list of transaction with identical keys */
-    /* go the the end to insert new record */
-    do {
-      if (!p_tcaphash_contcall1->next_contcall) {
-       p_tcaphash_contcall=append_tcaphash_contcall(p_tcaphash_contcall1,
-                                                    p_tcaphash_context);
-       break;
-      }
-      p_tcaphash_contcall1 = p_tcaphash_contcall1->next_contcall;
-    } while (p_tcaphash_contcall1 != NULL );
-  } else {
-    p_tcaphash_contcall = new_tcaphash_cont(p_tcaphash_cont_key,
-                                           p_tcaphash_context);
-  }
-  return p_tcaphash_contcall;
-}
-
-
-static struct tcaphash_endcall_t *
-create_tcaphash_end(struct tcaphash_end_info_key_t *p_tcaphash_end_key,
-                   struct tcaphash_context_t *p_tcaphash_context)
-{
-  struct tcaphash_endcall_t *p_tcaphash_endcall1 = NULL;
-  struct tcaphash_endcall_t *p_tcaphash_endcall = NULL;
-
-  p_tcaphash_endcall1 = (struct tcaphash_endcall_t *)
-    g_hash_table_lookup(tcaphash_end, p_tcaphash_end_key);
-
-  if (p_tcaphash_endcall1) {
-    /* Walk through list of transaction with identical keys */
-    /* go the the end to insert new record */
-    do {
-      if (!p_tcaphash_endcall1->next_endcall) {
-       p_tcaphash_endcall=append_tcaphash_endcall(p_tcaphash_endcall1,
-                                                  p_tcaphash_context);
-       break;
-      }
-      p_tcaphash_endcall1 = p_tcaphash_endcall1->next_endcall;
-    } while (p_tcaphash_endcall1 != NULL );
-  } else {
-    p_tcaphash_endcall = new_tcaphash_end(p_tcaphash_end_key,
-                                         p_tcaphash_context);
-  }
-  return p_tcaphash_endcall;
-}
-
-
-/*
- * Routine called when the TAP is initialized.
- * so hash table are (re)created
- */
-void
-tcapsrt_init_routine(void)
-{
-
-  /* free hash-table for SRT */
-  if (tcaphash_context != NULL) {
-#ifdef DEBUG_TCAPSRT
-    dbg(16,"Destroy hash_context \n");
-#endif
-    g_hash_table_destroy(tcaphash_context);
-  }
-
-  if (tcaphash_begin != NULL) {
-#ifdef DEBUG_TCAPSRT
-    dbg(16,"Destroy hash_begin \n");
-#endif
-    g_hash_table_destroy(tcaphash_begin);
-  }
-
-  if (tcaphash_cont != NULL) {
-#ifdef DEBUG_TCAPSRT
-    dbg(16,"Destroy hash_cont \n");
-#endif
-    g_hash_table_destroy(tcaphash_cont);
-  }
-
-  if (tcaphash_end != NULL) {
-#ifdef DEBUG_TCAPSRT
-    dbg(16,"Destroy hash_end \n");
-#endif
-    g_hash_table_destroy(tcaphash_end);
-  }
-
-  if (tcaphash_ansi != NULL) {
-#ifdef DEBUG_TCAPSRT
-    dbg(16,"Destroy hash_ansi \n");
-#endif
-    g_hash_table_destroy(tcaphash_ansi);
-  }
-
-#ifdef DEBUG_TCAPSRT
-  dbg(16,"Create hash \n");
-#endif
-  /* create new hash-tables for SRT */
-  tcaphash_context = g_hash_table_new(tcaphash_context_calchash, tcaphash_context_equal);
-  tcaphash_begin   = g_hash_table_new(tcaphash_begin_calchash, tcaphash_begin_equal);
-  tcaphash_cont    = g_hash_table_new(tcaphash_cont_calchash, tcaphash_cont_equal);
-  tcaphash_end     = g_hash_table_new(tcaphash_end_calchash, tcaphash_end_equal);
-  tcaphash_ansi    = g_hash_table_new(tcaphash_ansi_calchash, tcaphash_ansi_equal);
-
-  /* Reset the session counter */
-  tcapsrt_global_SessionId=1;
-
-  /* Display of SRT only if Persistent Stat */
-  gtcap_DisplaySRT=gtcap_PersistentSRT || gtcap_HandleSRT&gtcap_StatSRT;
-}
-
-/*
- * Service Response Time analyze
- * Called just after dissector call
- * Associate a TCAP context to a tcap session and display session related infomations
- * like the first frame, the last, the session duration,
- * and a uniq session identifier for the filtering
- *
- * For ETSI tcap, the TCAP context can be reached through three keys
- * - a key (BEGIN) identifying the session according to the tcap source identifier
- * - a key (CONT) identifying the established session (src_id and dst_id)
- * - a key (END) identifying the session according to the tcap destination identifier
- *
- * For ANSI tcap, the TCAP context is reached through a uniq key
- * - a key (ANSI) identifying the session according to the tcap identifier
-*/
-struct tcaphash_context_t *
-tcapsrt_call_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
-                     struct tcapsrt_info_t *p_tcapsrt_info)
-{
-  struct tcaphash_context_t *tcap_context=NULL;
-
-  /* if this packet isn't loaded because of a read filter, don't output anything */
-  if(pinfo == NULL || pinfo->fd->num == 0) {
-    return NULL;
-  }
-
-  switch (p_tcapsrt_info->ope) {
-
-  case TC_BEGIN:
-#ifdef DEBUG_TCAPSRT
-    dbg(1,"\nTC_BEGIN ");
-#endif
-    tcap_context=tcaphash_begin_matching(tvb, pinfo, tree, p_tcapsrt_info);
-    break;
-
-  case TC_CONT:
-#ifdef DEBUG_TCAPSRT
-    dbg(1,"\nTC_CONT ");
-#endif
-    tcap_context=tcaphash_cont_matching(tvb, pinfo, tree, p_tcapsrt_info);
-    break;
-
-  case TC_ABORT:
-#ifdef DEBUG_TCAPSRT
-    dbg(1,"\nTC_ABORT ");
-#endif
-    tcap_context=tcaphash_end_matching(tvb, pinfo, tree, p_tcapsrt_info);
-    break;
-
-  case TC_END:
-#ifdef DEBUG_TCAPSRT
-    dbg(1,"\nTC_END ");
-#endif
-    tcap_context=tcaphash_end_matching(tvb, pinfo, tree, p_tcapsrt_info);
-    break;
-
-  case TC_ANSI_ALL:
-  case TC_ANSI_ABORT:
-#ifdef DEBUG_TCAPSRT
-    dbg(1,"\nTC_ANSI ");
-#endif
-    tcap_context=tcaphash_ansi_matching(tvb, pinfo, tree, p_tcapsrt_info);
-    break;
-
-  default:
-#ifdef DEBUG_TCAPSRT
-    dbg(1,"\nUnknown %d ", p_tcapsrt_info->ope);
-#endif
-    break;
-  } /* switch tcapop */
-#ifdef DEBUG_TCAPSRT
-  if (tcap_context)
-    dbg(1,"session %d ", tcap_context->session_id);
-#endif
-  return tcap_context;
-}
-
-
-/*
- * Create the record identifiying the TCAP transaction
- * When the identifier for the transaction is reused, check
- * the following criteria before to append a new record:
- * - a timeout corresponding to a message retransmission is detected,
- * - a message hast been lost
- * - or the previous transaction has been  be closed
- */
-static struct tcaphash_context_t *
-tcaphash_begin_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
-                       struct tcapsrt_info_t *p_tcapsrt_info)
-{
-  struct tcaphash_context_t *p_tcaphash_context=NULL;
-  struct tcaphash_context_key_t tcaphash_context_key;
-  struct tcaphash_begincall_t *p_tcaphash_begincall, *p_new_tcaphash_begincall=NULL;
-  struct tcaphash_begin_info_key_t tcaphash_begin_key;
-  proto_item *pi;
-  proto_item *stat_item=NULL;
-  proto_tree *stat_tree=NULL;
-
-  /* prepare the key data */
-  tcaphash_begin_key.tid = p_tcapsrt_info->src_tid;
-  if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
-  {
-    /* We have MTP3 PCs (so we can safely do this cast) */
-    tcaphash_begin_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
-    tcaphash_begin_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
-  } else {
-    /* Don't have MTP3 PCs (maybe we're over SUA?) */
-    tcaphash_begin_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
-    tcaphash_begin_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
-  }
-  tcaphash_begin_key.hashKey=tcaphash_begin_calchash(&tcaphash_begin_key);
-
-  /* look up the request */
-#ifdef DEBUG_TCAPSRT
-  dbg(10,"\n Hbegin #%u ", pinfo->fd->num);
-  dbg(11,"key %lx ",tcaphash_begin_key.hashKey);
-  dbg(51,"PC %s %s ",ep_address_to_str(&pinfo->src), ep_address_to_str(&pinfo->dst));
-  dbg(51,"Tid %lx \n",tcaphash_begin_key.tid);
-#endif
-
-  p_tcaphash_begincall = (struct tcaphash_begincall_t *)
-  g_hash_table_lookup(tcaphash_begin, &tcaphash_begin_key);
-
-  if (p_tcaphash_begincall) {
-    /* Walk through list of transaction with identical keys */
-    do {
-      /* Check if the request with this reqSeqNum has been seen, with the same Message Type */
-      if (pinfo->fd->num == p_tcaphash_begincall->context->first_frame) {
-       /* We have seen this request before -> do nothing */
-#ifdef DEBUG_TCAPSRT
-       dbg(22,"Already seen ");
-#endif
-       p_tcaphash_context=p_tcaphash_begincall->context;
-       break;
-      }
-      /* If the last record for Tcap transaction with identifier has not been reached */
-      if (!p_tcaphash_begincall->next_begincall) {
-       /* check if we have to create a new record or not */
-       /* if last request has been responded (response number is known)
-          and this request appears after last response (has bigger frame number)
-          and last request occurred after the timeout for repetition,
-          or
-          if last request hasn't been responded (so number unknown)
-          and this request appears after last request (has bigger frame number)
-          and this request occurred after the timeout for message lost */
-       if ( ( p_tcaphash_begincall->context->last_frame != 0
-              && pinfo->fd->num > p_tcaphash_begincall->context->first_frame
-              && (guint) pinfo->fd->abs_ts.secs > (guint)(p_tcaphash_begincall->context->begin_time.secs + gtcap_RepetitionTimeout)
-              ) ||
-            ( p_tcaphash_begincall->context->last_frame == 0
-              && pinfo->fd->num > p_tcaphash_begincall->context->first_frame
-              && (guint)pinfo->fd->abs_ts.secs > (guint)(p_tcaphash_begincall->context->begin_time.secs + gtcap_LostTimeout)
-              )
-            )
-         {
-           /* we decide that we have a new request */
-           /* Append new record to the list */
-#ifdef DEBUG_TCAPSRT
-           dbg(12,"(timeout) Append key %lx ",tcaphash_begin_key.hashKey);
-           dbg(12,"Frame %u rsp %u ",pinfo->fd->num,p_tcaphash_begincall->context->last_frame );
-#endif
-           tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
-           p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
-
-           p_new_tcaphash_begincall = append_tcaphash_begincall(p_tcaphash_begincall,
-                                                                p_tcaphash_context,
-                                                                pinfo);
-#ifdef DEBUG_TCAPSRT
-           dbg(12,"Update key %lx ",tcaphash_begin_key.hashKey);
-#endif
-           update_tcaphash_begincall(p_new_tcaphash_begincall, pinfo);
-         } else { /* timeout or message lost */
-
-         /* If the Tid is reused for a closed Transaction */
-         /* Or if we received an TC_BEGIN for a Transaction marked as "closed" */
-         /* (this is the case, for pre-arranged END, the transaction is marked as closed */
-         /* by the upper layer, thank to a callback method close) */
-         if ( p_tcaphash_begincall->context->closed) {
-#ifdef DEBUG_TCAPSRT
-           dbg(12,"(closed) Append key %lu ",tcaphash_begin_key.hashKey);
-           dbg(12,"Frame %u rsp %u ",pinfo->fd->num,p_tcaphash_begincall->context->last_frame );
-#endif
-           tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
-           p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
-           p_new_tcaphash_begincall = append_tcaphash_begincall(p_tcaphash_begincall,
-                                                                p_tcaphash_context,
-                                                                pinfo);
-
-#ifdef DEBUG_TCAPSRT
-           dbg(12,"Update key %lu ",tcaphash_begin_key.hashKey);
-#endif
-           update_tcaphash_begincall(p_new_tcaphash_begincall, pinfo);
-
-         } else {
-           /* the TCAP session is not closed, so, either messages have been lost */
-           /* or it's a duplicate request. Mark it as such. */
-#ifdef DEBUG_TCAPSRT
-           dbg(21,"Display_duplicate %d ",p_tcaphash_begincall->context->first_frame);
-#endif
-           p_tcaphash_context=p_tcaphash_begincall->context;
-           if (gtcap_DisplaySRT && tree) {
-             stat_item = proto_tree_add_text(tree, tvb, 0, -1, "Stat");
-             PROTO_ITEM_SET_GENERATED(stat_item);
-             stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
-             pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_Duplicate, tvb, 0, 0,
-                                             p_tcaphash_context->first_frame,
-                                             "Duplicate with session %u in frame %u",
-                                             p_tcaphash_context->session_id,p_tcaphash_context->first_frame);
-             PROTO_ITEM_SET_GENERATED(pi);
-           }
-           return p_tcaphash_context;
-         } /* Previous session closed */
-       } /* test with Timeout or message Lost */
-       break;
-      } /* Next call is NULL */
-      /* Repeat the tests for the next record with the same transaction identifier */
-      p_tcaphash_begincall = p_tcaphash_begincall->next_begincall;
-    } while (p_tcaphash_begincall != NULL );
-    /*
-     * End of analyze for the list be TC_BEGIN with same transaction ID
-     */
-  } else { /* p_tcaphash_begincall has not been found */
-    /*
-     * Create a new TCAP context
-     */
-#ifdef DEBUG_TCAPSRT
-    dbg(10,"New key %lx ",tcaphash_begin_key.hashKey);
-#endif
-
-    tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
-    p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
-    p_tcaphash_begincall = new_tcaphash_begin(&tcaphash_begin_key, p_tcaphash_context);
-
-#ifdef DEBUG_TCAPSRT
-    dbg(11,"Update key %lx ",tcaphash_begin_key.hashKey);
-    dbg(11,"Frame reqlink #%u ", pinfo->fd->num);
-#endif
-    update_tcaphash_begincall(p_tcaphash_begincall, pinfo);
-  }
-
-  /* display tcap session, if available */
-  if ( gtcap_DisplaySRT && tree &&
-       p_tcaphash_context &&
-       p_tcaphash_context->session_id) {
-    stat_item = proto_tree_add_text(tree, tvb, 0, 0, "Stat");
-    PROTO_ITEM_SET_GENERATED(stat_item);
-    stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
-    pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
-    PROTO_ITEM_SET_GENERATED(pi);
-
-    /* add link to response frame, if available */
-    /* p_tcaphash_begincall->context->last_frame) */
-    if( p_tcaphash_context->last_frame != 0 ){
-#ifdef DEBUG_TCAPSRT
-      dbg(20,"Display_frameRsplink %d ",p_tcaphash_context->last_frame);
-#endif
-      pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_BeginSession, tvb, 0, 0,
-                                     p_tcaphash_context->last_frame,
-                                     "End of session in frame %u",
-                                     p_tcaphash_context->last_frame);
-      PROTO_ITEM_SET_GENERATED(pi);
-    }
-  }
-  return p_tcaphash_context;
-}
-
-
-/*
-* Try to find a TCAP session according to the source and destination
-* Identifier given in the TC_CONT
-* If nothing is found, it is probably a session in opening state, so try to find
-* a tcap session registered with a TC_BEGIN "key", matching the destination Id of the TC_CONT
-* Then associate the TC_CONT "key" to the TCAP context, and create a TC_END "key"
-* and display the available info for the TCAP context
-*/
-static struct tcaphash_context_t *
-tcaphash_cont_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
-                      struct tcapsrt_info_t *p_tcapsrt_info)
-{
-  struct tcaphash_context_t *p_tcaphash_context=NULL;
-  struct tcaphash_contcall_t *p_tcaphash_contcall;
-  struct tcaphash_cont_info_key_t tcaphash_cont_key;
-  struct tcaphash_begin_info_key_t tcaphash_begin_key;
-  struct tcaphash_begincall_t *p_tcaphash_begincall;
-  struct tcaphash_end_info_key_t tcaphash_end_key;
-  proto_item *pi;
-  proto_item *stat_item=NULL;
-  proto_tree *stat_tree=NULL;
-
-#ifdef DEBUG_TCAPSRT
-  dbg(10,"\n Hcont #%u ", pinfo->fd->num);
-#endif
-
-  /* look only for matching request, if matching conversation is available. */
-  tcaphash_cont_key.src_tid = p_tcapsrt_info->src_tid;
-  tcaphash_cont_key.dst_tid = p_tcapsrt_info->dst_tid;
-  if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
-  {
-    /* We have MTP3 PCs (so we can safely do this cast) */
-    tcaphash_cont_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
-    tcaphash_cont_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
-  } else {
-    /* Don't have MTP3 PCs (maybe we're over SUA?) */
-    tcaphash_cont_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
-    tcaphash_cont_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
-  }
-  tcaphash_cont_key.hashKey=tcaphash_cont_calchash(&tcaphash_cont_key);
-
-#ifdef DEBUG_TCAPSRT
-  dbg(11,"Ckey %lx ", tcaphash_cont_key.hashKey);
-  dbg(51,"PC %s %s ",ep_address_to_str(&pinfo->src), ep_address_to_str(&pinfo->dst));
-  dbg(51,"Tid %lx %lx \n",tcaphash_cont_key.src_tid, tcaphash_cont_key.dst_tid);
-#endif
-  p_tcaphash_contcall = find_tcaphash_cont(&tcaphash_cont_key, pinfo);
-  if(p_tcaphash_contcall) {
-#ifdef DEBUG_TCAPSRT
-    dbg(12,"CFound ");
-#endif
-    p_tcaphash_context=p_tcaphash_contcall->context;
-  } else { /* cont not found */
-#ifdef DEBUG_TCAPSRT
-    dbg(12,"CnotFound ");
-#endif
-    /* Find the TCAP transaction according to the TC_BEGIN */
-    tcaphash_begin_key.tid = p_tcapsrt_info->dst_tid;
-    if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
-    {
-      /* We have MTP3 PCs (so we can safely do this cast) */
-      tcaphash_begin_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
-      tcaphash_begin_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
-    } else {
-      /* Don't have MTP3 PCs (maybe we're over SUA?) */
-      tcaphash_begin_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
-      tcaphash_begin_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
-    }
-    tcaphash_begin_key.hashKey=tcaphash_begin_calchash(&tcaphash_begin_key);
-
-#ifdef DEBUG_TCAPSRT
-    dbg(11,"Bkey %lx ", tcaphash_begin_key.hashKey);
-    dbg(51,"PC %s %s ",ep_address_to_str(&pinfo->src), ep_address_to_str(&pinfo->dst));
-    dbg(51,"Tid %lx \n",tcaphash_begin_key.tid);
-#endif
-    p_tcaphash_begincall = find_tcaphash_begin(&tcaphash_begin_key, pinfo, FALSE);
-    if(!p_tcaphash_begincall){
-        /* Do we have a continue from the same source? */
-        tcaphash_begin_key.tid = p_tcapsrt_info->src_tid;
-        tcaphash_begin_key.hashKey=tcaphash_begin_calchash(&tcaphash_begin_key);
-        p_tcaphash_begincall = find_tcaphash_begin(&tcaphash_begin_key, pinfo,FALSE);
-    }
-    if(p_tcaphash_begincall &&
-       !p_tcaphash_begincall->context->contcall ) {
-#ifdef DEBUG_TCAPSRT
-      dbg(12,"BFound \n");
-#endif
-      p_tcaphash_context=p_tcaphash_begincall->context;
-      p_tcaphash_context->responded=TRUE;
-
-#ifdef DEBUG_TCAPSRT
-      dbg(10,"New Ckey %lx ",tcaphash_cont_key.hashKey);
-      dbg(11,"Frame reqlink #%u \n", pinfo->fd->num);
-#endif
-      create_tcaphash_cont(&tcaphash_cont_key,
-                           p_tcaphash_begincall->context);
-
-      tcaphash_end_key.tid = p_tcapsrt_info->src_tid;
-      if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
-      {
-        /* We have MTP3 PCs (so we can safely do this cast) */
-        tcaphash_end_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
-        tcaphash_end_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
-      } else {
-        /* Don't have MTP3 PCs (maybe we're over SUA?) */
-        tcaphash_end_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
-        tcaphash_end_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
-      }
-      tcaphash_end_key.hashKey=tcaphash_end_calchash(&tcaphash_end_key);
-
-#ifdef DEBUG_TCAPSRT
-      dbg(10,"New Ekey %lx ",tcaphash_end_key.hashKey);
-      dbg(11,"Frame reqlink #%u ", pinfo->fd->num);
-#endif
-      create_tcaphash_end(&tcaphash_end_key,
-                          p_tcaphash_begincall->context);
-
-    } else { /* Begin not found */
-#ifdef DEBUG_TCAPSRT
-      dbg(12,"BnotFound ");
-#endif
-    } /* begin found */
-  } /* cont found */
-    /* display tcap session, if available */
-  if (gtcap_DisplaySRT && tree &&
-      p_tcaphash_context &&
-      p_tcaphash_context->session_id) {
-    stat_item = proto_tree_add_text(tree, tvb, 0, -1, "Stat");
-    PROTO_ITEM_SET_GENERATED(stat_item);
-    stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
-    pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
-    PROTO_ITEM_SET_GENERATED(pi);
-  }
-
-  return p_tcaphash_context;
-}
-
-/*
-* Try to find a TCAP session according to the destination Identifier given in the TC_END/TC_ABORT
-* If nothing is found,
-* - either it is a session in opening state,
-* - or the session is closed/aborted by the remote, ( so we switch the src and dst tid )
-* so try to find a tcap session registered with a TC_BEGIN "key",
-* matching the destination Id of the TC_END
-* Then associate the TC_CONT "key" to the TCAP context
-* and display the available info for the TCAP context
-*/
-
-static struct tcaphash_context_t *
-tcaphash_end_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
-                     struct tcapsrt_info_t *p_tcapsrt_info)
-{
-  struct tcaphash_context_t *p_tcaphash_context=NULL;
-
-  struct tcaphash_end_info_key_t tcaphash_end_key;
-  struct tcaphash_endcall_t *p_tcaphash_endcall=NULL;
-
-  struct tcaphash_begin_info_key_t tcaphash_begin_key;
-  struct tcaphash_begincall_t *p_tcaphash_begincall=NULL;
-  proto_item *pi;
-  nstime_t delta;
-  proto_item *stat_item=NULL;
-  proto_tree *stat_tree=NULL;
-
-#ifdef DEBUG_TCAPSRT
-  dbg(10,"\n Hend #%u ", pinfo->fd->num);
-#endif
-  /* look only for matching request, if matching conversation is available. */
-  tcaphash_end_key.tid = p_tcapsrt_info->dst_tid;
-  if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
-  {
-    /* We have MTP3 PCs (so we can safely do this cast) */
-    tcaphash_end_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
-    tcaphash_end_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
-  } else {
-    /* Don't have MTP3 PCs (maybe we're over SUA?) */
-    tcaphash_end_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
-    tcaphash_end_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
-  }
-  tcaphash_end_key.hashKey=tcaphash_end_calchash(&tcaphash_end_key);
-
-#ifdef DEBUG_TCAPSRT
-  dbg(11,"Ekey %lx ",tcaphash_end_key.hashKey);
-  dbg(11,"PC %s %s ",ep_address_to_str(&pinfo->src), ep_address_to_str(&pinfo->dst));
-  dbg(51,"Tid %lx ",tcaphash_end_key.tid);
-#endif
-  p_tcaphash_endcall = find_tcaphash_end(&tcaphash_end_key, pinfo,TRUE);
-
-  if(!p_tcaphash_endcall) {
-#ifdef DEBUG_TCAPSRT
-    dbg(12,"EnotFound ");
-#endif
-    tcaphash_begin_key.tid = p_tcapsrt_info->dst_tid;
-    if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
-    {
-      /* We have MTP3 PCs (so we can safely do this cast) */
-      tcaphash_begin_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
-      tcaphash_begin_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
-    } else {
-      /* Don't have MTP3 PCs (maybe we're over SUA?) */
-      tcaphash_begin_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
-      tcaphash_begin_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
-    }
-    tcaphash_begin_key.hashKey=tcaphash_begin_calchash(&tcaphash_begin_key);
-
-#ifdef DEBUG_TCAPSRT
-    dbg(11,"Bkey %lx ", tcaphash_begin_key.hashKey);
-    dbg(51,"PC %s %s ",ep_address_to_str(&pinfo->src), ep_address_to_str(&pinfo->dst));
-    dbg(51,"Tid %lx ",tcaphash_begin_key.tid);
-#endif
-    p_tcaphash_begincall = find_tcaphash_begin(&tcaphash_begin_key, pinfo,FALSE);
-    if(!p_tcaphash_begincall) {
-#ifdef DEBUG_TCAPSRT
-      dbg(12,"BnotFound ");
-#endif
-    }
-  }
-  if (p_tcaphash_endcall) {
-    /* Use the TC_BEGIN Destination reference */
-    p_tcaphash_context=p_tcaphash_endcall->context;
-  } else if (p_tcaphash_begincall) {
-    /* Use the TC_BEGIN Source reference */
-    p_tcaphash_context=p_tcaphash_begincall->context;
-  }
-
-  if (p_tcaphash_context) {
-
-#ifdef DEBUG_TCAPSRT
-    dbg(12,"Found, req=%d ",p_tcaphash_context->first_frame);
-#endif
-    if (gtcap_DisplaySRT && tree) {
-      stat_item = proto_tree_add_text(tree, tvb, 0, -1, "Stat");
-      PROTO_ITEM_SET_GENERATED(stat_item);
-      stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
-
-      pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
-      PROTO_ITEM_SET_GENERATED(pi);
-    }
-
-#ifdef DEBUG_TCAPSRT
-    dbg(20,"Display framereqlink %d ",p_tcaphash_context->first_frame);
-#endif
-    /* Indicate the frame to which this is a reply. */
-    if (gtcap_DisplaySRT && stat_tree) {
-      pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_EndSession, tvb, 0, 0,
-                                     p_tcaphash_context->first_frame,
-                                     "Begin of session in frame %u",
-                                     p_tcaphash_context->first_frame);
-      PROTO_ITEM_SET_GENERATED(pi);
-      /* Calculate Service Response Time */
-      nstime_delta(&delta, &pinfo->fd->abs_ts, &p_tcaphash_context->begin_time);
-
-      /* display Service Response Time and make it filterable */
-      pi = proto_tree_add_time(stat_tree, hf_tcapsrt_SessionTime, tvb, 0, 0, &delta);
-      PROTO_ITEM_SET_GENERATED(pi);
-    }
-    /* Close the context and remove it (if needed) */
-    tcapsrt_close(p_tcaphash_context,pinfo);
-
-  } else {/* context present */
-#ifdef DEBUG_TCAPSRT
-    dbg(12,"Context notFound ");
-#endif
-  }
-  return p_tcaphash_context;
-}
-
-/*
- * ANSI PART
- * Create the record identifiying the TCAP transaction
- * When the identifier for the transaction is reused, check
- * the following criteria before to append a new record:
- * - a timeout corresponding to a message retransmission is detected,
- * - a message hast been lost
- * - or the previous transaction has been  be closed
- */
-static struct tcaphash_context_t *
-tcaphash_ansi_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
-                      struct tcapsrt_info_t *p_tcapsrt_info)
-{
-  struct tcaphash_context_t *p_tcaphash_context=NULL;
-  struct tcaphash_context_key_t tcaphash_context_key;
-  struct tcaphash_ansicall_t *p_tcaphash_ansicall, *p_new_tcaphash_ansicall;
-  struct tcaphash_ansi_info_key_t tcaphash_ansi_key;
-  proto_item *pi;
-  nstime_t delta;
-  gboolean isResponse=FALSE;
-  proto_tree * stat_tree=NULL;
-  proto_item * stat_item=NULL;
-
-  /* prepare the key data */
-  tcaphash_ansi_key.tid = p_tcapsrt_info->src_tid;
-  if (pinfo->src.type == AT_SS7PC && pinfo->dst.type == AT_SS7PC)
-  {
-    /* We have MTP3 PCs (so we can safely do this cast) */
-    tcaphash_ansi_key.opc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->src.data);
-    tcaphash_ansi_key.dpc_hash = mtp3_pc_hash((const mtp3_addr_pc_t *)pinfo->dst.data);
-  } else {
-    /* Don't have MTP3 PCs (maybe we're over SUA?) */
-    tcaphash_ansi_key.opc_hash = g_str_hash(ep_address_to_str(&pinfo->src));
-    tcaphash_ansi_key.dpc_hash = g_str_hash(ep_address_to_str(&pinfo->dst));
-  }
-  tcaphash_ansi_key.hashKey=tcaphash_ansi_calchash(&tcaphash_ansi_key);
-
-  /* look up the request */
-#ifdef DEBUG_TCAPSRT
-  dbg(10,"\n Hansi #%u ", pinfo->fd->num);
-  dbg(11,"key %lx ",tcaphash_ansi_key.hashKey);
-  dbg(51,"PC %s %s ",ep_address_to_str(&pinfo->src), ep_address_to_str(&pinfo->dst));
-  dbg(51,"Tid %lx ",tcaphash_ansi_key.tid);
-#endif
-  p_tcaphash_ansicall = (struct tcaphash_ansicall_t *)
-    g_hash_table_lookup(tcaphash_ansi, &tcaphash_ansi_key);
-
-  if (p_tcaphash_ansicall) {
-    /* Walk through list of transaction with identical keys */
-    do {
-      /* Check if the request with this reqSeqNum has been seen */
-      if (pinfo->fd->num == p_tcaphash_ansicall->context->first_frame) {
-       /* We have seen this request before -> do nothing */
-#ifdef DEBUG_TCAPSRT
-       dbg(22,"Request already seen ");
-#endif
-       isResponse=FALSE;
-       p_tcaphash_context=p_tcaphash_ansicall->context;
-       break;
-      }
-
-      /* Check if the reponse with this reqSeqNum has been seen */
-      if (pinfo->fd->num == p_tcaphash_ansicall->context->last_frame) {
-       /* We have seen this response before -> do nothing */
-#ifdef DEBUG_TCAPSRT
-       dbg(22,"Response already seen ");
-#endif
-       isResponse=TRUE;
-       p_tcaphash_context=p_tcaphash_ansicall->context;
-       break;
-      }
-
-      /* Check for the first Request without Response
-       received before this frame */
-      if ( pinfo->fd->num > p_tcaphash_ansicall->context->first_frame &&
-          p_tcaphash_ansicall->context->last_frame==0 ) {
-       /* Take it, and update the context */
-
-#ifdef DEBUG_TCAPSRT
-       dbg(12,"Update key %lx ",tcaphash_ansi_key.hashKey);
-#endif
-       p_tcaphash_ansicall->context->last_frame = pinfo->fd->num;
-       p_tcaphash_ansicall->context->responded = TRUE;
-       p_tcaphash_ansicall->context->closed = TRUE;
-       p_tcaphash_context=p_tcaphash_ansicall->context;
-       isResponse=TRUE;
-
-       if (gtcap_DisplaySRT && tree) {
-         stat_item = proto_tree_add_text(tree, tvb, 0, -1, "Stat");
-         PROTO_ITEM_SET_GENERATED(stat_item);
-         stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
-
-         pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
-         PROTO_ITEM_SET_GENERATED(pi);
-
-#ifdef DEBUG_TCAPSRT
-         dbg(20,"Display framereqlink %d ",p_tcaphash_context->first_frame);
-#endif
-         /* Indicate the frame to which this is a reply. */
-         pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_EndSession, tvb, 0, 0,
-                                         p_tcaphash_context->first_frame,
-                                         "Begin of session in frame %u",
-                                         p_tcaphash_context->first_frame);
-         PROTO_ITEM_SET_GENERATED(pi);
-         /* Calculate Service Response Time */
-         nstime_delta(&delta, &pinfo->fd->abs_ts, &p_tcaphash_context->begin_time);
-
-         /* display Service Response Time and make it filterable */
-         pi = proto_tree_add_time(stat_tree, hf_tcapsrt_SessionTime, tvb, 0, 0, &delta);
-         PROTO_ITEM_SET_GENERATED(pi);
-       }
-       break;
-      } /* Lastframe=0, so take it */
-
-
-      /* If the last record for Tcap transaction with identifier has been reached */
-      if (!p_tcaphash_ansicall->next_ansicall) {
-       /* check if we have to create a new record or not */
-       /* if last request has been responded (response number in known)
-          and this request appears after last response (has bigger frame number)
-          and last request occurred after the timeout for repetition,
-          or
-          if last request hasn't been responded (so number unknown)
-          and this request appears after last request (has bigger frame number)
-          and this request occurred after the timeout for message lost */
-       if ( ( p_tcaphash_ansicall->context->last_frame != 0
-              && pinfo->fd->num > p_tcaphash_ansicall->context->first_frame
-              && (guint) pinfo->fd->abs_ts.secs > (guint)(p_tcaphash_ansicall->context->begin_time.secs + gtcap_RepetitionTimeout)
-              ) ||
-            ( p_tcaphash_ansicall->context->last_frame == 0
-              && pinfo->fd->num > p_tcaphash_ansicall->context->first_frame
-              && (guint)pinfo->fd->abs_ts.secs > (guint)(p_tcaphash_ansicall->context->begin_time.secs + gtcap_LostTimeout)
-              )
-            )
-         {
-           /* we decide that we have a new request */
-           /* Append new record to the list */
-#ifdef DEBUG_TCAPSRT
-           dbg(12,"(timeout) Append key %lx ",tcaphash_ansi_key.hashKey);
-           dbg(12,"Frame %u rsp %u ",pinfo->fd->num,p_tcaphash_ansicall->context->last_frame );
-#endif
-           tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
-           p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
-           p_new_tcaphash_ansicall = append_tcaphash_ansicall(p_tcaphash_ansicall,
-                                                                p_tcaphash_context,
-                                                                pinfo);
-
-#ifdef DEBUG_TCAPSRT
-           dbg(12,"Update key %lx ",tcaphash_ansi_key.hashKey);
-#endif
-           update_tcaphash_ansicall(p_new_tcaphash_ansicall, pinfo);
-           p_tcaphash_ansicall=p_new_tcaphash_ansicall;
-         } else {
-
-         /* If the Tid is reused for a closed Transaction */
-         if ( p_tcaphash_ansicall->context->closed) {
-#ifdef DEBUG_TCAPSRT
-           dbg(12,"(closed) Append key %lu ",tcaphash_ansi_key.hashKey);
-           dbg(12,"Frame %u rsp %u ",pinfo->fd->num,p_tcaphash_ansicall->context->last_frame );
-#endif
-           tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
-           p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
-           p_new_tcaphash_ansicall = append_tcaphash_ansicall(p_tcaphash_ansicall,
-                                                                p_tcaphash_context,
-                                                                pinfo);
-
-#ifdef DEBUG_TCAPSRT
-           dbg(12,"Update key %lu ",tcaphash_ansi_key.hashKey);
-#endif
-           update_tcaphash_ansicall(p_new_tcaphash_ansicall, pinfo);
-           p_tcaphash_ansicall=p_new_tcaphash_ansicall;
-
-         } else {
-           /* the Tid is reused for an opened Transaction */
-           /* so, this is the reply to the request of our context */
-           p_tcaphash_context=p_tcaphash_ansicall->context;
-#ifdef DEBUG_TCAPSRT
-           dbg(12,"Found, req=%d ",p_tcaphash_context->first_frame);
-#endif
-
-           if (gtcap_DisplaySRT && tree) {
-             stat_item = proto_tree_add_text(tree, tvb, 0, -1, "Stat");
-             PROTO_ITEM_SET_GENERATED(stat_item);
-             stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
-
-             pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
-             PROTO_ITEM_SET_GENERATED(pi);
-
-#ifdef DEBUG_TCAPSRT
-             dbg(20,"Display framereqlink %d ",p_tcaphash_context->first_frame);
-#endif
-             /* Indicate the frame to which this is a reply. */
-             pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_EndSession, tvb, 0, 0,
-                                             p_tcaphash_context->first_frame,
-                                             "Begin of session in frame %u",
-                                             p_tcaphash_context->first_frame);
-             PROTO_ITEM_SET_GENERATED(pi);
-             /* Calculate Service Response Time */
-             nstime_delta(&delta, &pinfo->fd->abs_ts, &p_tcaphash_context->begin_time);
-
-             /* display Service Response Time and make it filterable */
-             pi = proto_tree_add_time(stat_tree, hf_tcapsrt_SessionTime, tvb, 0, 0, &delta);
-             PROTO_ITEM_SET_GENERATED(pi);
-           }
-           p_tcaphash_context=p_tcaphash_ansicall->context;
-         } /* test with Timeout */
-       } /* closed */
-       break;
-      } /* Next call is NULL */
-      p_tcaphash_ansicall = p_tcaphash_ansicall->next_ansicall;
-    } while (p_tcaphash_ansicall != NULL );
-    /*
-     * New TCAP context
-     */
-  } else { /* p_tcaphash_ansicall has not been found */
-#ifdef DEBUG_TCAPSRT
-    dbg(10,"New key %lx ",tcaphash_ansi_key.hashKey);
-#endif
-
-    tcaphash_context_key.session_id = tcapsrt_global_SessionId++;
-    p_tcaphash_context = new_tcaphash_context(&tcaphash_context_key, pinfo);
-    p_tcaphash_ansicall = new_tcaphash_ansi(&tcaphash_ansi_key, p_tcaphash_context);
-
-#ifdef DEBUG_TCAPSRT
-    dbg(11,"Update key %lx ",tcaphash_ansi_key.hashKey);
-    dbg(11,"Frame reqlink #%u ", pinfo->fd->num);
-#endif
-    update_tcaphash_ansicall(p_tcaphash_ansicall, pinfo);
-  }
-
-  /* display tcap session, if available */
-  if ( gtcap_DisplaySRT && tree &&
-       p_tcaphash_context &&
-       p_tcaphash_context->session_id) {
-    stat_item = proto_tree_add_text(tree, tvb, 0, -1, "Stat");
-    PROTO_ITEM_SET_GENERATED(stat_item);
-    stat_tree = proto_item_add_subtree(stat_item, ett_tcap_stat);
-    pi = proto_tree_add_uint(stat_tree, hf_tcapsrt_SessionId, tvb, 0,0, p_tcaphash_context->session_id);
-    PROTO_ITEM_SET_GENERATED(pi);
-  }
-
-
-  /* add link to response frame, if available */
-  if( gtcap_DisplaySRT && stat_tree &&
-      p_tcaphash_ansicall->context->last_frame != 0){
-    if (!isResponse) { /* Request */
-#ifdef DEBUG_TCAPSRT
-      dbg(20,"Display_frameRsplink %d ",p_tcaphash_ansicall->context->last_frame);
-#endif
-      pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_BeginSession, tvb, 0, 0,
-                                     p_tcaphash_ansicall->context->last_frame,
-                                     "End of session in frame %u",
-                                     p_tcaphash_ansicall->context->last_frame);
-      PROTO_ITEM_SET_GENERATED(pi);
-    } else { /* Response */
-#ifdef DEBUG_TCAPSRT
-      dbg(20,"Display framereqlink %d ",p_tcaphash_context->first_frame);
-#endif
-      /* Indicate the frame to which this is a reply. */
-      if (gtcap_DisplaySRT) {
-       pi = proto_tree_add_uint_format(stat_tree, hf_tcapsrt_EndSession, tvb, 0, 0,
-                                       p_tcaphash_context->first_frame,
-                                       "Begin of session in frame %u",
-                                       p_tcaphash_context->first_frame);
-       PROTO_ITEM_SET_GENERATED(pi);
-       /* Calculate Service Response Time */
-       nstime_delta(&delta, &pinfo->fd->abs_ts, &p_tcaphash_context->begin_time);
-
-       /* display Service Response Time and make it filterable */
-       pi = proto_tree_add_time(stat_tree, hf_tcapsrt_SessionTime, tvb, 0, 0, &delta);
-       PROTO_ITEM_SET_GENERATED(pi);
-      }
-    } /* Request or Response */
-  }
-  return p_tcaphash_context;
-}
-
-
-/*
- * Initialize the Message Info used by the main dissector
- * Data are linked to a TCAP transaction
- */
-struct tcapsrt_info_t *
-tcapsrt_razinfo(void)
-{
-  struct tcapsrt_info_t *p_tcapsrt_info ;
-
-  /* Global buffer for packet extraction */
-  tcapsrt_global_current++;
-  if(tcapsrt_global_current==MAX_TCAP_INSTANCE){
-    tcapsrt_global_current=0;
-  }
-
-  p_tcapsrt_info=&tcapsrt_global_info[tcapsrt_global_current];
-  memset(p_tcapsrt_info,0,sizeof(struct tcapsrt_info_t));
-
-  return p_tcapsrt_info;
-}
-
-void
-tcapsrt_close(struct tcaphash_context_t *p_tcaphash_context,
-             packet_info *pinfo)
-{
-#ifdef DEBUG_TCAPSRT
-  dbg(60,"Force close ");
-#endif
-  if (p_tcaphash_context) {
-    p_tcaphash_context->responded=TRUE;
-    p_tcaphash_context->last_frame = pinfo->fd->num;
-    p_tcaphash_context->end_time = pinfo->fd->abs_ts;
-    p_tcaphash_context->closed=TRUE;
-
-    /* If the endkey is present */
-    if (p_tcaphash_context->endcall
-       && !gtcap_PersistentSRT) {
-      if (p_tcaphash_context->endcall->next_endcall) {
-       if (p_tcaphash_context->endcall->previous_endcall ) {
-#ifdef DEBUG_TCAPSRT
-         dbg(20,"deplace Ehash ");
-#endif
-         p_tcaphash_context->endcall->previous_endcall->next_endcall
-           = p_tcaphash_context->endcall->next_endcall;
-         p_tcaphash_context->endcall->next_endcall->previous_endcall
-           = p_tcaphash_context->endcall->previous_endcall;
-         g_hash_table_remove(tcaphash_end, p_tcaphash_context->endcall->endkey);
-#ifdef MEM_TCAPSRT
-         g_free(p_tcaphash_context->endcall);
-#endif
-       } else {
-         /* cannot remove the father */
-#ifdef DEBUG_TCAPSRT
-         dbg(20,"father Ehash ");
-#endif
-       } /* no previous link, so father */
-      } else if (!gtcap_PersistentSRT) {
-#ifdef DEBUG_TCAPSRT
-       dbg(20,"remove Ehash ");
-#endif
-       g_hash_table_remove(tcaphash_end, p_tcaphash_context->endcall->endkey);
-#ifdef MEM_TCAPSRT
-       g_free(p_tcaphash_context->endcall->endkey);
-       g_free(p_tcaphash_context->endcall);
-#endif
-
-      } /* endcall without chained string */
-    } /* no endcall */
-
-
-    /* If the contkey is present */
-    if (p_tcaphash_context->contcall
-       && !gtcap_PersistentSRT) {
-      if (p_tcaphash_context->contcall->next_contcall) {
-       if (p_tcaphash_context->contcall->previous_contcall ) {
-#ifdef DEBUG_TCAPSRT
-         dbg(20,"deplace Chash ");
-#endif
-         p_tcaphash_context->contcall->previous_contcall->next_contcall
-           = p_tcaphash_context->contcall->next_contcall;
-         p_tcaphash_context->contcall->next_contcall->previous_contcall
-           = p_tcaphash_context->contcall->previous_contcall;
-         g_hash_table_remove(tcaphash_cont, p_tcaphash_context->contcall->contkey);
-#ifdef MEM_TCAPSRT
-         g_free(p_tcaphash_context->contcall);
-#endif
-       } else {
-         /* cannot remove the father */
-#ifdef DEBUG_TCAPSRT
-         dbg(20,"father Chash ");
-#endif
-       } /* no previous link, so father */
-      } else if (!gtcap_PersistentSRT) {
-#ifdef DEBUG_TCAPSRT
-       dbg(20,"remove Chash ");
-#endif
-       g_hash_table_remove(tcaphash_cont, p_tcaphash_context->contcall->contkey);
-#ifdef MEM_TCAPSRT
-       g_free(p_tcaphash_context->contcall->contkey);
-       g_free(p_tcaphash_context->contcall);
-#endif
-      } /* contcall without chained string */
-    } /* no contcall */
-
-
-    /* If the beginkey is present */
-    if (p_tcaphash_context->begincall
-       && !gtcap_PersistentSRT) {
-      if (p_tcaphash_context->begincall->next_begincall) {
-       if (p_tcaphash_context->begincall->previous_begincall ) {
-#ifdef DEBUG_TCAPSRT
-         dbg(20,"deplace Bhash ");
-#endif
-         p_tcaphash_context->begincall->previous_begincall->next_begincall
-           = p_tcaphash_context->begincall->next_begincall;
-         p_tcaphash_context->begincall->next_begincall->previous_begincall
-           = p_tcaphash_context->begincall->previous_begincall;
-         g_hash_table_remove(tcaphash_begin, p_tcaphash_context->begincall->beginkey);
-#ifdef MEM_TCAPSRT
-         g_free(p_tcaphash_context->begincall);
-#endif
-       } else {
-         /* cannot remove the father */
-#ifdef DEBUG_TCAPSRT
-         dbg(20,"father Bhash ");
-#endif
-       }
-      } else  if (!gtcap_PersistentSRT) {
-#ifdef DEBUG_TCAPSRT
-       dbg(20,"remove Bhash ");
-#endif
-       g_hash_table_remove(tcaphash_begin, p_tcaphash_context->begincall->beginkey);
-#ifdef MEM_TCAPSRT
-       g_free(p_tcaphash_context->begincall->beginkey);
-       g_free(p_tcaphash_context->begincall);
-#endif
-      } /* begincall without chained string */
-    } /* no begincall */
-
-    /* If the ansikey is present */
-    if (p_tcaphash_context->ansicall
-       && !gtcap_PersistentSRT) {
-      if (p_tcaphash_context->ansicall->next_ansicall) {
-       if (p_tcaphash_context->ansicall->previous_ansicall ) {
-#ifdef DEBUG_TCAPSRT
-         dbg(20,"deplace Ahash ");
-#endif
-         p_tcaphash_context->ansicall->previous_ansicall->next_ansicall
-           = p_tcaphash_context->ansicall->next_ansicall;
-         p_tcaphash_context->ansicall->next_ansicall->previous_ansicall
-           = p_tcaphash_context->ansicall->previous_ansicall;
-         g_hash_table_remove(tcaphash_ansi, p_tcaphash_context->ansicall->ansikey);
-#ifdef MEM_TCAPSRT
-         g_free(p_tcaphash_context->ansicall);
-#endif
-       } else {
-         /* cannot remove the father */
-#ifdef DEBUG_TCAPSRT
-         dbg(20,"father Ahash ");
-#endif
-       }
-      } else  if (!gtcap_PersistentSRT) {
-#ifdef DEBUG_TCAPSRT
-       dbg(20,"remove Ahash ");
-#endif
-       g_hash_table_remove(tcaphash_ansi, p_tcaphash_context->ansicall->ansikey);
-#ifdef MEM_TCAPSRT
-       g_free(p_tcaphash_context->ansicall->ansikey);
-       g_free(p_tcaphash_context->ansicall);
-#endif
-      } /* ansicall without chained string */
-    } /* no ansicall */
-
-    if (!gtcap_PersistentSRT) {
-#ifdef DEBUG_TCAPSRT
-      dbg(20,"remove context ");
-#endif
-      g_hash_table_remove(tcaphash_context, p_tcaphash_context->key);
-#ifdef MEM_TCAPSRT
-      g_free(p_tcaphash_context->key);
-      g_free(p_tcaphash_context);
-#endif
-    }
-  } else { /* no context */
-#ifdef DEBUG_TCAPSRT
-    dbg(20,"No context to remove ");
-#endif
-  }
-}
diff --git a/epan/tcap-persistentdata.h b/epan/tcap-persistentdata.h
deleted file mode 100644 (file)
index 93e68fb..0000000
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * tcap-persistentdata.h
- * Definitions for lists and hash tables used in wireshark's tcap dissector
- * for calculation of delays in tcap-transactions
- * Copyright 2006 Florent Drouin (based on h225-persistentdata from Lars Roland)
- *
- * Wireshark - Network traffic analyzer
- * By Gerald Combs <gerald@wireshark.org>
- * Copyright 1998 Gerald Combs
- *
- * $Id$
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef __tcapsrt_HASH__
-#define __tcapsrt_HASH__
-
-#include <epan/packet.h>
-#include <epan/conversation.h>
-#include <epan/dissectors/packet-tcap.h>
-#include "ws_symbol_export.h"
-
-/** @file
- * lists and hash tables used in wireshark's tcap dissector
- * for calculation of delays in tcap-calls
- */
-
-#define LENGTH_OID 23
-struct tcaphash_context_t {
-  struct tcaphash_context_key_t * key;
-  guint32 session_id;
-  guint32 first_frame;
-  guint32 last_frame;
-  nstime_t begin_time; /**< time of arrival of TC_BEGIN */
-  nstime_t end_time;   /**< time of closing message */
-  gboolean responded;  /**< true, if request has been responded */
-  gboolean closed;
-  gboolean upper_dissector;
-  gboolean oid_present;
-  gchar oid[LENGTH_OID+1];
-  gboolean subdissector_present;
-  dissector_handle_t subdissector_handle;
-  void (* callback) (tvbuff_t *,packet_info *, proto_tree *, struct tcaphash_context_t *);
-  struct tcaphash_begincall_t * begincall;
-  struct tcaphash_contcall_t * contcall;
-  struct tcaphash_endcall_t * endcall;
-  struct tcaphash_ansicall_t * ansicall;
-};
-
-struct tcaphash_begincall_t {
-  struct tcaphash_begin_info_key_t * beginkey;
-  struct tcaphash_context_t * context;
-  gboolean father;
-  struct tcaphash_begincall_t * next_begincall;
-  struct tcaphash_begincall_t * previous_begincall;
-};
-
-struct tcaphash_contcall_t {
-  struct tcaphash_cont_info_key_t * contkey;
-  struct tcaphash_context_t * context;
-  gboolean father;
-  struct tcaphash_contcall_t * next_contcall;
-  struct tcaphash_contcall_t * previous_contcall;
-};
-
-struct tcaphash_endcall_t {
-  struct tcaphash_end_info_key_t * endkey;
-  struct tcaphash_context_t * context;
-  gboolean father;
-  struct tcaphash_endcall_t * next_endcall;
-  struct tcaphash_endcall_t * previous_endcall;
-};
-
-struct tcaphash_ansicall_t {
-  struct tcaphash_ansi_info_key_t * ansikey;
-  struct tcaphash_context_t * context;
-  gboolean father;
-  struct tcaphash_ansicall_t * next_ansicall;
-  struct tcaphash_ansicall_t * previous_ansicall;
-};
-
-/** The Key for the hash table is the TCAP origine transaction identifier
-   of the TC_BEGIN containing the InitialDP */
-
-struct tcaphash_context_key_t {
-  guint32 session_id;
-};
-
-struct tcaphash_begin_info_key_t {
-  guint32 hashKey;
-  guint32 tid;
-  guint32 opc_hash;
-  guint32 dpc_hash;
-};
-
-struct tcaphash_cont_info_key_t {
-  guint32 hashKey;
-  guint32 src_tid;
-  guint32 dst_tid;
-  guint32 opc_hash;
-  guint32 dpc_hash;
-};
-
-struct tcaphash_end_info_key_t {
-  guint32 hashKey;
-  guint32 tid;
-  guint32 opc_hash;
-  guint32 dpc_hash;
-};
-
-struct tcaphash_ansi_info_key_t {
-  guint32 hashKey;
-  guint32 tid;
-  guint32 opc_hash;
-  guint32 dpc_hash;
-};
-
-
-/** List of infos to store for the analyse */
-struct tcapsrt_info_t {
-  guint32 tcap_session_id;
-  guint32 src_tid;
-  guint32 dst_tid;
-  guint8 ope;
-};
-
-/**
- * Routine called when the TAP is initialized.
- * so hash table are (re)created
- */
-void tcapsrt_init_routine(void);
-
-/**
- * Initialize the Message Info used by the main dissector
- * Data are linked to a TCAP transaction
- */
-struct tcapsrt_info_t * tcapsrt_razinfo(void);
-
-void tcapsrt_close(struct tcaphash_context_t * p_tcaphash_context,
-                  packet_info * pinfo _U_);
-
-/**
- * Service Response Time analyze
- * Called just after dissector call
- * Associate a TCAP context to a tcap session and display session related infomations
- * like the first frame, the last, the session duration,
- * and a uniq session identifier for the filtering
- *
- * For ETSI tcap, the TCAP context can be reached through three keys
- * - a key (BEGIN) identifying the session according to the tcap source identifier
- * - a key (CONT) identifying the established session (src_id and dst_id)
- * - a key (END) identifying the session according to the tcap destination identifier
- *
- * For ANSI tcap, the TCAP context is reached through a uniq key
- * - a key (ANSI) identifying the session according to the tcap identifier
-*/
-struct tcaphash_context_t * tcapsrt_call_matching(tvbuff_t *tvb,
-                                                 packet_info * pinfo _U_,
-                                                 proto_tree *tree,
-                                                 struct tcapsrt_info_t * p_tcap_info);
-
-WS_DLL_PUBLIC gboolean gtcap_StatSRT;
-
-#endif /* __tcapsrt_HASH__*/
index d1fd5dbf4424753572d0dd2088c987f55f0bc9b9..ddbe9951d11f26474eeb886568050543b73bb61f 100644 (file)
@@ -37,7 +37,7 @@
 #include "epan/value_string.h"
 #include "epan/stat_cmd_args.h"
 #include "epan/asn1.h"
-#include "epan/camel-persistentdata.h"
+#include "epan/dissectors/packet-camel.h"
 
 void register_tap_listener_camelcounter(void);
 
index 64c357c2ff1163aa27098f8e687a3ceb48bd47ee..a53d81784c29533161b47bcd46d67f8618fc0269 100644 (file)
@@ -35,7 +35,7 @@
 #include "epan/value_string.h"
 #include "epan/asn1.h"
 #include "epan/dissectors/packet-camel.h"
-#include "epan/camel-persistentdata.h"
+#include "epan/dissectors/packet-tcap.h"
 #include "epan/timestats.h"
 #include "epan/stat_cmd_args.h"
 
index 1e1598070177fd4c5f637c693486dcf4de55e2aa..d5e3ad26b8d0f60a46425fb7f00ce93cccbf6c3e 100644 (file)
@@ -35,7 +35,7 @@
 #include <epan/tap.h>
 #include <epan/packet.h>
 #include <epan/asn1.h>
-#include <epan/camel-persistentdata.h>
+#include <epan/dissectors/packet-camel.h>
 
 #include "../stat_menu.h"
 
index d9d396d8de57249dc9940427cba001ea600b9ef2..d12f14e60294307ae07790eea37209dd5da70231 100644 (file)
@@ -34,7 +34,7 @@
 #include <epan/tap.h>
 #include <epan/packet.h>
 #include <epan/asn1.h>
-#include <epan/camel-persistentdata.h>
+#include <epan/dissectors/packet-camel.h>
 
 #include "../file.h"
 #include "../stat_menu.h"