]> git.samba.org - obnox/wireshark/wip.git/blobdiff - epan/dissectors/packet-jxta.c
various code cleanup:
[obnox/wireshark/wip.git] / epan / dissectors / packet-jxta.c
index 1c3d066cef3f094355cf9d8c369f66080dc1bd56..fcabe44d690373e320c4de2577e5b608fe7c0b40 100644 (file)
@@ -1,6 +1,6 @@
 /* packet-jxta.c
  * Routines for JXTA packet dissection
- * Copyright 2004, Mike Duigou <bondolo@jxta.org>
+ * Copyright 2004-05, Mike Duigou <bondolo@jxta.org>
  * Heavily based on packet-jabber.c, which in turn is heavily based on 
  * on packet-acap.c, which in turn is heavily based on 
  * packet-imap.c, Copyright 1999, Richard Sharpe <rsharpe@ns.aus.com>
 #endif
 
 #include <stdio.h>
-
 #include <string.h>
+
 #include <glib.h>
+
 #include <epan/packet.h>
+#include <epan/conversation.h>
 #include <epan/strutil.h>
 #include <epan/prefs.h>
-#include "packet-tcp.h"
+#include <epan/tap.h>
+#include <epan/emem.h>
+
+#include "packet-jxta.h"
+
+static const gchar JXTA_UDP_SIG[] = { 'J', 'X', 'T', 'A' };
+static const gchar JXTA_MSG_SIG[] = { 'j', 'x', 'm', 'g' };
+static const gchar JXTA_MSGELEM_SIG[] = { 'j', 'x', 'e', 'l' };
+
+static const gchar JXTA_WELCOME_MSG_SIG[] = { 'J', 'X', 'T', 'A', 'H', 'E', 'L', 'L', 'O', ' ' };
 
 static int proto_jxta = -1;
+static int proto_welcome_jxta = -1;
+static int proto_udp_jxta = -1;
+static int proto_framing_jxta = -1;
+static int proto_message_jxta = -1;
+static int jxta_tap = -1;
+
+static dissector_table_t media_type_dissector_table = NULL;
+static dissector_handle_t tcp_jxta_handle = NULL;
 
-static int hf_jxta_udp = -1;
 static int hf_jxta_udpsig = -1;
-static int hf_jxta_welcome = -1;
-static int hf_jxta_framing = -1;
-static int hf_jxta_framing_header_name_length = -1;
+static int hf_jxta_welcome_initiator = -1;
+static int hf_jxta_welcome_sig = -1;
+static int hf_jxta_welcome_destAddr = -1;
+static int hf_jxta_welcome_pubAddr = -1;
+static int hf_jxta_welcome_peerid = -1;
+static int hf_jxta_welcome_noProp = -1;
+static int hf_jxta_welcome_version = -1;
+static int hf_jxta_framing_header = -1;
 static int hf_jxta_framing_header_name = -1;
 static int hf_jxta_framing_header_value_length = -1;
 static int hf_jxta_framing_header_value = -1;
-static int hf_jxta_message = -1;
+static int hf_jxta_message_address = -1;
+static int hf_jxta_message_src = -1;
+static int hf_jxta_message_dst = -1;
 static int hf_jxta_message_sig = -1;
 static int hf_jxta_message_version = -1;
 static int hf_jxta_message_namespaces_count = -1;
-static int hf_jxta_message_namespace_len = -1;
 static int hf_jxta_message_namespace_name = -1;
 static int hf_jxta_message_element_count = -1;
 static int hf_jxta_element = -1;
 static int hf_jxta_element_sig = -1;
 static int hf_jxta_element_namespaceid = -1;
 static int hf_jxta_element_flags = -1;
-static int hf_jxta_element_name_len = -1;
+static int hf_jxta_element_flag_hasType = -1;
+static int hf_jxta_element_flag_hasEncoding = -1;
+static int hf_jxta_element_flag_hasSignature = -1;
 static int hf_jxta_element_name = -1;
-static int hf_jxta_element_type_len = -1;
 static int hf_jxta_element_type = -1;
-static int hf_jxta_element_encoding_len = -1;
 static int hf_jxta_element_encoding = -1;
-static int hf_jxta_element_data_length = -1;
 static int hf_jxta_element_content_len = -1;
 static int hf_jxta_element_content = -1;
-static int hf_jxta_element_signature = -1;
+static int hf_jxta_element_content_text = -1;
 
+/** our header fields */
+static hf_register_info hf[] = {
+    {&hf_jxta_udpsig,
+     {"Signature", "jxta.udpsig", FT_STRING, BASE_NONE, NULL, 0x0,
+      "JXTA UDP Signature", HFILL}
+     },
+    {&hf_jxta_welcome_initiator,
+     {"Initiator", "jxta.welcome.initiator", FT_BOOLEAN, BASE_NONE, NULL, 0x00,
+      "JXTA Connection Welcome Message Initiator", HFILL}
+     },
+    {&hf_jxta_welcome_sig,
+     {"Signature", "jxta.welcome.signature", FT_STRING, BASE_NONE, NULL, 0x0,
+      "JXTA Connection Welcome Message Signature", HFILL}
+     },
+    {&hf_jxta_welcome_destAddr,
+     {"Destination Address", "jxta.welcome.destAddr", FT_STRING, BASE_NONE, NULL, 0x0,
+      "JXTA Connection Welcome Message Destination Address", HFILL}
+     },
+    {&hf_jxta_welcome_pubAddr,
+     {"Public Address", "jxta.welcome.pubAddr", FT_STRING, BASE_NONE, NULL, 0x0,
+      "JXTA Connection Welcome Message Public Address", HFILL}
+     },
+    {&hf_jxta_welcome_peerid,
+     {"PeerID", "jxta.welcome.peerid", FT_STRING, BASE_NONE, NULL, 0x0,
+      "JXTA Connection Welcome Message PeerID", HFILL}
+     },
+    {&hf_jxta_welcome_noProp,
+     {"No Propagate Flag", "jxta.welcome.noPropFlag", FT_STRING, BASE_NONE, NULL, 0x0,
+      "JXTA Connection Welcome Message No Propagate Flag", HFILL}
+     },
+    {&hf_jxta_welcome_version,
+     {"Version", "jxta.welcome.version", FT_STRING, BASE_NONE, NULL, 0x0,
+      "JXTA Connection Welcome Message Version", HFILL}
+     },
+    {&hf_jxta_framing_header,
+     {"Header", "jxta.framing.header", FT_NONE, BASE_NONE, NULL, 0x0,
+      "JXTA Message Framing Header", HFILL}
+     },
+    {&hf_jxta_framing_header_name,
+     {"Name", "jxta.framing.header.name", FT_UINT_STRING, BASE_NONE, NULL, 0x0,
+      "JXTA Message Framing Header Name", HFILL}
+     },
+    {&hf_jxta_framing_header_value_length,
+     {"Value Length", "jxta.framing.header.valuelen", FT_UINT16, BASE_DEC, NULL, 0x0,
+      "JXTA Message Framing Header Value Length", HFILL}
+     },
+    {&hf_jxta_framing_header_value,
+     {"Value", "jxta.framing.header.value", FT_BYTES, BASE_HEX, NULL, 0x0,
+      "JXTA Message Framing Header Value", HFILL}
+     },
+    {&hf_jxta_message_address,
+     {"Address", "jxta.message.address", FT_STRING, BASE_NONE, NULL, 0x0,
+      "JXTA Message Address (source or destination)", HFILL}
+     },
+    {&hf_jxta_message_src,
+     {"Source", "jxta.message.source", FT_STRING, BASE_NONE, NULL, 0x0,
+      "JXTA Message Source", HFILL}
+     },
+    {&hf_jxta_message_dst,
+     {"Destination", "jxta.message.destination", FT_STRING, BASE_NONE, NULL, 0x0,
+      "JXTA Message Destination", HFILL}
+     },
+    {&hf_jxta_message_sig,
+     {"Signature", "jxta.message.signature", FT_STRING, BASE_NONE, NULL, 0x0,
+      "JXTA Message Signature", HFILL}
+     },
+    {&hf_jxta_message_version,
+     {"Version", "jxta.message.version", FT_UINT8, BASE_DEC, NULL, 0x0,
+      "JXTA Message Version", HFILL}
+     },
+    {&hf_jxta_message_namespaces_count,
+     {"Namespace Count", "jxta.message.namespaces", FT_UINT16, BASE_DEC, NULL, 0x0,
+      "JXTA Message Namespaces", HFILL}
+     },
+    {&hf_jxta_message_namespace_name,
+     {"Namespace Name", "jxta.message.namespace.name", FT_UINT_STRING, BASE_NONE, NULL, 0x0,
+      "JXTA Message Namespace Name", HFILL}
+     },
+    {&hf_jxta_message_element_count,
+     {"Element Count", "jxta.message.elements", FT_UINT16, BASE_DEC, NULL, 0x0,
+      "JXTA Message Element Count", HFILL}
+     },
+    {&hf_jxta_element,
+     {"JXTA Message Element", "jxta.message.element", FT_NONE, BASE_NONE, NULL, 0x0,
+      "JXTA Message Element", HFILL}
+     },
+    {&hf_jxta_element_sig,
+     {"Signature", "jxta.message.element.signature", FT_STRING, BASE_NONE, NULL, 0x0,
+      "JXTA Message Element Signature", HFILL}
+     },
+    {&hf_jxta_element_namespaceid,
+     {"Namespace ID", "jxta.message.element.namespaceid", FT_UINT8, BASE_DEC, NULL, 0x0,
+      "JXTA Message Element Namespace ID", HFILL}
+     },
+    {&hf_jxta_element_flags,
+     {"Flags", "jxta.message.element.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
+      "JXTA Message Element Flags", HFILL}
+     },
+    {&hf_jxta_element_flag_hasType,
+     {"hasType", "jxta.message.element.flags.hasType", FT_BOOLEAN, 3, TFS(&flags_set_truth), 0x01,
+      "JXTA Message Element Flag -- hasType", HFILL}
+     },
+    {&hf_jxta_element_flag_hasEncoding,
+     {"hasEncoding", "jxta.message.element.flags.hasEncoding", FT_BOOLEAN, 3, TFS(&flags_set_truth), 0x02,
+      "JXTA Message Element Flag -- hasEncoding", HFILL}
+     },
+    {&hf_jxta_element_flag_hasSignature,
+     {"hasSignature", "jxta.message.element.flags.hasSignature", FT_BOOLEAN, 3, TFS(&flags_set_truth), 0x04,
+      "JXTA Message Element Flag -- hasSignature", HFILL}
+     },
+    {&hf_jxta_element_name,
+     {"Element Name", "jxta.message.element.name", FT_UINT_STRING, BASE_NONE, NULL, 0x0,
+      "JXTA Message Element Name", HFILL}
+     },
+    {&hf_jxta_element_type,
+     {"Element Type", "jxta.message.element.type", FT_UINT_STRING, BASE_NONE, NULL, 0x0,
+      "JXTA Message Element Name", HFILL}
+     },
+    {&hf_jxta_element_encoding,
+     {"Element Type", "jxta.message.element.encoding", FT_UINT_STRING, BASE_NONE, NULL, 0x0,
+      "JXTA Message Element Encoding", HFILL}
+     },
+    {&hf_jxta_element_content_text,
+     {"Element Content", "jxta.message.element.text_content", FT_UINT_STRING, BASE_HEX, NULL, 0x0,
+      "JXTA Message Element Text Content", HFILL}
+     },
+    {&hf_jxta_element_content_len,
+     {"Element Content Length", "jxta.message.element.content.length", FT_UINT32, BASE_DEC, NULL, 0x0,
+      "JXTA Message Element Content Length", HFILL}
+     },
+    {&hf_jxta_element_content,
+     {"Element Content", "jxta.message.element.content", FT_BYTES, BASE_HEX, NULL, 0x0,
+      "JXTA Message Element Content", HFILL}
+     },
+};
+
+/**
+*    JXTA Protocol subtree handles
+**/
 static gint ett_jxta_welcome = -1;
 static gint ett_jxta_udp = -1;
 static gint ett_jxta_framing = -1;
