From Sebastien Tandel:
[obnox/wireshark/wip.git] / epan / dissectors / packet-jxta.c
1 /* packet-jxta.c
2  * Routines for JXTA packet dissection
3  * Copyright 2004-06, Mike Duigou <bondolo@jxta.org>
4  * Heavily based on packet-jabber.c, which in turn is heavily based on
5  * on packet-acap.c, which in turn is heavily based on
6  * packet-imap.c, Copyright 1999, Richard Sharpe <rsharpe@ns.aus.com>
7  *
8  * $Id$
9  *
10  * Wireshark - Network traffic analyzer
11  * By Gerald Combs <gerald@wireshark.org>
12  * Copyright 1998 Gerald Combs
13  *
14  * Copied from packet-pop.c, packet-jabber.c, packet-udp.c
15  *
16  * JXTA specification from http://spec.jxta.org
17  *
18  * This program is free software; you can redistribute it and/or
19  * modify it under the terms of the GNU General Public License
20  * as published by the Free Software Foundation; either version 2
21  * of the License, or (at your option) any later version.
22  *
23  * This program is distributed in the hope that it will be useful,
24  * but WITHOUT ANY WARRANTY; without even the implied warranty of
25  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26  * GNU General Public License for more details.
27  *
28  * You should have received a copy of the GNU General Public License
29  * along with this program; if not, write to the Free Software
30  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
31  */
32
33 #ifdef HAVE_CONFIG_H
34 # include "config.h"
35 #endif
36
37 #include <limits.h>
38 #include <stdio.h>
39 #include <string.h>
40
41 #include <glib.h>
42
43 #include <epan/packet.h>
44 #include <epan/conversation.h>
45 #include <epan/strutil.h>
46 #include <epan/prefs.h>
47 #include <epan/tap.h>
48 #include <epan/emem.h>
49 #include <epan/ws_strsplit.h>
50
51 #include "packet-jxta.h"
52
53 static const gchar JXTA_UDP_SIG[] = { 'J', 'X', 'T', 'A' };
54 static const gchar JXTA_MSG_SIG[] = { 'j', 'x', 'm', 'g' };
55 static const gchar JXTA_MSGELEM_SIG[] = { 'j', 'x', 'e', 'l' };
56
57 static const gchar JXTA_WELCOME_MSG_SIG[] = { 'J', 'X', 'T', 'A', 'H', 'E', 'L', 'L', 'O', ' ' };
58
59 static const gchar* JXTA_WELCOME_MSG_VERSION_1_1 = "1.1";
60
61 static int proto_jxta = -1;
62 static int proto_message_jxta = -1;
63 static int jxta_tap = -1;
64
65 static dissector_table_t media_type_dissector_table = NULL;
66 static dissector_handle_t data_handle = NULL;
67 static dissector_handle_t stream_jxta_handle = NULL;
68 static dissector_handle_t message_jxta_handle;
69
70 static int hf_jxta_udp = -1;
71 static int hf_jxta_udpsig = -1;
72 static int hf_jxta_welcome = -1;
73 static int hf_jxta_welcome_initiator = -1;
74 static int hf_jxta_welcome_sig = -1;
75 static int hf_jxta_welcome_destAddr = -1;
76 static int hf_jxta_welcome_pubAddr = -1;
77 static int hf_jxta_welcome_peerid = -1;
78 static int hf_jxta_welcome_noProp = -1;
79 static int hf_jxta_welcome_variable = -1;
80 static int hf_jxta_welcome_version = -1;
81 static int hf_jxta_framing = -1;
82 static int hf_jxta_framing_header = -1;
83 static int hf_jxta_framing_header_name = -1;
84 static int hf_jxta_framing_header_value_length = -1;
85 static int hf_jxta_framing_header_value = -1;
86 static int hf_jxta_message_address = -1;
87 static int hf_jxta_message_src = -1;
88 static int hf_jxta_message_dst = -1;
89 static int hf_jxta_message_sig = -1;
90 static int hf_jxta_message_version = -1;
91 static int hf_jxta_message_namespaces_count = -1;
92 static int hf_jxta_message_namespace_name = -1;
93 static int hf_jxta_message_element_count = -1;
94 static int hf_jxta_element = -1;
95 static int hf_jxta_element_sig = -1;
96 static int hf_jxta_element_namespaceid = -1;
97 static int hf_jxta_element_flags = -1;
98 static int hf_jxta_element_flag_hasType = -1;
99 static int hf_jxta_element_flag_hasEncoding = -1;
100 static int hf_jxta_element_flag_hasSignature = -1;
101 static int hf_jxta_element_name = -1;
102 static int hf_jxta_element_type = -1;
103 static int hf_jxta_element_encoding = -1;
104 static int hf_jxta_element_content_len = -1;
105 static int hf_jxta_element_content = -1;
106
107 /** our header fields */
108 static hf_register_info hf[] = {
109     {&hf_jxta_udp,
110      {"JXTA UDP", "jxta.udp", FT_NONE, BASE_NONE, NULL, 0x0,
111       "JXTA UDP", HFILL}
112      },
113     {&hf_jxta_udpsig,
114      {"Signature", "jxta.udpsig", FT_STRING, BASE_NONE, NULL, 0x0,
115       "JXTA UDP Signature", HFILL}
116      },
117     {&hf_jxta_welcome,
118      {"Welcome", "jxta.welcome", FT_NONE, BASE_NONE, NULL, 0x00,
119       "JXTA Connection Welcome Message", HFILL}
120      },
121     {&hf_jxta_welcome_initiator,
122      {"Initiator", "jxta.welcome.initiator", FT_BOOLEAN, BASE_NONE, NULL, 0x00,
123       "JXTA Connection Welcome Message Initiator", HFILL}
124      },
125     {&hf_jxta_welcome_sig,
126      {"Signature", "jxta.welcome.signature", FT_STRING, BASE_NONE, NULL, 0x0,
127       "JXTA Connection Welcome Message Signature", HFILL}
128      },
129     {&hf_jxta_welcome_destAddr,
130      {"Destination Address", "jxta.welcome.destAddr", FT_STRING, BASE_NONE, NULL, 0x0,
131       "JXTA Connection Welcome Message Destination Address", HFILL}
132      },
133     {&hf_jxta_welcome_pubAddr,
134      {"Public Address", "jxta.welcome.pubAddr", FT_STRING, BASE_NONE, NULL, 0x0,
135       "JXTA Connection Welcome Message Public Address", HFILL}
136      },
137     {&hf_jxta_welcome_peerid,
138      {"PeerID", "jxta.welcome.peerid", FT_STRING, BASE_NONE, NULL, 0x0,
139       "JXTA Connection Welcome Message PeerID", HFILL}
140      },
141     {&hf_jxta_welcome_noProp,
142      {"No Propagate Flag", "jxta.welcome.noPropFlag", FT_STRING, BASE_NONE, NULL, 0x0,
143       "JXTA Connection Welcome Message No Propagate Flag", HFILL}
144      },
145     {&hf_jxta_welcome_variable,
146      {"Variable Parameter", "jxta.welcome.variable", FT_STRING, BASE_NONE, NULL, 0x0,
147       "JXTA Connection Welcome Message Variable Parameter", HFILL}
148      },
149     {&hf_jxta_welcome_version,
150      {"Version", "jxta.welcome.version", FT_STRING, BASE_NONE, NULL, 0x0,
151       "JXTA Connection Welcome Message Version", HFILL}
152      },
153     {&hf_jxta_framing,
154      {"Framing", "jxta.framing", FT_NONE, BASE_NONE, NULL, 0x0,
155       "JXTA Message Framing", HFILL}
156      },
157     {&hf_jxta_framing_header,
158      {"Header", "jxta.framing.header", FT_NONE, BASE_NONE, NULL, 0x0,
159       "JXTA Message Framing Header", HFILL}
160      },
161     {&hf_jxta_framing_header_name,
162      {"Name", "jxta.framing.header.name", FT_UINT_STRING, BASE_NONE, NULL, 0x0,
163       "JXTA Message Framing Header Name", HFILL}
164      },
165     {&hf_jxta_framing_header_value_length,
166      {"Value Length", "jxta.framing.header.valuelen", FT_UINT16, BASE_DEC, NULL, 0x0,
167       "JXTA Message Framing Header Value Length", HFILL}
168      },
169     {&hf_jxta_framing_header_value,
170      {"Value", "jxta.framing.header.value", FT_BYTES, BASE_HEX, NULL, 0x0,
171       "JXTA Message Framing Header Value", HFILL}
172      },
173     {&hf_jxta_message_address,
174      {"Address", "jxta.message.address", FT_STRING, BASE_NONE, NULL, 0x0,
175       "JXTA Message Address (source or destination)", HFILL}
176      },
177     {&hf_jxta_message_src,
178      {"Source", "jxta.message.source", FT_STRING, BASE_NONE, NULL, 0x0,
179       "JXTA Message Source", HFILL}
180      },
181     {&hf_jxta_message_dst,
182      {"Destination", "jxta.message.destination", FT_STRING, BASE_NONE, NULL, 0x0,
183       "JXTA Message Destination", HFILL}
184      },
185     {&hf_jxta_message_sig,
186      {"Signature", "jxta.message.signature", FT_STRING, BASE_NONE, NULL, 0x0,
187       "JXTA Message Signature", HFILL}
188      },
189     {&hf_jxta_message_version,
190      {"Version", "jxta.message.version", FT_UINT8, BASE_DEC, NULL, 0x0,
191       "JXTA Message Version", HFILL}
192      },
193     {&hf_jxta_message_namespaces_count,
194      {"Namespace Count", "jxta.message.namespaces", FT_UINT16, BASE_DEC, NULL, 0x0,
195       "JXTA Message Namespaces", HFILL}
196      },
197     {&hf_jxta_message_namespace_name,
198      {"Namespace Name", "jxta.message.namespace.name", FT_UINT_STRING, BASE_NONE, NULL, 0x0,
199       "JXTA Message Namespace Name", HFILL}
200      },
201     {&hf_jxta_message_element_count,
202      {"Element Count", "jxta.message.elements", FT_UINT16, BASE_DEC, NULL, 0x0,
203       "JXTA Message Element Count", HFILL}
204      },
205     {&hf_jxta_element,
206      {"JXTA Message Element", "jxta.message.element", FT_NONE, BASE_NONE, NULL, 0x0,
207       "JXTA Message Element", HFILL}
208      },
209     {&hf_jxta_element_sig,
210      {"Signature", "jxta.message.element.signature", FT_STRING, BASE_NONE, NULL, 0x0,
211       "JXTA Message Element Signature", HFILL}
212      },
213     {&hf_jxta_element_namespaceid,
214      {"Namespace ID", "jxta.message.element.namespaceid", FT_UINT8, BASE_DEC, NULL, 0x0,
215       "JXTA Message Element Namespace ID", HFILL}
216      },
217     {&hf_jxta_element_flags,
218      {"Flags", "jxta.message.element.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
219       "JXTA Message Element Flags", HFILL}
220      },
221     {&hf_jxta_element_flag_hasType,
222      {"hasType", "jxta.message.element.flags.hasType", FT_BOOLEAN, 3, TFS(&flags_set_truth), 0x01,
223       "JXTA Message Element Flag -- hasType", HFILL}
224      },
225     {&hf_jxta_element_flag_hasEncoding,
226      {"hasEncoding", "jxta.message.element.flags.hasEncoding", FT_BOOLEAN, 3, TFS(&flags_set_truth), 0x02,
227       "JXTA Message Element Flag -- hasEncoding", HFILL}
228      },
229     {&hf_jxta_element_flag_hasSignature,
230      {"hasSignature", "jxta.message.element.flags.hasSignature", FT_BOOLEAN, 3, TFS(&flags_set_truth), 0x04,
231       "JXTA Message Element Flag -- hasSignature", HFILL}
232      },
233     {&hf_jxta_element_name,
234      {"Element Name", "jxta.message.element.name", FT_UINT_STRING, BASE_NONE, NULL, 0x0,
235       "JXTA Message Element Name", HFILL}
236      },
237     {&hf_jxta_element_type,
238      {"Element Type", "jxta.message.element.type", FT_UINT_STRING, BASE_NONE, NULL, 0x0,
239       "JXTA Message Element Name", HFILL}
240      },
241     {&hf_jxta_element_encoding,
242      {"Element Type", "jxta.message.element.encoding", FT_UINT_STRING, BASE_NONE, NULL, 0x0,
243       "JXTA Message Element Encoding", HFILL}
244      },
245     {&hf_jxta_element_content_len,
246      {"Element Content Length", "jxta.message.element.content.length", FT_UINT32, BASE_DEC, NULL, 0x0,
247       "JXTA Message Element Content Length", HFILL}
248      },
249     {&hf_jxta_element_content,
250      {"Element Content", "jxta.message.element.content", FT_BYTES, BASE_HEX, NULL, 0x0,
251       "JXTA Message Element Content", HFILL}
252      },
253 };
254
255 /**
256 *    JXTA Protocol subtree handles
257 **/
258 static gint ett_jxta = -1;
259 static gint ett_jxta_welcome = -1;
260 static gint ett_jxta_udp = -1;
261 static gint ett_jxta_framing = -1;
262 static gint ett_jxta_framing_header = -1;
263 static gint ett_jxta_msg = -1;
264 static gint ett_jxta_elem = -1;
265 static gint ett_jxta_elem_flags = -1;
266
267 /**
268 *   JXTA Protocol subtree array
269 **/
270 static gint *const ett[] = {
271     &ett_jxta,
272     &ett_jxta_welcome,
273     &ett_jxta_udp,
274     &ett_jxta_framing,
275     &ett_jxta_framing_header,
276     &ett_jxta_msg,
277     &ett_jxta_elem,
278     &ett_jxta_elem_flags
279 };
280
281 /**
282 *   global preferences
283 **/
284 static gboolean gDESEGMENT = TRUE;
285 static gboolean gUDP_HEUR = TRUE;
286 static gboolean gTCP_HEUR = TRUE;
287 static gboolean gSCTP_HEUR = FALSE;
288
289 /**
290 *   Stream Conversation data
291 **/
292 struct jxta_stream_conversation_data {
293     port_type tpt_ptype;
294
295     address initiator_tpt_address;
296     guint32 initiator_tpt_port;
297     guint32 initiator_welcome_frame;
298     address initiator_address;
299
300     address receiver_tpt_address;
301     guint32 receiver_tpt_port;
302     guint32 receiver_welcome_frame;
303     address receiver_address;
304 };
305
306 typedef struct jxta_stream_conversation_data jxta_stream_conversation_data;
307
308 /**
309 *   Prototypes
310 **/
311 static gboolean dissect_jxta_UDP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree);
312 static gboolean dissect_jxta_TCP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree);
313 static gboolean dissect_jxta_SCTP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree);
314
315 static int dissect_jxta_udp(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree);
316 static int dissect_jxta_stream(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree);
317 static conversation_t *get_tpt_conversation(packet_info * pinfo, gboolean create);
318
319 static int dissect_jxta_welcome(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, address * found_addr, gboolean initiator);
320 static int dissect_jxta_message_framing(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, guint64 * content_length,
321                                         gchar ** content_type);
322 static int dissect_jxta_message(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree);
323 static int dissect_jxta_message_element(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, guint ns_count,
324                                         const gchar ** namespaces);
325
326 void proto_reg_handoff_jxta(void);
327
328 /**
329 *   Heuristically dissect a tvbuff containing a JXTA UDP Message
330 *
331 *   @param  tvb The buffer to dissect.
332 *   @param  pinfo Packet Info.
333 *   @param  tree The protocol tree.
334 *   @return TRUE if the tvb contained JXTA data which was dissected otherwise FALSE
335 **/
336 static gboolean dissect_jxta_UDP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
337 {
338     /* This is a heuristic dissector, which means we get all the UDP
339      * traffic not sent to a known dissector and not claimed by
340      * a heuristic dissector called before us!
341      */
342     int save_desegment_offset;
343     guint32 save_desegment_len;
344     int ret;
345
346     if (!gUDP_HEUR)
347         return FALSE;
348
349     if (tvb_memeql(tvb, 0, JXTA_UDP_SIG, sizeof(JXTA_UDP_SIG)) != 0) {
350         return FALSE;
351     }
352
353     save_desegment_offset = pinfo->desegment_offset;
354     save_desegment_len = pinfo->desegment_len;
355     ret = dissect_jxta_udp(tvb, pinfo, tree);
356     if (ret < 0) {
357         /*
358          * UDP is not a packet stream protocol, so the UDP dissector
359          * should not, and will not, do the sort of dissection help
360          * that the TCP dissector will.  If JXTA messages don't
361          * start and end on UDP packet boundaries, the JXTA dissector
362          * will have to do its own byte stream reassembly.
363          */
364         pinfo->desegment_offset = save_desegment_offset;
365         pinfo->desegment_len = save_desegment_len;
366         return FALSE;
367     } else if (ret == 0) {
368         /*
369          * A clear rejection.
370          */
371         pinfo->desegment_offset = save_desegment_offset;
372         pinfo->desegment_len = save_desegment_len;
373         return FALSE;
374     } else {
375         /*
376          * A clear acceptance.
377          */
378         return TRUE;
379     }
380 }
381
382 /**
383 *   Heuristically dissect a tvbuff containing a JXTA TCP Stream
384 *
385 *   @param  tvb The buffer to dissect.
386 *   @param  pinfo Packet Info.
387 *   @param  tree The protocol tree.
388 *   @return TRUE if the tvb contained JXTA data which was dissected otherwise FALSE
389 **/
390 static gboolean dissect_jxta_TCP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
391 {
392     /* This is a heuristic dissector, which means we get all the TCP
393      * traffic not sent to a known dissector and not claimed by
394      * a heuristic dissector called before us!
395      */
396     int save_desegment_offset;
397     guint32 save_desegment_len;
398     int ret;
399
400     if (!gTCP_HEUR)
401         return FALSE;
402
403     save_desegment_offset = pinfo->desegment_offset;
404     save_desegment_len = pinfo->desegment_len;
405     ret = dissect_jxta_stream(tvb, pinfo, tree);
406     if (ret < 0) {
407         /*
408          * A heuristic dissector for a TCP-based protocol can reject
409          * a packet, or it can request that more data be provided.
410          * It must not attempt to do both, as the notion of doing both
411          * is nonsensical - if the packet isn't considered a packet
412          * for the dissector's protocol, that dissector won't be
413          * dissecting it no matter *how* much more data is added.
414          *
415          * Therefore, we treat a negative return from
416          * dissect_jxta_stream() as a rejection.
417          *
418          * If that's not desired - i.e., if we should keep trying to get
419          * more data, in the hopes that we'll eventually be able to
420          * determine whether the packet is a JXTA packet or not - we
421          * should, in this case, leave pinfo->desegment_offset and
422          * pinfo->desegment_len alone, and return TRUE, *NOT* FALSE.
423          */
424         pinfo->desegment_offset = save_desegment_offset;
425         pinfo->desegment_len = save_desegment_len;
426         return FALSE;
427     } else if (ret == 0) {
428         /*
429          * A clear rejection.
430          */
431         pinfo->desegment_offset = save_desegment_offset;
432         pinfo->desegment_len = save_desegment_len;
433         return FALSE;
434     } else {
435         /*
436          * A clear acceptance.
437          */
438         return TRUE;
439     }
440 }
441
442 /**
443 *   Heuristically dissect a tvbuff containing a JXTA SCTP Stream
444 *
445 *   @param  tvb The buffer to dissect.
446 *   @param  pinfo Packet Info.
447 *   @param  tree The protocol tree.
448 *   @return TRUE if the tvb contained JXTA data which was dissected otherwise FALSE
449 **/
450 static gboolean dissect_jxta_SCTP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
451 {
452     /* This is a heuristic dissector, which means we get all the SCTP
453      * traffic not sent to a known dissector and not claimed by
454      * a heuristic dissector called before us!
455      */
456     int save_desegment_offset;
457     guint32 save_desegment_len;
458     int ret;
459
460     if (!gSCTP_HEUR)
461         return FALSE;
462
463     save_desegment_offset = pinfo->desegment_offset;
464     save_desegment_len = pinfo->desegment_len;
465     ret = dissect_jxta_stream(tvb, pinfo, tree);
466     if (ret < 0) {
467         /*
468          * SCTP is not a byte stream protocol, so the SCTP dissector
469          * should not, and will not, do the sort of dissection help
470          * that the SCTP dissector will.  If JXTA messages don't
471          * start and end on SCTP packet boundaries, the JXTA dissector
472          * will have to do its own byte stream reassembly.
473          *
474          * The SCTP dissector currently won't do reassembly.  If that
475          * causes a problem for the JXTA dissector, the correct fix
476          * is to implement reassembly in the SCTP dissector, so *all*
477          * dissectors for protocols running atop SCTP can benefit from
478          * it.
479          */
480         pinfo->desegment_offset = save_desegment_offset;
481         pinfo->desegment_len = save_desegment_len;
482         return FALSE;
483     } else if (ret == 0) {
484         /*
485          * A clear rejection.
486          */
487         pinfo->desegment_offset = save_desegment_offset;
488         pinfo->desegment_len = save_desegment_len;
489         return FALSE;
490     } else {
491         /*
492          * A clear acceptance.
493          */
494         return TRUE;
495     }
496 }
497
498 /**
499 *   Dissect a tvbuff containing a JXTA UDP header, JXTA Message framing and a JXTA Message
500 *
501 *   @param  tvb The buffer to dissect.
502 *   @param  pinfo Packet Info.
503 *   @param  tree The protocol tree.
504 *   @return Number of bytes from the tvbuff_t which were processed, 0 (zero) if
505 *           the packet was not recognized as a JXTA packet and negative if the
506 *           dissector needs more bytes in order to process a PDU.
507 **/
508 static int dissect_jxta_udp(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
509 {
510     guint offset = 0;
511     guint available;
512     gint needed = 0;
513
514     conversation_t *conversation =
515         find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
516
517     if (conversation == NULL) {
518         /*
519          * No conversation exists yet - create one.
520          */
521         conversation =
522             conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
523     }
524
525     DISSECTOR_ASSERT(find_dissector("jxta.udp"));
526
527     conversation_set_dissector(conversation, find_dissector("jxta.udp"));
528
529     while (TRUE) {
530         tvbuff_t *jxta_message_framing_tvb;
531         gint processed = 0;
532         guint64 content_length = -1;
533         gchar *content_type = NULL;
534
535         available = tvb_reported_length_remaining(tvb, offset);
536         if (available < sizeof(JXTA_UDP_SIG)) {
537             needed = (gint) (sizeof(JXTA_UDP_SIG) - available);
538             break;
539         }
540
541         if (tvb_memeql(tvb, offset, JXTA_UDP_SIG, sizeof(JXTA_UDP_SIG)) != 0) {
542             /* not ours */
543             return 0;
544         }
545
546         offset += sizeof(JXTA_UDP_SIG);
547
548         jxta_message_framing_tvb = tvb_new_subset(tvb, offset, -1, -1);
549         processed = dissect_jxta_message_framing(jxta_message_framing_tvb, pinfo, NULL, &content_length, &content_type);
550
551         if ((0 == processed) || (NULL == content_type) || (content_length <= 0) || (content_length > UINT_MAX)) {
552             /** Buffer did not begin with valid framing headers */
553             return 0;
554         }
555
556         if (processed < 0) {
557             needed = -processed;
558             break;
559         }
560
561         /* Redo header processing, this time populating the tree. */
562         processed = dissect_jxta_message_framing(jxta_message_framing_tvb, pinfo, tree, &content_length, &content_type);
563
564
565         offset += processed;
566
567         available = tvb_reported_length_remaining(tvb, offset);
568         if (available < content_length) {
569             needed = (gint) (content_length - available);
570             break;
571         }
572
573         offset += (guint) content_length;
574
575         break;
576     }
577
578     if ((needed > 0) && gDESEGMENT && pinfo->can_desegment) {
579         pinfo->desegment_offset = 0;
580         pinfo->desegment_len = needed;
581         return -needed;
582     }
583
584     if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
585         col_set_str(pinfo->cinfo, COL_PROTOCOL, "JXTA");
586     }
587
588     if (tree) {
589         guint tree_offset = 0;
590         proto_item *jxta_tree_item =
591             proto_tree_add_protocol_format(tree, proto_jxta, tvb, offset, -1, "JXTA" );
592         proto_tree *jxta_tree = proto_item_add_subtree(jxta_tree_item, ett_jxta);
593         proto_item *jxta_udp_tree_item =
594             proto_tree_add_none_format(jxta_tree, hf_jxta_udp, tvb, tree_offset, -1, "JXTA UDP Message");
595         proto_tree *jxta_udp_tree = proto_item_add_subtree(jxta_udp_tree_item, ett_jxta_udp);
596         tvbuff_t *jxta_message_framing_tvb;
597         guint64 content_length = -1;
598         gchar *content_type = NULL;
599         tvbuff_t *jxta_message_tvb;
600         gboolean dissected = FALSE;
601         gint processed = 0;
602
603         proto_tree_add_item(jxta_udp_tree, hf_jxta_udpsig, tvb, tree_offset, sizeof(JXTA_UDP_SIG), FALSE);
604         tree_offset += sizeof(JXTA_UDP_SIG);
605
606         jxta_message_framing_tvb = tvb_new_subset(tvb, tree_offset, -1, -1);
607         processed = dissect_jxta_message_framing(jxta_message_framing_tvb, pinfo, NULL, &content_length, &content_type);
608
609         if ((0 == processed) || (NULL == content_type) || (content_length <= 0) || (content_length > UINT_MAX)) {
610             /** Buffer did not begin with valid framing headers */
611             return 0;
612         }
613
614         processed = dissect_jxta_message_framing(jxta_message_framing_tvb, pinfo, tree, &content_length, &content_type);
615
616         tree_offset += processed;
617
618         jxta_message_tvb = tvb_new_subset(tvb, tree_offset, (gint) content_length, (gint) content_length);
619
620         dissected = dissector_try_string(media_type_dissector_table, content_type, jxta_message_tvb, pinfo, tree);
621
622         if (!dissected) {
623             call_dissector(data_handle, jxta_message_tvb, pinfo, tree);
624         }
625
626         tree_offset += (guint) content_length;
627
628         proto_item_set_end(jxta_udp_tree_item, tvb, tree_offset);
629
630         DISSECTOR_ASSERT(offset == tree_offset);
631     }
632
633     return offset;
634 }
635
636 /**
637 *   Dissect a tvbuff containing JXTA stream PDUs. This commonly includes
638 *   connections over TCP sockets.
639 *
640 *   <p/>The stream (in both directions) will consist of a JXTA Welcome Message
641 *   followed by an indeterminate number of JXTA Message Framing Headers and
642 *   JXTA Messages.
643 *
644 *   @param  tvb The buffer to dissect.
645 *   @param  pinfo Packet Info.
646 *   @param  tree The protocol tree.
647 *   @return Number of bytes from the tvbuff_t which were processed, 0 (zero) if
648 *           the packet was not recognized as a JXTA packet and negative if the
649 *           dissector needs more bytes in order to process a PDU.
650 **/
651 static int dissect_jxta_stream(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
652 {
653     guint offset = 0;
654     guint available = tvb_reported_length_remaining(tvb, offset);
655     gint processed;
656     gint needed = 0;
657     conversation_t *tpt_conversation = NULL;
658     jxta_stream_conversation_data *tpt_conv_data = NULL;
659     proto_item *jxta_tree_item = NULL;
660     proto_tree *jxta_tree = NULL;
661
662     /*g_message("Dissecting %s : %d", (NULL != tree) ? "for display" : "", pinfo->fd->num );*/
663
664     if (available < sizeof(JXTA_WELCOME_MSG_SIG)) {
665         needed = (gint) (sizeof(JXTA_WELCOME_MSG_SIG) - available);
666         goto Common_Exit;
667     }
668
669     if (0 == tvb_memeql(tvb, 0, JXTA_WELCOME_MSG_SIG, sizeof(JXTA_WELCOME_MSG_SIG))) {
670         /* The beginning of a JXTA stream connection */
671         address *welcome_addr;
672         gboolean initiator = FALSE;
673
674         tpt_conversation = get_tpt_conversation(pinfo, TRUE);
675         tpt_conv_data = (jxta_stream_conversation_data *) conversation_get_proto_data(tpt_conversation, proto_jxta);
676
677         if (0 == tpt_conv_data->initiator_welcome_frame) {
678             /* The initiator welcome frame */
679             tpt_conv_data->tpt_ptype = pinfo->ptype;
680             tpt_conv_data->initiator_welcome_frame = pinfo->fd->num;
681             COPY_ADDRESS(&tpt_conv_data->initiator_tpt_address, &pinfo->src);
682             tpt_conv_data->initiator_tpt_port = pinfo->srcport;
683
684             welcome_addr = &tpt_conv_data->initiator_address;
685             initiator = TRUE;
686         } else {
687             if (tpt_conv_data->initiator_welcome_frame >= pinfo->fd->num) {
688                 /* what we saw previously was the receiver welcome message */
689                 tpt_conv_data->receiver_welcome_frame = tpt_conv_data->initiator_welcome_frame;
690                 tpt_conv_data->receiver_tpt_address = tpt_conv_data->initiator_tpt_address;
691                 tpt_conv_data->receiver_tpt_port = tpt_conv_data->initiator_tpt_port;
692                 tpt_conv_data->receiver_address = tpt_conv_data->initiator_address;
693                 tpt_conv_data->initiator_welcome_frame = pinfo->fd->num;
694                 COPY_ADDRESS(&tpt_conv_data->initiator_tpt_address, &pinfo->src);
695                 tpt_conv_data->initiator_tpt_port = pinfo->srcport;
696
697                 welcome_addr = &tpt_conv_data->initiator_address;
698                 initiator = TRUE;
699             } else {
700                 /* The receiver welcome frame */
701                 tpt_conv_data->tpt_ptype = pinfo->ptype;
702                 tpt_conv_data->receiver_welcome_frame = pinfo->fd->num;
703                 COPY_ADDRESS(&tpt_conv_data->receiver_tpt_address, &pinfo->src);
704                 tpt_conv_data->receiver_tpt_port = pinfo->srcport;
705
706                 welcome_addr = &tpt_conv_data->receiver_address;
707                 initiator = FALSE;
708             }
709         }
710
711         processed = dissect_jxta_welcome(tvb, pinfo, NULL, welcome_addr, initiator);
712
713         if( processed < 0 ) {
714             needed = -processed;
715             goto Common_Exit;
716         }
717
718         /* redo, this time creating the display tree. */
719         jxta_tree_item =
720             proto_tree_add_protocol_format(tree, proto_jxta, tvb, offset, -1, "JXTA" );
721         jxta_tree = proto_item_add_subtree(jxta_tree_item, ett_jxta);
722
723         processed = dissect_jxta_welcome(tvb, pinfo, jxta_tree, welcome_addr, initiator);
724     } else {
725         /* Somewhere in the middle of a JXTA stream connection */
726         guint64 content_length = -1;
727         gchar *content_type = NULL;
728         gint headers_len = dissect_jxta_message_framing(tvb, pinfo, NULL, &content_length, &content_type);
729
730         /*g_message("%d Tpt %s:%d -> %s:%d tvb len=%d\n\t%s %u", pinfo->fd->num,
731                               address_to_str(&pinfo->src), pinfo->srcport,
732                               address_to_str(&pinfo->dst), pinfo->destport,
733                               tvb_reported_length_remaining(tvb, 0),
734                               (content_type) ? content_type : "[unknown content type]", (guint) content_length);*/
735
736         if ((0 == headers_len) || (NULL == content_type) || (content_length <= 0) || (content_length > UINT_MAX)) {
737             /** Buffer did not begin with valid framing headers */
738             return 0;
739         }
740
741         if (headers_len < 0) {
742             /* negative headers_len means we need more bytes */
743             needed = -headers_len;
744             goto Common_Exit;
745         }
746
747         jxta_tree_item =
748             proto_tree_add_protocol_format(tree, proto_jxta, tvb, offset, -1, "JXTA" );
749         jxta_tree = proto_item_add_subtree(jxta_tree_item, ett_jxta);
750
751         /* Redo header processing, this time populating the tree. */
752         headers_len = dissect_jxta_message_framing(tvb, pinfo, jxta_tree, &content_length, &content_type);
753
754         available = tvb_reported_length_remaining(tvb, offset + headers_len);
755         if (available >= content_length) {
756             tvbuff_t *jxta_message_tvb = tvb_new_subset(tvb, offset + headers_len, (gint) content_length, (gint) content_length);
757             conversation_t *peer_conversation = NULL;
758             address saved_src_addr;
759             guint32 saved_src_port = 0;
760             address saved_dst_addr;
761             guint32 saved_dst_port = 0;
762             port_type saved_port_type = PT_NONE;
763             gboolean dissected;
764
765             tpt_conversation = get_tpt_conversation(pinfo, TRUE);
766
767             if (NULL != tpt_conversation) {
768                 tpt_conv_data = (jxta_stream_conversation_data *) conversation_get_proto_data(tpt_conversation, proto_jxta);
769
770                 if ((AT_NONE != tpt_conv_data->initiator_address.type) && (AT_NONE != tpt_conv_data->receiver_address.type)) {
771                     peer_conversation =
772                         find_conversation(pinfo->fd->num, &tpt_conv_data->initiator_address, &tpt_conv_data->receiver_address,
773                                           PT_NONE, 0, 0, NO_PORT_B);
774
775                     if (NULL == peer_conversation) {
776                         peer_conversation =
777                             conversation_new(pinfo->fd->num, &tpt_conv_data->initiator_address,
778                                              &tpt_conv_data->receiver_address, PT_NONE, 0, 0, NO_PORT_B);
779                         conversation_set_dissector(peer_conversation, stream_jxta_handle);
780                     }
781
782                 } else {
783                     g_warning("Uninitialized peer conversation");
784                 }
785             }
786
787             /* Use our source and destination addresses if we have them */
788             if (NULL != peer_conversation) {
789                 saved_src_addr = pinfo->src;
790                 saved_src_port = pinfo->srcport;
791                 saved_dst_addr = pinfo->dst;
792                 saved_dst_port = pinfo->destport;
793                 saved_port_type = pinfo->ptype;
794                 /*g_message("%d Tpt %s:%d -> %s:%d", pinfo->fd->num, ip_to_str(tpt_conv_data->initiator_tpt_address.data),
795                           tpt_conv_data->initiator_tpt_port, ip_to_str(tpt_conv_data->receiver_tpt_address.data),
796                           tpt_conv_data->receiver_tpt_port);*/
797                 if (ADDRESSES_EQUAL(&pinfo->src, &tpt_conv_data->initiator_tpt_address)
798                     && tpt_conv_data->initiator_tpt_port == pinfo->srcport) {
799                     /*g_message("%d From initiator : %s -> %s ", pinfo->fd->num, tpt_conv_data->initiator_address.data,
800                               tpt_conv_data->receiver_address.data);*/
801                     pinfo->src = tpt_conv_data->initiator_address;
802                     pinfo->dst = tpt_conv_data->receiver_address;
803                 } else if (ADDRESSES_EQUAL(&pinfo->src, &tpt_conv_data->receiver_tpt_address) &&
804                            tpt_conv_data->receiver_tpt_port == pinfo->srcport) {
805                     /*g_message("%d From receiver : %s -> %s ", pinfo->fd->num, tpt_conv_data->receiver_address.data,
806                               tpt_conv_data->initiator_address.data);*/
807                     pinfo->src = tpt_conv_data->receiver_address;
808                     pinfo->dst = tpt_conv_data->initiator_address;
809                 } else {
810                     /*g_message("%d Nothing matches %s:%d -> %s:%d", pinfo->fd->num, ip_to_str(pinfo->src.data), pinfo->srcport,
811                               ip_to_str(pinfo->dst.data), pinfo->destport);*/
812                 }
813                 /* JXTA doesn't use ports */
814                 pinfo->ptype = PT_NONE;
815                 pinfo->srcport = 0;
816                 pinfo->destport = 0;
817             }
818
819             dissected =
820                 dissector_try_string(media_type_dissector_table, content_type, jxta_message_tvb, pinfo, tree);
821
822             if (!dissected) {
823                 call_dissector(data_handle, jxta_message_tvb, pinfo, jxta_tree);
824             }
825
826             /* Restore the saved src and dst addresses */
827             if (NULL != peer_conversation) {
828                 pinfo->src = saved_src_addr;
829                 pinfo->srcport = saved_src_port;
830                 pinfo->dst = saved_dst_addr;
831                 pinfo->destport = saved_dst_port;
832                 pinfo->ptype = saved_port_type;
833             }
834
835             processed = (guint) content_length + headers_len;
836         } else {
837             /* we need more bytes before we can process message body. */
838             needed = (gint) ((guint) content_length - available);
839             goto Common_Exit;
840         }
841     }
842
843     offset += processed;
844
845 Common_Exit:
846     if ((needed > 0) && gDESEGMENT && pinfo->can_desegment) {
847         /*g_message( "Requesting %d more bytes", needed );*/
848         pinfo->desegment_offset = offset;
849         pinfo->desegment_len = needed;
850         return -needed;
851     }
852
853     return offset;
854 }
855
856 /**
857 *   Find or possibly create a transport conversation object for the connection
858 *   which is associated with the packet info.
859 *
860 *   @param pinfo  The packet info from the underlying transport.
861 *   @param create If TRUE then create a new conversation object if necessary.
862 **/
863 static conversation_t *get_tpt_conversation(packet_info * pinfo, gboolean create)
864 {
865     conversation_t *tpt_conversation =
866         find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
867     jxta_stream_conversation_data *tpt_conv_data;
868
869     if (tpt_conversation == NULL) {
870         if (!create) {
871             return NULL;
872         }
873
874         /*
875          * No conversation exists yet - create one.
876          */
877         tpt_conversation =
878             conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
879     }
880
881     conversation_set_dissector(tpt_conversation, stream_jxta_handle);
882
883     tpt_conv_data = (jxta_stream_conversation_data *) conversation_get_proto_data(tpt_conversation, proto_jxta);
884
885     if (NULL == tpt_conv_data) {
886         tpt_conv_data = se_alloc(sizeof(jxta_stream_conversation_data));
887         tpt_conv_data->tpt_ptype = pinfo->ptype;
888
889         COPY_ADDRESS(&tpt_conv_data->initiator_tpt_address, &pinfo->src);
890         tpt_conv_data->initiator_tpt_port = pinfo->srcport;
891         tpt_conv_data->initiator_welcome_frame = 0;
892         /* XXX bondolo This is not quite correct as it should include port until a peerid can be associated. */
893         COPY_ADDRESS(&tpt_conv_data->initiator_address, &pinfo->src);
894
895         COPY_ADDRESS(&tpt_conv_data->receiver_tpt_address, &pinfo->dst);
896         tpt_conv_data->receiver_tpt_port = pinfo->destport;
897         tpt_conv_data->receiver_welcome_frame = 0;
898         /* XXX bondolo This is not quite correct as it should include port until a peerid can be associated. */
899         COPY_ADDRESS(&tpt_conv_data->receiver_address, &pinfo->dst);
900
901         conversation_add_proto_data(tpt_conversation, proto_jxta, tpt_conv_data);
902     }
903
904     return tpt_conversation;
905 }
906
907 /**
908 *   Dissect a tvbuff containing a JXTA Welcome Message
909 *
910 *   @param  tvb The buffer to dissect.
911 *   @param  pinfo Packet Info.
912 *   @param  tree The protocol tree.
913 *   @param  found_addr The address found in the welcome message.
914 *   @param  initiator If TRUE then we believe this welcome message to be the initiator's.
915 *   @return Number of bytes from the tvbuff_t which were processed, 0 (zero) if
916 *           the packet was not recognized as a JXTA packet and negative if the
917 *           dissector needs more bytes in order to process a PDU.
918 **/
919 static int dissect_jxta_welcome(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, address * found_addr, gboolean initiator)
920 {
921     guint offset = 0;
922     gint afterwelcome;
923     gint first_linelen;
924     guint available = tvb_reported_length_remaining(tvb, offset);
925     gchar **tokens = NULL;
926
927     if (available < sizeof(JXTA_WELCOME_MSG_SIG)) {
928         return (gint) (available - sizeof(JXTA_WELCOME_MSG_SIG));
929     }
930
931     if (0 != tvb_memeql(tvb, 0, JXTA_WELCOME_MSG_SIG, sizeof(JXTA_WELCOME_MSG_SIG))) {
932         /* not ours! */
933         return 0;
934     }
935
936     first_linelen = tvb_find_line_end(tvb, offset, -1, &afterwelcome, gDESEGMENT && pinfo->can_desegment);
937
938     if (-1 == first_linelen) {
939         if (available > 4096) {
940             /* it's too far too be reasonable */
941             return 0;
942         } else {
943             /* ask for more bytes */
944             return -1;
945         }
946     }
947
948     /* Dissect the Welcome Message */
949
950     if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
951         col_set_str(pinfo->cinfo, COL_PROTOCOL, "JXTA");
952     }
953
954     if (check_col(pinfo->cinfo, COL_INFO)) {
955         col_add_str(pinfo->cinfo, COL_INFO, "Welcome");
956     }
957
958     {
959         gchar *welcomeline = tvb_get_ephemeral_string(tvb, offset, first_linelen);
960         gchar **current_token;
961         guint token_offset = offset;
962         proto_item *jxta_welcome_tree_item = NULL;
963         proto_tree *jxta_welcome_tree = NULL;
964
965         tokens = g_strsplit(welcomeline, " ", 255);
966         current_token = tokens;
967
968         if (tree) {
969             jxta_welcome_tree_item =
970                 proto_tree_add_none_format(tree, hf_jxta_welcome, tvb, offset, afterwelcome,
971                                            "JXTA Connection Welcome Message, %s", welcomeline);
972             jxta_welcome_tree = proto_item_add_subtree(jxta_welcome_tree_item, ett_jxta_welcome);
973         }
974
975         if (jxta_welcome_tree) {
976             proto_item *jxta_welcome_initiator_item =
977                 proto_tree_add_boolean(jxta_welcome_tree, hf_jxta_welcome_initiator, tvb, 0, 0, initiator);
978             PROTO_ITEM_SET_GENERATED(jxta_welcome_initiator_item);
979         }
980
981         if (NULL != *current_token) {
982             if (jxta_welcome_tree) {
983                 proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_sig, tvb, token_offset, strlen(*current_token), FALSE);
984             }
985
986             token_offset += strlen(*current_token) + 1;
987             current_token++;
988         } else {
989             /* invalid welcome message */
990             afterwelcome = 0;
991             goto Common_Exit;
992         }
993
994         if (NULL != *current_token) {
995             if (jxta_welcome_tree) {
996                 proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_destAddr, tvb, token_offset, strlen(*current_token),
997                                     FALSE);
998             }
999
1000             token_offset += strlen(*current_token) + 1;
1001             current_token++;
1002         } else {
1003             /* invalid welcome message */
1004             afterwelcome = 0;
1005             goto Common_Exit;
1006         }
1007
1008         if (NULL != *current_token) {
1009             if (jxta_welcome_tree) {
1010                 proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_pubAddr, tvb, token_offset, strlen(*current_token), FALSE);
1011             }
1012
1013             token_offset += strlen(*current_token) + 1;
1014             current_token++;
1015         } else {
1016             /* invalid welcome message */
1017             afterwelcome = 0;
1018             goto Common_Exit;
1019         }
1020
1021         if (NULL != *current_token) {
1022             if (jxta_welcome_tree) {
1023                 proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_peerid, tvb, token_offset, strlen(*current_token), FALSE);
1024             }
1025
1026             if (check_col(pinfo->cinfo, COL_INFO)) {
1027                 col_append_str(pinfo->cinfo, COL_INFO, (initiator ? " -> " : " <- ") );
1028                 col_append_str(pinfo->cinfo, COL_INFO, *current_token);
1029             }
1030
1031             if (NULL != found_addr) {
1032                 found_addr->type = AT_URI;
1033                 found_addr->len = strlen(*current_token);
1034                 /* FIXME 20050605 bondolo THIS ALLOCATION IS A MEMORY LEAK! */
1035                 found_addr->data = g_strdup(*current_token);
1036             }
1037
1038             token_offset += strlen(*current_token) + 1;
1039             current_token++;
1040         } else {
1041             /* invalid welcome message */
1042             afterwelcome = 0;
1043             goto Common_Exit;
1044         }
1045
1046         if (NULL != *current_token) {
1047             int variable_tokens = 0;
1048             gchar **variable_token = current_token;
1049
1050             while(NULL != *variable_token) {
1051                 variable_tokens++;
1052                 variable_token++;
1053             }
1054
1055             if( variable_tokens < 1 ) {
1056               /* invalid welcome message */
1057               afterwelcome = 0;
1058               goto Common_Exit;
1059             }
1060
1061             if( (2 == variable_tokens) && (0 == strcmp(JXTA_WELCOME_MSG_VERSION_1_1, current_token[variable_tokens -1])) ) {
1062                   if (jxta_welcome_tree) {
1063                       proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_noProp, tvb, token_offset, strlen(*current_token), FALSE);
1064                   }
1065
1066                   token_offset += strlen(*current_token) + 1;
1067                   current_token++;
1068
1069                   if (jxta_welcome_tree) {
1070                       proto_tree_add_item(jxta_welcome_tree, hf_jxta_welcome_version, tvb, token_offset, strlen(*current_token), FALSE);
1071                   }
1072             } else {
1073                 /* Unrecognized Welcome Version */
1074                 int each_variable_token;
1075
1076                 for( each_variable_token = 0; each_variable_token < variable_tokens; each_variable_token++ ) {
1077                   if (jxta_welcome_tree) {
1078                       jxta_welcome_tree_item = proto_tree_add_item(jxta_welcome_tree,
1079                         (each_variable_token < (variable_tokens -1) ? hf_jxta_welcome_variable : hf_jxta_welcome_version),
1080                         tvb, token_offset, strlen(*current_token), FALSE);
1081
1082                         proto_item_append_text(jxta_welcome_tree_item, " (UNRECOGNIZED)");
1083                   }
1084
1085                   token_offset += strlen(*current_token) + 1;
1086                   current_token++;
1087                 }
1088             }
1089         } else {
1090             /* invalid welcome message */
1091             afterwelcome = 0;
1092             goto Common_Exit;
1093         }
1094     }
1095
1096 Common_Exit:
1097     g_strfreev(tokens);
1098
1099     col_set_writable(pinfo->cinfo, FALSE);
1100
1101     return afterwelcome;
1102 }
1103
1104 /**
1105 *   Dissect a tvbuff containing JXTA Message framing.
1106 *
1107 *   @param  tvb The buffer to dissect.
1108 *   @param  pinfo Packet Info.
1109 *   @param  tree The protocol tree.
1110 *   @param  content_length Pointer to a buffer for storing the value of the
1111 *           "content-length" header or NULL.
1112 *   @param  content_type Pointer-to-a-pointer for a new buffer for storing the
1113 *           value of the "content_type-length" header or NULL.
1114 *   @return Number of bytes from the tvbuff_t which were processed, 0 (zero) if
1115 *           the packet was not recognized as a JXTA packet and negative if the
1116 *           dissector needs more bytes in order to process a PDU.
1117 **/
1118 static int dissect_jxta_message_framing(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, guint64 * content_length,
1119                                         gchar ** content_type)
1120 {
1121     guint offset = 0;
1122     guint available;
1123     gint needed = 0;
1124
1125     /*
1126      *   First go around. Make sure all of the bytes are there.
1127      */
1128     do {
1129         guint8 headername_len;
1130         guint8 headername_offset;
1131         guint16 headervalue_len;
1132         guint16 headervalue_offset;
1133
1134         available = tvb_reported_length_remaining(tvb, offset);
1135         if (available < sizeof(guint8)) {
1136             needed = (gint) (sizeof(guint8) - available);
1137             break;
1138         } else {
1139             headername_len = tvb_get_guint8(tvb, offset);
1140             offset += sizeof(guint8);
1141             headername_offset = offset;
1142
1143             available = tvb_reported_length_remaining(tvb, offset);
1144             if (available < headername_len) {
1145                 needed = (gint) (headername_len - available);
1146                 break;
1147             }
1148
1149             if (0 == headername_len) {
1150                 break;
1151             }
1152             offset += headername_len;
1153         }
1154
1155         available = tvb_reported_length_remaining(tvb, offset);
1156         if (available < sizeof(guint16)) {
1157             needed = (gint) (sizeof(guint16) - available);
1158             break;
1159         } else {
1160             headervalue_len = tvb_get_ntohs(tvb, offset);
1161             offset += sizeof(guint16);
1162             headervalue_offset = offset;
1163
1164             available = tvb_reported_length_remaining(tvb, offset);
1165             if (available < headervalue_len) {
1166                 needed = (gint) (headervalue_len - available);
1167                 break;
1168             }
1169
1170             offset += headervalue_len;
1171         }
1172
1173         if (content_type && (sizeof("content-type") - 1) == headername_len) {
1174             if (0 == tvb_strncaseeql(tvb, headername_offset, "content-type", sizeof("content-type") - 1)) {
1175                 *content_type = tvb_get_ephemeral_string(tvb, headervalue_offset, headervalue_len);
1176             }
1177         }
1178
1179
1180         if (content_length && (sizeof(guint64) == headervalue_len) && ((sizeof("content-length") - 1) == headername_len)) {
1181             if (0 == tvb_strncaseeql(tvb, headername_offset, "content-length", sizeof("content-length") - 1)) {
1182                 *content_length = tvb_get_ntoh64(tvb, headervalue_offset);
1183             }
1184         }
1185     } while (TRUE);
1186
1187     if ((needed > 0) && gDESEGMENT && pinfo->can_desegment) {
1188         pinfo->desegment_offset = 0;
1189         pinfo->desegment_len = needed;
1190         return -needed;
1191     }
1192
1193     /*
1194      *   Second (optional pass) Now that we are sure that all the bytes are there we update the protocol tree.
1195      */
1196     if (tree) {
1197         guint tree_offset = 0;
1198         proto_item *framing_tree_item =
1199             proto_tree_add_none_format(tree, hf_jxta_framing, tvb, tree_offset, -1, "JXTA Message Framing Headers");
1200         proto_tree *framing_tree = proto_item_add_subtree(framing_tree_item, ett_jxta_framing);
1201
1202         /* parse framing headers */
1203         do {
1204             guint8 headernamelen = tvb_get_guint8(tvb, tree_offset);
1205             proto_item *framing_header_tree_item =
1206                 proto_tree_add_item(framing_tree, hf_jxta_framing_header, tvb, tree_offset, -1, FALSE);
1207             proto_tree *framing_header_tree = proto_item_add_subtree(framing_header_tree_item, ett_jxta_framing_header);
1208
1209             /*
1210              *   Put header name into the protocol tree
1211              */
1212             proto_tree_add_item(framing_header_tree, hf_jxta_framing_header_name, tvb, tree_offset, 1, headernamelen);
1213
1214             /*
1215              *   Append header name into the header protocol item. It's a nice hint so you don't have to reveal all headers.
1216              */
1217             if (headernamelen > 0) {
1218                 proto_item_append_text(framing_header_tree_item, " \"%s\"",
1219                                        tvb_format_text(tvb, tree_offset + sizeof(guint8), headernamelen));
1220             }
1221
1222             tree_offset += sizeof(guint8) + headernamelen;
1223
1224             if (headernamelen > 0) {
1225                 guint16 headervaluelen = tvb_get_ntohs(tvb, tree_offset);
1226
1227                 if (tree) {
1228                     proto_tree_add_uint(framing_header_tree, hf_jxta_framing_header_value_length, tvb, tree_offset,
1229                                         sizeof(guint16), headervaluelen);
1230
1231                     /** TODO bondolo Add specific handling for known header types */
1232
1233                     /*
1234                      * Put header value into protocol tree.
1235                      */
1236                     proto_tree_add_item(framing_header_tree, hf_jxta_framing_header_value, tvb, tree_offset + sizeof(guint16),
1237                                         headervaluelen, FALSE);
1238                 }
1239
1240                 tree_offset += sizeof(guint16) + headervaluelen;
1241             }
1242
1243             proto_item_set_end(framing_header_tree_item, tvb, tree_offset);
1244
1245             if (0 == headernamelen) {
1246                 break;
1247             }
1248         } while (TRUE);
1249
1250         proto_item_set_end(framing_tree_item, tvb, tree_offset);
1251
1252         DISSECTOR_ASSERT(offset == tree_offset);
1253     }
1254
1255     /* return how many bytes we used up. */
1256     return offset;
1257 }
1258
1259 /**
1260 *   Dissect a tvbuff containing a JXTA Message.
1261 *
1262 *   @param  tvb The buffer to dissect.
1263 *   @param  pinfo Packet Info.
1264 *   @param  tree The protocol tree.
1265 *   @return Number of bytes from the tvbuff_t which were processed, 0 (zero) if
1266 *           the packet was not recognized as a JXTA packet and negative if the
1267 *           dissector needs more bytes in order to process a PDU.
1268 **/
1269 static int dissect_jxta_message(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
1270 {
1271     guint offset = 0;
1272     guint available;
1273     gint needed = 0;
1274
1275     while (TRUE) {
1276         /* First pass. Make sure all of the bytes we need are available */
1277         available = tvb_reported_length_remaining(tvb, offset);
1278         if (available < sizeof(JXTA_MSG_SIG)) {
1279             needed = (gint) (sizeof(JXTA_MSG_SIG) - available);
1280             break;
1281         }
1282
1283         if (tvb_memeql(tvb, offset, JXTA_MSG_SIG, sizeof(JXTA_MSG_SIG)) != 0) {
1284             /* It is not one of ours */
1285             return 0;
1286         }
1287
1288         offset += sizeof(JXTA_MSG_SIG);
1289
1290         available = tvb_reported_length_remaining(tvb, offset);
1291         if (available < sizeof(guint8)) {
1292             needed = (gint) (sizeof(guint8) - available);
1293             break;
1294         } else {
1295             guint8 message_version = tvb_get_guint8(tvb, offset);
1296
1297             offset += sizeof(guint8);
1298
1299             if (0 != message_version) {
1300                 /* Sort of a lie, we say that we don't recognize it at all. */
1301                 return 0;
1302             }
1303         }
1304
1305         available = tvb_reported_length_remaining(tvb, offset);
1306         if (available < sizeof(guint16)) {
1307             needed = (gint) (sizeof(guint16) - available);
1308             break;
1309         } else {
1310             guint16 msg_ns_count = tvb_get_ntohs(tvb, offset);
1311             guint each_namespace;
1312
1313             offset += sizeof(guint16);
1314
1315             for (each_namespace = 0; each_namespace < msg_ns_count; each_namespace++) {
1316                 guint16 namespace_len;
1317
1318                 available = tvb_reported_length_remaining(tvb, offset);
1319                 if (available < sizeof(namespace_len)) {
1320                     needed = (gint) (sizeof(namespace_len) - available);
1321                     break;
1322                 }
1323
1324                 namespace_len = tvb_get_ntohs(tvb, offset);
1325
1326                 available = tvb_reported_length_remaining(tvb, offset + sizeof(namespace_len));
1327                 if (available < namespace_len) {
1328                     needed = (gint) (namespace_len - available);
1329                     break;
1330                 }
1331
1332                 offset += sizeof(namespace_len) + namespace_len;
1333             }
1334         }
1335
1336         /* parse element count */
1337         available = tvb_reported_length_remaining(tvb, offset);
1338         if (available < sizeof(guint16)) {
1339             needed = (gint) (sizeof(guint16) - available);
1340             break;
1341         } else {
1342             guint16 elem_count = tvb_get_ntohs(tvb, offset);
1343             guint each_elem;
1344
1345             offset += sizeof(guint16);
1346
1347             /* parse elements */
1348
1349             for (each_elem = 0; each_elem < elem_count; each_elem++) {
1350                 tvbuff_t *jxta_message_element_tvb = tvb_new_subset(tvb, offset, -1, -1);
1351                 int processed = dissect_jxta_message_element(jxta_message_element_tvb, pinfo, NULL, 0, NULL);
1352
1353                 if (processed < 0) {
1354                     needed = -processed;
1355                     break;
1356                 }
1357
1358                 if (0 == processed) {
1359                     /* XXX bondolo Not really clear what we should do! */
1360                     g_warning( "Failure processing message element #%d of %d of frame %d", each_elem, elem_count, pinfo->fd->num );
1361                     return 0;
1362                 }
1363
1364                 offset += processed;
1365             }
1366         }
1367
1368         break;
1369     }
1370
1371     if ((needed > 0) && gDESEGMENT && pinfo->can_desegment) {
1372         pinfo->desegment_offset = 0;
1373         pinfo->desegment_len = needed;
1374         return -needed;
1375     }
1376
1377     if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
1378         col_set_str(pinfo->cinfo, COL_PROTOCOL, "JXTA");
1379     }
1380
1381     if (check_col(pinfo->cinfo, COL_INFO)) {
1382         gchar src_addr[MAX_ADDR_STR_LEN];
1383         gchar dst_addr[MAX_ADDR_STR_LEN];
1384
1385         address_to_str_buf(&pinfo->src, src_addr, sizeof src_addr);
1386         address_to_str_buf(&pinfo->dst, dst_addr, sizeof dst_addr);
1387
1388         /* append the port if appropriate */
1389         if (PT_NONE != pinfo->ptype) {
1390             size_t len = strlen(src_addr);
1391             src_addr[len] = ':';
1392             g_snprintf(&src_addr[len + 1], 256 - len - 1, "%d", pinfo->srcport);
1393
1394             len = strlen(dst_addr);
1395             dst_addr[len] = ':';
1396             g_snprintf(&dst_addr[len + 1], 256 - len - 1, "%d", pinfo->destport);
1397         }
1398
1399         col_add_fstr(pinfo->cinfo, COL_INFO, "Message, %s -> %s", src_addr, dst_addr);
1400
1401         col_set_writable(pinfo->cinfo, FALSE);
1402     }
1403
1404     if (tree) {
1405         guint tree_offset = 0;
1406         proto_item *jxta_msg_tree_item = NULL;
1407         proto_tree *jxta_msg_tree = NULL;
1408         guint8 message_version;
1409         const gchar **namespaces = NULL;
1410         guint16 msg_ns_count;
1411         guint each_namespace;
1412         guint16 elem_count;
1413         guint each_elem;
1414         gchar src_addr[256];
1415         gchar dst_addr[256];
1416         proto_item *tree_item;
1417
1418         address_to_str_buf(&pinfo->src, src_addr, sizeof src_addr);
1419         address_to_str_buf(&pinfo->dst, dst_addr, sizeof dst_addr);
1420
1421         if (PT_NONE != pinfo->ptype) {
1422             size_t len = strlen(src_addr);
1423             src_addr[len] = ':';
1424             g_snprintf(&src_addr[len + 1], 256 - len - 1, "%d", pinfo->srcport);
1425
1426             len = strlen(dst_addr);
1427             dst_addr[len] = ':';
1428             g_snprintf(&dst_addr[len + 1], 256 - len - 1, "%d", pinfo->destport);
1429         }
1430
1431         jxta_msg_tree_item = proto_tree_add_protocol_format(tree, proto_message_jxta, tvb, tree_offset, -1,
1432                                                             "JXTA Message, %s -> %s", src_addr, dst_addr);
1433
1434         jxta_msg_tree = proto_item_add_subtree(jxta_msg_tree_item, ett_jxta_msg);
1435
1436         proto_tree_add_item(jxta_msg_tree, hf_jxta_message_sig, tvb, tree_offset, sizeof(JXTA_MSG_SIG), FALSE);
1437         tree_offset += sizeof(JXTA_MSG_SIG);
1438
1439         tree_item = proto_tree_add_string(jxta_msg_tree, hf_jxta_message_src, tvb, 0, 0, src_addr);
1440         PROTO_ITEM_SET_GENERATED(tree_item);
1441
1442         tree_item = proto_tree_add_string(jxta_msg_tree, hf_jxta_message_address, tvb, 0, 0, src_addr);
1443         PROTO_ITEM_SET_HIDDEN(tree_item);
1444         PROTO_ITEM_SET_GENERATED(tree_item);
1445
1446         tree_item = proto_tree_add_string(jxta_msg_tree, hf_jxta_message_dst, tvb, 0, 0, dst_addr);
1447         PROTO_ITEM_SET_GENERATED(tree_item);
1448
1449         tree_item = proto_tree_add_string(jxta_msg_tree, hf_jxta_message_address, tvb, 0, 0, dst_addr);
1450         PROTO_ITEM_SET_HIDDEN(tree_item);
1451         PROTO_ITEM_SET_GENERATED(tree_item);
1452
1453         message_version = tvb_get_guint8(tvb, tree_offset);
1454         proto_tree_add_uint(jxta_msg_tree, hf_jxta_message_version, tvb, tree_offset, sizeof(guint8), message_version);
1455         tree_offset += sizeof(guint8);
1456
1457         msg_ns_count = tvb_get_ntohs(tvb, tree_offset);
1458         proto_tree_add_uint(jxta_msg_tree, hf_jxta_message_namespaces_count, tvb, tree_offset, sizeof(guint16), msg_ns_count);
1459         tree_offset += sizeof(guint16);
1460
1461         namespaces = ep_alloc((msg_ns_count + 2) * sizeof(const gchar *));
1462         namespaces[0] = "";
1463         namespaces[1] = "jxta";
1464
1465         /* parse namespaces */
1466         for (each_namespace = 0; each_namespace < msg_ns_count; each_namespace++) {
1467             guint16 namespace_len = tvb_get_ntohs(tvb, tree_offset);
1468
1469             namespaces[2 + each_namespace] = tvb_get_ephemeral_string(tvb, tree_offset + sizeof(namespace_len), namespace_len);
1470             proto_tree_add_item(jxta_msg_tree, hf_jxta_message_namespace_name, tvb, tree_offset, sizeof(namespace_len), FALSE);
1471             tree_offset += sizeof(namespace_len) + namespace_len;
1472         }
1473
1474         /* parse element count */
1475         elem_count = tvb_get_ntohs(tvb, tree_offset);
1476         proto_tree_add_item(jxta_msg_tree, hf_jxta_message_element_count, tvb, tree_offset, sizeof(guint16), FALSE);
1477         tree_offset += sizeof(guint16);
1478
1479         /* parse elements */
1480         for (each_elem = 0; each_elem < elem_count; each_elem++) {
1481             tvbuff_t *jxta_message_element_tvb = tvb_new_subset(tvb, tree_offset, -1, -1);
1482
1483             tree_offset +=
1484                 dissect_jxta_message_element(jxta_message_element_tvb, pinfo, jxta_msg_tree, msg_ns_count + 2, namespaces);
1485         }
1486
1487         proto_item_set_end(jxta_msg_tree_item, tvb, tree_offset);
1488
1489         DISSECTOR_ASSERT(tree_offset == offset);
1490     }
1491
1492     if ((offset > 0) && (AT_URI == pinfo->src.type) && (AT_URI == pinfo->dst.type)) {
1493         jxta_tap_header *tap_header = se_alloc(sizeof(jxta_tap_header));
1494
1495         tap_header->src_address = pinfo->src;
1496         tap_header->dest_address = pinfo->dst;
1497         tap_header->size = offset;
1498
1499         tap_queue_packet(jxta_tap, pinfo, tap_header);
1500     }
1501
1502     return offset;
1503 }
1504
1505 /**
1506 *   Dissect a tvbuff containing a JXTA Message Element.
1507 *
1508 *   @param  tvb The buffer to dissect.
1509 *   @param  pinfo Packet Info.
1510 *   @param  tree The protocol tree.
1511 *   @return Number of bytes from the tvbuff_t which were processed, 0 (zero) if
1512 *           the packet was not recognized as a JXTA packet and negative if the
1513 *           dissector needs more bytes in order to process a PDU.
1514 **/
1515 static int dissect_jxta_message_element(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, guint ns_count,
1516                                         const gchar ** namespaces)
1517 {
1518     guint offset = 0;
1519     guint available;
1520     gint needed = 0;
1521     guint8 flags;
1522
1523     /* First pass. Make sure all of the bytes we need are available */
1524
1525     while (TRUE) {
1526         /* signature field */
1527         available = tvb_reported_length_remaining(tvb, offset);
1528         if (available < sizeof(JXTA_MSGELEM_SIG)) {
1529             needed = (gint) (sizeof(JXTA_MSGELEM_SIG) - available);
1530         }
1531
1532         if (tvb_memeql(tvb, offset, JXTA_MSGELEM_SIG, sizeof(JXTA_MSGELEM_SIG)) != 0) {
1533             /* It is not one of ours */
1534             return 0;
1535         }
1536
1537         offset += sizeof(JXTA_MSGELEM_SIG);
1538
1539         /* namespace id field */
1540         available = tvb_reported_length_remaining(tvb, offset);
1541         if (available < sizeof(guint8)) {
1542             needed = (gint) (sizeof(guint8) - available);
1543             break;
1544         }
1545
1546         offset += sizeof(guint8);
1547
1548         /* flags field */
1549         available = tvb_reported_length_remaining(tvb, offset);
1550         if (available < sizeof(guint8)) {
1551             needed = (gint) (sizeof(guint8) - available);
1552             break;
1553         } else {
1554             flags = tvb_get_guint8(tvb, offset);
1555             offset += sizeof(guint8);
1556         }
1557
1558         /* name field */
1559         available = tvb_reported_length_remaining(tvb, offset);
1560         if (available < sizeof(guint16)) {
1561             needed = (gint) (sizeof(guint16) - available);
1562             break;
1563         } else {
1564             guint16 name_len = tvb_get_ntohs(tvb, offset);
1565             offset += sizeof(guint16);
1566
1567             available = tvb_reported_length_remaining(tvb, offset);
1568             if (available < name_len) {
1569                 needed = (gint) (name_len - available);
1570                 break;
1571             }
1572
1573             offset += name_len;
1574         }
1575
1576         /* type field */
1577         if ((flags & 0x01) != 0) {
1578             guint16 type_len;
1579
1580             available = tvb_reported_length_remaining(tvb, offset);
1581             if (available < sizeof(guint16)) {
1582                 needed = (gint) (sizeof(guint16) - available);
1583                 break;
1584             }
1585
1586             type_len = tvb_get_ntohs(tvb, offset);
1587             offset += sizeof(guint16);
1588
1589             available = tvb_reported_length_remaining(tvb, offset);
1590             if (available < type_len) {
1591                 needed = (gint) (type_len - available);
1592                 break;
1593             }
1594
1595             offset += type_len;
1596         }
1597
1598         /* encoding field */
1599         if ((flags & 0x02) != 0) {
1600             guint16 encoding_len;
1601
1602             available = tvb_reported_length_remaining(tvb, offset);
1603             if (available < sizeof(guint16)) {
1604                 needed = (gint) (sizeof(guint16) - available);
1605                 break;
1606             }
1607
1608             encoding_len = tvb_get_ntohs(tvb, offset);
1609             offset += sizeof(guint16);
1610
1611             available = tvb_reported_length_remaining(tvb, offset);
1612             if (available < encoding_len) {
1613                 needed = (gint) (encoding_len - available);
1614                 break;
1615             }
1616
1617             offset += encoding_len;
1618         }
1619
1620         /* content field */
1621         available = tvb_reported_length_remaining(tvb, offset);
1622         if (available < sizeof(guint16)) {
1623             needed = (gint) (sizeof(guint16) - available);
1624             break;
1625         } else {
1626             guint32 content_len = tvb_get_ntohl(tvb, offset);
1627             offset += sizeof(guint32);
1628
1629             available = tvb_reported_length_remaining(tvb, offset);
1630             if (available < content_len) {
1631                 needed = (gint) (content_len - available);
1632                 break;
1633             }
1634
1635             offset += content_len;
1636         }
1637
1638         /* signature element field */
1639         if ((flags & 0x04) != 0) {
1640             tvbuff_t *jxta_signature_element_tvb;
1641             int processed;
1642
1643             jxta_signature_element_tvb = tvb_new_subset(tvb, offset, -1, -1);
1644
1645             processed = dissect_jxta_message_element(jxta_signature_element_tvb, pinfo, NULL, 0, NULL);
1646
1647             if (processed == 0) {
1648                 return offset;
1649             }
1650
1651             if (processed < 0) {
1652                 needed = -processed;
1653                 break;
1654             }
1655
1656             offset += processed;
1657         }
1658
1659         break;
1660     }
1661
1662     if ((needed > 0) && gDESEGMENT && pinfo->can_desegment) {
1663         pinfo->desegment_offset = 0;
1664         pinfo->desegment_len = needed;
1665         return -needed;
1666     }
1667
1668     /* Second (optional) pass : build the proto tree */
1669     if (tree) {
1670         guint tree_offset = 0;
1671         proto_item *jxta_elem_tree_item = proto_tree_add_item(tree, hf_jxta_element, tvb, tree_offset, -1, FALSE);
1672         proto_tree *jxta_elem_tree = proto_item_add_subtree(jxta_elem_tree_item, ett_jxta_elem);
1673         guint8 namespaceID;
1674         proto_item *namespace_ti;
1675         guint16 name_len;
1676         proto_item *flags_ti;
1677         proto_tree *jxta_elem_flags_tree = NULL;
1678         guint32 content_len;
1679         gchar *mediatype = NULL;
1680         gboolean media_type_recognized = FALSE;
1681         tvbuff_t *element_content_tvb;
1682         proto_item * jxta_elem_length_item = NULL;
1683
1684         proto_tree_add_item(jxta_elem_tree, hf_jxta_element_sig, tvb, tree_offset, sizeof(JXTA_MSGELEM_SIG), FALSE);
1685         tree_offset += sizeof(JXTA_MSGELEM_SIG);
1686
1687         namespaceID = tvb_get_guint8(tvb, tree_offset);
1688         namespace_ti =
1689             proto_tree_add_uint(jxta_elem_tree, hf_jxta_element_namespaceid, tvb, tree_offset, sizeof(guint8), namespaceID);
1690         if (namespaceID < ns_count) {
1691             proto_item_append_text(namespace_ti, " (%s)", namespaces[namespaceID]);
1692         } else {
1693             proto_item_append_text(namespace_ti, " * BAD *");
1694         }
1695         tree_offset += sizeof(guint8);
1696
1697         flags = tvb_get_guint8(tvb, tree_offset);
1698         flags_ti = proto_tree_add_uint(jxta_elem_tree, hf_jxta_element_flags, tvb, tree_offset, sizeof(guint8), flags);
1699         jxta_elem_flags_tree = proto_item_add_subtree(flags_ti, ett_jxta_elem_flags);
1700         proto_tree_add_boolean(jxta_elem_flags_tree, hf_jxta_element_flag_hasType, tvb, tree_offset, 1, flags);
1701         proto_tree_add_boolean(jxta_elem_flags_tree, hf_jxta_element_flag_hasEncoding, tvb, tree_offset, 1, flags);
1702         proto_tree_add_boolean(jxta_elem_flags_tree, hf_jxta_element_flag_hasSignature, tvb, tree_offset, 1, flags);
1703         tree_offset += sizeof(guint8);
1704
1705         name_len = tvb_get_ntohs(tvb, tree_offset);
1706         proto_item_append_text(jxta_elem_tree_item, " \"%s\"", tvb_format_text(tvb, tree_offset + sizeof(guint16), name_len));
1707         proto_tree_add_item(jxta_elem_tree, hf_jxta_element_name, tvb, tree_offset, sizeof(guint16), FALSE);
1708         tree_offset += sizeof(guint16) + name_len;
1709
1710         /* process type */
1711         if ((flags & 0x01) != 0) {
1712             guint16 type_len = tvb_get_ntohs(tvb, tree_offset);
1713             proto_tree_add_item(jxta_elem_tree, hf_jxta_element_type, tvb, tree_offset, sizeof(guint16), FALSE);
1714             tree_offset += sizeof(guint16);
1715
1716             mediatype = tvb_get_ephemeral_string(tvb, tree_offset, type_len);
1717
1718             /* remove any params */
1719             {
1720                 gchar *parms_at = strchr(mediatype, ';');
1721
1722                 if (NULL != parms_at) {
1723                     *parms_at = '\0';
1724                 }
1725             }
1726
1727             /* force to lower case */
1728 #if GLIB_MAJOR_VERSION < 2
1729             g_strdown(mediatype);
1730 #else
1731             {
1732                 gchar *mediatype_lowercase = g_ascii_strdown(mediatype, -1);
1733                 mediatype = mediatype_lowercase;
1734             }
1735 #endif
1736             tree_offset += type_len;
1737         }
1738
1739         /* process encoding */
1740         if ((flags & 0x02) != 0) {
1741             guint16 encoding_len = tvb_get_ntohs(tvb, tree_offset);
1742             proto_tree_add_item(jxta_elem_tree, hf_jxta_element_encoding, tvb, tree_offset, sizeof(guint16), FALSE);
1743             tree_offset += sizeof(guint16) + encoding_len;
1744         }
1745
1746         /* content */
1747         content_len = tvb_get_ntohl(tvb, tree_offset);
1748         jxta_elem_length_item = proto_tree_add_item(jxta_elem_tree, hf_jxta_element_content_len, tvb, tree_offset, sizeof(guint32), FALSE);
1749         tree_offset += sizeof(guint32);
1750
1751         element_content_tvb = tvb_new_subset(tvb, tree_offset, content_len, content_len);
1752
1753         if (mediatype) {
1754             if (0 == strcmp("application/x-jxta-tls-block", mediatype)) {
1755                 /* If we recognize it as a TLS packet then we shuffle it off to ssl dissector. */
1756                 dissector_handle_t ssl_handle = find_dissector("ssl");
1757                 if (NULL != ssl_handle) {
1758                     int processed = call_dissector(ssl_handle, element_content_tvb, pinfo, jxta_elem_tree);
1759                     media_type_recognized = processed != 0;
1760                 }
1761             } else if (0 == strcmp("application/gzip", mediatype)) {
1762                 tvbuff_t *uncomp_tvb = tvb_uncompress(element_content_tvb, 0, tvb_length(element_content_tvb));
1763
1764                 if( NULL != uncomp_tvb ) {
1765                     proto_item_append_text( jxta_elem_length_item, " -> (%u uncompressed)", tvb_length(uncomp_tvb) );
1766
1767                     tvb_set_child_real_data_tvbuff(element_content_tvb, uncomp_tvb);
1768                     add_new_data_source(pinfo, uncomp_tvb, "Uncompressed Element Content");
1769
1770                     /* XXX bondolo 20060201 Force XML for uncompressed data. */
1771                     media_type_recognized = dissector_try_string(media_type_dissector_table,
1772                                                              "text/xml", uncomp_tvb, pinfo, jxta_elem_tree);
1773                 }
1774             } else {
1775                 media_type_recognized = dissector_try_string(media_type_dissector_table,
1776                                                              mediatype, element_content_tvb, pinfo, jxta_elem_tree);
1777             }
1778
1779         }
1780
1781         if (!media_type_recognized) {
1782             /* display it as raw data */
1783             call_dissector(data_handle, element_content_tvb, pinfo, jxta_elem_tree);
1784         }
1785         tree_offset += content_len;
1786
1787         /* process the signature element */
1788         if ((flags & 0x04) != 0) {
1789             tvbuff_t *jxta_message_element_tvb = tvb_new_subset(tvb, tree_offset, -1, -1);
1790
1791             tree_offset += dissect_jxta_message_element(jxta_message_element_tvb, pinfo, jxta_elem_tree, ns_count, namespaces);
1792         }
1793
1794         proto_item_set_end(jxta_elem_tree_item, tvb, tree_offset);
1795
1796         DISSECTOR_ASSERT(tree_offset == offset);
1797     }
1798
1799     return offset;
1800 }
1801
1802 /**
1803 *    Register jxta protocol and jxta message protocol, header fields, subtree types, preferences.
1804 **/
1805 void proto_register_jxta(void)
1806 {
1807     module_t *jxta_module;
1808
1809     media_type_dissector_table = find_dissector_table("media_type");
1810
1811     data_handle = find_dissector("data");
1812
1813     proto_jxta = proto_register_protocol("JXTA P2P", "JXTA", "jxta");
1814
1815     jxta_tap = register_tap("jxta");
1816
1817     /* The JXTA Binary Message Wire Format : Registered and dissected by MIME type */
1818     proto_message_jxta = proto_register_protocol("JXTA Message", "JXTA Message", "jxta.message");
1819
1820     message_jxta_handle = new_create_dissector_handle(dissect_jxta_message, proto_message_jxta);
1821
1822     dissector_add_string("media_type", "application/x-jxta-msg", message_jxta_handle);
1823
1824     /* Register header fields */
1825     proto_register_field_array(proto_jxta, hf, array_length(hf));
1826
1827     /* Register JXTA Sub-tree */
1828     proto_register_subtree_array(ett, array_length(ett));
1829
1830     /* Register preferences */
1831     /* register re-init routine */
1832     jxta_module = prefs_register_protocol(proto_jxta, proto_reg_handoff_jxta);
1833
1834     prefs_register_bool_preference(jxta_module, "desegment",
1835                                    "Reassemble JXTA messages spanning multiple UDP/TCP/HTTP segments",
1836                                    "Whether the JXTA dissector should reassemble messages spanning multiple UDP/HTTP/TCP segments."
1837                                    " To use this option you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings "
1838                                    " and enable \"Reassemble fragmented IP datagrams\" in the IP protocol settings.",
1839                                    &gDESEGMENT);
1840
1841     prefs_register_bool_preference(jxta_module, "udp.heuristic", "Try to discover JXTA in UDP datagrams",
1842                                    "Enable to inspect UDP datagrams for JXTA messages.", &gUDP_HEUR);
1843
1844     prefs_register_bool_preference(jxta_module, "tcp.heuristic", "Try to discover JXTA in TCP connections",
1845                                    "Enable to inspect TCP connections for JXTA conversations.", &gTCP_HEUR);
1846
1847     prefs_register_bool_preference(jxta_module, "sctp.heuristic", "Try to discover JXTA in SCTP connections",
1848                                    "Enable to inspect SCTP connections for JXTA conversations.", &gSCTP_HEUR);
1849 }
1850
1851 /**
1852 *   Update registrations in response to
1853 **/
1854 void proto_reg_handoff_jxta(void)
1855 {
1856     static gboolean init_done = FALSE;
1857
1858     if (!init_done) {
1859         /* XXX 20051004 bondolo We could dynamically add dissectors based upon prefs. */
1860         new_register_dissector("jxta.udp", dissect_jxta_udp, proto_jxta);
1861         heur_dissector_add("udp", dissect_jxta_UDP_heur, proto_jxta);
1862
1863         new_register_dissector("jxta.stream", dissect_jxta_stream, proto_jxta);
1864         stream_jxta_handle = find_dissector("jxta.stream");
1865         heur_dissector_add("tcp", dissect_jxta_TCP_heur, proto_jxta);
1866         heur_dissector_add("sctp", dissect_jxta_SCTP_heur, proto_jxta);
1867
1868         init_done = TRUE;
1869     }
1870 }