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