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