+static gint ett_jxta_framing_header = -1;
 static gint ett_jxta_msg = -1;
 static gint ett_jxta_elem = -1;
+static gint ett_jxta_elem_flags = -1;
 
-static dissector_handle_t udpm_jxta_handle;
-static dissector_handle_t tcp_jxta_handle;
-static dissector_handle_t http_jxta_handle;
-
-/** our header fields */
-static hf_register_info hf[] = {
-  { &hf_jxta_udp,
-    { "JXTA UDP Message", "jxta.udp", FT_NONE, BASE_NONE, NULL, 0x0,
-      "JXTA UDP Message", HFILL }
-  },
-  { &hf_jxta_udpsig,
-    { "Signature", "jxta.udpsig", FT_STRING, BASE_NONE, NULL, 0x0,
-      "JXTA UDP Signature", HFILL }
-  },
-  { &hf_jxta_welcome,
-    { "Welcome Message", "jxta.welcome", FT_NONE, BASE_NONE, NULL, 0x0,
-      "JXTA Connection Welcome Message", HFILL }
-  },
-  { &hf_jxta_framing,
-    { "JXTA Message Framing", "jxta.framing", FT_NONE, BASE_NONE, NULL, 0x0,
-      "JXTA Message Framing Header", HFILL }
-  },
-  { &hf_jxta_framing_header_name_length,
-    { "Name Length", "jxta.framing.header.namelen", FT_UINT8, BASE_DEC, NULL, 0x0,
-      "JXTA Message Framing Header Name Length", HFILL }
-  },
-  { &hf_jxta_framing_header_name,
-    { "Name", "jxta.framing.header.name", FT_STRING, FT_NONE, NULL, 0x0,
-      "JXTA Message Framing Header Name", HFILL }
-  },
-  { &hf_jxta_framing_header_value_length,
-    { "Value Length", "jxta.framing.header.valuelen", FT_UINT16, BASE_DEC, NULL, 0x0,
-      "JXTA Message Framing Header Value Length", HFILL }
-  },
-  { &hf_jxta_framing_header_value,
-    { "Value", "jxta.framing.header.value", FT_BYTES, BASE_HEX, NULL, 0x0,
-      "JXTA Message Framing Header Value", HFILL }
-  },
-  { &hf_jxta_message,
-    { "JXTA Message", "jxta.message", FT_NONE, BASE_NONE, NULL, 0x0,
-      "JXTA Message", HFILL }
-  },
-  { &hf_jxta_message_sig,
-    { "Signature", "jxta.message.signature", FT_STRING, BASE_NONE, NULL, 0x0,
-      "JXTA Message Signature", HFILL }
-  },
-  { &hf_jxta_message_version,
-    { "Version", "jxta.message.version", FT_UINT8, BASE_DEC, NULL, 0x0,
-      "JXTA Message Version", HFILL }
-  },
-  { &hf_jxta_message_namespaces_count,
-    { "Namespace Count", "jxta.message.namespaces", FT_UINT16, BASE_DEC, NULL, 0x0,
-      "JXTA Message Namespaces", HFILL }
-  },
-  { &hf_jxta_message_namespace_len,
-    { "Namespace Name Length", "jxta.message.namespace.len", FT_UINT16, BASE_DEC, NULL, 0x0,
-      "JXTA Message Namespace Name Length", HFILL }
-  },
-  { &hf_jxta_message_namespace_name,
-    { "Namespace Name", "jxta.message.namespace.name", FT_STRING, BASE_NONE, NULL, 0x0,
-      "JXTA Message Namespace Name", HFILL }
-  },
-  { &hf_jxta_message_element_count,
-    { "Element Count", "jxta.message.elements", FT_UINT16, BASE_DEC, NULL, 0x0,
-      "JXTA Message Element Count", HFILL }
-  },
-  { &hf_jxta_element,
-    { "JXTA Message Element", "jxta.message.element", FT_NONE, BASE_NONE, NULL, 0x0,
-      "JXTA Message Element", HFILL }
-  },
-  { &hf_jxta_element_sig,
-    { "Signature", "jxta.message.element.signature", FT_STRING, BASE_NONE, NULL, 0x0,
-      "JXTA Message Element Signature", HFILL }
-  },
-  { &hf_jxta_element_namespaceid,
-    { "Namespace ID", "jxta.message.element.namespaceid", FT_UINT8, BASE_DEC, NULL, 0x0,
-      "JXTA Message Element Namespace ID", HFILL }
-  },
-  
-  /* TODO 20050104 bondolo This should be a bitfield */
-  
-  { &hf_jxta_element_flags,
-    { "Flags", "jxta.message.element.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
-      "JXTA Message Element Flags", HFILL }
-  },
-  { &hf_jxta_element_name_len,
-    { "Element Name Length", "jxta.message.element.name.length", FT_UINT16, BASE_DEC, NULL, 0x0,
-      "JXTA Message Element Name Length", HFILL }
-  },
-  { &hf_jxta_element_name,
-    { "Element Name", "jxta.message.element.name", FT_STRING, BASE_NONE, NULL, 0x0,
-      "JXTA Message Element Name", HFILL }
-  },
-  { &hf_jxta_element_type_len,
-    { "Element Type Length", "jxta.message.element.type.length", FT_UINT16, BASE_DEC, NULL, 0x0,
-      "JXTA Message Element Name Length", HFILL }
-  },
-  { &hf_jxta_element_type,
-    { "Element Type", "jxta.message.element.type", FT_STRING, BASE_NONE, NULL, 0x0,
-      "JXTA Message Element Name", HFILL }
-  },
-  { &hf_jxta_element_encoding_len,
-    { "Element Type Length", "jxta.message.element.encoding.length", FT_UINT16, BASE_DEC, NULL, 0x0,
-      "JXTA Message Element Encoding Length", HFILL }
-  },
-  { &hf_jxta_element_encoding,
-    { "Element Type", "jxta.message.element.encoding", FT_STRING, BASE_NONE, NULL, 0x0,
-      "JXTA Message Element Encoding", HFILL }
-  },
-  { &hf_jxta_element_content_len,
-    { "Element Content Length", "jxta.message.element.content.length", FT_UINT32, BASE_DEC, NULL, 0x0,
-      "JXTA Message Element Content Length", HFILL }
-  },
-  { &hf_jxta_element_content,
-    { "Element Content", "jxta.message.element.content", FT_BYTES, BASE_HEX, NULL, 0x0,
-      "JXTA Message Element Content", HFILL }
-  },
-  { &hf_jxta_element_signature,
-    { "Element Signature", "jxta.message.element.signature", FT_NONE, BASE_NONE, NULL, 0x0,
-      "JXTA Message Element Signature", HFILL }
-  }
+/** 
+*   JXTA Protocol subtree array
+**/
+static gint *const ett[] = {
+    &ett_jxta_welcome,
+    &ett_jxta_udp,
+    &ett_jxta_framing,
+    &ett_jxta_framing_header,
+    &ett_jxta_msg,
+    &ett_jxta_elem,
+    &ett_jxta_elem_flags
 };
 
-/** setup protocol subtree array */
-static gint * const ett[] = {
-  &ett_jxta_welcome,
-  &ett_jxta_udp,
-  &ett_jxta_framing,
-  &ett_jxta_msg,
-  &ett_jxta_elem
+/** 
+*   global preferences
+**/
+static gboolean gDESEGMENT = TRUE;
+static gboolean gUDP_HEUR = FALSE;
+static gboolean gTCP_HEUR = FALSE;
+
+/**
+*   Stream Conversation data
+**/
+struct jxta_stream_conversation_data {
+    port_type tpt_ptype;
+    guint32 initiator_welcome_frame;
+    address initiator_tpt_address;
+    guint32 initiator_tpt_port;
+    address initiator_address;
+    guint32 receiver_welcome_frame;
+    address receiver_tpt_address;
+    guint32 receiver_tpt_port;
+    address receiver_address;
 };
 
-static int gUDP_MULTICAST_PORT_JXTA = 1234;
-static int gHTTP_PORT_JXTA = 9700;
-static int gTCP_PORT_JXTA = 9701;
+typedef struct jxta_stream_conversation_data jxta_stream_conversation_data;
 
-static int regUDP_MULTICAST_PORT_JXTA = -1;
-static int regHTTP_PORT_JXTA = -1;
-static int regTCP_PORT_JXTA = -1;
+static GMemChunk *my_conv_structs = NULL;
+static GMemChunk *my_tap_structs = NULL;
 
+/**
+*   Prototypes
+**/
+static gboolean dissect_jxta_UDP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree);
+static gboolean dissect_jxta_TCP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree);
 
