b25fd3dcfe586e13b1a2317c1acb634434a4f974
[obnox/wireshark/wip.git] / epan / dissectors / packet-jxta.c
1 /* packet-jxta.c
2  *
3  * Routines for JXTA packet dissection
4  * JXTA specification from https://jxta-spec.dev.java.net
5  *
6  * Copyright 2004-08, Mike Duigou <bondolo@dev.java.net>
7  *
8  * Heavily based on packet-jabber.c, which in turn is heavily based on
9  * on packet-acap.c, which in turn is heavily based on
10  * packet-imap.c, Copyright 1999, Richard Sharpe <rsharpe@ns.aus.com>
11  * Copied from packet-pop.c, packet-jabber.c, packet-udp.c, packet-http.c
12  *
13  * $Id$
14  *
15  * Wireshark - Network traffic analyzer
16  * By Gerald Combs <gerald@wireshark.org>
17  * Copyright 2000 Gerald Combs
18  *
19  * This program is free software; you can redistribute it and/or
20  * modify it under the terms of the GNU General Public License
21  * as published by the Free Software Foundation; either version 2
22  * of the License, or (at your option) any later version.
23  *
24  * This program is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License
30  * along with this program; if not, write to the Free Software
31  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
32  */
33
34 #ifdef HAVE_CONFIG_H
35 # include "config.h"
36 #endif
37
38 #include <limits.h>
39 #include <stdio.h>
40 #include <string.h>
41
42 #define G_LOG_DOMAIN "jxta"
43
44 #include <glib.h>
45
46 #include <epan/packet.h>
47 #include <epan/conversation.h>
48 #include <epan/strutil.h>
49 #include <epan/prefs.h>
50 #include <epan/tap.h>
51 #include <epan/emem.h>
52 #include <epan/ws_strsplit.h>
53
54 #include "packet-jxta.h"
55
56 static const gchar JXTA_UDP_SIG[] = { 'J', 'X', 'T', 'A' };
57 static const gchar JXTA_MSG_SIG[] = { 'j', 'x', 'm', 'g' };
58 static const gchar JXTA_MSGELEM_SIG[] = { 'j', 'x', 'e', 'l' };
59
60 static const gchar JXTA_WELCOME_MSG_SIG[] = { 'J', 'X', 'T', 'A', 'H', 'E', 'L', 'L', 'O', ' ' };
61
62 static const gchar* JXTA_WELCOME_MSG_VERSION_1_1 = "1.1";
63 static const gchar* JXTA_WELCOME_MSG_VERSION_3_0 = "3.0";
64
65 static const int JXTA_MSG_VERSION_1 = 0;
66 static const int JXTA_MSG_VERSION_2 = 1;
67
68 static const int JXTAMSG1_ELMFLAG_TYPE = 1 << 0;
69 static const int JXTAMSG1_ELMFLAG_ENCODING = 1 << 1;
70 static const int JXTAMSG1_ELMFLAG_SIGNATURE = 1 << 2;
71
72 static const int JXTAMSG2_ELMFLAG_UINT64_LENS = 1 << 0;
73 static const int JXTAMSG2_ELMFLAG_NAME_LITERAL = 1 << 1;
74 static const int JXTAMSG2_ELMFLAG_TYPE = 1 << 2;
75 static const int JXTAMSG2_ELMFLAG_SIGNATURE = 1 << 3;
76 static const int JXTAMSG2_ELMFLAG_ENCODINGS = 1 << 4;
77
78 static int proto_jxta = -1;
79 static int proto_message_jxta = -1;
80 static int jxta_tap = -1;
81
82 static dissector_table_t media_type_dissector_table = NULL;
83 static dissector_handle_t media_handle = NULL;
84 static dissector_handle_t data_handle = NULL;
85 static dissector_handle_t stream_jxta_handle = NULL;
86 static dissector_handle_t message_jxta_handle;
87
88 static int hf_uri_addr = -1;
89 static int hf_uri_src = -1;
90 static int hf_uri_dst = -1;
91 static int hf_jxta_udp = -1;
92 static int hf_jxta_udpsig = -1;
93 static int hf_jxta_welcome = -1;
94 static int hf_jxta_welcome_initiator = -1;
95 static int hf_jxta_welcome_sig = -1;
96 static int hf_jxta_welcome_destAddr = -1;
97 static int hf_jxta_welcome_pubAddr = -1;
98 static int hf_jxta_welcome_peerid = -1;
99 static int hf_jxta_welcome_noProp = -1;
100 static int hf_jxta_welcome_msgVers = -1;
101 static int hf_jxta_welcome_variable = -1;
102 static int hf_jxta_welcome_version = -1;
103 static int hf_jxta_framing = -1;
104 static int hf_jxta_framing_header = -1;
105 static int hf_jxta_framing_header_name = -1;
106 static int hf_jxta_framing_header_value_length = -1;
107 static int hf_jxta_framing_header_value = -1;
108 static int hf_jxta_message_address = -1;
109 static int hf_jxta_message_src = -1;
110 static int hf_jxta_message_dst = -1;
111 static int hf_jxta_message_sig = -1;
112 static int hf_jxta_message_version = -1;
113 static int hf_jxta_message_flags = -1;
114 static int hf_jxta_message_flag_utf16be = -1;
115 static int hf_jxta_message_flag_ucs32be = -1;
116 static int hf_jxta_message_names_count = -1;
117 static int hf_jxta_message_names_name = -1;
118 static int hf_jxta_message_element_count = -1;
119 static int hf_jxta_element = -1;
120 static int hf_jxta_element_sig = -1;
121 static int hf_jxta_element1_namespaceid = -1;
122 static int hf_jxta_element2_namespaceid = -1;
123 static int hf_jxta_element2_nameid = -1;
124 static int hf_jxta_element2_mimeid = -1;
125 static int hf_jxta_element2_encodingid = -1;
126 static int hf_jxta_element_flags = -1;
127 static int hf_jxta_element1_flag_hasType = -1;
128 static int hf_jxta_element1_flag_hasEncoding = -1;
129 static int hf_jxta_element1_flag_hasSignature = -1;
130 static int hf_jxta_element2_flag_64bitlens = -1;
131 static int hf_jxta_element2_flag_nameLiteral = -1;
132 static int hf_jxta_element2_flag_hasType = -1;
133 static int hf_jxta_element2_flag_hasSignature = -1;
134 static int hf_jxta_element2_flag_hasEncoding = -1;
135 static int hf_jxta_element2_flag_sigOfEncoded = -1;
136 static int hf_jxta_element_name = -1;
137 static int hf_jxta_element_type = -1;
138 static int hf_jxta_element_encoding = -1;
139 static int hf_jxta_element_content_len = -1;
140 static int hf_jxta_element_content_len64 = -1;
141 static int hf_jxta_element_content = -1;
142
143 /** our header fields */
144 static hf_register_info hf[] = {
145     {&hf_uri_addr,
146      {"Address", "uri.addr", FT_STRING, BASE_NONE, NULL, 0x0,
147       "URI Address (source or destination)", HFILL}
148      },
149     {&hf_uri_src,
150      {"Source", "uri.src", FT_STRING, BASE_NONE, NULL, 0x0,
151       "URI Source", HFILL}
152      },
153     {&hf_uri_dst,
154      {"Destination", "uri.dst", FT_STRING, BASE_NONE, NULL, 0x0,
155       "URI Destination", HFILL}
156      },
157     {&hf_jxta_udp,
158      {"JXTA UDP", "jxta.udp", FT_NONE, BASE_NONE, NULL, 0x0,
159       "JXTA UDP", HFILL}
160      },
161     {&hf_jxta_udpsig,
162      {"Signature", "jxta.udpsig", FT_STRING, BASE_NONE, NULL, 0x0,
163       "JXTA UDP Signature", HFILL}
164      },
165     {&hf_jxta_welcome,
166      {"Welcome", "jxta.welcome", FT_NONE, BASE_NONE, NULL, 0x00,
167       "JXTA Connection Welcome Message", HFILL}
168      },
169     {&hf_jxta_welcome_initiator,
170      {"Initiator", "jxta.welcome.initiator", FT_BOOLEAN, BASE_NONE, NULL, 0x00,
171       "JXTA Connection Welcome Message Initiator", HFILL}
172      },
173     {&hf_jxta_welcome_sig,
174      {"Signature", "jxta.welcome.signature", FT_STRING, BASE_NONE, NULL, 0x0,
175       "JXTA Connection Welcome Message Signature", HFILL}
176      },
177     {&hf_jxta_welcome_destAddr,
178      {"Destination Address", "jxta.welcome.destAddr", FT_STRING, BASE_NONE, NULL, 0x0,
179       "JXTA Connection Welcome Message Destination Address", HFILL}
180      },
181     {&hf_jxta_welcome_pubAddr,
182      {"Public Address", "jxta.welcome.pubAddr", FT_STRING, BASE_NONE, NULL, 0x0,
183       "JXTA Connection Welcome Message Public Address", HFILL}
184      },
185     {&hf_jxta_welcome_peerid,
186      {"PeerID", "jxta.welcome.peerid", FT_STRING, BASE_NONE, NULL, 0x0,
187       "JXTA Connection Welcome Message PeerID", HFILL}
188      },
189     {&hf_jxta_welcome_noProp,
190      {"No Propagate Flag", "jxta.welcome.noPropFlag", FT_STRING, BASE_NONE, NULL, 0x0,
191       "JXTA Connection Welcome Message No Propagate Flag", HFILL}
192      },
193     {&hf_jxta_welcome_msgVers,
194      {"Preferred Message Version", "jxta.welcome.msgVersion", FT_STRING, BASE_NONE, NULL, 0x0,
195       "JXTA Connection Welcome Message Preferred Message Version", HFILL}
196      },
197     {&hf_jxta_welcome_variable,
198      {"Variable Parameter", "jxta.welcome.variable", FT_STRING, BASE_NONE, NULL, 0x0,
199       "JXTA Connection Welcome Message Variable Parameter", HFILL}
200      },
201     {&hf_jxta_welcome_version,
202      {"Version", "jxta.welcome.version", FT_STRING, BASE_NONE, NULL, 0x0,
203       "JXTA Connection Welcome Message Version", HFILL}
204      },
205     {&hf_jxta_framing,
206      {"Framing", "jxta.framing", FT_NONE, BASE_NONE, NULL, 0x0,
207       "JXTA Message Framing", HFILL}
208      },
209     {&hf_jxta_framing_header,
210      {"Header", "jxta.framing.header", FT_NONE, BASE_NONE, NULL, 0x0,
211       "JXTA Message Framing Header", HFILL}
212      },
213     {&hf_jxta_framing_header_name,
214      {"Name", "jxta.framing.header.name", FT_UINT_STRING, BASE_NONE, NULL, 0x0,
215       "JXTA Message Framing Header Name", HFILL}
216      },
217     {&hf_jxta_framing_header_value_length,
218      {"Value Length", "jxta.framing.header.valuelen", FT_UINT16, BASE_DEC, NULL, 0x0,
219       "JXTA Message Framing Header Value Length", HFILL}
220      },
221     {&hf_jxta_framing_header_value,
222      {"Value", "jxta.framing.header.value", FT_BYTES, BASE_HEX, NULL, 0x0,
223       "JXTA Message Framing Header Value", HFILL}
224      },
225     {&hf_jxta_message_address,
226      {"Address", "jxta.message.address", FT_STRING, BASE_NONE, NULL, 0x0,
227       "JXTA Message Address (source or destination)", HFILL}
228      },
229     {&hf_jxta_message_src,
230      {"Source", "jxta.message.source", FT_STRING, BASE_NONE, NULL, 0x0,
231       "JXTA Message Source", HFILL}
232      },
233     {&hf_jxta_message_dst,
234      {"Destination", "jxta.message.destination", FT_STRING, BASE_NONE, NULL, 0x0,
235       "JXTA Message Destination", HFILL}
236      },
237     {&hf_jxta_message_sig,
238      {"Signature", "jxta.message.signature", FT_STRING, BASE_NONE, NULL, 0x0,
239       "JXTA Message Signature", HFILL}
240      },
241     {&hf_jxta_message_version,
242      {"Version", "jxta.message.version", FT_UINT8, BASE_DEC, NULL, 0x0,
243       "JXTA Message Version", HFILL}
244      },
245     {&hf_jxta_message_flags,
246      {"Flags", "jxta.message.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
247       "JXTA Message Flags", HFILL}
248      },
249     {&hf_jxta_message_flag_utf16be,
250      {"UTF16BE", "jxta.message.flags.UTF-16BE", FT_BOOLEAN, 2, TFS(&flags_set_truth), 0x01,
251       "JXTA Message Element Flag -- UTF16-BE Strings", HFILL}
252      },
253     {&hf_jxta_message_flag_ucs32be,
254      {"UCS32BE", "jxta.message.flags.UCS32BE", FT_BOOLEAN, 2, TFS(&flags_set_truth), 0x02,
255       "JXTA Message Flag -- UCS32-BE Strings", HFILL}
256      },
257     {&hf_jxta_message_names_count,
258      {"Names Count", "jxta.message.names", FT_UINT16, BASE_DEC, NULL, 0x0,
259       "JXTA Message Names Table", HFILL}
260      },
261     {&hf_jxta_message_names_name,
262      {"Names Table Name", "jxta.message.names.name", FT_UINT_STRING, BASE_NONE, NULL, 0x0,
263       "JXTA Message Names Table Name", HFILL}
264      },
265     {&hf_jxta_message_element_count,
266      {"Element Count", "jxta.message.elements", FT_UINT16, BASE_DEC, NULL, 0x0,
267       "JXTA Message Element Count", HFILL}
268      },
269     {&hf_jxta_element,
270      {"JXTA Message Element", "jxta.message.element", FT_NONE, BASE_NONE, NULL, 0x0,
271       "JXTA Message Element", HFILL}
272      },
273     {&hf_jxta_element_sig,
274      {"Signature", "jxta.message.element.signature", FT_STRING, BASE_NONE, NULL, 0x0,
275       "JXTA Message Element Signature", HFILL}
276      },
277     {&hf_jxta_element1_namespaceid,
278      {"Namespace ID", "jxta.message.element.namespaceid", FT_UINT8, BASE_DEC, NULL, 0x0,
279       "JXTA Message Element Namespace ID", HFILL}
280      },
281     {&hf_jxta_element2_namespaceid,
282      {"Namespace ID", "jxta.message.element.namespaceid", FT_UINT16, BASE_DEC, NULL, 0x0,
283       "JXTA Message Element Namespace ID", HFILL}
284      },
285     {&hf_jxta_element_flags,
286      {"Flags", "jxta.message.element.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
287       "JXTA Message Element Flags", HFILL}
288      },
289     {&hf_jxta_element1_flag_hasType,
290      {"hasType", "jxta.message.element.flags.hasType", FT_BOOLEAN, 3, TFS(&flags_set_truth), 0x01,
291       "JXTA Message Element Flag -- hasType", HFILL}
292      },
293     {&hf_jxta_element1_flag_hasEncoding,
294      {"hasEncoding", "jxta.message.element.flags.hasEncoding", FT_BOOLEAN, 3, TFS(&flags_set_truth), 0x02,
295       "JXTA Message Element Flag -- hasEncoding", HFILL}
296      },
297     {&hf_jxta_element1_flag_hasSignature,
298      {"hasSignature", "jxta.message.element.flags.hasSignature", FT_BOOLEAN, 3, TFS(&flags_set_truth), 0x04,
299       "JXTA Message Element Flag -- hasSignature", HFILL}
300      },
301     {&hf_jxta_element2_flag_64bitlens,
302      {"uint64Lens", "jxta.message.element.flags.uint64Lens", FT_BOOLEAN, 6, TFS(&flags_set_truth), 0x01,
303       "JXTA Message Element Flag -- uint64Lens", HFILL}
304      },
305     {&hf_jxta_element2_flag_nameLiteral,
306      {"nameLiteral", "jxta.message.element.flags.nameLiteral", FT_BOOLEAN, 6, TFS(&flags_set_truth), 0x02,
307       "JXTA Message Element Flag -- nameLiteral", HFILL}
308      },
309     {&hf_jxta_element2_flag_hasType,
310      {"hasEncoding", "jxta.message.element.flags.hasType", FT_BOOLEAN, 6, TFS(&flags_set_truth), 0x04,
311       "JXTA Message Element Flag -- hasType", HFILL}
312      },
313     {&hf_jxta_element2_flag_hasSignature,
314      {"hasSignature", "jxta.message.element.flags.hasSignature", FT_BOOLEAN, 6, TFS(&flags_set_truth), 0x08,
315       "JXTA Message Element Flag -- hasSignature", HFILL}
316      },
317     {&hf_jxta_element2_flag_hasEncoding,
318      {"hasSignature", "jxta.message.element.flags.hasEncoding", FT_BOOLEAN, 6, TFS(&flags_set_truth), 0x10,
319       "JXTA Message Element Flag -- hasEncoding", HFILL}
320      },
321     {&hf_jxta_element2_flag_sigOfEncoded,
322      {"sigOfEncoded", "jxta.message.element.flags.sigOfEncoded", FT_BOOLEAN, 6, TFS(&flags_set_truth), 0x20,
323       "JXTA Message Element Flag -- sigOfEncoded", HFILL}
324      },
325     {&hf_jxta_element2_nameid,
326      {"Name ID", "jxta.message.element.nameid", FT_UINT16, BASE_DEC, NULL, 0x0,
327       "JXTA Message Element Name ID", HFILL}
328      },
329     {&hf_jxta_element_name,
330      {"Element Name", "jxta.message.element.name", FT_UINT_STRING, BASE_NONE, NULL, 0x0,
331       "JXTA Message Element Name", HFILL}
332      },
333     {&hf_jxta_element2_mimeid,
334      {"MIME ID", "jxta.message.element.mimeid", FT_UINT16, BASE_DEC, NULL, 0x0,
335       "JXTA Message Element MIME ID", HFILL}
336      },
337     {&hf_jxta_element2_encodingid,
338      {"Encoding ID", "jxta.message.element.encodingid", FT_UINT16, BASE_DEC, NULL, 0x0,
339       "JXTA Message Element Encoding ID", HFILL}
340      },
341     {&hf_jxta_element_type,
342      {"Element Type", "jxta.message.element.type", FT_UINT_STRING, BASE_NONE, NULL, 0x0,
343       "JXTA Message Element Name", HFILL}
344      },
345     {&hf_jxta_element_encoding,
346      {"Element Type", "jxta.message.element.encoding", FT_UINT_STRING, BASE_NONE, NULL, 0x0,
347       "JXTA Message Element Encoding", HFILL}
348      },
349     {&hf_jxta_element_content_len,
350      {"Element Content Length", "jxta.message.element.content.length", FT_UINT32, BASE_DEC, NULL, 0x0,
351       "JXTA Message Element Content Length", HFILL}
352      },
353     {&hf_jxta_element_content_len64,
354      {"Element Content Length", "jxta.message.element.content.length", FT_UINT64, BASE_DEC, NULL, 0x0,
355       "JXTA Message Element Content Length", HFILL}
356      },
357     {&hf_jxta_element_content,
358      {"Element Content", "jxta.message.element.content", FT_BYTES, BASE_HEX, NULL, 0x0,
359       "JXTA Message Element Content", HFILL}
360      },
361 };
362
363 /**
364 *    JXTA Protocol subtree handles
365 **/
366 static gint ett_jxta = -1;
367 static gint ett_jxta_welcome = -1;
368 static gint ett_jxta_udp = -1;
369 static gint ett_jxta_framing = -1;
370 static gint ett_jxta_framing_header = -1;
371 static gint ett_jxta_msg = -1;
372 static gint ett_jxta_msg_flags = -1;
373 static gint ett_jxta_elem = -1;
374 static gint ett_jxta_elem_1_flags = -1;
375 static gint ett_jxta_elem_2_flags = -1;
376
377 /**
378 *   JXTA Protocol subtree array
379 **/
380 static gint *const ett[] = {
381     &ett_jxta,
382     &ett_jxta_welcome,
383     &ett_jxta_udp,
384     &ett_jxta_framing,
385     &ett_jxta_framing_header,
386     &ett_jxta_msg,
387     &ett_jxta_msg_flags,
388     &ett_jxta_elem,
389     &ett_jxta_elem_1_flags,
390     &ett_jxta_elem_2_flags
391 };
392
393 /**
394 *   global preferences
395 **/
396 static gboolean gDESEGMENT = TRUE;
397 static gboolean gUDP_HEUR = TRUE;
398 static gboolean gTCP_HEUR = TRUE;
399 static gboolean gSCTP_HEUR = TRUE;
400 static gboolean gMSG_MEDIA = TRUE;
401
402 /**
403 *   Stream Conversation data
404 **/
405 struct jxta_stream_conversation_data {
406     port_type tpt_ptype;
407
408     address initiator_tpt_address;
409     guint32 initiator_tpt_port;
410     guint32 initiator_welcome_frame;
411     address initiator_address;
412
413     address receiver_tpt_address;
414     guint32 receiver_tpt_port;
415     guint32 receiver_welcome_frame;
416     address receiver_address;
417 };
418
419 typedef struct jxta_stream_conversation_data jxta_stream_conversation_data;
420
421 /**
422 *   Prototypes
423 **/
424 static gboolean dissect_jxta_UDP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree);
425 static gboolean dissect_jxta_TCP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree);
426 static gboolean dissect_jxta_SCTP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree);
427
428 static int dissect_jxta_udp(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree);
429 static int dissect_jxta_stream(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree);
430 static conversation_t *get_tpt_conversation(packet_info * pinfo, gboolean create);
431 static conversation_t *get_peer_conversation(packet_info * pinfo, jxta_stream_conversation_data* tpt_conv_data, gboolean create);
432
433 static int dissect_jxta_welcome(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, address * found_addr, gboolean initiator);
434 static int dissect_jxta_message_framing(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, guint64 * content_length,
435                                         gchar ** content_type);
436 static int dissect_jxta_message(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree);
437 static int dissect_jxta_message_element_1(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, guint ns_count,
438                                         const gchar ** namespaces);
439 static int dissect_jxta_message_element_2(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, guint ns_count,
440                                         const gchar ** namespaces);
441 static int dissect_media( const gchar* fullmediatype, tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree);
442
443 void proto_reg_handoff_jxta(void);
444
445 /**
446 *   Heuristically dissect a tvbuff containing a JXTA UDP Message
447 *
448 *   @param  tvb The buffer to dissect.
449 *   @param  pinfo Packet Info.
450 *   @param  tree The protocol tree.
451 *   @return TRUE if the tvb contained JXTA data which was dissected otherwise FALSE
452 **/
453 static gboolean dissect_jxta_UDP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
454 {
455     /* This is a heuristic dissector, which means we get all the UDP
456      * traffic not sent to a known dissector and not claimed by
457      * a heuristic dissector called before us!
458      */
459     int save_desegment_offset;
460     guint32 save_desegment_len;
461     int ret;
462
463     if (tvb_memeql(tvb, 0, JXTA_UDP_SIG, sizeof(JXTA_UDP_SIG)) != 0) {
464         return FALSE;
465     }
466
467     save_desegment_offset = pinfo->desegment_offset;
468     save_desegment_len = pinfo->desegment_len;
469     ret = dissect_jxta_udp(tvb, pinfo, tree);
470
471     /* g_message( "%d Heuristic UDP Dissection : %d", pinfo->fd->num, ret ); */
472
473     if (ret < 0) {
474         /*
475          * UDP is not a packet stream protocol, so the UDP dissector
476          * should not, and will not, do the sort of dissection help
477          * that the TCP dissector will.  If JXTA messages don't
478          * start and end on UDP packet boundaries, the JXTA dissector
479          * will have to do its own byte stream reassembly.
480          */
481         pinfo->desegment_offset = save_desegment_offset;
482         pinfo->desegment_len = save_desegment_len;
483         return FALSE;
484     } else if (ret == 0) {
485         /*
486          * A clear rejection.
487          */
488         pinfo->desegment_offset = save_desegment_offset;
489         pinfo->desegment_len = save_desegment_len;
490         return FALSE;
491     } else {
492         /*
493          * A clear acceptance.
494          */
495         return TRUE;
496     }
497 }
498
499 /**
500 *   Heuristically dissect a tvbuff containing a JXTA TCP Stream
501 *
502 *   @param  tvb The buffer to dissect.
503 *   @param  pinfo Packet Info.
504 *   @param  tree The protocol tree.
505 *   @return TRUE if the tvb contained JXTA data which was dissected otherwise FALSE
506 **/
507 static gboolean dissect_jxta_TCP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
508 {
509     /* This is a heuristic dissector, which means we get all the TCP
510      * traffic not sent to a known dissector and not claimed by
511      * a heuristic dissector called before us!
512      */
513     int save_desegment_offset;
514     guint32 save_desegment_len;
515     int ret;
516
517     save_desegment_offset = pinfo->desegment_offset;
518     save_desegment_len = pinfo->desegment_len;
519     ret = dissect_jxta_stream(tvb, pinfo, tree);
520
521     /* g_message( "%d Heuristic TCP Dissection : %d", pinfo->fd->num, ret ); */
522
523     if (ret < 0) {
524         /*
525          * A heuristic dissector for a TCP-based protocol can reject
526          * a packet, or it can request that more data be provided.
527          * It must not attempt to do both, as the notion of doing both
528          * is nonsensical - if the packet isn't considered a packet
529          * for the dissector's protocol, that dissector won't be
530          * dissecting it no matter *how* much more data is added.
531          *
532          * Therefore, we treat a negative return from
533          * dissect_jxta_stream() as a rejection.
534          *
535          * If that's not desired - i.e., if we should keep trying to get
536          * more data, in the hopes that we'll eventually be able to
537          * determine whether the packet is a JXTA packet or not - we
538          * should, in this case, leave pinfo->desegment_offset and
539          * pinfo->desegment_len alone, and return TRUE, *NOT* FALSE.
540          */
541         pinfo->desegment_offset = save_desegment_offset;
542         pinfo->desegment_len = save_desegment_len;
543         return FALSE;
544     } else if (ret == 0) {
545         /*
546          * A clear rejection.
547          */
548         pinfo->desegment_offset = save_desegment_offset;
549         pinfo->desegment_len = save_desegment_len;
550         return FALSE;
551     } else {
552         /*
553          * A clear acceptance.
554          */
555         return TRUE;
556     }
557 }
558
559 /**
560 *   Heuristically dissect a tvbuff containing a JXTA SCTP Stream
561 *
562 *   @param  tvb The buffer to dissect.
563 *   @param  pinfo Packet Info.
564 *   @param  tree The protocol tree.
565 *   @return TRUE if the tvb contained JXTA data which was dissected otherwise FALSE
566 **/
567 static gboolean dissect_jxta_SCTP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
568 {
569     /* This is a heuristic dissector, which means we get all the SCTP
570      * traffic not sent to a known dissector and not claimed by
571      * a heuristic dissector called before us!
572      */
573     int save_desegment_offset;
574     guint32 save_desegment_len;
575     int ret;
576
577     save_desegment_offset = pinfo->desegment_offset;
578     save_desegment_len = pinfo->desegment_len;
579     ret = dissect_jxta_stream(tvb, pinfo, tree);
580
581     /* g_message( "%d Heuristic SCTP Dissection : %d", pinfo->fd->num, ret ); */
582
583     if (ret < 0) {
584         /*
585          * SCTP is not a byte stream protocol, so the SCTP dissector
586          * should not, and will not, do the sort of dissection help
587          * that the SCTP dissector will.  If JXTA messages don't
588          * start and end on SCTP packet boundaries, the JXTA dissector
589          * will have to do its own byte stream reassembly.
590          *
591          * The SCTP dissector currently won't do reassembly.  If that
592          * causes a problem for the JXTA dissector, the correct fix
593          * is to implement reassembly in the SCTP dissector, so *all*
594          * dissectors for protocols running atop SCTP can benefit from
595          * it.
596          */
597         pinfo->desegment_offset = save_desegment_offset;
598         pinfo->desegment_len = save_desegment_len;
599         return FALSE;
600     } else if (ret == 0) {
601         /*
602          * A clear rejection.
603          */
604         pinfo->desegment_offset = save_desegment_offset;
605         pinfo->desegment_len = save_desegment_len;
606         return FALSE;
607     } else {
608         /*
609          * A clear acceptance.
610          */
611         return TRUE;
612     }
613 }
614
615 /**
616 *   Dissect a tvbuff containing a JXTA UDP header, JXTA Message framing and a JXTA Message
617 *
618 *   @param  tvb The buffer to dissect.
619 *   @param  pinfo Packet Info.
620 *   @param  tree The protocol tree.
621 *   @return Number of bytes from the tvbuff_t which were processed, 0 (zero) if
622 *           the packet was not recognized as a JXTA packet and negative if the
623 *           dissector needs more bytes in order to process a PDU.
624 **/
625 static int dissect_jxta_udp(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
626 {
627     guint offset = 0;
628     guint available;
629     gint needed = 0;
630
631     conversation_t *conversation =
632         find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
633
634     if (conversation == NULL) {
635         /*
636          * No conversation exists yet - create one.
637          */
638         conversation =
639             conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
640     }
641
642     DISSECTOR_ASSERT(find_dissector("jxta.udp"));
643
644     conversation_set_dissector(conversation, find_dissector("jxta.udp"));
645
646     while (TRUE) {
647         tvbuff_t *jxta_message_framing_tvb;
648         gint processed = 0;
649         guint64 content_length = -1;
650         gchar *content_type = NULL;
651
652         available = tvb_reported_length_remaining(tvb, offset);
653         if (available < sizeof(JXTA_UDP_SIG)) {
654             needed = (gint) (sizeof(JXTA_UDP_SIG) - available);
655             break;
656         }
657
658         if (tvb_memeql(tvb, offset, JXTA_UDP_SIG, sizeof(JXTA_UDP_SIG)) != 0) {
659             /* not ours */
660             return 0;
661         }
662
663         offset += sizeof(JXTA_UDP_SIG);
664
665         jxta_message_framing_tvb = tvb_new_subset(tvb, offset, -1, -1);
666         processed = dissect_jxta_message_framing(jxta_message_framing_tvb, pinfo, NULL, &content_length, &content_type);
667
668         if ((0 == processed) || (NULL == content_type) || (content_length <= 0) || (content_length > UINT_MAX)) {
669             /** Buffer did not begin with valid framing headers */
670             return 0;
671         }
672
673         if (processed < 0) {
674             needed = -processed;
675             break;
676         }
677
678         offset += processed;
679
680         available = tvb_reported_length_remaining(tvb, offset);
681         if (available < content_length) {
682             needed = (gint) (content_length - available);
683             break;
684         }
685
686         offset += (guint) content_length;
687
688         break;
689     }
690
691     if ((needed > 0) && gDESEGMENT && pinfo->can_desegment) {
692         /* g_message( "UDP requesting %d more bytes", needed ); */
693         pinfo->desegment_offset = 0;
694         pinfo->desegment_len = needed;
695         return -needed;
696     }
697
698     if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
699         col_set_str(pinfo->cinfo, COL_PROTOCOL, "JXTA");
700     }
701
702     if (tree) {
703         guint tree_offset = 0;
704         proto_item *jxta_tree_item =
705             proto_tree_add_protocol_format(tree, proto_jxta, tvb, offset, -1, "JXTA" );
706         proto_tree *jxta_tree = proto_item_add_subtree(jxta_tree_item, ett_jxta);
707         proto_item *jxta_udp_tree_item =
708             proto_tree_add_none_format(jxta_tree, hf_jxta_udp, tvb, tree_offset, -1, "JXTA UDP Message");
709         proto_tree *jxta_udp_tree = proto_item_add_subtree(jxta_udp_tree_item, ett_jxta_udp);
710         tvbuff_t *jxta_message_framing_tvb;
711         guint64 content_length = -1;
712         gchar *content_type = NULL;
713         tvbuff_t *jxta_message_tvb;
714
715         proto_tree_add_item(jxta_udp_tree, hf_jxta_udpsig, tvb, tree_offset, sizeof(JXTA_UDP_SIG), FALSE);
716         tree_offset += sizeof(JXTA_UDP_SIG);
717
718         jxta_message_framing_tvb = tvb_new_subset(tvb, tree_offset, -1, -1);
719
720         tree_offset += dissect_jxta_message_framing(jxta_message_framing_tvb, pinfo, jxta_tree, &content_length, &content_type);
721
722         jxta_message_tvb = tvb_new_subset(tvb, tree_offset, (gint) content_length, (gint) content_length);
723
724         tree_offset += dissect_media(content_type, jxta_message_tvb, pinfo, tree);
725
726         proto_item_set_end(jxta_udp_tree_item, tvb, tree_offset);
727
728         DISSECTOR_ASSERT(offset == tree_offset);
729     }
730
731     return offset;
732 }
733
734 /**
735 *   Dissect a tvbuff containing JXTA stream PDUs. This commonly includes
736 *   connections over TCP sockets.
737 *
738 *   <p/>The stream (in both directions) will consist of a JXTA Welcome Message
739 *   followed by an indeterminate number of JXTA Message Framing Headers and
740 *   JXTA Messages.
741 *
742 *   @param  tvb The buffer to dissect.
743 *   @param  pinfo Packet Info.
744 *   @param  tree The protocol tree.
745 *   @return Number of bytes from the tvbuff_t which were processed, 0 (zero) if
746 *           the packet was not recognized as a JXTA packet and negative if the
747 *           dissector needs more bytes in order to process a PDU.
748 **/
749 static int dissect_jxta_stream(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
750 {
751     guint offset = 0;
752     guint available = tvb_reported_length_remaining(tvb, offset);
753     gint processed = 0;
754     gint needed = 0;
755     conversation_t *tpt_conversation = NULL;
756     jxta_stream_conversation_data *tpt_conv_data = NULL;
757     proto_item *jxta_tree_item = NULL;
758     proto_tree *jxta_tree = NULL;
759
760     /* g_message("Dissecting%s : %d", (NULL != tree) ? " for display" : "", pinfo->fd->num ); */
761
762     if (available < sizeof(JXTA_WELCOME_MSG_SIG)) {
763         needed = (gint) (sizeof(JXTA_WELCOME_MSG_SIG) - available);
764         goto Common_Exit;
765     }
766
767     if (0 == tvb_memeql(tvb, 0, JXTA_WELCOME_MSG_SIG, sizeof(JXTA_WELCOME_MSG_SIG))) {
768         /* The beginning of a JXTA stream connection */
769         address *welcome_addr;
770         gboolean initiator = FALSE;
771
772         tpt_conversation = get_tpt_conversation(pinfo, TRUE);
773         tpt_conv_data = (jxta_stream_conversation_data *) conversation_get_proto_data(tpt_conversation, proto_jxta);
774
775         if (0 == tpt_conv_data->initiator_welcome_frame) {
776             /* The initiator welcome frame */
777             tpt_conv_data->tpt_ptype = pinfo->ptype;
778             tpt_conv_data->initiator_welcome_frame = pinfo->fd->num;
779             SE_COPY_ADDRESS(&tpt_conv_data->initiator_tpt_address, &pinfo->src);
780             tpt_conv_data->initiator_tpt_port = pinfo->srcport;
781
782             welcome_addr = &tpt_conv_data->initiator_address;
783             initiator = TRUE;
784         } else {
785             if (tpt_conv_data->initiator_welcome_frame >= pinfo->fd->num) {
786                 /* what we saw previously was the receiver welcome message */
787                 tpt_conv_data->receiver_welcome_frame = tpt_conv_data->initiator_welcome_frame;
788                 tpt_conv_data->receiver_tpt_address = tpt_conv_data->initiator_tpt_address;
789                 tpt_conv_data->receiver_tpt_port = tpt_conv_data->initiator_tpt_port;
790                 tpt_conv_data->receiver_address = tpt_conv_data->initiator_address;
791                 tpt_conv_data->initiator_welcome_frame = pinfo->fd->num;
792                 SE_COPY_ADDRESS(&tpt_conv_data->initiator_tpt_address, &pinfo->src);
793                 tpt_conv_data->initiator_tpt_port = pinfo->srcport;
794
795                 welcome_addr = &tpt_conv_data->initiator_address;
796                 initiator = TRUE;
797             } else {
798                 /* The receiver welcome frame */
799                 tpt_conv_data->tpt_ptype = pinfo->ptype;
800                 tpt_conv_data->receiver_welcome_frame = pinfo->fd->num;
801                 SE_COPY_ADDRESS(&tpt_conv_data->receiver_tpt_address, &pinfo->src);
802                 tpt_conv_data->receiver_tpt_port = pinfo->srcport;
803
804                 welcome_addr = &tpt_conv_data->receiver_address;
805                 initiator = FALSE;
806             }
807         }
808
809         processed = dissect_jxta_welcome(tvb, pinfo, NULL, welcome_addr, initiator);
810
811         if( processed < 0 ) {
812             needed = -processed;
813             goto Common_Exit;
814         }
815
816         /* redo, this time creating the display tree. */
817         jxta_tree_item = proto_tree_add_protocol_format(tree, proto_jxta, tvb, offset, -1, "JXTA" );
818         jxta_tree = proto_item_add_subtree(jxta_tree_item, ett_jxta);
819
820         processed = dissect_jxta_welcome(tvb, pinfo, jxta_tree, welcome_addr, initiator);
821     } else {
822         /* Somewhere in the middle of a JXTA stream connection */
823         gint64 content_length = -1L;
824         gchar *content_type = NULL;
825         gint headers_len = dissect_jxta_message_framing(tvb, pinfo, NULL, (guint64*) &content_length, &content_type);
826
827         if ((0 == headers_len) || (NULL == content_type) || (content_length <= 0) || (content_length > UINT_MAX)) {
828             /** Buffer did not begin with valid framing headers */
829             return 0;
830         }
831
832         /* g_message("%d Tpt %s:%d -> %s:%d tvb len=%d\n\t%s %d", pinfo->fd->num,
833                   address_to_str(&pinfo->src), pinfo->srcport,
834                   address_to_str(&pinfo->dst), pinfo->destport,
835                   tvb_reported_length_remaining(tvb, 0),
836                   content_type ? content_type : "[unknown content type]", (gint) content_length); */
837
838         if (headers_len < 0) {
839             /* negative headers_len means we need more bytes */
840             needed = -headers_len;
841             goto Common_Exit;
842         }
843
844         available = tvb_reported_length_remaining(tvb, offset + headers_len);
845         if (available >= content_length) {
846             tvbuff_t *jxta_message_tvb = tvb_new_subset(tvb, offset + headers_len, (gint) content_length, (gint) content_length);
847             conversation_t *peer_conversation = NULL;
848
849             jxta_tree_item = proto_tree_add_protocol_format(tree, proto_jxta, tvb, offset, -1, "JXTA" );
850             jxta_tree = proto_item_add_subtree(jxta_tree_item, ett_jxta);
851
852             /* Redo header processing, this time populating the tree. */
853             headers_len = dissect_jxta_message_framing(tvb, pinfo, jxta_tree, &content_length, &content_type);
854
855             tpt_conversation = get_tpt_conversation(pinfo, TRUE);
856
857             if (NULL != tpt_conversation) {
858                 tpt_conv_data = (jxta_stream_conversation_data *) conversation_get_proto_data(tpt_conversation, proto_jxta);
859                 if (tpt_conv_data) {
860                   peer_conversation = get_peer_conversation(pinfo, tpt_conv_data, TRUE);
861                 }
862             }
863
864             /* Use our source and destination addresses if we have them */
865             if (NULL != peer_conversation) {
866                 /* g_message("%d Tpt %s:%d -> %s:%d", pinfo->fd->num,
867                           address_to_str(&tpt_conv_data->initiator_tpt_address), tpt_conv_data->initiator_tpt_port,
868                           address_to_str(&tpt_conv_data->receiver_tpt_address), tpt_conv_data->receiver_tpt_port); */
869
870                 if (ADDRESSES_EQUAL(&pinfo->src, &tpt_conv_data->initiator_tpt_address)
871                     && tpt_conv_data->initiator_tpt_port == pinfo->srcport) {
872                     /* g_message("%d From initiator : %s -> %s ", pinfo->fd->num,
873                               address_to_str(&tpt_conv_data->initiator_address),
874                               address_to_str(&tpt_conv_data->receiver_address)); */
875                     pinfo->src = tpt_conv_data->initiator_address;
876                     pinfo->srcport = 0;
877                     pinfo->dst = tpt_conv_data->receiver_address;
878                     pinfo->destport = 0;
879                     pinfo->ptype = PT_NONE;
880                 } else if (ADDRESSES_EQUAL(&pinfo->src, &tpt_conv_data->receiver_tpt_address) &&
881                            tpt_conv_data->receiver_tpt_port == pinfo->srcport) {
882                     /* g_message("%d From receiver : %s -> %s ", pinfo->fd->num,
883                               address_to_str(&tpt_conv_data->receiver_address),
884                               address_to_str(&tpt_conv_data->initiator_address)); */
885                     pinfo->src = tpt_conv_data->receiver_address;
886                     pinfo->srcport = 0;
887                     pinfo->dst = tpt_conv_data->initiator_address;
888                     pinfo->destport = 0;
889                     pinfo->ptype = PT_NONE;
890                 } else {
891                     /* g_message("%d Nothing matches %s:%d -> %s:%d", pinfo->fd->num,
892                               address_to_str(&pinfo->src), pinfo->srcport,
893                               address_to_str(&pinfo->dst), pinfo->destport); */
894                 }
895             }
896
897             processed = headers_len;
898
899             processed += dissect_media(content_type, jxta_message_tvb, pinfo, tree);
900         } else {
901             /* we need more bytes before we can process message body. */
902             needed = (gint) ((guint) content_length - available);
903             goto Common_Exit;
904         }
905     }
906
907     offset += processed;
908
909 Common_Exit:
910     if ((needed > 0) && gDESEGMENT && pinfo->can_desegment) {
911         /* g_message( "Stream requesting %d more bytes", needed ); */
912         pinfo->desegment_offset = offset;
913         pinfo->desegment_len = needed;
914         return -needed;
915     }
916
917     return offset;
918 }
919
920 /**
921 *   Find or possibly create a transport conversation object for the connection
922 *   which is associated with the packet info.
923 *
924 *   @param pinfo  The packet info from the underlying transport.
925 *   @param create If TRUE then create a new conversation object if necessary.
926 **/
927 static conversation_t *get_tpt_conversation(packet_info * pinfo, gboolean create)
928 {
929     conversation_t *tpt_conversation =
930         find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
931     jxta_stream_conversation_data *tpt_conv_data;
932
933     if (tpt_conversation == NULL) {
934         if (!create) {
935             return NULL;
936         }
937
938         /*
939          * No conversation exists yet - create one.
940          */
941         tpt_conversation =
942             conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
943     }
944
945     conversation_set_dissector(tpt_conversation, stream_jxta_handle);
946
947     tpt_conv_data = (jxta_stream_conversation_data *) conversation_get_proto_data(tpt_conversation, proto_jxta);
948
949     if (NULL == tpt_conv_data) {
950         tpt_conv_data = se_alloc(sizeof(jxta_stream_conversation_data));
951         tpt_conv_data->tpt_ptype = pinfo->ptype;
952
953         SE_COPY_ADDRESS(&tpt_conv_data->initiator_tpt_address, &pinfo->src);
954         tpt_conv_data->initiator_tpt_port = pinfo->srcport;
955         tpt_conv_data->initiator_welcome_frame = 0;
956         tpt_conv_data->initiator_address.type = AT_NONE;
957         tpt_conv_data->initiator_address.len = 0;
958         tpt_conv_data->initiator_address.data = NULL;
959
960         SE_COPY_ADDRESS(&tpt_conv_data->receiver_tpt_address, &pinfo->dst);
961         tpt_conv_data->receiver_tpt_port = pinfo->destport;
962         tpt_conv_data->receiver_welcome_frame = 0;
963         tpt_conv_data->receiver_address.type = AT_NONE;
964         tpt_conv_data->receiver_address.len = 0;
965         tpt_conv_data->receiver_address.data = NULL;
966
967         conversation_add_proto_data(tpt_conversation, proto_jxta, tpt_conv_data);
968     }
969
970     return tpt_conversation;
971 }
972
973 /**
974 *   Find or possibly create a peer conversation object for the connection
975 *   which is associated with the packet info.
976 *
977 *   @param tpt_conv_data  The transport conversation from which we will locate the peer conversation.
978 *   @param create If TRUE then create a new conversation object if necessary.
979 **/
980 static conversation_t *get_peer_conversation(packet_info * pinfo, jxta_stream_conversation_data* tpt_conv_data, gboolean create)
981 {
982     conversation_t * peer_conversation = NULL;
983
984      if ((AT_NONE != tpt_conv_data->initiator_address.type) && (AT_NONE != tpt_conv_data->receiver_address.type)) {
985          peer_conversation = find_conversation(pinfo->fd->num, &tpt_conv_data->initiator_address, &tpt_conv_data->receiver_address,
986                                                PT_NONE, 0, 0, NO_PORT_B);
987
988          if (create && (NULL == peer_conversation)) {
989              peer_conversation = conversation_new(pinfo->fd->num, &tpt_conv_data->initiator_address,
990                                                   &tpt_conv_data->receiver_address, PT_NONE, 0, 0, NO_PORT_B);
991              conversation_set_dissector(peer_conversation, stream_jxta_handle);
992          }
993
994      } else {
995          g_warning("Uninitialized peer conversation");
996      }
997
998     return peer_conversation;
999 }
1000
1001 /**
1002 *   Dissect a tvbuff containing a JXTA Welcome Message
1003 *
1004 *   @param  tvb The buffer to dissect.
1005 *   @param  pinfo Packet Info.
1006 *   @param  tree The protocol tree.
1007 *   @param  found_addr The address found in the welcome message.
1008 *   @param  initiator If TRUE then we believe this welcome message to be the initiator's.
1009 *   @return Number of bytes from the tvbuff_t which were processed, 0 (zero) if
1010 *           the packet was not recognized as a JXTA packet and negative if the
1011 *           dissector needs more bytes in order to process a PDU.
1012 **/
1013 static int dissect_jxta_welcome(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, address * found_addr, gboolean initiator)
1014 {
1015     guint offset = 0;
1016     gint afterwelcome;
1017     gint first_linelen;
1018     guint available = tvb_reported_length_remaining(tvb, offset);
1019     gchar **tokens = NULL;
1020
1021     if (available < sizeof(JXTA_WELCOME_MSG_SIG)) {
1022         return (gint) (available - sizeof(JXTA_WELCOME_MSG_SIG));
1023     }
1024
1025     if (0 != tvb_memeql(tvb, 0, JXTA_WELCOME_MSG_SIG, sizeof(JXTA_WELCOME_MSG_SIG))) {
1026         /* not ours! */
1027         return 0;
1028     }
1029
1030     first_linelen = tvb_find_line_end(tvb, offset, -1, &afterwelcome, gDESEGMENT && pinfo->can_desegment);
1031
1032     if (-1 == first_linelen) {
1033         if (available > 4096) {
1034             /* it's too far too be reasonable */
1035             return 0;
1036         } else {
1037             /* ask for more bytes */
1038             return -1;
1039         }
1040     }
1041
1042     /* Dissect the Welcome Message */
1043
1044     if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
1045         col_set_str(pinfo->cinfo, COL_PROTOCOL, "JXTA");
1046     }
1047
1048     if (check_col(pinfo->cinfo, COL_INFO)) {
1049         col_set_str(pinfo->cinfo, COL_INFO, "Welcome");
1050     }
1051
1052     {
1053         gchar *welcomeline = tvb_get_ephemeral_string(tvb, offset, first_linelen);
1054         gchar **current_token;
1055         guint token_offset = offset;
1056         proto_item *jxta_welcome_tree_item = NULL;
1057         proto_tree *jxta_welcome_tree = NULL;
1058
1059         tokens = g_strsplit(welcomeline, " ", 255);
1060         current_token = tokens;
1061
1062         if (tree) {
1063             jxta_welcome_tree_item =
1064                 proto_tree_add_none_format(tree, hf_jxta_welcome, tvb, offset, afterwelcome,
1065                                            "JXTA Connection Welcome Message, %s", welcomeline);
1066             jxta_welcome_tree = proto_item_add_subtree(jxta_welcome_tree_item, ett_jxta_welcome);
1067         }
1068
1069         if (jxta_welcome_tree) {
1070             proto_item *jxta_welcome_initiator_item =
1071                 proto_tree_add_boolean(jxta_welcome_tree, hf_jxta_welcome_initiator, tvb, 0, 0, initiator);
1072             PROTO_ITEM_SET_GENERATED(jxta_welcome_initiator_item);
1073         }
1074
1075         if (NULL != *current_token) {
1076             if (jxta_welcome_tree) {
1077                 proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_sig, tvb, token_offset, strlen(*current_token), FALSE);
1078             }
1079
1080             token_offset += strlen(*current_token) + 1;
1081             current_token++;
1082         } else {
1083             /* invalid welcome message */
1084             afterwelcome = 0;
1085             goto Common_Exit;
1086         }
1087
1088         if (NULL != *current_token) {
1089             if (jxta_welcome_tree) {
1090                 proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_destAddr, tvb, token_offset, strlen(*current_token),
1091                                     FALSE);
1092             }
1093
1094             token_offset += strlen(*current_token) + 1;
1095             current_token++;
1096         } else {
1097             /* invalid welcome message */
1098             afterwelcome = 0;
1099             goto Common_Exit;
1100         }
1101
1102         if (NULL != *current_token) {
1103             if (jxta_welcome_tree) {
1104                 proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_pubAddr, tvb, token_offset, strlen(*current_token), FALSE);
1105             }
1106
1107             token_offset += strlen(*current_token) + 1;
1108             current_token++;
1109         } else {
1110             /* invalid welcome message */
1111             afterwelcome = 0;
1112             goto Common_Exit;
1113         }
1114
1115         if (NULL != *current_token) {
1116             if (jxta_welcome_tree) {
1117                 proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_peerid, tvb, token_offset, strlen(*current_token), FALSE);
1118             }
1119
1120             if (check_col(pinfo->cinfo, COL_INFO)) {
1121                 col_append_str(pinfo->cinfo, COL_INFO, (initiator ? " -> " : " <- ") );
1122                 col_append_str(pinfo->cinfo, COL_INFO, *current_token);
1123             }
1124
1125             if (NULL != found_addr) {
1126                 found_addr->type = AT_URI;
1127                 found_addr->len = strlen(*current_token);
1128                 found_addr->data = se_strdup(*current_token);
1129             }
1130
1131             token_offset += strlen(*current_token) + 1;
1132             current_token++;
1133         } else {
1134             /* invalid welcome message */
1135             afterwelcome = 0;
1136             goto Common_Exit;
1137         }
1138
1139         if (NULL != *current_token) {
1140             int variable_tokens = 0;
1141             gchar **variable_token = current_token;
1142
1143             while(NULL != *variable_token) {
1144                 variable_tokens++;
1145                 variable_token++;
1146             }
1147
1148             if( variable_tokens < 1 ) {
1149               /* invalid welcome message */
1150               afterwelcome = 0;
1151               goto Common_Exit;
1152             }
1153
1154             if( (2 == variable_tokens) && (0 == strcmp(JXTA_WELCOME_MSG_VERSION_1_1, current_token[variable_tokens -1])) ) {
1155                   if (jxta_welcome_tree) {
1156                       proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_noProp, tvb, token_offset, strlen(*current_token), FALSE);
1157                   }
1158
1159                   token_offset += strlen(*current_token) + 1;
1160                   current_token++;
1161
1162                   if (jxta_welcome_tree) {
1163                       proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_version, tvb, token_offset, strlen(*current_token), FALSE);
1164                   }
1165             } else if( (3 == variable_tokens) && (0 == strcmp(JXTA_WELCOME_MSG_VERSION_3_0, current_token[variable_tokens -1])) ) {
1166                   if (jxta_welcome_tree) {
1167                       proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_noProp, tvb, token_offset, strlen(*current_token), FALSE);
1168                   }
1169
1170                   token_offset += strlen(*current_token) + 1;
1171                   current_token++;
1172
1173                   if (jxta_welcome_tree) {
1174                       proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_msgVers, tvb, token_offset, strlen(*current_token), FALSE);
1175                   }
1176
1177                   token_offset += strlen(*current_token) + 1;
1178                   current_token++;
1179
1180                   if (jxta_welcome_tree) {
1181                       proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_version, tvb, token_offset, strlen(*current_token), FALSE);
1182                   }
1183             } else {
1184                 /* Unrecognized Welcome Version */
1185                 int each_variable_token;
1186
1187                 for( each_variable_token = 0; each_variable_token < variable_tokens; each_variable_token++ ) {
1188                   if (jxta_welcome_tree) {
1189                       jxta_welcome_tree_item = proto_tree_add_item(jxta_welcome_tree,
1190                         (each_variable_token < (variable_tokens -1) ? hf_jxta_welcome_variable : hf_jxta_welcome_version),
1191                         tvb, token_offset, strlen(*current_token), FALSE);
1192
1193                         proto_item_append_text(jxta_welcome_tree_item, " (UNRECOGNIZED)");
1194                   }
1195
1196                   token_offset += strlen(*current_token) + 1;
1197                   current_token++;
1198                 }
1199             }
1200         } else {
1201             /* invalid welcome message */
1202             afterwelcome = 0;
1203             goto Common_Exit;
1204         }
1205     }
1206
1207 Common_Exit:
1208     g_strfreev(tokens);
1209
1210     col_set_writable(pinfo->cinfo, FALSE);
1211
1212     return afterwelcome;
1213 }
1214
1215 /**
1216 *   Dissect a tvbuff containing JXTA Message framing.
1217 *
1218 *   @param  tvb The buffer to dissect.
1219 *   @param  pinfo Packet Info.
1220 *   @param  tree The protocol tree.
1221 *   @param  content_length Pointer to a buffer for storing the value of the
1222 *           "content-length" header or NULL.
1223 *   @param  content_type Pointer-to-a-pointer for a new buffer for storing the
1224 *           value of the "content_type-length" header or NULL.
1225 *   @return Number of bytes from the tvbuff_t which were processed, 0 (zero) if
1226 *           the packet was not recognized as a JXTA packet and negative if the
1227 *           dissector needs more bytes in order to process a PDU.
1228 **/
1229 static int dissect_jxta_message_framing(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, guint64 * content_length,
1230                                         gchar ** content_type)
1231 {
1232     guint offset = 0;
1233     guint available;
1234     gint needed = 0;
1235
1236     /*
1237      *   First go around. Make sure all of the bytes are there.
1238      */
1239     do {
1240         guint8 headername_len;
1241         guint8 headername_offset;
1242         guint16 headervalue_len;
1243         guint16 headervalue_offset;
1244
1245         available = tvb_reported_length_remaining(tvb, offset);
1246         if (available < sizeof(guint8)) {
1247             needed = (gint) (sizeof(guint8) - available);
1248             break;
1249         } else {
1250             headername_len = tvb_get_guint8(tvb, offset);
1251             offset += sizeof(guint8);
1252             headername_offset = offset;
1253
1254             available = tvb_reported_length_remaining(tvb, offset);
1255             if (available < headername_len) {
1256                 needed = (gint) (headername_len - available);
1257                 break;
1258             }
1259
1260             if (0 == headername_len) {
1261                 break;
1262             }
1263             offset += headername_len;
1264         }
1265
1266         available = tvb_reported_length_remaining(tvb, offset);
1267         if (available < sizeof(guint16)) {
1268             needed = (gint) (sizeof(guint16) - available);
1269             break;
1270         } else {
1271             headervalue_len = tvb_get_ntohs(tvb, offset);
1272             offset += sizeof(guint16);
1273             headervalue_offset = offset;
1274
1275             available = tvb_reported_length_remaining(tvb, offset);
1276             if (available < headervalue_len) {
1277                 needed = (gint) (headervalue_len - available);
1278                 break;
1279             }
1280
1281             offset += headervalue_len;
1282         }
1283
1284         if (content_type && (sizeof("content-type") - 1) == headername_len) {
1285             if (0 == tvb_strncaseeql(tvb, headername_offset, "content-type", sizeof("content-type") - 1)) {
1286                 *content_type = tvb_get_ephemeral_string(tvb, headervalue_offset, headervalue_len);
1287             }
1288         }
1289
1290
1291         if (content_length && (sizeof(guint64) == headervalue_len) && ((sizeof("content-length") - 1) == headername_len)) {
1292             if (0 == tvb_strncaseeql(tvb, headername_offset, "content-length", sizeof("content-length") - 1)) {
1293                 *content_length = tvb_get_ntoh64(tvb, headervalue_offset);
1294             }
1295         }
1296     } while (TRUE);
1297
1298     if ((needed > 0) && gDESEGMENT && pinfo->can_desegment) {
1299         /* g_message( "Framing requesting %d more bytes", needed ); */
1300         pinfo->desegment_offset = 0;
1301         pinfo->desegment_len = needed;
1302         return -needed;
1303     }
1304
1305     /*
1306      *   Second (optional pass) Now that we are sure that all the bytes are there we update the protocol tree.
1307      */
1308     if (tree) {
1309         guint tree_offset = 0;
1310         proto_item *framing_tree_item =
1311             proto_tree_add_none_format(tree, hf_jxta_framing, tvb, tree_offset, -1, "JXTA Message Framing Headers");
1312         proto_tree *framing_tree = proto_item_add_subtree(framing_tree_item, ett_jxta_framing);
1313
1314         /* parse framing headers */
1315         do {
1316             guint8 headernamelen = tvb_get_guint8(tvb, tree_offset);
1317             proto_item *framing_header_tree_item =
1318                 proto_tree_add_item(framing_tree, hf_jxta_framing_header, tvb, tree_offset, -1, FALSE);
1319             proto_tree *framing_header_tree = proto_item_add_subtree(framing_header_tree_item, ett_jxta_framing_header);
1320
1321             /*
1322              *   Put header name into the protocol tree
1323              */
1324             proto_tree_add_item(framing_header_tree, hf_jxta_framing_header_name, tvb, tree_offset, 1, headernamelen);
1325
1326             /*
1327              *   Append header name into the header protocol item. It's a nice hint so you don't have to reveal all headers.
1328              */
1329             if (headernamelen > 0) {
1330                 proto_item_append_text(framing_header_tree_item, " \"%s\"",
1331                                        tvb_format_text(tvb, tree_offset + sizeof(guint8), headernamelen));
1332             }
1333
1334             tree_offset += sizeof(guint8) + headernamelen;
1335
1336             if (headernamelen > 0) {
1337                 guint16 headervaluelen = tvb_get_ntohs(tvb, tree_offset);
1338
1339                 if (tree) {
1340                     proto_tree_add_uint(framing_header_tree, hf_jxta_framing_header_value_length, tvb, tree_offset,
1341                                         sizeof(guint16), headervaluelen);
1342
1343                     /** TODO bondolo Add specific handling for known header types */
1344
1345                     /*
1346                      * Put header value into protocol tree.
1347                      */
1348                     proto_tree_add_item(framing_header_tree, hf_jxta_framing_header_value, tvb, tree_offset + sizeof(guint16),
1349                                         headervaluelen, FALSE);
1350                 }
1351
1352                 tree_offset += sizeof(guint16) + headervaluelen;
1353             }
1354
1355             proto_item_set_end(framing_header_tree_item, tvb, tree_offset);
1356
1357             if (0 == headernamelen) {
1358                 break;
1359             }
1360         } while (TRUE);
1361
1362         proto_item_set_end(framing_tree_item, tvb, tree_offset);
1363
1364         DISSECTOR_ASSERT(offset == tree_offset);
1365     }
1366
1367     /* return how many bytes we used up. */
1368     return offset;
1369 }
1370
1371 /**
1372 *   Dissect a tvbuff containing one or more JXTA Messages.
1373 *
1374 *   @param  tvb The buffer to dissect.
1375 *   @param  pinfo Packet Info.
1376 *   @param  tree The protocol tree.
1377 *   @return Number of bytes from the tvbuff_t which were processed, 0 (zero) if
1378 *           the packet was not recognized as a JXTA packet and negative if the
1379 *           dissector needs more bytes in order to process a PDU.
1380 **/
1381 static int dissect_jxta_message(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
1382 {
1383     gint complete_messages = 0;
1384     guint offset = 0;
1385     guint tree_offset = 0;
1386     guint available;
1387     gint needed = 0;
1388     gchar* src_addr;
1389     gchar* dst_addr;
1390
1391     while (TRUE) {
1392         guint8 message_version;
1393         guint message_start_offset = offset;
1394
1395         /* First pass. Make sure all of the bytes we need are available */
1396         available = tvb_reported_length_remaining(tvb, offset);
1397
1398         if((0 == available) && (0 != complete_messages)) {
1399             /* We have discovered all of the complete messages in the tvbuff. */
1400             break;
1401         }
1402
1403         if (available < sizeof(JXTA_MSG_SIG)) {
1404             needed = (gint) (sizeof(JXTA_MSG_SIG) - available);
1405             break;
1406         }
1407
1408         if (tvb_memeql(tvb, offset, JXTA_MSG_SIG, sizeof(JXTA_MSG_SIG)) != 0) {
1409             /* It is not one of ours */
1410             return 0;
1411         }
1412
1413         offset += sizeof(JXTA_MSG_SIG);
1414
1415         available = tvb_reported_length_remaining(tvb, offset);
1416         if (available < sizeof(guint8)) {
1417             needed = (gint) (sizeof(guint8) - available);
1418             break;
1419         } else {
1420             message_version = tvb_get_guint8(tvb, offset);
1421
1422             offset += sizeof(guint8);
1423
1424             if ((JXTA_MSG_VERSION_1 != message_version) && (JXTA_MSG_VERSION_2 != message_version)) {
1425                 /* Sort of a lie, we say that we don't recognize it at all. */
1426                 return 0;
1427             }
1428         }
1429
1430         /* Read the flags (Version 2 and later) */
1431         if(message_version > 0) {
1432             available = tvb_reported_length_remaining(tvb, offset);
1433             if (available < sizeof(guint8)) {
1434                 needed = (gint) (sizeof(guint8) - available);
1435                 break;
1436             } else {
1437                 offset += sizeof(guint8);
1438             }
1439         }
1440
1441         /* Read names table */
1442         available = tvb_reported_length_remaining(tvb, offset);
1443         if (available < sizeof(guint16)) {
1444             needed = (gint) (sizeof(guint16) - available);
1445             break;
1446         } else {
1447             guint16 msg_names_count = tvb_get_ntohs(tvb, offset);
1448             guint each_name;
1449
1450             offset += sizeof(guint16);
1451
1452             for (each_name = 0; each_name < msg_names_count; each_name++) {
1453                 guint16 name_len;
1454
1455                 available = tvb_reported_length_remaining(tvb, offset);
1456                 if (available < sizeof(name_len)) {
1457                     needed = (gint) (sizeof(name_len) - available);
1458                     break;
1459                 }
1460
1461                 name_len = tvb_get_ntohs(tvb, offset);
1462
1463                 available = tvb_reported_length_remaining(tvb, offset + sizeof(name_len));
1464                 if (available < name_len) {
1465                     needed = (gint) (name_len - available);
1466                     break;
1467                 }
1468
1469                 offset += sizeof(name_len) + name_len;
1470             }
1471         }
1472
1473         /* parse element count */
1474         available = tvb_reported_length_remaining(tvb, offset);
1475         if (available < sizeof(guint16)) {
1476             needed = (gint) (sizeof(guint16) - available);
1477             break;
1478         } else {
1479             guint16 elem_count = tvb_get_ntohs(tvb, offset);
1480             guint each_elem;
1481
1482             offset += sizeof(guint16);
1483
1484             /* parse elements */
1485             for (each_elem = 0; each_elem < elem_count; each_elem++) {
1486                 tvbuff_t *jxta_message_element_tvb = tvb_new_subset(tvb, offset, -1, -1);
1487                 int processed;
1488
1489                 if(JXTA_MSG_VERSION_1 == message_version) {
1490                     processed = dissect_jxta_message_element_1(jxta_message_element_tvb, pinfo, NULL, 0, NULL);
1491                 } else if(JXTA_MSG_VERSION_2 == message_version) {
1492                     processed = dissect_jxta_message_element_2(jxta_message_element_tvb, pinfo, NULL, 0, NULL);
1493                 } else {
1494                     /* Sort of a lie, we say that we don't recognize it at all. */
1495                     return 0;
1496                 }
1497
1498                 if (processed < 0) {
1499                     needed = -processed;
1500                     break;
1501                 }
1502
1503                 if (0 == processed) {
1504                     /* XXX bondolo Not really clear what we should do! */
1505                     g_warning( "Failure processing message element #%d of %d of frame %d", each_elem, elem_count, pinfo->fd->num );
1506                     return 0;
1507                 }
1508
1509                 offset += processed;
1510             }
1511         }
1512
1513         if ((AT_URI == pinfo->src.type) && (AT_URI == pinfo->dst.type)) {
1514             jxta_tap_header *tap_header = se_alloc(sizeof(jxta_tap_header));
1515
1516             tap_header->src_address = pinfo->src;
1517             tap_header->dest_address = pinfo->dst;
1518             tap_header->size = offset - message_start_offset ;
1519
1520             tap_queue_packet(jxta_tap, pinfo, tap_header);
1521         }
1522
1523         complete_messages++;
1524
1525         /* g_message( "%d Scanned message #%d: ", pinfo->fd->num, complete_messages ); */
1526     }
1527
1528     if ((needed > 0) && gDESEGMENT && pinfo->can_desegment) {
1529         /* g_message( "Message requesting %d more bytes", needed ); */
1530         pinfo->desegment_offset = 0;
1531         pinfo->desegment_len = needed;
1532         return -needed;
1533     }
1534
1535     src_addr = address_to_str(&pinfo->src);
1536     dst_addr = address_to_str(&pinfo->dst);
1537
1538     /* append the port if appropriate */
1539     if (PT_NONE != pinfo->ptype) {
1540         size_t len = strlen(src_addr);
1541         src_addr[len] = ':';
1542         g_snprintf(&src_addr[len + 1], MAX_ADDR_STR_LEN - len - 1, "%d", pinfo->srcport);
1543
1544         len = strlen(dst_addr);
1545         dst_addr[len] = ':';
1546         g_snprintf(&dst_addr[len + 1], MAX_ADDR_STR_LEN - len - 1, "%d", pinfo->destport);
1547     }
1548
1549     if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
1550         col_set_str(pinfo->cinfo, COL_PROTOCOL, "JXTA");
1551     }
1552
1553     if (check_col(pinfo->cinfo, COL_INFO)) {
1554         if( complete_messages > 1 ) {
1555             col_add_fstr(pinfo->cinfo, COL_INFO, "%d Messages, %s -> %s", complete_messages, src_addr, dst_addr);
1556         } else {
1557             col_add_fstr(pinfo->cinfo, COL_INFO, "Message, %s -> %s", src_addr, dst_addr);
1558         }
1559
1560         col_set_writable(pinfo->cinfo, FALSE);
1561     }
1562
1563     while( tree && (complete_messages > 0) ) {
1564         proto_item *jxta_msg_tree_item = NULL;
1565         proto_tree *jxta_msg_tree = NULL;
1566         guint8 message_version;
1567         const gchar **names_table = NULL;
1568         guint16 msg_names_count;
1569         guint each_name;
1570         guint16 elem_count;
1571         guint each_elem;
1572         proto_item *tree_item;
1573
1574         jxta_msg_tree_item = proto_tree_add_protocol_format(tree, proto_message_jxta, tvb, tree_offset, -1,
1575                                                             "JXTA Message, %s -> %s", src_addr, dst_addr);
1576
1577         jxta_msg_tree = proto_item_add_subtree(jxta_msg_tree_item, ett_jxta_msg);
1578
1579         proto_tree_add_item(jxta_msg_tree, hf_jxta_message_sig, tvb, tree_offset, sizeof(JXTA_MSG_SIG), FALSE);
1580         tree_offset += sizeof(JXTA_MSG_SIG);
1581
1582         tree_item = proto_tree_add_string(jxta_msg_tree, hf_jxta_message_src, tvb, 0, 0, src_addr);
1583         PROTO_ITEM_SET_GENERATED(tree_item);
1584
1585         tree_item = proto_tree_add_string(jxta_msg_tree, hf_jxta_message_address, tvb, 0, 0, src_addr);
1586         PROTO_ITEM_SET_HIDDEN(tree_item);
1587         PROTO_ITEM_SET_GENERATED(tree_item);
1588
1589         if(AT_URI == pinfo->src.type) {
1590             tree_item = proto_tree_add_string(jxta_msg_tree, hf_uri_src, tvb, 0, 0, src_addr);
1591             PROTO_ITEM_SET_HIDDEN(tree_item);
1592             PROTO_ITEM_SET_GENERATED(tree_item);
1593             tree_item = proto_tree_add_string(jxta_msg_tree, hf_uri_addr, tvb, 0, 0, src_addr);
1594             PROTO_ITEM_SET_HIDDEN(tree_item);
1595             PROTO_ITEM_SET_GENERATED(tree_item);
1596         }
1597
1598         tree_item = proto_tree_add_string(jxta_msg_tree, hf_jxta_message_dst, tvb, 0, 0, dst_addr);
1599         PROTO_ITEM_SET_GENERATED(tree_item);
1600
1601         tree_item = proto_tree_add_string(jxta_msg_tree, hf_jxta_message_address, tvb, 0, 0, dst_addr);
1602         PROTO_ITEM_SET_HIDDEN(tree_item);
1603         PROTO_ITEM_SET_GENERATED(tree_item);
1604
1605         if(AT_URI == pinfo->dst.type) {
1606             tree_item = proto_tree_add_string(jxta_msg_tree, hf_uri_dst, tvb, 0, 0, src_addr);
1607             PROTO_ITEM_SET_HIDDEN(tree_item);
1608             PROTO_ITEM_SET_GENERATED(tree_item);
1609             tree_item = proto_tree_add_string(jxta_msg_tree, hf_uri_addr, tvb, 0, 0, dst_addr);
1610             PROTO_ITEM_SET_HIDDEN(tree_item);
1611             PROTO_ITEM_SET_GENERATED(tree_item);
1612         }
1613
1614         message_version = tvb_get_guint8(tvb, tree_offset);
1615         proto_tree_add_uint(jxta_msg_tree, hf_jxta_message_version, tvb, tree_offset, sizeof(guint8), message_version);
1616         tree_offset += sizeof(guint8);
1617
1618         if( message_version > 0 ) {
1619             guint8 flags = tvb_get_guint8(tvb, tree_offset);
1620             proto_item *flags_ti = proto_tree_add_uint(jxta_msg_tree, hf_jxta_message_flags, tvb, tree_offset, sizeof(guint8), flags);
1621             proto_tree *jxta_msg_flags_tree = proto_item_add_subtree(flags_ti, ett_jxta_msg_flags);
1622             proto_tree_add_boolean(jxta_msg_flags_tree, hf_jxta_message_flag_utf16be, tvb, tree_offset, 1, flags);
1623             proto_tree_add_boolean(jxta_msg_flags_tree, hf_jxta_message_flag_ucs32be, tvb, tree_offset, 1, flags);
1624             tree_offset += sizeof(guint8);
1625         }
1626
1627         msg_names_count = tvb_get_ntohs(tvb, tree_offset);
1628         proto_tree_add_uint(jxta_msg_tree, hf_jxta_message_names_count, tvb, tree_offset, sizeof(guint16), msg_names_count);
1629         tree_offset += sizeof(guint16);
1630
1631         names_table = ep_alloc((msg_names_count + 2) * sizeof(const gchar *));
1632         names_table[0] = "";
1633         names_table[1] = "jxta";
1634
1635         /* parse names */
1636         for (each_name = 0; each_name < msg_names_count; each_name++) {
1637             guint16 name_len = tvb_get_ntohs(tvb, tree_offset);
1638
1639             names_table[2 + each_name] = tvb_get_ephemeral_string(tvb, tree_offset + sizeof(name_len), name_len);
1640             proto_tree_add_item(jxta_msg_tree, hf_jxta_message_names_name, tvb, tree_offset, sizeof(name_len), FALSE);
1641             tree_offset += sizeof(name_len) + name_len;
1642         }
1643
1644         /* parse element count */
1645         elem_count = tvb_get_ntohs(tvb, tree_offset);
1646         proto_tree_add_item(jxta_msg_tree, hf_jxta_message_element_count, tvb, tree_offset, sizeof(guint16), FALSE);
1647         tree_offset += sizeof(guint16);
1648
1649         /* FIXME bondolo Element count 0 (Process elements until FIN) should be supported. */
1650
1651         /* parse elements */
1652         for (each_elem = 0; each_elem < elem_count; each_elem++) {
1653             tvbuff_t *jxta_message_element_tvb = tvb_new_subset(tvb, tree_offset, -1, -1);
1654
1655             if(JXTA_MSG_VERSION_1 == message_version) {
1656                 tree_offset +=
1657                     dissect_jxta_message_element_1(jxta_message_element_tvb, pinfo, jxta_msg_tree, msg_names_count + 2, names_table);
1658             } else if(JXTA_MSG_VERSION_2 == message_version) {
1659                 tree_offset +=
1660                     dissect_jxta_message_element_2(jxta_message_element_tvb, pinfo, jxta_msg_tree, msg_names_count + 2, names_table);
1661             } else {
1662                 /* Sort of a lie, we say that we don't recognize it at all. */
1663                 return 0;
1664             }
1665        }
1666
1667        proto_item_set_end(jxta_msg_tree_item, tvb, tree_offset);
1668
1669        complete_messages--;
1670     }
1671
1672     if( tree ) {
1673         /* g_message( "%d tvb offset : %d  tree offset : %d", pinfo->fd->num, offset, tree_offset ); */
1674         DISSECTOR_ASSERT(tree_offset == offset);
1675     }
1676
1677     return offset;
1678 }
1679
1680 /**
1681 *   Dissect a tvbuff containing a JXTA Message Element (Version 1).
1682 *
1683 *   @param  tvb The buffer to dissect.
1684 *   @param  pinfo Packet Info.
1685 *   @param  tree The protocol tree.
1686 *   @return Number of bytes from the tvbuff_t which were processed, 0 (zero) if
1687 *           the packet was not recognized as a JXTA packet and negative if the
1688 *           dissector needs more bytes in order to process a PDU.
1689 **/
1690 static int dissect_jxta_message_element_1(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, guint ns_count,
1691                                         const gchar ** names_table)
1692 {
1693     guint offset = 0;
1694     guint available;
1695     gint needed = 0;
1696     guint8 flags;
1697
1698     /* First pass. Make sure all of the bytes we need are available */
1699
1700     while (TRUE) {
1701         /* signature field */
1702         available = tvb_reported_length_remaining(tvb, offset);
1703         if (available < sizeof(JXTA_MSGELEM_SIG)) {
1704             needed = (gint) (sizeof(JXTA_MSGELEM_SIG) - available);
1705         }
1706
1707         if (tvb_memeql(tvb, offset, JXTA_MSGELEM_SIG, sizeof(JXTA_MSGELEM_SIG)) != 0) {
1708             /* It is not one of ours */
1709             return 0;
1710         }
1711
1712         offset += sizeof(JXTA_MSGELEM_SIG);
1713
1714         /* namespace id field */
1715         available = tvb_reported_length_remaining(tvb, offset);
1716         if (available < sizeof(guint8)) {
1717             needed = (gint) (sizeof(guint8) - available);
1718             break;
1719         }
1720
1721         offset += sizeof(guint8);
1722
1723         /* flags field */
1724         available = tvb_reported_length_remaining(tvb, offset);
1725         if (available < sizeof(guint8)) {
1726             needed = (gint) (sizeof(guint8) - available);
1727             break;
1728         } else {
1729             flags = tvb_get_guint8(tvb, offset);
1730             offset += sizeof(guint8);
1731         }
1732
1733         /* name field */
1734         available = tvb_reported_length_remaining(tvb, offset);
1735         if (available < sizeof(guint16)) {
1736             needed = (gint) (sizeof(guint16) - available);
1737             break;
1738         } else {
1739             guint16 name_len = tvb_get_ntohs(tvb, offset);
1740             offset += sizeof(guint16);
1741
1742             available = tvb_reported_length_remaining(tvb, offset);
1743             if (available < name_len) {
1744                 needed = (gint) (name_len - available);
1745                 break;
1746             }
1747
1748             offset += name_len;
1749         }
1750
1751         /* type field */
1752         if ((flags & JXTAMSG1_ELMFLAG_TYPE) != 0) {
1753             guint16 type_len;
1754
1755             available = tvb_reported_length_remaining(tvb, offset);
1756             if (available < sizeof(guint16)) {
1757                 needed = (gint) (sizeof(guint16) - available);
1758                 break;
1759             }
1760
1761             type_len = tvb_get_ntohs(tvb, offset);
1762             offset += sizeof(guint16);
1763
1764             available = tvb_reported_length_remaining(tvb, offset);
1765             if (available < type_len) {
1766                 needed = (gint) (type_len - available);
1767                 break;
1768             }
1769
1770             offset += type_len;
1771         }
1772
1773         /* encoding field */
1774         if ((flags & JXTAMSG1_ELMFLAG_ENCODING) != 0) {
1775             guint16 encoding_len;
1776
1777             available = tvb_reported_length_remaining(tvb, offset);
1778             if (available < sizeof(guint16)) {
1779                 needed = (gint) (sizeof(guint16) - available);
1780                 break;
1781             }
1782
1783             encoding_len = tvb_get_ntohs(tvb, offset);
1784             offset += sizeof(guint16);
1785
1786             available = tvb_reported_length_remaining(tvb, offset);
1787             if (available < encoding_len) {
1788                 needed = (gint) (encoding_len - available);
1789                 break;
1790             }
1791
1792             offset += encoding_len;
1793         }
1794
1795         /* content field */
1796         available = tvb_reported_length_remaining(tvb, offset);
1797         if (available < sizeof(guint16)) {
1798             needed = (gint) (sizeof(guint16) - available);
1799             break;
1800         } else {
1801             guint32 content_len = tvb_get_ntohl(tvb, offset);
1802             offset += sizeof(guint32);
1803
1804             available = tvb_reported_length_remaining(tvb, offset);
1805             if (available < content_len) {
1806                 needed = (gint) (content_len - available);
1807                 break;
1808             }
1809
1810             offset += content_len;
1811         }
1812
1813         /* signature element field */
1814         if ((flags & JXTAMSG1_ELMFLAG_SIGNATURE) != 0) {
1815             tvbuff_t *jxta_signature_element_tvb;
1816             int processed;
1817
1818             jxta_signature_element_tvb = tvb_new_subset(tvb, offset, -1, -1);
1819
1820             processed = dissect_jxta_message_element_1(jxta_signature_element_tvb, pinfo, NULL, 0, NULL);
1821
1822             if (processed == 0) {
1823                 return offset;
1824             }
1825
1826             if (processed < 0) {
1827                 needed = -processed;
1828                 break;
1829             }
1830
1831             offset += processed;
1832         }
1833
1834         break;
1835     }
1836
1837     if ((needed > 0) && gDESEGMENT && pinfo->can_desegment) {
1838         /* g_message( "Element1 requesting %d more bytes", needed ); */
1839         pinfo->desegment_offset = 0;
1840         pinfo->desegment_len = needed;
1841         return -needed;
1842     }
1843
1844     /* Second (optional) pass : build the proto tree */
1845     if (tree) {
1846         guint tree_offset = 0;
1847         proto_item *jxta_elem_tree_item = proto_tree_add_item(tree, hf_jxta_element, tvb, tree_offset, -1, FALSE);
1848         proto_tree *jxta_elem_tree = proto_item_add_subtree(jxta_elem_tree_item, ett_jxta_elem);
1849         guint8 namespaceID;
1850         proto_item *namespace_ti;
1851         guint16 name_len;
1852         proto_item *flags_ti;
1853         proto_tree *jxta_elem_flags_tree = NULL;
1854         guint32 content_len;
1855         gchar *mediatype = NULL;
1856         tvbuff_t *element_content_tvb;
1857         proto_item * jxta_elem_length_item = NULL;
1858
1859         proto_tree_add_item(jxta_elem_tree, hf_jxta_element_sig, tvb, tree_offset, sizeof(JXTA_MSGELEM_SIG), FALSE);
1860         tree_offset += sizeof(JXTA_MSGELEM_SIG);
1861
1862         namespaceID = tvb_get_guint8(tvb, tree_offset);
1863         namespace_ti =
1864             proto_tree_add_uint(jxta_elem_tree, hf_jxta_element1_namespaceid, tvb, tree_offset, sizeof(guint8), namespaceID);
1865         if (namespaceID < ns_count) {
1866             proto_item_append_text(namespace_ti, " (%s)", names_table[namespaceID]);
1867         } else {
1868             proto_item_append_text(namespace_ti, " * BAD *");
1869         }
1870         tree_offset += sizeof(guint8);
1871
1872         flags = tvb_get_guint8(tvb, tree_offset);
1873         flags_ti = proto_tree_add_uint(jxta_elem_tree, hf_jxta_element_flags, tvb, tree_offset, sizeof(guint8), flags);
1874         jxta_elem_flags_tree = proto_item_add_subtree(flags_ti, ett_jxta_elem_1_flags);
1875         proto_tree_add_boolean(jxta_elem_flags_tree, hf_jxta_element1_flag_hasType, tvb, tree_offset, 1, flags);
1876         proto_tree_add_boolean(jxta_elem_flags_tree, hf_jxta_element1_flag_hasEncoding, tvb, tree_offset, 1, flags);
1877         proto_tree_add_boolean(jxta_elem_flags_tree, hf_jxta_element1_flag_hasSignature, tvb, tree_offset, 1, flags);
1878         tree_offset += sizeof(guint8);
1879
1880         name_len = tvb_get_ntohs(tvb, tree_offset);
1881         proto_item_append_text(jxta_elem_tree_item, " \"%s\"", tvb_format_text(tvb, tree_offset + sizeof(guint16), name_len));
1882         proto_tree_add_item(jxta_elem_tree, hf_jxta_element_name, tvb, tree_offset, sizeof(guint16), FALSE);
1883         tree_offset += sizeof(guint16) + name_len;
1884
1885         /* process type */
1886         if ((flags & JXTAMSG1_ELMFLAG_TYPE) != 0) {
1887             guint16 type_len = tvb_get_ntohs(tvb, tree_offset);
1888             proto_tree_add_item(jxta_elem_tree, hf_jxta_element_type, tvb, tree_offset, sizeof(guint16), FALSE);
1889             tree_offset += sizeof(guint16);
1890
1891             mediatype = tvb_get_ephemeral_string(tvb, tree_offset, type_len);
1892
1893             tree_offset += type_len;
1894         }
1895
1896         /* process encoding */
1897         if ((flags & JXTAMSG1_ELMFLAG_ENCODING) != 0) {
1898             guint16 encoding_len = tvb_get_ntohs(tvb, tree_offset);
1899             proto_tree_add_item(jxta_elem_tree, hf_jxta_element_encoding, tvb, tree_offset, sizeof(guint16), FALSE);
1900             tree_offset += sizeof(guint16) + encoding_len;
1901         }
1902
1903         /* content */
1904         content_len = tvb_get_ntohl(tvb, tree_offset);
1905         jxta_elem_length_item = proto_tree_add_item(jxta_elem_tree, hf_jxta_element_content_len, tvb, tree_offset, sizeof(guint32), FALSE);
1906         tree_offset += sizeof(guint32);
1907
1908         element_content_tvb = tvb_new_subset(tvb, tree_offset, content_len, content_len);
1909
1910         tree_offset += dissect_media(mediatype, element_content_tvb, pinfo, jxta_elem_tree);
1911
1912         /* process the signature element */
1913         if ((flags & JXTAMSG1_ELMFLAG_SIGNATURE) != 0) {
1914             tvbuff_t *jxta_message_element_tvb = tvb_new_subset(tvb, tree_offset, -1, -1);
1915
1916             tree_offset += dissect_jxta_message_element_1(jxta_message_element_tvb, pinfo, jxta_elem_tree, ns_count, names_table);
1917         }
1918
1919         proto_item_set_end(jxta_elem_tree_item, tvb, tree_offset);
1920
1921         DISSECTOR_ASSERT(tree_offset == offset);
1922     }
1923
1924     return offset;
1925 }
1926
1927 /**
1928 *   Dissect a tvbuff containing a JXTA Message Element (Version 2).
1929 *
1930 *   @param  tvb The buffer to dissect.
1931 *   @param  pinfo Packet Info.
1932 *   @param  tree The protocol tree.
1933 *   @param  names_count The number of elements in the names table.
1934 *   @param  names The table of names.
1935 *   @return Number of bytes from the tvbuff_t which were processed, 0 (zero) if
1936 *           the packet was not recognized as a JXTA packet and negative if the
1937 *           dissector needs more bytes in order to process a PDU.
1938 **/
1939 static int dissect_jxta_message_element_2(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, guint names_count,
1940                                         const gchar ** names_table)
1941 {
1942     guint offset = 0;
1943     guint available;
1944     gint needed = 0;
1945     guint8 flags;
1946
1947     /* First pass. Make sure all of the bytes we need are available */
1948
1949     while (TRUE) {
1950         /* signature field */
1951         available = tvb_reported_length_remaining(tvb, offset);
1952         if (available < sizeof(JXTA_MSGELEM_SIG)) {
1953             needed = (gint) (sizeof(JXTA_MSGELEM_SIG) - available);
1954         }
1955
1956         if (tvb_memeql(tvb, offset, JXTA_MSGELEM_SIG, sizeof(JXTA_MSGELEM_SIG)) != 0) {
1957             /* It is not one of ours */
1958             return 0;
1959         }
1960
1961         offset += sizeof(JXTA_MSGELEM_SIG);
1962
1963         /* flags field */
1964         available = tvb_reported_length_remaining(tvb, offset);
1965         if (available < sizeof(guint8)) {
1966             needed = (gint) (sizeof(guint8) - available);
1967             break;
1968         } else {
1969             flags = tvb_get_guint8(tvb, offset);
1970             offset += sizeof(guint8);
1971         }
1972
1973         /* namespace id field */
1974         available = tvb_reported_length_remaining(tvb, offset);
1975         if (available < sizeof(guint16)) {
1976             needed = (gint) (sizeof(guint16) - available);
1977             break;
1978         }
1979
1980         offset += sizeof(guint16);
1981
1982         /* name field */
1983         if ((flags & JXTAMSG2_ELMFLAG_NAME_LITERAL) == 0) {
1984             available = tvb_reported_length_remaining(tvb, offset);
1985             if (available < sizeof(guint16)) {
1986                 needed = (gint) (sizeof(guint16) - available);
1987                 break;
1988             }
1989
1990             offset += sizeof(guint16);
1991         } else {
1992             /* literal name field */
1993             available = tvb_reported_length_remaining(tvb, offset);
1994             if (available < sizeof(guint16)) {
1995                 needed = (gint) (sizeof(guint16) - available);
1996                 break;
1997             } else {
1998                 guint16 name_len = tvb_get_ntohs(tvb, offset);
1999                 offset += sizeof(guint16);
2000
2001                 available = tvb_reported_length_remaining(tvb, offset);
2002                 if (available < name_len) {
2003                     needed = (gint) (name_len - available);
2004                     break;
2005                 }
2006
2007                 offset += name_len;
2008             }
2009         }
2010
2011         /* type field */
2012         if ((flags & JXTAMSG2_ELMFLAG_TYPE) != 0) {
2013             available = tvb_reported_length_remaining(tvb, offset);
2014             if (available < sizeof(guint16)) {
2015                 needed = (gint) (sizeof(guint16) - available);
2016                 break;
2017             }
2018
2019             offset += sizeof(guint16);
2020         }
2021
2022         /* encoding field */
2023         if ((flags & JXTAMSG2_ELMFLAG_ENCODINGS) != 0) {
2024             available = tvb_reported_length_remaining(tvb, offset);
2025             if (available < sizeof(guint16)) {
2026                 needed = (gint) (sizeof(guint16) - available);
2027                 break;
2028             }
2029
2030             offset += sizeof(guint16);
2031         }
2032
2033
2034         /* content field */
2035         if ((flags & JXTAMSG2_ELMFLAG_UINT64_LENS) != 0) {
2036             available = tvb_reported_length_remaining(tvb, offset);
2037             if (available < sizeof(guint64)) {
2038                 needed = (gint) (sizeof(guint64) - available);
2039                 break;
2040             } else {
2041                 guint64 content_len = tvb_get_ntoh64(tvb, offset);
2042                 offset += sizeof(guint64);
2043
2044                 available = tvb_reported_length_remaining(tvb, offset);
2045                 if (available < content_len) {
2046                     needed = (gint) (content_len - available);
2047                     break;
2048                 }
2049
2050                 offset += (guint) content_len;
2051             }
2052         } else {
2053             available = tvb_reported_length_remaining(tvb, offset);
2054             if (available < sizeof(guint32)) {
2055                 needed = (gint) (sizeof(guint32) - available);
2056                 break;
2057             } else {
2058                 guint64 content_len = tvb_get_ntohl(tvb, offset);
2059                 offset += sizeof(guint32);
2060
2061                 available = tvb_reported_length_remaining(tvb, offset);
2062                 if (available < content_len) {
2063                     needed = (gint) (content_len - available);
2064                     break;
2065                 }
2066
2067                 offset += (guint) content_len;
2068             }
2069         }
2070
2071         /* signature element field */
2072         if ((flags & JXTAMSG2_ELMFLAG_SIGNATURE) != 0) {
2073             tvbuff_t *jxta_signature_element_tvb;
2074             int processed;
2075
2076             jxta_signature_element_tvb = tvb_new_subset(tvb, offset, -1, -1);
2077
2078             processed = dissect_jxta_message_element_2(jxta_signature_element_tvb, pinfo, NULL, 0, NULL);
2079
2080             if (processed == 0) {
2081                 return offset;
2082             }
2083
2084             if (processed < 0) {
2085                 needed = -processed;
2086                 break;
2087             }
2088
2089             offset += processed;
2090         }
2091
2092         break;
2093     }
2094
2095     if ((needed > 0) && gDESEGMENT && pinfo->can_desegment) {
2096         /* g_message( "Element2 requesting %d more bytes", needed ); */
2097         pinfo->desegment_offset = 0;
2098         pinfo->desegment_len = needed;
2099         return -needed;
2100     }
2101
2102     /* Second (optional) pass : build the proto tree */
2103     if (tree) {
2104         guint tree_offset = 0;
2105         proto_item *jxta_elem_tree_item = proto_tree_add_item(tree, hf_jxta_element, tvb, tree_offset, -1, FALSE);
2106         proto_tree *jxta_elem_tree = proto_item_add_subtree(jxta_elem_tree_item, ett_jxta_elem);
2107         proto_item *flags_ti;
2108         proto_tree *jxta_elem_flags_tree = NULL;
2109         guint16 namespaceID;
2110         proto_item *namespace_ti;
2111         guint16 nameID;
2112         proto_item *name_ti;
2113         guint64 content_len;
2114         gchar *mediatype = NULL;
2115         tvbuff_t *element_content_tvb;
2116         proto_item * jxta_elem_length_item = NULL;
2117
2118         proto_tree_add_item(jxta_elem_tree, hf_jxta_element_sig, tvb, tree_offset, sizeof(JXTA_MSGELEM_SIG), FALSE);
2119         tree_offset += sizeof(JXTA_MSGELEM_SIG);
2120
2121         flags = tvb_get_guint8(tvb, tree_offset);
2122         flags_ti = proto_tree_add_uint(jxta_elem_tree, hf_jxta_element_flags, tvb, tree_offset, sizeof(guint8), flags);
2123         jxta_elem_flags_tree = proto_item_add_subtree(flags_ti, ett_jxta_elem_2_flags);
2124         proto_tree_add_boolean(jxta_elem_flags_tree, hf_jxta_element2_flag_64bitlens, tvb, tree_offset, 1, flags);
2125         proto_tree_add_boolean(jxta_elem_flags_tree, hf_jxta_element2_flag_nameLiteral, tvb, tree_offset, 1, flags);
2126         proto_tree_add_boolean(jxta_elem_flags_tree, hf_jxta_element2_flag_hasType, tvb, tree_offset, 1, flags);
2127         proto_tree_add_boolean(jxta_elem_flags_tree, hf_jxta_element2_flag_hasSignature, tvb, tree_offset, 1, flags);
2128         proto_tree_add_boolean(jxta_elem_flags_tree, hf_jxta_element2_flag_hasEncoding, tvb, tree_offset, 1, flags);
2129         proto_tree_add_boolean(jxta_elem_flags_tree, hf_jxta_element2_flag_sigOfEncoded, tvb, tree_offset, 1, flags);
2130         tree_offset += sizeof(guint8);
2131
2132         /* Namespace */
2133         namespaceID = tvb_get_ntohs(tvb, tree_offset);
2134         namespace_ti =
2135             proto_tree_add_uint(jxta_elem_tree, hf_jxta_element2_namespaceid, tvb, tree_offset, sizeof(guint16), namespaceID);
2136         if (namespaceID < names_count) {
2137             proto_item_append_text(namespace_ti, " (%s)", names_table[namespaceID]);
2138         } else {
2139             proto_item_append_text(namespace_ti, " * BAD *");
2140         }
2141         tree_offset += sizeof(guint16);
2142
2143         /* Name */
2144         if ((flags & JXTAMSG2_ELMFLAG_NAME_LITERAL) == 0) {
2145             nameID = tvb_get_ntohs(tvb, tree_offset);
2146             name_ti =
2147                 proto_tree_add_uint(jxta_elem_tree, hf_jxta_element2_nameid, tvb, tree_offset, sizeof(guint16), nameID);
2148             if (namespaceID < names_count) {
2149                 proto_item_append_text(name_ti, " (%s)", names_table[nameID]);
2150             } else {
2151                 proto_item_append_text(name_ti, " * BAD *");
2152             }
2153             tree_offset += sizeof(guint16);
2154         } else {
2155             /* literal name */
2156             guint16 name_len = tvb_get_ntohs(tvb, tree_offset);
2157             proto_item_append_text(jxta_elem_tree_item, " \"%s\"", tvb_format_text(tvb, tree_offset + sizeof(guint16), name_len));
2158             proto_tree_add_item(jxta_elem_tree, hf_jxta_element_name, tvb, tree_offset, sizeof(guint16), FALSE);
2159             tree_offset += sizeof(guint16) + name_len;
2160         }
2161
2162         /* process type */
2163         if ((flags & JXTAMSG2_ELMFLAG_TYPE) != 0) {
2164             guint16 mimeID = tvb_get_ntohs(tvb, tree_offset);
2165             proto_item *mime_ti =
2166                 proto_tree_add_uint(jxta_elem_tree, hf_jxta_element2_mimeid, tvb, tree_offset, sizeof(guint16), mimeID);
2167
2168             if (mimeID < names_count) {
2169                 proto_item_append_text(mime_ti, " (%s)", names_table[mimeID]);
2170                 mediatype = ep_strdup( names_table[mimeID] );
2171             } else {
2172                 proto_item_append_text(mime_ti, " * BAD *");
2173             }
2174
2175             tree_offset += sizeof(guint16);
2176         } else {
2177             mediatype = "application/octect-stream";
2178         }
2179
2180         /* process encoding */
2181         if ((flags & JXTAMSG2_ELMFLAG_ENCODINGS) != 0) {
2182             guint16 encodingID = tvb_get_ntohs(tvb, tree_offset);
2183             proto_item *encoding_ti =
2184                 proto_tree_add_uint(jxta_elem_tree, hf_jxta_element2_encodingid, tvb, tree_offset, sizeof(guint16), encodingID);
2185
2186             if (encodingID < names_count) {
2187                 proto_item_append_text(encoding_ti, " (%s)", names_table[encodingID]);
2188             } else {
2189                 proto_item_append_text(encoding_ti, " * BAD *");
2190             }
2191
2192             tree_offset += sizeof(guint16);
2193         }
2194
2195
2196         if ((flags & JXTAMSG2_ELMFLAG_UINT64_LENS) != 0) {
2197             content_len = tvb_get_ntoh64(tvb, tree_offset);
2198             jxta_elem_length_item = proto_tree_add_item(jxta_elem_tree, hf_jxta_element_content_len64, tvb, tree_offset, sizeof(guint64), FALSE);
2199             tree_offset += sizeof(guint64);
2200         } else {
2201             content_len = tvb_get_ntohl(tvb, tree_offset);
2202             jxta_elem_length_item = proto_tree_add_item(jxta_elem_tree, hf_jxta_element_content_len, tvb, tree_offset, sizeof(guint32), FALSE);
2203             tree_offset += sizeof(guint32);
2204         }
2205
2206         /* content */
2207         element_content_tvb = tvb_new_subset(tvb, tree_offset, (gint)content_len, (gint)content_len);
2208
2209         tree_offset += dissect_media(mediatype, element_content_tvb, pinfo, jxta_elem_tree);
2210
2211         /* process the signature element */
2212         if ((flags & JXTAMSG2_ELMFLAG_SIGNATURE) != 0) {
2213             tvbuff_t *jxta_message_element_tvb = tvb_new_subset(tvb, tree_offset, -1, -1);
2214
2215             tree_offset += dissect_jxta_message_element_1(jxta_message_element_tvb, pinfo, jxta_elem_tree, names_count, names_table);
2216         }
2217
2218         proto_item_set_end(jxta_elem_tree_item, tvb, tree_offset);
2219
2220         DISSECTOR_ASSERT(tree_offset == offset);
2221     }
2222
2223     return offset;
2224 }
2225
2226 /**
2227 *   Dissect a tvbuff containing arbitrary typed data.
2228 *
2229 *   <p/>We provide special handling for type media types :
2230 *   <dl>
2231 *       <dt>application/x-jxta-tls-block</dt>
2232 *       <dd>We hand this data off to SSL to dissect.</dd>
2233 *       <dt>application/gzip</dt>
2234 *       <dd>We decompress the data and then dissect the contents as <tt>text/xml;charset="UTF-8"</tt></dd>
2235 *   </dl>
2236 *
2237 *   @param  fullmediatype The full media type of the buffer to dissect including params
2238 *   @param  tvb The buffer to dissect.
2239 *   @param  pinfo Packet Info.
2240 *   @param  tree The protocol tree.
2241 *   @return Number of bytes from the tvbuff_t which were processed, 0 (zero) if
2242 *           the packet was not recognized and negative if the dissector needs
2243 *           more bytes in order to process a PDU.
2244 **/
2245 static int dissect_media( const gchar* fullmediatype, tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) {
2246     int dissected = 0;
2247
2248     if (fullmediatype) {
2249         gchar *mediatype = ep_strdup(fullmediatype);
2250         gchar *parms_at = strchr(mediatype, ';');
2251         const char *save_match_string = pinfo->match_string;
2252         void * save_private_data = pinfo->private_data;
2253
2254         /* Based upon what is done in packet-media.c we set up type and params */
2255         if (NULL != parms_at) {
2256             pinfo->private_data = ep_strdup( parms_at + 1 );
2257             *parms_at = '\0';
2258         } else {
2259             pinfo->private_data = NULL;
2260         }
2261
2262         /* Set the version that goes to packet-media.c before converting case */
2263         pinfo->match_string = ep_strdup(mediatype);
2264
2265         /* force to lower case */
2266 #if GLIB_MAJOR_VERSION < 2
2267         g_strdown(mediatype);
2268 #else
2269         {
2270             gchar *mediatype_lowercase = g_ascii_strdown(mediatype, -1);
2271             mediatype = ep_strdup(mediatype_lowercase);
2272             g_free(mediatype_lowercase);
2273         }
2274 #endif
2275
2276         if (0 == strcmp("application/x-jxta-tls-block", mediatype)) {
2277             /* If we recognize it as a TLS packet then we shuffle it off to ssl dissector. */
2278             dissector_handle_t ssl_handle = find_dissector("ssl");
2279             if (NULL != ssl_handle) {
2280                 dissected = call_dissector(ssl_handle, tvb, pinfo, tree);
2281             }
2282         } else if (0 == strcmp("application/gzip", mediatype)) {
2283             tvbuff_t *uncomp_tvb = tvb_uncompress(tvb, 0, tvb_length(tvb));
2284
2285             if( NULL != uncomp_tvb ) {
2286                 tvb_set_child_real_data_tvbuff(tvb, uncomp_tvb);
2287                 add_new_data_source(pinfo, uncomp_tvb, "Uncompressed Element Content");
2288
2289                 /* XXX bondolo 20060201 Force XML for uncompressed data. */
2290                 dissected = dissect_media("text/xml;charset=\"UTF-8\"", uncomp_tvb, pinfo, tree);
2291
2292                 if( dissected > 0 ) {
2293                     /* report back the uncompressed length. */
2294                     dissected = tvb_length(tvb);
2295                 }
2296             }
2297         } else {
2298             dissected = dissector_try_string(media_type_dissector_table, mediatype, tvb, pinfo, tree) ? tvb_length(tvb) : 0;
2299
2300             if( dissected != (int) tvb_length(tvb) ) {
2301                 /* g_message( "%s : %d expected, %d dissected", mediatype, tvb_length(tvb), dissected ); */
2302             }
2303         }
2304
2305         if (0 == dissected) {
2306             dissected = call_dissector(media_handle, tvb, pinfo, tree);
2307         }
2308
2309         pinfo->match_string = save_match_string;
2310         pinfo->private_data = save_private_data;
2311     }
2312
2313     if(0 == dissected) {
2314         /* display it as raw data */
2315         dissected = call_dissector_only(data_handle, tvb, pinfo, tree);
2316     }
2317
2318     return dissected;
2319 }
2320
2321 /**
2322 *    Register jxta protocol and jxta message protocol, header fields, subtree types, preferences.
2323 **/
2324 void proto_register_jxta(void)
2325 {
2326     module_t *jxta_module;
2327
2328     proto_jxta = proto_register_protocol("JXTA P2P", "JXTA", "jxta");
2329
2330     jxta_tap = register_tap("jxta");
2331
2332     proto_message_jxta = proto_register_protocol("JXTA Message", "JXTA Message", "jxta.message");
2333
2334     message_jxta_handle = new_create_dissector_handle(dissect_jxta_message, proto_message_jxta);
2335
2336     /* Register header fields */
2337     proto_register_field_array(proto_jxta, hf, array_length(hf));
2338
2339     /* Register JXTA Sub-tree */
2340     proto_register_subtree_array(ett, array_length(ett));
2341
2342     /* Register preferences */
2343     /* register re-init routine */
2344     jxta_module = prefs_register_protocol(proto_jxta, proto_reg_handoff_jxta);
2345
2346     prefs_register_bool_preference(jxta_module, "msg.mediatype", "Register binary JXTA Message as a media type",
2347                                    "Enable to have correctly typed MIME media dissected as JXTA Messages.", &gMSG_MEDIA);
2348
2349     prefs_register_bool_preference(jxta_module, "desegment",
2350                                    "Reassemble JXTA messages spanning multiple UDP/TCP/SCTP segments",
2351                                    "Whether the JXTA dissector should reassemble messages spanning multiple UDP/TCP/SCTP segments."
2352                                    " To use this option you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings "
2353                                    " and enable \"Reassemble fragmented IP datagrams\" in the IP protocol settings.",
2354                                    &gDESEGMENT);
2355
2356     prefs_register_bool_preference(jxta_module, "udp.heuristic", "Try to discover JXTA in UDP datagrams",
2357                                    "Enable to inspect UDP datagrams for JXTA messages.", &gUDP_HEUR);
2358
2359     prefs_register_bool_preference(jxta_module, "tcp.heuristic", "Try to discover JXTA in TCP connections",
2360                                    "Enable to inspect TCP connections for JXTA conversations.", &gTCP_HEUR);
2361
2362     prefs_register_bool_preference(jxta_module, "sctp.heuristic", "Try to discover JXTA in SCTP connections",
2363                                    "Enable to inspect SCTP connections for JXTA conversations.", &gSCTP_HEUR);
2364 }
2365
2366
2367 /**
2368 *   Update registrations in response to preferences changes.
2369 **/
2370 void proto_reg_handoff_jxta(void)
2371 {
2372     static gboolean init_done = FALSE;
2373
2374     static gboolean msg_media_register_done = FALSE;
2375
2376     static gboolean udp_register_done = FALSE;
2377     static gboolean tcp_register_done = FALSE;
2378     static gboolean sctp_register_done = FALSE;
2379
2380     if(!init_done) {
2381         media_type_dissector_table = find_dissector_table("media_type");
2382
2383         data_handle = find_dissector("data");
2384
2385         media_handle = find_dissector("media");
2386
2387         new_register_dissector("jxta.udp", dissect_jxta_udp, proto_jxta);
2388
2389         new_register_dissector("jxta.stream", dissect_jxta_stream, proto_jxta);
2390         stream_jxta_handle = find_dissector("jxta.stream");
2391
2392         init_done = TRUE;
2393         }
2394
2395     if( gMSG_MEDIA ) {
2396         if( !msg_media_register_done ) {
2397             /* g_message( "Registering JXTA Message media type" ); */
2398             dissector_add_string("media_type", "application/x-jxta-msg", message_jxta_handle);
2399             msg_media_register_done = TRUE;
2400             }
2401     } else {
2402         if( msg_media_register_done ) {
2403             /* g_message( "Deregistering JXTA Message media type" ); */
2404             dissector_delete_string("media_type", "application/x-jxta-msg", message_jxta_handle);
2405             msg_media_register_done = FALSE;
2406             }
2407     }
2408
2409     if( gUDP_HEUR ) {
2410         if( !udp_register_done ) {
2411             /* g_message( "Registering UDP Heuristic dissector" ); */
2412             heur_dissector_add("udp", dissect_jxta_UDP_heur, proto_jxta);
2413             udp_register_done = TRUE;
2414             }
2415     } else {
2416         if( udp_register_done ) {
2417             /* g_message( "Deregistering UDP Heuristic dissector" ); */
2418             heur_dissector_delete("udp", dissect_jxta_UDP_heur, proto_jxta);
2419             udp_register_done = FALSE;
2420             }
2421     }
2422
2423     if( gTCP_HEUR ) {
2424         if( !tcp_register_done ) {
2425             /* g_message( "Registering TCP Heuristic dissector" ); */
2426             heur_dissector_add("tcp", dissect_jxta_TCP_heur, proto_jxta);
2427             tcp_register_done = TRUE;
2428             }
2429     } else {
2430         if( tcp_register_done ) {
2431             /* g_message( "Deregistering TCP Heuristic dissector" ); */
2432             heur_dissector_delete("tcp", dissect_jxta_TCP_heur, proto_jxta);
2433             tcp_register_done = FALSE;
2434             }
2435     }
2436
2437     if( gSCTP_HEUR ) {
2438         if( !sctp_register_done ) {
2439             /* g_message( "Registering SCTP Heuristic dissector" ); */
2440             heur_dissector_add("sctp", dissect_jxta_SCTP_heur, proto_jxta);
2441             sctp_register_done = TRUE;
2442             }
2443     } else {
2444         if( sctp_register_done ) {
2445             /* g_message( "Deregistering SCTP Heuristic dissector" ); */
2446             heur_dissector_delete("sctp", dissect_jxta_SCTP_heur, proto_jxta);
2447             sctp_register_done = FALSE;
2448             }
2449     }
2450 }