-static void dissect_jxta_framing(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+static int dissect_jxta_udp(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree);
+static int dissect_jxta_tcp(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree);
 
-static void dissect_jxta_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+static int dissect_jxta_welcome(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, address * found_addr, gboolean initiator);
+static int dissect_jxta_message_framing(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, guint64 * content_length,
+                                        gchar **content_type);
+static int dissect_jxta_message(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree);
+static int dissect_jxta_message_element(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, guint ns_count,
+                                        const gchar **namespaces);
 
 void proto_reg_handoff_jxta(void);
+void proto_reg_handoff_message_jxta(void);
 
 /**
-    Dissect a tvbuff containing a JXTA UDP header, JXTA Message framing and a JXTA Message
+*   Heuristically dissect a tvbuff containing a JXTA UDP Message
+*
+*   @param  tvb The buffer to dissect.
+*   @param  pinfo Packet Info.
+*   @param  tree The protocol tree.
+*   @return TRUE if the tvb contained JXTA data which was dissected otherwise FALSE
 **/
-static void dissect_jxta_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
-  proto_tree      *jxta_tree = NULL;
-  proto_item      *ti;
+static gboolean dissect_jxta_UDP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
+{
+    /* This is a heuristic dissector, which means we get all the UDP
+     * traffic not sent to a known dissector and not claimed by
+     * a heuristic dissector called before us!
+     */
+
+    if (!gUDP_HEUR)
+        return FALSE;
 
-  if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
-    col_set_str(pinfo->cinfo, COL_PROTOCOL, "JXTA");
+    if (tvb_memeql(tvb, 0, JXTA_UDP_SIG, sizeof(JXTA_UDP_SIG)) != 0) {
+        return FALSE;
     }
 
-  if (check_col(pinfo->cinfo, COL_INFO)) {
-    /*
-     * bondolo For now just say its a message. eventually put in dest addr.
+    return dissect_jxta_udp(tvb, pinfo, tree) > 0;
+}
+
+/**
+*   Heuristically dissect a tvbuff containing a JXTA TCP Stream
+*    
+*   @param  tvb The buffer to dissect.
+*   @param  pinfo Packet Info.
+*   @param  tree The protocol tree.
+*   @return TRUE if the tvb contained JXTA data which was dissected otherwise FALSE
+**/
+static gboolean dissect_jxta_TCP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
+{
+    /* This is a heuristic dissector, which means we get all the TCP
+     * traffic not sent to a known dissector and not claimed by
+     * a heuristic dissector called before us!
      */
-    col_add_fstr(pinfo->cinfo, COL_INFO, "%s", "UDP Message");
-  }
 
-  guint32 udpsignature = tvb_get_ntohl( tvb, 0 );
-    
-  gboolean goodsig = 0 == (udpsignature ^ 0x4A585441U);
-    
-  if (tree) {
-    ti = proto_tree_add_item(tree, hf_jxta_udp, tvb, 0, -1, FALSE);
-    jxta_tree = proto_item_add_subtree(ti, ett_jxta_udp);
-    
-    ti = proto_tree_add_item( jxta_tree, hf_jxta_udpsig, tvb, 0, 4, FALSE );
-    
-    if( goodsig ) {
-        PROTO_ITEM_SET_HIDDEN( ti );
+    if (!gTCP_HEUR)
+        return FALSE;
+
+    if (tvb_memeql(tvb, 0, JXTA_WELCOME_MSG_SIG, sizeof(JXTA_WELCOME_MSG_SIG)) != 0) {
+        return FALSE;
     }
-  }
-  
-  if( goodsig ) {
-    tvbuff_t* jxta_framed_message_tvb = tvb_new_subset( tvb, 4, tvb_length(tvb) - 4, tvb_length(tvb) - 4 );
 
-    dissect_jxta_framing( jxta_framed_message_tvb, pinfo, tree );
-  }
+    return dissect_jxta_tcp(tvb, pinfo, tree) > 0;
 }
 
-static void dissect_jxta_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
-  dissect_jxta_message( tvb, pinfo, tree );
-}
+/**
+*   Dissect a tvbuff containing a JXTA UDP header, JXTA Message framing and a JXTA Message
+*    
+*   @param  tvb The buffer to dissect.
+*   @param  pinfo Packet Info.
+*   @param  tree The protocol tree.
+*   @return number of bytes from the tvbuff_t which were processed.
+**/
+static int dissect_jxta_udp(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
+{
+    guint offset = 0;
+    guint available;
+    gint needed = 0;
+
+    conversation_t *conversation =
+        find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
+
+    if (conversation == NULL) {
+        /*
+         * No conversation exists yet - create one.
+         */
+        conversation =
+            conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
+    }
+
+    DISSECTOR_ASSERT(find_dissector("jxta.udp"));
+
+    conversation_set_dissector(conversation, find_dissector("jxta.udp"));
+
+    while (TRUE) {
+        tvbuff_t *jxta_message_framing_tvb;
+        gint processed = 0;
+        guint64 content_length = -1;
+
+        available = tvb_reported_length_remaining(tvb, offset);
+        if (available < sizeof(JXTA_UDP_SIG)) {
+            needed = (gint) (available - sizeof(JXTA_UDP_SIG));
+            break;
+        }
+
+        if (tvb_memeql(tvb, offset, JXTA_UDP_SIG, sizeof(JXTA_UDP_SIG)) != 0) {
+            /* not ours */
+            return 0;
+        }
+
+        offset += sizeof(JXTA_UDP_SIG);
+
+        jxta_message_framing_tvb = tvb_new_subset(tvb, offset, -1, -1);
+        processed = dissect_jxta_message_framing(jxta_message_framing_tvb, pinfo, NULL, &content_length, NULL);
+
+        if (0 == processed) {
+            /* rejected! */
+            return 0;
+        }
+
+        if (processed < 0) {
+            needed = -processed;
+            break;
+        }
+
+        offset += processed;
+
+        available = tvb_reported_length_remaining(tvb, offset);
+        if (available < content_length) {
+            needed = (gint) (available - content_length);
+            break;
+        }
+
+        offset += (guint) content_length;
+
+        break;
+    }
 
-static void dissect_jxta_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
-  tcp_dissect_pdus(tvb, pinfo, tree, TRUE, 0, NULL, dissect_jxta_tcp_pdu);
+    if ((needed > 0) && gDESEGMENT && pinfo->can_desegment) {
+        pinfo->desegment_offset = 0;
+        pinfo->desegment_len = needed;
+        return -needed;
+    }
+
+    if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+        col_set_str(pinfo->cinfo, COL_PROTOCOL, "JXTA");
+    }
+
+    if (tree) {
+        guint tree_offset = 0;
+        proto_item *jxta_udp_tree_item = proto_tree_add_protocol_format(tree, proto_udp_jxta, tvb, tree_offset, -1, "JXTA UDP Message" );
+        proto_tree *jxta_udp_tree = proto_item_add_subtree(jxta_udp_tree_item, ett_jxta_udp);
+        tvbuff_t *jxta_message_framing_tvb;
+        guint64 content_length = -1;
+        gchar *content_type = NULL;
+        tvbuff_t *jxta_message_tvb;
+        gboolean dissected = FALSE;
+        gint processed = 0;
+        dissector_handle_t mime_dissector_handle;
+
+        proto_tree_add_item(jxta_udp_tree, hf_jxta_udpsig, tvb, tree_offset, sizeof(JXTA_UDP_SIG), FALSE);
+        tree_offset += sizeof(JXTA_UDP_SIG);
+
+        jxta_message_framing_tvb = tvb_new_subset(tvb, tree_offset, -1, -1);
+        processed = dissect_jxta_message_framing(jxta_message_framing_tvb, pinfo, tree, &content_length, &content_type);
+        tree_offset += processed;
+
+        jxta_message_tvb = tvb_new_subset(tvb, tree_offset, (gint) content_length, (gint) content_length);
+        mime_dissector_handle = dissector_get_string_handle(media_type_dissector_table, content_type);
+        dissected = 0 < call_dissector(mime_dissector_handle, jxta_message_tvb, pinfo, tree);        
+
+        if (!dissected) {
+            dissector_handle_t data_handle = find_dissector("data");
+            call_dissector(data_handle, jxta_message_tvb, pinfo, tree);
+        }
+
+        tree_offset += (guint) content_length;
+
+        proto_item_set_end(jxta_udp_tree_item, tvb, tree_offset);
+
+        DISSECTOR_ASSERT(offset == tree_offset);
+    }
+    
+    return offset;
 }
 
 /**
-    Dissect a tvbuff containing a JXTA Message framing and a JXTA Message
+*   Dissect a tvbuff containing JXTA TCP PDUs
+*    
+*   @param  tvb The buffer to dissect.
+*   @param  pinfo Packet Info.
+*   @param  tree The protocol tree.
+*   @return number of bytes from the tvbuff_t which were processed.
 **/
-static void dissect_jxta_framing(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
-  proto_tree      *jxta_tree = NULL;
-  proto_item      *ti;
-  guint offset = 0;
+static int dissect_jxta_tcp(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
+{
+    guint offset = 0;
+    guint available = 0;
+    gint processed;
+    conversation_t *tpt_conversation =
+        find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
+    jxta_stream_conversation_data * tpt_conv_data;
+
+    if (tpt_conversation == NULL) {
+        /*
+         * No conversation exists yet - create one.
+         */
+        tpt_conversation =
+            conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
+    }
+
+    conversation_set_dissector(tpt_conversation, tcp_jxta_handle);
     
-  if (tree) {
-    ti = proto_tree_add_item(tree, hf_jxta_framing, tvb, 0, -1, FALSE);
-    jxta_tree = proto_item_add_subtree(ti, ett_jxta_framing);
+    tpt_conv_data = (jxta_stream_conversation_data*) conversation_get_proto_data(tpt_conversation, proto_jxta);
+    
+    if( NULL == tpt_conv_data ) {
+        tpt_conv_data = (jxta_stream_conversation_data*) g_mem_chunk_alloc(my_conv_structs);
+        tpt_conv_data->tpt_ptype = PT_NONE;
+        tpt_conv_data->initiator_welcome_frame = 0;
+        tpt_conv_data->initiator_address.type = AT_NONE;
+        tpt_conv_data->initiator_address.len = 0;
+        tpt_conv_data->initiator_address.data = NULL;
+        tpt_conv_data->receiver_welcome_frame = 0;
+        tpt_conv_data->receiver_address.type = AT_NONE;
+        tpt_conv_data->receiver_address.len = 0;
+        tpt_conv_data->receiver_address.data = NULL;
+        conversation_add_proto_data(tpt_conversation, proto_jxta, tpt_conv_data);
     }
     
-  /* parse framing headers */
-  do {
-    guint8 headernamelen = tvb_get_guint8( tvb, offset );
+    if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+        col_set_str(pinfo->cinfo, COL_PROTOCOL, "JXTA");
+    }
+
+    if (0 == tvb_memeql(tvb, 0, JXTA_WELCOME_MSG_SIG, sizeof(JXTA_WELCOME_MSG_SIG))) {
+        address * welcome_addr;
+        gboolean initiator = FALSE;
+
+        if( 0 == tpt_conv_data->initiator_welcome_frame ) {
+            tpt_conv_data->tpt_ptype= pinfo->ptype;
+            tpt_conv_data->initiator_welcome_frame = pinfo->fd->num;
+            COPY_ADDRESS( &tpt_conv_data->initiator_tpt_address, &pinfo->src );
+            tpt_conv_data->initiator_tpt_port = pinfo->srcport;
+
+            welcome_addr = &tpt_conv_data->initiator_address;
+            initiator = TRUE;
+        } else {
+            if( tpt_conv_data->initiator_welcome_frame >= pinfo->fd->num ) {
+                /* what we saw previously was the receiver welcome message */
+                tpt_conv_data->receiver_welcome_frame = tpt_conv_data->initiator_welcome_frame;
+                tpt_conv_data->receiver_tpt_address = tpt_conv_data->initiator_tpt_address;
+                tpt_conv_data->receiver_tpt_port = tpt_conv_data->initiator_tpt_port;
+                tpt_conv_data->receiver_address = tpt_conv_data->initiator_address;
+                tpt_conv_data->initiator_welcome_frame = pinfo->fd->num;
+                COPY_ADDRESS( &tpt_conv_data->initiator_tpt_address, &pinfo->src );
+                tpt_conv_data->initiator_tpt_port = pinfo->srcport;
+
+                welcome_addr = &tpt_conv_data->initiator_address;
+                initiator = TRUE;
+            } else {
+                tpt_conv_data->tpt_ptype= pinfo->ptype;
+                tpt_conv_data->receiver_welcome_frame = pinfo->fd->num;
+                COPY_ADDRESS( &tpt_conv_data->receiver_tpt_address, &pinfo->src );
+                tpt_conv_data->receiver_tpt_port = pinfo->srcport;
+
+                welcome_addr = &tpt_conv_data->receiver_address;
+                initiator = FALSE;
+            }
+        }
+
+        processed = dissect_jxta_welcome(tvb, pinfo, tree, welcome_addr, initiator);
+    } else {
+        guint64 content_length = 0;
+        gchar *content_type = NULL;
+        gboolean dissected;
+        conversation_t *peer_conversation = NULL;
+        address saved_src_addr;
+        guint32 saved_src_port = 0;
+        address saved_dst_addr;
+        guint32 saved_dst_port = 0;
+        port_type saved_port_type = PT_NONE;
+
+        if( (AT_NONE != tpt_conv_data->initiator_address.type) && (AT_NONE != tpt_conv_data->receiver_address.type) ) {
+            peer_conversation =
+                find_conversation(pinfo->fd->num, &tpt_conv_data->initiator_address, &tpt_conv_data->receiver_address, PT_NONE, 0, 0, NO_PORT_B);
+
+            if( NULL == peer_conversation ) {
+                peer_conversation =
+                    conversation_new(pinfo->fd->num, &tpt_conv_data->initiator_address, &tpt_conv_data->receiver_address, PT_NONE, 0, 0, NO_PORT_B);
+            }
+
+            conversation_set_dissector(peer_conversation, tcp_jxta_handle);
+        } else {
+/*            g_warning( "Uninitialized peer conversation" ); */
+        }
+
+        /* Use our source and destination addresses if we have them */
+        if( NULL != peer_conversation ) {
+             saved_src_addr = pinfo->src;
+             saved_src_port = pinfo->srcport;
+             saved_dst_addr = pinfo->dst;
+             saved_dst_port = pinfo->destport;
+             saved_port_type = pinfo->ptype;
+/*                 g_warning( "%d Tpt %s:%d -> %s:%d", pinfo->fd->num, ip_to_str(tpt_conv_data->initiator_tpt_address.data), tpt_conv_data->initiator_tpt_port, ip_to_str(tpt_conv_data->receiver_tpt_address.data), tpt_conv_data->receiver_tpt_port ); */
+             if( ADDRESSES_EQUAL( &pinfo->src, &tpt_conv_data->initiator_tpt_address ) && 
+                tpt_conv_data->initiator_tpt_port == pinfo->srcport ) {
+/*                    g_warning( "%d From initiator : %s -> %s ", pinfo->fd->num, tpt_conv_data->initiator_address.data, tpt_conv_data->receiver_address.data ); */
+                 pinfo->src = tpt_conv_data->initiator_address;
+                 pinfo->dst = tpt_conv_data->receiver_address;
+             } else if( ADDRESSES_EQUAL( &pinfo->src, &tpt_conv_data->receiver_tpt_address ) && 
+                 tpt_conv_data->receiver_tpt_port == pinfo->srcport ) {
+/*                    g_warning( "%d From receiver : %s -> %s ", pinfo->fd->num, tpt_conv_data->receiver_address.data, tpt_conv_data->initiator_address.data ); */
+                 pinfo->src = tpt_conv_data->receiver_address;
+                 pinfo->dst = tpt_conv_data->initiator_address;
+             } else {
+/*                    g_warning( "%d Nothing matches %s:%d -> %s:%d", pinfo->fd->num, ip_to_str(pinfo->src.data), pinfo->srcport, ip_to_str(pinfo->dst.data), pinfo->destport ); */
+             }
+             /* JXTA doesn't use ports */
+             pinfo->ptype = PT_NONE;
+             pinfo->srcport = 0;
+             pinfo->destport = 0;
+        }
+
+        processed = dissect_jxta_message_framing(tvb, pinfo, tree, &content_length, &content_type);
+
+        if ((processed > 0) && (NULL != content_type) && (0 != content_length)) {
+            guint msg_offset = offset + processed;
 
-    if(tree) {
-      ti = proto_tree_add_item( jxta_tree, hf_jxta_framing_header_name_length, tvb, offset, 1, FALSE );
-      PROTO_ITEM_SET_HIDDEN( ti );
+            available = tvb_reported_length_remaining(tvb, msg_offset);
+            if (available >= content_length) {
+                tvbuff_t *jxta_message_tvb = tvb_new_subset(tvb, msg_offset, (gint)content_length, (gint)content_length);
+
+                dissected = dissector_try_string(media_type_dissector_table, content_type, jxta_message_tvb, pinfo, tree);
+
+                if (!dissected) {
+                    dissector_handle_t data_handle = find_dissector("data");
+                    call_dissector(data_handle, jxta_message_tvb, pinfo, tree);
+                }
+
+                processed += (guint) content_length;
+            } else {
+                processed = available - (guint) content_length;
+            }
+
+        }
+
+        /* Restore the saved src and dst addresses */
+        if( NULL != peer_conversation ) {
+            pinfo->src = saved_src_addr;
+            pinfo->srcport = saved_src_port;
+            pinfo->dst = saved_dst_addr;
+            pinfo->destport = saved_dst_port;
+            pinfo->ptype = saved_port_type;
+        }
     }
-    
-    if( tree && (headernamelen > 0) ) {
-      /*
-       * Put header name into protocol tree.
-       */
-      ti = proto_tree_add_string(jxta_tree, hf_jxta_framing_header_name, tvb, offset+1, headernamelen, 
-        tvb_format_text(tvb, offset+1, headernamelen));
+
+    if (processed <= 0) {
+        pinfo->desegment_offset = offset;
+        pinfo->desegment_len = -processed;
+        return processed;
     }
-    
-    offset += 1 + headernamelen;
-      
-    if( headernamelen > 0 ) {
-      guint16 headervaluelen = tvb_get_ntohs( tvb, offset );
 
-      if( tree ) {
-        ti = proto_tree_add_item(jxta_tree, hf_jxta_framing_header_value_length, tvb, offset, 2, FALSE );
-        PROTO_ITEM_SET_HIDDEN( ti );
+    offset += processed;
+
+    return offset;
+}
 
-        /** TODO bondolo Add specific handling for known header types */
+/**
+*   Dissect a tvbuff containing a JXTA Welcome Message
+*
+*   @param  tvb The buffer to dissect.
+*   @param  pinfo Packet Info.
+*   @param  tree The protocol tree.
+*   @param  found_addr The address found in the welcome message.
+*   @param  initiator If TRUE then we believe this welcome message to be the initiator's.
+*   @return number of bytes from the tvbuff_t which were processed.
+**/
+static int dissect_jxta_welcome(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, address *found_addr, gboolean initiator )
+{
+    guint offset = 0;
+    gint afterwelcome;
+    gint first_linelen;
+    guint available = tvb_reported_length_remaining(tvb, offset);
 
-        /*
-         * Put header value into protocol tree.
-         */
-        ti = proto_tree_add_item(jxta_tree, hf_jxta_framing_header_value, tvb, offset+2, headervaluelen, FALSE );
-      }
-      
-      offset += 2 + headervaluelen;
+    if (available < sizeof(JXTA_WELCOME_MSG_SIG)) {
+        return (gint) (available - sizeof(JXTA_WELCOME_MSG_SIG));
     }
-    
-    if( 0 == headernamelen ) {
-      break;
+
+    if (0 != tvb_memeql(tvb, 0, JXTA_WELCOME_MSG_SIG, sizeof(JXTA_WELCOME_MSG_SIG))) {
+        /* not ours! */
+        return 0;
+    }
+
+    first_linelen = tvb_find_line_end(tvb, offset, -1, &afterwelcome, gDESEGMENT && pinfo->can_desegment);
+
+    if (-1 == first_linelen) {
+        if (available > 4096) {
+            /* it's too far too be reasonable */
+            return 0;
+        } else {
+            /* ask for more bytes */
+            return -1;
+        }
+    }
+
+    if (check_col(pinfo->cinfo, COL_INFO)) {
+        col_add_str(pinfo->cinfo, COL_INFO, "Welcome");
     }
-  } while( TRUE );
-  
-  tvbuff_t* jxta_message_tvb = tvb_new_subset( tvb, offset, tvb_length(tvb) - offset, tvb_length(tvb) - offset );
 
-  /* Call it a new layer and pass the tree as we got it */
-  dissect_jxta_message( jxta_message_tvb, pinfo, tree );
+    {
+        gchar * welcomeline = ep_tvb_get_string( tvb, offset, first_linelen );
+        gchar** tokens = g_strsplit( welcomeline, " ", 6 );
+        gchar** current_token = tokens;
+        guint token_offset = offset;
+        proto_item *jxta_welcome_tree_item = NULL;
+        proto_tree *jxta_welcome_tree = NULL;  
+
+        if (tree) {
+           jxta_welcome_tree_item = proto_tree_add_protocol_format(tree, proto_welcome_jxta, tvb, offset, afterwelcome, "JXTA Connection Welcome Message, %s", welcomeline);
+           jxta_welcome_tree = proto_item_add_subtree(jxta_welcome_tree_item, ett_jxta_welcome);
+           }
+        
+        if( jxta_welcome_tree ) {
+            proto_item *jxta_welcome_initiator_item = proto_tree_add_boolean(jxta_welcome_tree, hf_jxta_welcome_initiator, tvb, 0, 0, initiator);
+            PROTO_ITEM_SET_GENERATED(jxta_welcome_initiator_item);
+            }
+
+        if( NULL != *current_token ) {
+            if( jxta_welcome_tree ) {
+                proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_sig, tvb, token_offset, strlen( *current_token ), FALSE);
+            }
+
+            token_offset += strlen( *current_token ) + 1;
+            current_token++;
+            }
+
+        if( NULL != *current_token ) {
+            if( jxta_welcome_tree ) {
+                proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_destAddr, tvb, token_offset, strlen( *current_token ), FALSE);
+            }
+
+            token_offset += strlen( *current_token ) + 1;
+            current_token++;
+            }
+
+        if( NULL != *current_token ) {
+            if( jxta_welcome_tree ) {
+                proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_pubAddr, tvb, token_offset, strlen( *current_token ), FALSE);
+            }
+
+            token_offset += strlen( *current_token ) + 1;
+            current_token++;
+            }
+
+        if( NULL != *current_token ) {
+            if( jxta_welcome_tree ) {
+                proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_peerid, tvb, token_offset, strlen( *current_token ), FALSE);
+            }
+
+            if (check_col(pinfo->cinfo, COL_INFO)) {
+                col_append_str( pinfo->cinfo, COL_INFO, ", " );
+                col_append_str( pinfo->cinfo, COL_INFO, *current_token );
+            }
+
+            if( NULL != found_addr ) {
+                found_addr->type = AT_URI;
+                found_addr->len = strlen( *current_token );
+                /* FIXME 20050605 bondolo THIS ALLOCATION IS A MEMORY LEAK! */
+                found_addr->data = g_strdup( *current_token );
+            }
+
+            token_offset += strlen( *current_token ) + 1;
+            current_token++;
+            }
+
+        if( NULL != *current_token ) {
+            if( jxta_welcome_tree ) {
+                proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_noProp, tvb, token_offset, strlen( *current_token ), FALSE);
+            }
+
+            token_offset += strlen( *current_token ) + 1;
+            current_token++;
+            }
+
+        if( NULL != *current_token ) {
+            if( jxta_welcome_tree ) {
+                proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_version, tvb, token_offset, strlen( *current_token ), FALSE);
+            }
+            token_offset += strlen( *current_token ) + 1;
+            current_token++;
+            }
+
+        g_strfreev(tokens);
+    }
+
+    col_set_writable(pinfo->cinfo, FALSE);
+
+    return afterwelcome;
 }
 
 /**
-    Dissect a tvbuff containing a JXTA Message
+*   Dissect a tvbuff containing JXTA Message framing.
+*    
+*   @param  tvb The buffer to dissect.
+*   @param  pinfo Packet Info.
+*   @param  tree The protocol tree.
+*   @return number of bytes from the tvbuff_t which were processed.
 **/
-static void dissect_jxta_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
-  proto_tree      *jxta_tree = NULL;
-  proto_item      *ti;
+static int dissect_jxta_message_framing(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, guint64 * content_length,
+                                        gchar **content_type)
+{
+    guint offset = 0;
+    guint available;
+    gint needed = 0;
+
+    /*
+     *   First go around. Make sure all of the bytes are there.
+     */
+    do {
+        guint8 headername_len;
+        guint8 headername_offset;
+        guint16 headervalue_len;
+        guint16 headervalue_offset;
 
-  if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
-    col_set_str(pinfo->cinfo, COL_PROTOCOL, "JXTA");
+        available = tvb_reported_length_remaining(tvb, offset);
+        if (available < sizeof(guint8)) {
+            needed = (gint) (available - sizeof(guint8));
+            break;
+        } else {
+            headername_len = tvb_get_guint8(tvb, offset);
+            offset += sizeof(guint8);
+            headername_offset = offset;
+
+            available = tvb_reported_length_remaining(tvb, offset);
+            if (available < headername_len) {
+                needed = (gint) (available - headername_len);
+                break;
+            }
+
+            if (0 == headername_len) {
+                break;
+            }
+            offset += headername_len;
+        }
+
+        available = tvb_reported_length_remaining(tvb, offset);
+        if (available < sizeof(guint16)) {
+            needed = (gint) (available - sizeof(guint16));
+            break;
+        } else {
+            headervalue_len = tvb_get_ntohs(tvb, offset);
+            offset += sizeof(guint16);
+            headervalue_offset = offset;
+
+            available = tvb_reported_length_remaining(tvb, offset);
+            if (available < headervalue_len) {
+                needed = (gint) (available - headervalue_len);
+                break;
+            }
+
+            offset += headervalue_len;
+        }
+
+        if (content_type && (sizeof("content-type") - 1) == headername_len) {
+            if (0 == tvb_strncaseeql(tvb, headername_offset, "content-type", sizeof("content-type") - 1)) {
+                *content_type = ep_tvb_get_string(tvb, headervalue_offset, headervalue_len);
+            }
+        }
+
+
+        if (content_length && (sizeof(guint64) == headervalue_len) && ((sizeof("content-length") - 1) == headername_len)) {
+            if (0 == tvb_strncaseeql(tvb, headername_offset, "content-length", sizeof("content-length") - 1)) {
+                *content_length = tvb_get_ntoh64(tvb, headervalue_offset);
+            }
+        }
+    } while (TRUE);
+
+    if ((needed > 0) && gDESEGMENT && pinfo->can_desegment) {
+        pinfo->desegment_offset = 0;
+        pinfo->desegment_len = needed;
+        return -needed;
     }
 
-  if (check_col(pinfo->cinfo, COL_INFO)) {
     /*
-     * TODO bondolo For now just say its a message. eventually put in dest addr.
+     *   Second (optional pass) Now that we are sure that all the bytes are there we update the protocol tree.
      */
-    col_add_fstr(pinfo->cinfo, COL_INFO, "%s", "Message");
-  }
-
-  if (tree) {
-    ti = proto_tree_add_item(tree, hf_jxta_message, tvb, 0, -1, FALSE);
-    jxta_tree = proto_item_add_subtree(ti, ett_jxta_udp);
-  }
-  
-  guint32 msgsignature = tvb_get_ntohl( tvb, 0 );
-    
-  gboolean goodsig = 0 == (msgsignature ^ 0x6A786D67U);
-  
-  if( tree ) {
-    ti = proto_tree_add_item( jxta_tree, hf_jxta_message_sig, tvb, 0, sizeof(guint32), FALSE );
-    
-    if( goodsig ) {
-        guint8 messageVersion;
-        PROTO_ITEM_SET_HIDDEN( ti );
+    if (tree) {
+        guint tree_offset = 0;
+        proto_item *framing_tree_item = proto_tree_add_protocol_format(tree, proto_framing_jxta, tvb, tree_offset, -1, "JXTA Message Framing Headers");
+        proto_tree *framing_tree = proto_item_add_subtree(framing_tree_item, ett_jxta_framing);
+
+        /* parse framing headers */
+        do {
+            guint8 headernamelen = tvb_get_guint8(tvb, tree_offset);
+            proto_item *framing_header_tree_item =
+                proto_tree_add_item(framing_tree, hf_jxta_framing_header, tvb, tree_offset, -1, FALSE);
+            proto_tree *framing_header_tree = proto_item_add_subtree(framing_header_tree_item, ett_jxta_framing_header);
+
+            /*
+             *   Put header name into the protocol tree
+             */
+            proto_tree_add_item(framing_header_tree, hf_jxta_framing_header_name, tvb, tree_offset, 1, headernamelen);
+
+            /*
+             *   Append header name into the header protocol item. It's a nice hint so you don't have to reveal all headers.
+             */
+            if (headernamelen > 0) {
+                proto_item_append_text(framing_header_tree_item, " \"%s\"",
+                                       tvb_format_text(tvb, tree_offset + sizeof(guint8), headernamelen));
+            }
+
+            tree_offset += sizeof(guint8) + headernamelen;
+
+            if (headernamelen > 0) {
+                guint16 headervaluelen = tvb_get_ntohs(tvb, tree_offset);
+
+                if (tree) {
+                    proto_tree_add_uint(framing_header_tree, hf_jxta_framing_header_value_length, tvb, tree_offset,
+                                        sizeof(guint16), headervaluelen);
+
+                /** TODO bondolo Add specific handling for known header types */
+
+                    /*
+                     * Put header value into protocol tree.
+                     */
+                    proto_tree_add_item(framing_header_tree, hf_jxta_framing_header_value, tvb, tree_offset + sizeof(guint16),
+                                        headervaluelen, FALSE);
+                }
+
+                tree_offset += sizeof(guint16) + headervaluelen;
+            }
+
+            proto_item_set_end(framing_header_tree_item, tvb, tree_offset);
+
+            if (0 == headernamelen) {
+                break;
+            }
+        } while (TRUE);
+
+        proto_item_set_end(framing_tree_item, tvb, tree_offset);
+
+        DISSECTOR_ASSERT(offset == tree_offset);
+    }
+
+    /* return how many bytes we used up. */
+    return offset;
+}
+
+/**
+*   Dissect a tvbuff containing a JXTA Message.
+*    
+*   @param  tvb The buffer to dissect.
+*   @param  pinfo Packet Info.
+*   @param  tree The protocol tree.
+*   @return number of bytes from the tvbuff_t which were processed.
+**/
+static int dissect_jxta_message(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
+{
+    guint offset = 0;
+    guint available;
+    gint needed = 0;
+
+    while (TRUE) {
+        /* First pass. Make sure all of the bytes we need are available */
+        available = tvb_reported_length_remaining(tvb, offset);
+        if (available < sizeof(JXTA_MSG_SIG)) {
+            needed = (gint) (available - sizeof(JXTA_MSG_SIG));
+            break;
+        }
+
+        if (tvb_memeql(tvb, offset, JXTA_MSG_SIG, sizeof(JXTA_MSG_SIG)) != 0) {
+            /* It is not one of ours */
+            return 0;
+        }
+
+        offset += sizeof(JXTA_MSG_SIG);
+
+        available = tvb_reported_length_remaining(tvb, offset);
+        if (available < sizeof(guint8)) {
+            needed = (gint) (available - sizeof(guint8));
+            break;
+        } else {
+            guint8 message_version = tvb_get_guint8(tvb, offset);
+
+            offset += sizeof(guint8);
+
+            if (0 != message_version) {
+                /* Sort of a lie, we say that we don't recognize it at all. */
+                return 0;
+            }
+        }
+
+        available = tvb_reported_length_remaining(tvb, offset);
+        if (available < sizeof(guint16)) {
+            needed = (gint) (available - sizeof(guint16));
+            break;
+        } else {
+            guint16 msg_ns_count = tvb_get_ntohs(tvb, offset);
+            guint each_namespace;
+
+            offset += sizeof(guint16);
+
+            for (each_namespace = 0; each_namespace < msg_ns_count; each_namespace++) {
+                guint16 namespace_len;
+
+                available = tvb_reported_length_remaining(tvb, offset);
+                if (available < sizeof(namespace_len)) {
+                    needed = (gint) (available - sizeof(namespace_len));
+                    break;
+                }
+
+                namespace_len = tvb_get_ntohs(tvb, offset);
+
+                available = tvb_reported_length_remaining(tvb, offset + sizeof(namespace_len));
+                if (available < namespace_len) {
+                    needed = (gint) (available - namespace_len);
+                    break;
+                }
+
+                offset += sizeof(namespace_len) + namespace_len;
+            }
+        }
+
+        /* parse element count */
+        available = tvb_reported_length_remaining(tvb, offset);
+        if (available < sizeof(guint16)) {
+            needed = (gint) (available - sizeof(guint16));
+            break;
+        } else {
+            guint16 elem_count = tvb_get_ntohs(tvb, offset);
+            guint each_elem;
+
+            offset += sizeof(guint16);
+
+            /* parse elements */
+
+            for (each_elem = 0; each_elem < elem_count; each_elem++) {
+                tvbuff_t *jxta_message_element_tvb = tvb_new_subset(tvb, offset, -1, -1);
+                int processed = dissect_jxta_message_element(jxta_message_element_tvb, pinfo, NULL, 0, NULL);
+
+                if (processed < 0) {
+                    needed = -processed;
+                    break;
+                }
+                
+                if( 0 == processed ) {
+                    /* XXX bondolo Not really clear what we should do! */
+/*                    g_warning( "Failure processing message element #%d of %d of frame %d", each_elem, elem_count, pinfo->fd->num ); */
+                    return 0;
+                }
+
+                offset += processed;
+            }
+        }
+
+        break;
+    }
+
+    if ((needed > 0) && gDESEGMENT && pinfo->can_desegment) {
+        pinfo->desegment_offset = 0;
+        pinfo->desegment_len = needed;
+        return -needed;
+    }
+
+    if (check_col(pinfo->cinfo, COL_INFO)) {
+        gchar src_addr[256];
+        gchar dst_addr[256];
+     
+        address_to_str_buf( &pinfo->src, src_addr, sizeof src_addr );
+        address_to_str_buf( &pinfo->dst, dst_addr, sizeof dst_addr );
+        
+        if( PT_NONE != pinfo->ptype ) {
+           size_t len = strlen( src_addr );
+           src_addr[len] = ':';
+           g_snprintf( &src_addr[len+1], 256 - len - 1, "%d", pinfo->srcport );
+
+           len = strlen( dst_addr );
+           dst_addr[len] = ':';
+           g_snprintf( &dst_addr[len+1], 256 - len - 1, "%d", pinfo->destport );
+        }
+
+        col_add_fstr(pinfo->cinfo, COL_INFO, "Message, %s -> %s", src_addr, dst_addr );
+
+        col_set_writable(pinfo->cinfo, FALSE);
+    }
+
+    if (tree) {
+        guint tree_offset = 0;
+        proto_item *jxta_msg_tree_item = NULL;
+        proto_tree *jxta_msg_tree = NULL;
+        guint8 message_version;
+        const gchar **namespaces = NULL;
+        guint16 msg_ns_count;
+        guint each_namespace;
+        guint16 elem_count;
+        guint each_elem;
+        gchar src_addr[256];
+        gchar dst_addr[256];
+        proto_item * tree_item;
         
-        messageVersion = tvb_get_guint8( tvb, sizeof(guint32) );
-        ti = proto_tree_add_item( jxta_tree, hf_jxta_message_version, tvb, sizeof(guint32), 1, FALSE );
+        address_to_str_buf( &pinfo->src, src_addr, sizeof src_addr );
+        address_to_str_buf( &pinfo->dst, dst_addr, sizeof dst_addr );
         
-        if( 0 == messageVersion ) {
-            int eachNamespace;
-            guint16 numberOfElements;
-            unsigned int offset = 7;
-            guint16 messageNamespaceCount = tvb_get_ntohs( tvb, 5 );
-            
-            /* parse namespaces */
-            /* TODO 20050103 bondolo Should record the namespaces and number them. */
-            for( eachNamespace = 0; eachNamespace < messageNamespaceCount; eachNamespace++ ) {
-                guint8 namespaceLen = tvb_get_guint8( tvb, offset );
-                
-                ti = proto_tree_add_item(jxta_tree, hf_jxta_message_namespace_len, tvb, offset++, namespaceLen, FALSE );
-                PROTO_ITEM_SET_HIDDEN( ti );
-                
-                ti = proto_tree_add_string(jxta_tree, hf_jxta_message_namespace_name, tvb, offset, namespaceLen, 
-                    tvb_format_text(tvb, offset, namespaceLen));
-                    
-                offset += namespaceLen;
+        if( PT_NONE != pinfo->ptype ) {
+           size_t len = strlen( src_addr );
+           src_addr[len] = ':';
+           g_snprintf( &src_addr[len+1], 256 - len - 1, "%d", pinfo->srcport );
+
+           len = strlen( dst_addr );
+           dst_addr[len] = ':';
+           g_snprintf( &dst_addr[len+1], 256 - len - 1, "%d", pinfo->destport );
+        }
+
+        jxta_msg_tree_item = proto_tree_add_protocol_format(tree, proto_message_jxta, tvb, tree_offset, -1,
+           "JXTA Message, %s -> %s", src_addr, dst_addr );
+
+        jxta_msg_tree = proto_item_add_subtree(jxta_msg_tree_item, ett_jxta_msg);
+
+        proto_tree_add_item(jxta_msg_tree, hf_jxta_message_sig, tvb, tree_offset, sizeof(JXTA_MSG_SIG), FALSE);
+        tree_offset += sizeof(JXTA_MSG_SIG);
+
+        tree_item = proto_tree_add_string(jxta_msg_tree, hf_jxta_message_src, tvb, 0, 0, src_addr);
+        PROTO_ITEM_SET_GENERATED(tree_item);
+
+        tree_item = proto_tree_add_string(jxta_msg_tree, hf_jxta_message_address, tvb, 0, 0, src_addr);
+        PROTO_ITEM_SET_HIDDEN(tree_item);
+        PROTO_ITEM_SET_GENERATED(tree_item);
+
+        tree_item = proto_tree_add_string(jxta_msg_tree, hf_jxta_message_dst, tvb, 0, 0, dst_addr);
+        PROTO_ITEM_SET_GENERATED(tree_item);
+
+        tree_item = proto_tree_add_string(jxta_msg_tree, hf_jxta_message_address, tvb, 0, 0, dst_addr);
+        PROTO_ITEM_SET_HIDDEN(tree_item);
+        PROTO_ITEM_SET_GENERATED(tree_item);
+
+        message_version = tvb_get_guint8(tvb, tree_offset);
+        proto_tree_add_uint(jxta_msg_tree, hf_jxta_message_version, tvb, tree_offset, sizeof(guint8), message_version);
+        tree_offset += sizeof(guint8);
+
+        msg_ns_count = tvb_get_ntohs(tvb, tree_offset);
+        proto_tree_add_uint(jxta_msg_tree, hf_jxta_message_namespaces_count, tvb, tree_offset, sizeof(guint16), msg_ns_count);
+        tree_offset += sizeof(guint16);
+
+        namespaces = ep_alloc((msg_ns_count + 2) * sizeof(const gchar *));
+        namespaces[0] = "";
+        namespaces[1] = "jxta";
+
+        /* parse namespaces */
+        for (each_namespace = 0; each_namespace < msg_ns_count; each_namespace++) {
+            guint16 namespace_len = tvb_get_ntohs(tvb, tree_offset);
+
+            namespaces[2 + each_namespace] = ep_tvb_get_string(tvb, tree_offset + sizeof(namespace_len), namespace_len);
+            proto_tree_add_item(jxta_msg_tree, hf_jxta_message_namespace_name, tvb, tree_offset, sizeof(namespace_len), FALSE);
+            tree_offset += sizeof(namespace_len) + namespace_len;
+        }
+
+        /* parse element count */
+        elem_count = tvb_get_ntohs(tvb, tree_offset);
+        proto_tree_add_item(jxta_msg_tree, hf_jxta_message_element_count, tvb, tree_offset, sizeof(guint16), FALSE);
+        tree_offset += sizeof(guint16);
+
+        /* parse elements */
+        for (each_elem = 0; each_elem < elem_count; each_elem++) {
+            tvbuff_t *jxta_message_element_tvb = tvb_new_subset(tvb, tree_offset, -1, -1);
+
+            tree_offset +=
+                dissect_jxta_message_element(jxta_message_element_tvb, pinfo, jxta_msg_tree, msg_ns_count + 2, namespaces);
+        }
+
+        proto_item_set_end(jxta_msg_tree_item, tvb, tree_offset);
+
+        DISSECTOR_ASSERT(tree_offset == offset);              
+    }
+
+    if ((offset > 0) && (AT_URI == pinfo->src.type) && (AT_URI == pinfo->dst.type)) {
+        jxta_tap_header * tap_header = (jxta_tap_header *) g_mem_chunk_alloc(my_tap_structs);
+        
+        tap_header->src_address = pinfo->src;
+        tap_header->dest_address = pinfo->dst;
+        tap_header->size = offset;
+
+        tap_queue_packet(jxta_tap, pinfo, tap_header);
+    }
+
+    return offset;
+}
+
+/**
+*   Dissect a tvbuff containing a JXTA Message Element.
+*    
+*   @param  tvb The buffer to dissect.
+*   @param  pinfo Packet Info.
+*   @param  tree The protocol tree.
+*   @return number of bytes from the tvbuff_t which were processed.
+**/
+static int dissect_jxta_message_element(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, guint ns_count,
+                                        const gchar **namespaces)
+{
+    guint offset = 0;
+    guint available;
+    gint needed = 0;
+    guint8 flags;
+
+    /* First pass. Make sure all of the bytes we need are available */
+
+    while (TRUE) {
+         /* signature field */
+        available = tvb_reported_length_remaining(tvb, offset);
+        if (available < sizeof(JXTA_MSGELEM_SIG)) {
+            needed = (gint) (available - sizeof(JXTA_MSGELEM_SIG));
+        }
+
+        if (tvb_memeql(tvb, offset, JXTA_MSGELEM_SIG, sizeof(JXTA_MSGELEM_SIG)) != 0) {
+            /* It is not one of ours */
+            return 0;
+        }
+
+        offset += sizeof(JXTA_MSGELEM_SIG);
+
+        /* namespace id field */
+        available = tvb_reported_length_remaining(tvb, offset);
+        if (available < sizeof(guint8)) {
+            needed = (gint) (available - sizeof(guint8));
+            break;
+        }
+
+        offset += sizeof(guint8);
+
+        /* flags field */
+        available = tvb_reported_length_remaining(tvb, offset);
+        if (available < sizeof(guint8)) {
+            needed = (gint) (available - sizeof(guint8));
+            break;
+        } else {
+            flags = tvb_get_guint8(tvb, offset);
+            offset += sizeof(guint8);
+        }
+
+        /* name field */
+        available = tvb_reported_length_remaining(tvb, offset);
+        if (available < sizeof(guint16)) {
+            needed = (gint) (available - sizeof(guint16));
+            break;
+        } else {
+            guint16 name_len = tvb_get_ntohs(tvb, offset);
+            offset += sizeof(guint16);
+
+            available = tvb_reported_length_remaining(tvb, offset);
+            if (available < name_len) {
+                needed = (gint) (available - name_len);
+                break;
             }
-            
-            /* parse elements */
-            numberOfElements = tvb_get_ntohs( tvb, offset );
-            ti = proto_tree_add_item(jxta_tree, hf_jxta_message_element_count, tvb, offset, sizeof(guint16), FALSE );
+
+            offset += name_len;
+        }
+
+        /* type field */
+        if ((flags & 0x01) != 0) {
+            guint16 type_len;
+
+            available = tvb_reported_length_remaining(tvb, offset);
+            if (available < sizeof(guint16)) {
+                needed = (gint) (available - sizeof(guint16));
+                break;
+            }
+
+            type_len = tvb_get_ntohs(tvb, offset);
             offset += sizeof(guint16);
-            
-            while( offset < tvb_length(tvb) ) {
-                    proto_tree   *jxta_elem_tree = NULL;
-                    proto_item      *elem_ti;
-                    
-                    elem_ti = proto_tree_add_item(jxta_tree, hf_jxta_element, tvb, 0, -1, FALSE);
-                    jxta_elem_tree = proto_item_add_subtree(elem_ti, ett_jxta_elem);
-
-                /* gross hack for parsing of signature element */
-                element_parse :
-                {
-                guint32 elemsignature = tvb_get_ntohl( tvb, offset );
-                gboolean goodsig = 0 == (elemsignature ^ 0x6A78656CU);
-   
-                ti = proto_tree_add_item( jxta_tree, hf_jxta_element_sig, tvb, offset, 4, FALSE );
-                offset += 4;
-                if( goodsig ) {
-                    guint8 namespaceID;
-                    guint8 flags;
-                    guint16 nameLen;
-                    guint32 elemContentLength;
-                    PROTO_ITEM_SET_HIDDEN( ti );
-
-                    namespaceID = tvb_get_guint8( tvb, offset );
-                    ti = proto_tree_add_item( jxta_elem_tree, hf_jxta_element_namespaceid, tvb, offset, sizeof(guint8), FALSE );
-                    offset += sizeof(guint8);
-                
-                    flags = tvb_get_guint8( tvb, offset );
-                    ti = proto_tree_add_item( jxta_elem_tree, hf_jxta_element_flags, tvb, offset, sizeof(guint8), FALSE );
-                    offset += sizeof(guint8);
-                    
-                    nameLen  = tvb_get_ntohs( tvb, offset );
-                    ti = proto_tree_add_item( jxta_elem_tree, hf_jxta_element_name_len, tvb, offset, sizeof(guint16), FALSE );
-                    offset += sizeof(guint16);
-                    PROTO_ITEM_SET_HIDDEN( ti );
-                    
-                    ti = proto_tree_add_string(jxta_elem_tree, hf_jxta_element_name, tvb, offset, nameLen, 
-                        tvb_format_text(tvb, offset, nameLen));
-                        
-                    offset += nameLen;
-                    
-                    /* process type */
-                    if( (flags & 0x01) != 0 ) {
-                        guint16 typeLen  = tvb_get_ntohs( tvb, offset );
-                        ti = proto_tree_add_item( jxta_elem_tree, hf_jxta_element_type_len, tvb, offset, sizeof(guint16), FALSE );
-                        offset += sizeof(guint16);
-                        PROTO_ITEM_SET_HIDDEN( ti );
-
-                        ti = proto_tree_add_string(jxta_elem_tree, hf_jxta_element_type, tvb, offset, typeLen, 
-                            tvb_format_text(tvb, offset, typeLen));
-
-                        offset += typeLen;
-                        }
-                    
-                    /* process encoding */
-                    if( (flags & 0x02) != 0 ) {
-                        guint16 encodingLen  = tvb_get_ntohs( tvb, offset );
-                        ti = proto_tree_add_item( jxta_elem_tree, hf_jxta_element_encoding_len, tvb, offset, sizeof(guint16), FALSE );
-                        offset += sizeof(guint16);
-                        PROTO_ITEM_SET_HIDDEN( ti );
-
-                        ti = proto_tree_add_string(jxta_elem_tree, hf_jxta_element_encoding, tvb, offset, encodingLen, 
-                            tvb_format_text(tvb, offset, encodingLen));
-
-                        offset += encodingLen;
-                        }
-                    
-                    /* content */
-                    elemContentLength = tvb_get_ntohl( tvb, offset );
-                    ti = proto_tree_add_item( jxta_elem_tree, hf_jxta_element_content_len, tvb, offset, sizeof(guint32), FALSE );
-                    offset += sizeof(guint32);
-                    
-                    ti = proto_tree_add_item( jxta_elem_tree, hf_jxta_element_content, tvb, offset, elemContentLength, FALSE );
-                    offset += elemContentLength;
-                    
-                    /* XXX Evil Hack Warning : handle parsing of signature element. Would be better with recursion.*/
-                    if( (flags & 0x04) != 0 ) {
-                        goto element_parse;
-                        }
-                    }
-                    
-                    proto_item_set_end( elem_ti, tvb, offset - 1 );
+
+            available = tvb_reported_length_remaining(tvb, offset);
+            if (available < type_len) {
+                needed = (gint) (available - type_len);
+                break;
+            }
+
+            offset += type_len;
+        }
+
+        /* encoding field */
+        if ((flags & 0x02) != 0) {
+            guint16 encoding_len;
+
+            available = tvb_reported_length_remaining(tvb, offset);
+            if (available < sizeof(guint16)) {
+                needed = (gint) (available - sizeof(guint16));
+                break;
+            }
+
+            encoding_len = tvb_get_ntohs(tvb, offset);
+            offset += sizeof(guint16);
+
+            available = tvb_reported_length_remaining(tvb, offset);
+            if (available < encoding_len) {
+                needed = (gint) (available - encoding_len);
+                break;
+            }
+
+            offset += encoding_len;
+        }
+
+        /* content field */
+        available = tvb_reported_length_remaining(tvb, offset);
+        if (available < sizeof(guint16)) {
+            needed = (gint) (available - sizeof(guint16));
+            break;
+        } else {
+            guint32 content_len = tvb_get_ntohl(tvb, offset);
+            offset += sizeof(guint32);
+
+            available = tvb_reported_length_remaining(tvb, offset);
+            if (available < content_len) {
+                needed = (gint) (available - content_len);
+                break;
+            }
+
+            offset += content_len;
+        }
+
+        /* signature element field */
+        if ((flags & 0x04) != 0) {
+            tvbuff_t *jxta_signature_element_tvb;
+            int processed;
+
+            jxta_signature_element_tvb = tvb_new_subset(tvb, offset, -1, -1);
+
+            processed = dissect_jxta_message_element(jxta_signature_element_tvb, pinfo, NULL, 0, NULL);
+
+            if (processed == 0) {
+                return offset;
+            }
+
+            if (processed < 0) {
+                needed = -processed;
+                break;
+            }
+
+            offset += processed;
+        }
+
+        break;
+    }
+
+    if ((needed > 0) && gDESEGMENT && pinfo->can_desegment) {
+        pinfo->desegment_offset = 0;
+        pinfo->desegment_len = needed;
+        return -needed;
+    }
+
+    /* Second (optional) pass : build the proto tree */
+    if (tree) {
+        guint tree_offset = 0;
+        proto_item *jxta_elem_tree_item = proto_tree_add_item(tree, hf_jxta_element, tvb, tree_offset, -1, FALSE);
+        proto_tree *jxta_elem_tree = proto_item_add_subtree(jxta_elem_tree_item, ett_jxta_elem);
+        guint8 namespaceID;
+        proto_item *namespace_ti;
+        guint16 name_len;
+        proto_item *flags_ti;
+        proto_tree *jxta_elem_flags_tree = NULL;
+        guint32 content_len;
+        gchar *mediatype = NULL;
+        gboolean media_type_recognized = FALSE;
+        tvbuff_t *element_content_tvb;
+
+        proto_tree_add_item(jxta_elem_tree, hf_jxta_element_sig, tvb, tree_offset, sizeof(JXTA_MSGELEM_SIG), FALSE);
+        tree_offset += sizeof(JXTA_MSGELEM_SIG);
+
+        namespaceID = tvb_get_guint8(tvb, tree_offset);
+        namespace_ti =
+            proto_tree_add_uint(jxta_elem_tree, hf_jxta_element_namespaceid, tvb, tree_offset, sizeof(guint8), namespaceID);
+        if (namespaceID < ns_count) {
+            proto_item_append_text(namespace_ti, " (%s)", namespaces[namespaceID]);
+        } else {
+            proto_item_append_text(namespace_ti, " * BAD *");
+        }
+        tree_offset += sizeof(guint8);
+
+        flags = tvb_get_guint8(tvb, tree_offset);
+        flags_ti = proto_tree_add_uint(jxta_elem_tree, hf_jxta_element_flags, tvb, tree_offset, sizeof(guint8), flags);
+        jxta_elem_flags_tree = proto_item_add_subtree(flags_ti, ett_jxta_elem_flags);
+        proto_tree_add_boolean(jxta_elem_flags_tree, hf_jxta_element_flag_hasType, tvb, tree_offset, 1, flags);
+        proto_tree_add_boolean(jxta_elem_flags_tree, hf_jxta_element_flag_hasEncoding, tvb, tree_offset, 1, flags);
+        proto_tree_add_boolean(jxta_elem_flags_tree, hf_jxta_element_flag_hasSignature, tvb, tree_offset, 1, flags);
+        tree_offset += sizeof(guint8);
+
+        name_len = tvb_get_ntohs(tvb, tree_offset);
+        proto_item_append_text(jxta_elem_tree_item, " \"%s\"", tvb_format_text(tvb, tree_offset + sizeof(guint16), name_len));
+        proto_tree_add_item(jxta_elem_tree, hf_jxta_element_name, tvb, tree_offset, sizeof(guint16), FALSE);
+        tree_offset += sizeof(guint16) + name_len;
+
+        /* process type */
+        if ((flags & 0x01) != 0) {
+            guint16 type_len = tvb_get_ntohs(tvb, tree_offset);
+            proto_tree_add_item(jxta_elem_tree, hf_jxta_element_type, tvb, tree_offset, sizeof(guint16), FALSE);
+            tree_offset += sizeof(guint16);
+
+            mediatype = ep_tvb_get_string(tvb, tree_offset, type_len);
+
+            /* remove any params */
+            {
+                gchar *parms_at = strchr(mediatype, ';');
+
+                if (NULL != parms_at) {
+                    *parms_at = '\0';
                 }
             }
+
+            /* force to lower case */
+#if GLIB_MAJOR_VERSION < 2
+            g_strdown(mediatype);
+#else
+            {
+                gchar *mediatype_lowercase = g_ascii_strdown(mediatype, -1);
+                mediatype = mediatype_lowercase;
+            }
+#endif
+            tree_offset += type_len;
+        }
+
+        /* process encoding */
+        if ((flags & 0x02) != 0) {
+            guint16 encoding_len = tvb_get_ntohs(tvb, tree_offset);
+            proto_tree_add_item(jxta_elem_tree, hf_jxta_element_encoding, tvb, tree_offset, sizeof(guint16), FALSE);
+            tree_offset += sizeof(guint16) + encoding_len;
+        }
+
+        /* content */
+        content_len = tvb_get_ntohl(tvb, tree_offset);
+        proto_tree_add_item(jxta_elem_tree, hf_jxta_element_content_len, tvb, tree_offset, sizeof(guint32), FALSE);
+        tree_offset += sizeof(guint32);
+
+        element_content_tvb = tvb_new_subset(tvb, tree_offset, content_len, content_len);
+
+        if (mediatype) {
+            if( 0 == strcmp( "application/x-jxta-tls-block", mediatype ) ) {
+                /* If we recognize it as a TLS packet then we shuffle it off to ssl dissector. */
+                dissector_handle_t ssl_handle = find_dissector("ssl");
+                if( NULL != ssl_handle ) {
+                    int processed = call_dissector(ssl_handle, element_content_tvb, pinfo, jxta_elem_tree);
+                    media_type_recognized = processed > 0;
+                    }
+            } else {
+                media_type_recognized = dissector_try_string(media_type_dissector_table,
+                                                         mediatype, element_content_tvb, pinfo, jxta_elem_tree);
+            }
+            
+        }
+
+        if (!media_type_recognized) {
+            dissector_handle_t data_handle = find_dissector("data");
+            call_dissector(data_handle, element_content_tvb, pinfo, jxta_elem_tree);
         }
-    }    
-  }
+        tree_offset += content_len;
+
+        if ((flags & 0x04) != 0) {
+            tvbuff_t *jxta_message_element_tvb = tvb_new_subset(tvb, tree_offset, -1, -1);
+
+            tree_offset += dissect_jxta_message_element(jxta_message_element_tvb, pinfo, jxta_elem_tree, ns_count, namespaces);
+        }
+
+        proto_item_set_end(jxta_elem_tree_item, tvb, tree_offset);
+
+        DISSECTOR_ASSERT(tree_offset == offset);
+    }
+
+    return offset;
 }
 
+static void jxta_dissector_init( void)
+{
+    /* destroy memory chunks if needed */
+
+    if ( NULL != my_tap_structs )
+       g_mem_chunk_destroy( my_tap_structs );
+
+
+    if ( NULL != my_conv_structs )
+       g_mem_chunk_destroy( my_conv_structs );
+
+    /* now create memory chunks */
+
+    my_tap_structs = g_mem_chunk_new( "my_tap_structs",
+           sizeof( jxta_tap_header ),
+           10 * sizeof( jxta_tap_header ),
+           G_ALLOC_ONLY);
+
+    my_conv_structs = g_mem_chunk_new( "my_conv_structs",
+           sizeof( jxta_stream_conversation_data ),
+           10 * sizeof( jxta_stream_conversation_data ),
+           G_ALLOC_ONLY);
+}
+
+/**
+*    Register jxta protocol and jxta message protocol, header fields, subtree types, preferences.
+**/
 void proto_register_jxta(void)
 {
-  module_t *jxta_module;
-
-  proto_jxta = proto_register_protocol("JXTA P2P", "JXTA", "jxta");
-  
-   /* Register header fields */
-  proto_register_field_array(proto_jxta, hf, array_length(hf));
-  
-  /* Register JXTA Sub-tree */
-  proto_register_subtree_array(ett, array_length(ett));
-
-  /* Register preferences */
-  jxta_module = prefs_register_protocol(proto_jxta, proto_reg_handoff_jxta);
-  
-  prefs_register_uint_preference(jxta_module, "tcp.port", "JXTA TCP Port",
-                                "Set the port for JXTA TCP messages",
-                                10, &gTCP_PORT_JXTA);
-
-  prefs_register_uint_preference(jxta_module, "http.port", "JXTA HTTP Port",
-                                "Set the port for JXTA HTTP messages",
-                                10, &gHTTP_PORT_JXTA);
-
-  prefs_register_uint_preference(jxta_module, "udp.port", "JXTA UDP Multicast Port",
-                                "Set the port for JXTA UDP Multicast messages",
-                                10, &gUDP_MULTICAST_PORT_JXTA);
+    module_t *jxta_module;
+
+    /* register re-init routine */
+
+    register_init_routine( &jxta_dissector_init);
+
+    proto_jxta = proto_register_protocol("JXTA P2P", "JXTA", "jxta");
+
+    jxta_tap = register_tap("jxta");
+
+    proto_welcome_jxta = proto_register_protocol("JXTA Connection Welcome Message", "JXTA Welcome", "jxta.welcome");
+    
+    proto_udp_jxta = proto_register_protocol("JXTA UDP", "JXTA UDP", "jxta.udp");
+
+    proto_framing_jxta = proto_register_protocol("JXTA Message Framing", "JXTA Framing", "jxta.framing");
+    
+    proto_message_jxta = proto_register_protocol("JXTA Message", "JXTA Message", "jxta.message");
+
+    /* Register header fields */
+    proto_register_field_array(proto_jxta, hf, array_length(hf));
+
+    /* Register JXTA Sub-tree */
+    proto_register_subtree_array(ett, array_length(ett));
+
+    /* Register preferences */
+    jxta_module = prefs_register_protocol(proto_jxta, proto_reg_handoff_jxta);
+
+    prefs_register_bool_preference(jxta_module, "desegment",
+                                   "Reassemble JXTA messages spanning multiple UDP/TCP/HTTP segments",
+                                   "Whether the JXTA dissector should reassemble messages spanning multiple UDP/TCP segments."
+                                   " To use this option you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings "
+                                   " and enable \"Reassemble fragmented IP datagrams\" in the IP protocol settings.",
+                                   &gDESEGMENT);
+
+    prefs_register_bool_preference(jxta_module, "udp.heuristic", "Try to discover JXTA in UDP datagrams",
+                                   "Enable to inspect UDP datagrams for JXTA messages.", &gUDP_HEUR);
+
+    prefs_register_bool_preference(jxta_module, "tcp.heuristic", "Try to discover JXTA in TCP connections",
+                                   "Enable to inspect TCP connections for JXTA conversations.", &gTCP_HEUR);
 }
 
-void proto_reg_handoff_jxta(void) {
-  static gboolean jxta_prefs_initialized = FALSE;
+void proto_reg_handoff_jxta(void)
+{
+    static gboolean init_done = FALSE;
+
+    if (!init_done) {
+        new_register_dissector("jxta.udp", dissect_jxta_udp, proto_jxta);
+        heur_dissector_add("udp", dissect_jxta_UDP_heur, proto_udp_jxta);
 
-  if (!jxta_prefs_initialized) {
-    udpm_jxta_handle = create_dissector_handle(dissect_jxta_udp, proto_jxta);
-    tcp_jxta_handle = create_dissector_handle(dissect_jxta_tcp, proto_jxta);
-    http_jxta_handle = create_dissector_handle(dissect_jxta_message, proto_jxta);
+        new_register_dissector("jxta.tcp", dissect_jxta_tcp, proto_jxta);
+        tcp_jxta_handle = find_dissector("jxta.tcp");
+        heur_dissector_add("tcp", dissect_jxta_TCP_heur, proto_jxta);
 
-    jxta_prefs_initialized = TRUE;
-  } else {
-    dissector_delete("udp.port", regUDP_MULTICAST_PORT_JXTA, udpm_jxta_handle);
+        init_done = TRUE;
+    }
+}
 
-    dissector_delete("tcp.port", regTCP_PORT_JXTA, tcp_jxta_handle);
+void proto_reg_handoff_message_jxta(void)
+{
+    static gboolean init_done = FALSE;
+    static dissector_handle_t message_jxta_handle;
 
-    dissector_delete("http.port", regHTTP_PORT_JXTA, http_jxta_handle);
-  }
+    if (!init_done) {
+        message_jxta_handle = new_create_dissector_handle(dissect_jxta_message, proto_message_jxta);
 
-  /* remember what ports we registered on for later removal */
-  regUDP_MULTICAST_PORT_JXTA = gUDP_MULTICAST_PORT_JXTA;
-  regTCP_PORT_JXTA = gTCP_PORT_JXTA;
-  regHTTP_PORT_JXTA = gHTTP_PORT_JXTA;
-   
-  /* register as a sub-dissector of UDP  tagged on port field */
-  dissector_add("udp.port", regUDP_MULTICAST_PORT_JXTA, udpm_jxta_handle);
+        media_type_dissector_table = find_dissector_table("media_type");
 
-  /* register as a sub-dissector of TCP tagged on port field*/
-  dissector_add("tcp.port", regTCP_PORT_JXTA, tcp_jxta_handle);
+        dissector_add_string("media_type", "application/x-jxta-msg", message_jxta_handle);
 
-  /* register as a sub-dissector of HTTP tagged on port field */
-  dissector_add("http.port", regHTTP_PORT_JXTA, http_jxta_handle);
+        init_done = TRUE;
+    }
 }