3 * Routines for JXTA packet dissection
4 * JXTA specification from https://jxta-spec.dev.java.net
6 * Copyright 2004-08, Mike Duigou <bondolo@dev.java.net>
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
15 * Wireshark - Network traffic analyzer
16 * By Gerald Combs <gerald@wireshark.org>
17 * Copyright 2000 Gerald Combs
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.
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.
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.
36 #define G_LOG_DOMAIN "jxta"
40 #include <wsutil/str_util.h>
42 #include <epan/packet.h>
43 #include <epan/conversation.h>
44 #include <epan/strutil.h>
45 #include <epan/prefs.h>
47 #include <epan/emem.h>
49 #include "packet-jxta.h"
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' };
55 static const gchar JXTA_WELCOME_MSG_SIG[] = { 'J', 'X', 'T', 'A', 'H', 'E', 'L', 'L', 'O', ' ' };
57 static const gchar* JXTA_WELCOME_MSG_VERSION_1_1 = "1.1";
58 static const gchar* JXTA_WELCOME_MSG_VERSION_3_0 = "3.0";
60 static const int JXTA_MSG_VERSION_1 = 0;
61 static const int JXTA_MSG_VERSION_2 = 1;
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;
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;
73 static int proto_jxta = -1;
74 static int proto_message_jxta = -1;
75 static int jxta_tap = -1;
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;
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;
138 * JXTA Protocol subtree handles
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;
152 * JXTA Protocol subtree array
154 static gint *const ett[] = {
159 &ett_jxta_framing_header,
163 &ett_jxta_elem_1_flags,
164 &ett_jxta_elem_2_flags
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;
177 * Stream Conversation data
179 struct jxta_stream_conversation_data {
182 address initiator_tpt_address;
183 guint32 initiator_tpt_port;
184 guint32 initiator_welcome_frame;
185 address initiator_address;
187 address receiver_tpt_address;
188 guint32 receiver_tpt_port;
189 guint32 receiver_welcome_frame;
190 address receiver_address;
193 typedef struct jxta_stream_conversation_data jxta_stream_conversation_data;
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);
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);
213 void proto_reg_handoff_jxta(void);
216 * Heuristically dissect a tvbuff containing a JXTA UDP Message
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
223 static gboolean dissect_jxta_UDP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void * data _U_)
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!
229 int save_desegment_offset;
230 guint32 save_desegment_len;
233 if (tvb_memeql(tvb, 0, JXTA_UDP_SIG, sizeof(JXTA_UDP_SIG)) != 0) {
237 save_desegment_offset = pinfo->desegment_offset;
238 save_desegment_len = pinfo->desegment_len;
239 ret = dissect_jxta_udp(tvb, pinfo, tree, NULL);
241 /* g_message( "%d Heuristic UDP Dissection : %d", pinfo->fd->num, ret ); */
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.
251 pinfo->desegment_offset = save_desegment_offset;
252 pinfo->desegment_len = save_desegment_len;
254 } else if (ret == 0) {
258 pinfo->desegment_offset = save_desegment_offset;
259 pinfo->desegment_len = save_desegment_len;
263 * A clear acceptance.
270 * Heuristically dissect a tvbuff containing a JXTA TCP Stream
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
277 static gboolean dissect_jxta_TCP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void * data _U_)
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!
283 int save_desegment_offset;
284 guint32 save_desegment_len;
287 save_desegment_offset = pinfo->desegment_offset;
288 save_desegment_len = pinfo->desegment_len;
289 ret = dissect_jxta_stream(tvb, pinfo, tree, NULL);
291 /* g_message( "%d Heuristic TCP Dissection : %d", pinfo->fd->num, ret ); */
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.
302 * Therefore, we treat a negative return from
303 * dissect_jxta_stream() as a rejection.
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.
311 pinfo->desegment_offset = save_desegment_offset;
312 pinfo->desegment_len = save_desegment_len;
314 } else if (ret == 0) {
318 pinfo->desegment_offset = save_desegment_offset;
319 pinfo->desegment_len = save_desegment_len;
323 * A clear acceptance.
330 * Heuristically dissect a tvbuff containing a JXTA SCTP Stream
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
337 static gboolean dissect_jxta_SCTP_heur(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void * data _U_)
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!
343 int save_desegment_offset;
344 guint32 save_desegment_len;
347 save_desegment_offset = pinfo->desegment_offset;
348 save_desegment_len = pinfo->desegment_len;
349 ret = dissect_jxta_stream(tvb, pinfo, tree, NULL);
351 /* g_message( "%d Heuristic SCTP Dissection : %d", pinfo->fd->num, ret ); */
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.
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
367 pinfo->desegment_offset = save_desegment_offset;
368 pinfo->desegment_len = save_desegment_len;
370 } else if (ret == 0) {
374 pinfo->desegment_offset = save_desegment_offset;
375 pinfo->desegment_len = save_desegment_len;
379 * A clear acceptance.
386 * Dissect a tvbuff containing a JXTA UDP header, JXTA Message framing and a JXTA Message
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.
395 static int dissect_jxta_udp(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void * data _U_)
401 conversation_t *conversation = find_or_create_conversation(pinfo);
403 DISSECTOR_ASSERT(find_dissector("jxta.udp"));
405 conversation_set_dissector(conversation, find_dissector("jxta.udp"));
408 tvbuff_t *jxta_message_framing_tvb;
410 guint64 content_length = -1;
411 gchar *content_type = NULL;
413 available = tvb_reported_length_remaining(tvb, offset);
414 if (available < sizeof(JXTA_UDP_SIG)) {
415 needed = (gint) (sizeof(JXTA_UDP_SIG) - available);
419 if (tvb_memeql(tvb, offset, JXTA_UDP_SIG, sizeof(JXTA_UDP_SIG)) != 0) {
424 offset += (int)sizeof(JXTA_UDP_SIG);
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);
429 if ((0 == processed) || (NULL == content_type) || (content_length <= 0) || (content_length > UINT_MAX)) {
430 /** Buffer did not begin with valid framing headers */
441 available = tvb_reported_length_remaining(tvb, offset);
442 if (available < content_length) {
443 needed = (gint) (content_length - available);
447 offset += (guint) content_length;
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;
459 col_set_str(pinfo->cinfo, COL_PROTOCOL, "JXTA");
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;
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);
477 jxta_message_framing_tvb = tvb_new_subset_remaining(tvb, tree_offset);
479 tree_offset += dissect_jxta_message_framing(jxta_message_framing_tvb, pinfo, jxta_tree, &content_length, &content_type);
481 jxta_message_tvb = tvb_new_subset(tvb, tree_offset, (gint) content_length, (gint) content_length);
483 tree_offset += dissect_media(content_type, jxta_message_tvb, pinfo, tree);
485 proto_item_set_end(jxta_udp_tree_item, tvb, tree_offset);
487 DISSECTOR_ASSERT(offset == tree_offset);
494 * Dissect a tvbuff containing JXTA stream PDUs. This commonly includes
495 * connections over TCP sockets.
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
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.
508 static int dissect_jxta_stream(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void * data _U_)
511 guint available = tvb_reported_length_remaining(tvb, offset);
514 jxta_stream_conversation_data *tpt_conv_data = NULL;
515 proto_item *jxta_tree_item = NULL;
516 proto_tree *jxta_tree = NULL;
518 /* g_message("Dissecting%s : %d", (NULL != tree) ? " for display" : "", pinfo->fd->num ); */
520 if (available < sizeof(JXTA_WELCOME_MSG_SIG)) {
521 needed = (gint) (sizeof(JXTA_WELCOME_MSG_SIG) - available);
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;
530 tpt_conv_data = get_tpt_conversation(pinfo);
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;
539 welcome_addr = &tpt_conv_data->initiator_address;
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;
552 welcome_addr = &tpt_conv_data->initiator_address;
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;
561 welcome_addr = &tpt_conv_data->receiver_address;
566 processed = dissect_jxta_welcome(tvb, pinfo, NULL, welcome_addr, initiator);
568 if( processed < 0 ) {
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);
577 processed = dissect_jxta_welcome(tvb, pinfo, jxta_tree, welcome_addr, initiator);
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);
584 if ((0 == headers_len) || (NULL == content_type) || (content_length <= 0) || (content_length > UINT_MAX)) {
585 /** Buffer did not begin with valid framing headers */
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); */
595 if (headers_len < 0) {
596 /* negative headers_len means we need more bytes */
597 needed = -headers_len;
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;
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);
609 /* Redo header processing, this time populating the tree. */
610 headers_len = dissect_jxta_message_framing(tvb, pinfo, jxta_tree, &content_length, &content_type);
612 tpt_conv_data = get_tpt_conversation(pinfo);
613 peer_conversation = get_peer_conversation(pinfo, tpt_conv_data, TRUE);
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); */
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;
628 pinfo->dst = tpt_conv_data->receiver_address;
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;
638 pinfo->dst = tpt_conv_data->initiator_address;
640 pinfo->ptype = PT_NONE;
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); */
648 processed = headers_len;
650 processed += dissect_media(content_type, jxta_message_tvb, pinfo, tree);
652 /* we need more bytes before we can process message body. */
653 needed = (gint) ((guint) content_length - available);
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;
672 * Find or possibly create a transport conversation object for the connection
673 * which is associated with the packet info.
675 * @param pinfo The packet info from the underlying transport.
677 static jxta_stream_conversation_data *get_tpt_conversation(packet_info * pinfo)
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;
683 if (tpt_conversation == NULL) {
685 * No conversation exists yet - create one.
688 conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
691 conversation_set_dissector(tpt_conversation, stream_jxta_handle);
693 tpt_conv_data = (jxta_stream_conversation_data *) conversation_get_proto_data(tpt_conversation, proto_jxta);
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;
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;
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;
713 conversation_add_proto_data(tpt_conversation, proto_jxta, tpt_conv_data);
716 return tpt_conv_data;
720 * Find or possibly create a peer conversation object for the connection
721 * which is associated with the packet info.
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.
726 static conversation_t *get_peer_conversation(packet_info * pinfo, jxta_stream_conversation_data* tpt_conv_data, gboolean create)
728 conversation_t * peer_conversation = NULL;
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);
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);
742 return peer_conversation;
746 * Dissect a tvbuff containing a JXTA Welcome Message
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.
757 static int dissect_jxta_welcome(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, address * found_addr, gboolean initiator)
762 guint available = tvb_reported_length_remaining(tvb, offset);
763 gchar **tokens = NULL;
765 if (available < sizeof(JXTA_WELCOME_MSG_SIG)) {
766 return (gint) (available - sizeof(JXTA_WELCOME_MSG_SIG));
769 if (0 != tvb_memeql(tvb, 0, JXTA_WELCOME_MSG_SIG, sizeof(JXTA_WELCOME_MSG_SIG))) {
774 first_linelen = tvb_find_line_end(tvb, offset, -1, &afterwelcome, gDESEGMENT && pinfo->can_desegment);
776 if (-1 == first_linelen) {
777 if (available > 4096) {
778 /* it's too far too be reasonable */
781 /* ask for more bytes */
786 /* Dissect the Welcome Message */
788 col_set_str(pinfo->cinfo, COL_PROTOCOL, "JXTA");
790 col_set_str(pinfo->cinfo, COL_INFO, "Welcome");
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;
799 tokens = g_strsplit(welcomeline, " ", 255);
800 current_token = tokens;
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);
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);
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);
820 token_offset += (guint) strlen(*current_token) + 1;
823 /* invalid welcome message */
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),
834 token_offset += (guint) strlen(*current_token) + 1;
837 /* invalid welcome message */
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);
847 token_offset += (guint) strlen(*current_token) + 1;
850 /* invalid welcome message */
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);
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);
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);
871 token_offset += (guint) strlen(*current_token) + 1;
874 /* invalid welcome message */
879 if (NULL != *current_token) {
880 int variable_tokens = 0;
881 gchar **variable_token = current_token;
883 while(NULL != *variable_token) {
888 if( variable_tokens < 1 ) {
889 /* invalid welcome message */
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);
899 token_offset += (guint) strlen(*current_token) + 1;
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);
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);
910 token_offset += (guint) strlen(*current_token) + 1;
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);
917 token_offset += (guint) strlen(*current_token) + 1;
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);
924 /* Unrecognized Welcome Version */
925 int each_variable_token;
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);
933 proto_item_append_text(jxta_welcome_tree_item, " (UNRECOGNIZED)");
936 token_offset += (guint) strlen(*current_token) + 1;
941 /* invalid welcome message */
950 col_set_writable(pinfo->cinfo, FALSE);
956 * Dissect a tvbuff containing JXTA Message framing.
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.
969 static int dissect_jxta_message_framing(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, guint64 * content_length,
970 gchar ** content_type)
977 * First go around. Make sure all of the bytes are there.
980 guint8 headername_len;
981 guint8 headername_offset;
982 guint16 headervalue_len;
983 guint16 headervalue_offset;
985 available = tvb_reported_length_remaining(tvb, offset);
986 if (available < sizeof(guint8)) {
987 needed = (gint) (sizeof(guint8) - available);
990 headername_len = tvb_get_guint8(tvb, offset);
991 offset += (int)sizeof(guint8);
992 headername_offset = offset;
994 available = tvb_reported_length_remaining(tvb, offset);
995 if (available < headername_len) {
996 needed = (gint) (headername_len - available);
1000 if (0 == headername_len) {
1003 offset += headername_len;
1006 available = tvb_reported_length_remaining(tvb, offset);
1007 if (available < sizeof(guint16)) {
1008 needed = (gint) (sizeof(guint16) - available);
1011 headervalue_len = tvb_get_ntohs(tvb, offset);
1012 offset += (int)sizeof(guint16);
1013 headervalue_offset = offset;
1015 available = tvb_reported_length_remaining(tvb, offset);
1016 if (available < headervalue_len) {
1017 needed = (gint) (headervalue_len - available);
1021 offset += headervalue_len;
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);
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);
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;
1046 * Second (optional pass) Now that we are sure that all the bytes are there we update the protocol 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);
1054 /* parse framing headers */
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);
1062 * Put header name into the protocol tree
1064 proto_tree_add_item(framing_header_tree, hf_jxta_framing_header_name, tvb, tree_offset, (int)sizeof(gint8), ENC_ASCII|ENC_NA);
1067 * Append header name into the header protocol item. It's a nice hint so you don't have to reveal all headers.
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));
1074 tree_offset += (int)sizeof(guint8) + headernamelen;
1076 if (headernamelen > 0) {
1077 guint16 headervaluelen = tvb_get_ntohs(tvb, tree_offset);
1080 proto_tree_add_uint(framing_header_tree, hf_jxta_framing_header_value_length, tvb, tree_offset,
1081 (int)sizeof(guint16), headervaluelen);
1083 /** TODO bondolo Add specific handling for known header types */
1086 * Put header value into protocol tree.
1088 proto_tree_add_item(framing_header_tree, hf_jxta_framing_header_value, tvb, tree_offset + (int)sizeof(guint16),
1089 headervaluelen, ENC_NA);
1092 tree_offset += (int)sizeof(guint16) + headervaluelen;
1095 proto_item_set_end(framing_header_tree_item, tvb, tree_offset);
1097 if (0 == headernamelen) {
1102 proto_item_set_end(framing_tree_item, tvb, tree_offset);
1104 DISSECTOR_ASSERT(offset == tree_offset);
1107 /* return how many bytes we used up. */
1112 * Dissect a tvbuff containing one or more JXTA Messages.
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.
1121 static int dissect_jxta_message(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void * data _U_)
1123 gint complete_messages = 0;
1125 guint tree_offset = 0;
1128 emem_strbuf_t* src_addr;
1129 emem_strbuf_t* dst_addr;
1132 guint8 message_version;
1133 guint message_start_offset = offset;
1135 /* First pass. Make sure all of the bytes we need are available */
1136 available = tvb_reported_length_remaining(tvb, offset);
1138 if((0 == available) && (0 != complete_messages)) {
1139 /* We have discovered all of the complete messages in the tvbuff. */
1143 if (available < sizeof(JXTA_MSG_SIG)) {
1144 needed = (gint) (sizeof(JXTA_MSG_SIG) - available);
1148 if (tvb_memeql(tvb, offset, JXTA_MSG_SIG, sizeof(JXTA_MSG_SIG)) != 0) {
1149 /* It is not one of ours */
1153 offset += (int)sizeof(JXTA_MSG_SIG);
1155 available = tvb_reported_length_remaining(tvb, offset);
1156 if (available < sizeof(guint8)) {
1157 needed = (gint) (sizeof(guint8) - available);
1160 message_version = tvb_get_guint8(tvb, offset);
1162 offset += (int)sizeof(guint8);
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. */
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);
1177 offset += (int)sizeof(guint8);
1181 /* Read names table */
1182 available = tvb_reported_length_remaining(tvb, offset);
1183 if (available < sizeof(guint16)) {
1184 needed = (gint) (sizeof(guint16) - available);
1187 guint16 msg_names_count = tvb_get_ntohs(tvb, offset);
1190 offset += (int)sizeof(guint16);
1192 for (each_name = 0; each_name < msg_names_count; each_name++) {
1195 available = tvb_reported_length_remaining(tvb, offset);
1196 if (available < sizeof(name_len)) {
1197 needed = (gint) (sizeof(name_len) - available);
1201 name_len = tvb_get_ntohs(tvb, offset);
1203 available = tvb_reported_length_remaining(tvb, offset + (int)sizeof(name_len));
1204 if (available < name_len) {
1205 needed = (gint) (name_len - available);
1209 offset += (int)sizeof(name_len) + name_len;
1213 /* parse element count */
1214 available = tvb_reported_length_remaining(tvb, offset);
1215 if (available < sizeof(guint16)) {
1216 needed = (gint) (sizeof(guint16) - available);
1219 guint16 elem_count = tvb_get_ntohs(tvb, offset);
1222 offset += (int)sizeof(guint16);
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);
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);
1234 /* Sort of a lie, we say that we don't recognize it at all. */
1238 if (processed < 0) {
1239 needed = -processed;
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 );
1249 offset += processed;
1253 if ((AT_URI == pinfo->src.type) && (AT_URI == pinfo->dst.type)) {
1254 jxta_tap_header *tap_header = se_alloc(sizeof(jxta_tap_header));
1256 tap_header->src_address = pinfo->src;
1257 tap_header->dest_address = pinfo->dst;
1258 tap_header->size = offset - message_start_offset ;
1260 tap_queue_packet(jxta_tap, pinfo, tap_header);
1263 complete_messages++;
1265 /* g_message( "%d Scanned message #%d: ", pinfo->fd->num, complete_messages ); */
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;
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));
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);
1284 col_set_str(pinfo->cinfo, COL_PROTOCOL, "JXTA");
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);
1290 col_add_fstr(pinfo->cinfo, COL_INFO, "Message, %s -> %s", src_addr->str, dst_addr->str);
1293 col_set_writable(pinfo->cinfo, FALSE);
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;
1305 proto_item *tree_item;
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);
1310 jxta_msg_tree = proto_item_add_subtree(jxta_msg_tree_item, ett_jxta_msg);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
1364 names_table = ep_alloc((msg_names_count + 2) * sizeof(const gchar *));
1365 names_table[0] = "";
1366 names_table[1] = "jxta";
1369 for (each_name = 0; each_name < msg_names_count; each_name++) {
1370 guint16 name_len = tvb_get_ntohs(tvb, tree_offset);
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;
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);
1382 /* FIXME bondolo Element count 0 (Process elements until FIN) should be supported. */
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);
1388 if(JXTA_MSG_VERSION_1 == message_version) {
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) {
1393 dissect_jxta_message_element_2(jxta_message_element_tvb, pinfo, jxta_msg_tree, msg_names_count + 2, names_table);
1395 /* Sort of a lie, we say that we don't recognize it at all. */
1400 proto_item_set_end(jxta_msg_tree_item, tvb, tree_offset);
1402 complete_messages--;
1406 /* g_message( "%d tvb offset : %d tree offset : %d", pinfo->fd->num, offset, tree_offset ); */
1407 DISSECTOR_ASSERT(tree_offset == offset);
1414 * Dissect a tvbuff containing a JXTA Message Element (Version 1).
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.
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)
1431 /* First pass. Make sure all of the bytes we need are available */
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);
1440 if (tvb_memeql(tvb, offset, JXTA_MSGELEM_SIG, sizeof(JXTA_MSGELEM_SIG)) != 0) {
1441 /* It is not one of ours */
1445 offset += (int)sizeof(JXTA_MSGELEM_SIG);
1447 /* namespace id field */
1448 available = tvb_reported_length_remaining(tvb, offset);
1449 if (available < sizeof(guint8)) {
1450 needed = (gint) (sizeof(guint8) - available);
1454 offset += (int)sizeof(guint8);
1457 available = tvb_reported_length_remaining(tvb, offset);
1458 if (available < sizeof(guint8)) {
1459 needed = (gint) (sizeof(guint8) - available);
1462 flags = tvb_get_guint8(tvb, offset);
1463 offset += (int)sizeof(guint8);
1467 available = tvb_reported_length_remaining(tvb, offset);
1468 if (available < sizeof(guint16)) {
1469 needed = (gint) (sizeof(guint16) - available);
1472 guint16 name_len = tvb_get_ntohs(tvb, offset);
1473 offset += (int)sizeof(guint16);
1475 available = tvb_reported_length_remaining(tvb, offset);
1476 if (available < name_len) {
1477 needed = (gint) (name_len - available);
1485 if ((flags & JXTAMSG1_ELMFLAG_TYPE) != 0) {
1488 available = tvb_reported_length_remaining(tvb, offset);
1489 if (available < sizeof(guint16)) {
1490 needed = (gint) (sizeof(guint16) - available);
1494 type_len = tvb_get_ntohs(tvb, offset);
1495 offset += (int)sizeof(guint16);
1497 available = tvb_reported_length_remaining(tvb, offset);
1498 if (available < type_len) {
1499 needed = (gint) (type_len - available);
1506 /* encoding field */
1507 if ((flags & JXTAMSG1_ELMFLAG_ENCODING) != 0) {
1508 guint16 encoding_len;
1510 available = tvb_reported_length_remaining(tvb, offset);
1511 if (available < sizeof(guint16)) {
1512 needed = (gint) (sizeof(guint16) - available);
1516 encoding_len = tvb_get_ntohs(tvb, offset);
1517 offset += (int)sizeof(guint16);
1519 available = tvb_reported_length_remaining(tvb, offset);
1520 if (available < encoding_len) {
1521 needed = (gint) (encoding_len - available);
1525 offset += encoding_len;
1529 available = tvb_reported_length_remaining(tvb, offset);
1530 if (available < sizeof(guint16)) {
1531 needed = (gint) (sizeof(guint16) - available);
1534 guint32 content_len = tvb_get_ntohl(tvb, offset);
1535 offset += (int)sizeof(guint32);
1537 available = tvb_reported_length_remaining(tvb, offset);
1538 if (available < content_len) {
1539 needed = (gint) (content_len - available);
1543 offset += content_len;
1546 /* signature element field */
1547 if ((flags & JXTAMSG1_ELMFLAG_SIGNATURE) != 0) {
1548 tvbuff_t *jxta_signature_element_tvb;
1551 jxta_signature_element_tvb = tvb_new_subset_remaining(tvb, offset);
1553 processed = dissect_jxta_message_element_1(jxta_signature_element_tvb, pinfo, NULL, 0, NULL);
1555 if (processed == 0) {
1559 if (processed < 0) {
1560 needed = -processed;
1564 offset += processed;
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;
1577 /* Second (optional) pass : build the proto tree */
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);
1583 proto_item *namespace_ti;
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;
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);
1594 namespaceID = tvb_get_guint8(tvb, tree_offset);
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]);
1600 proto_item_append_text(namespace_ti, " * BAD *");
1602 tree_offset += (int)sizeof(guint8);
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);
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;
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);
1623 mediatype = tvb_get_ephemeral_string(tvb, tree_offset, type_len);
1625 tree_offset += type_len;
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;
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);
1640 element_content_tvb = tvb_new_subset(tvb, tree_offset, content_len, content_len);
1642 tree_offset += dissect_media(mediatype, element_content_tvb, pinfo, jxta_elem_tree);
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);
1648 tree_offset += dissect_jxta_message_element_1(jxta_message_element_tvb, pinfo, jxta_elem_tree, ns_count, names_table);
1651 proto_item_set_end(jxta_elem_tree_item, tvb, tree_offset);
1653 DISSECTOR_ASSERT(tree_offset == offset);
1660 * Dissect a tvbuff containing a JXTA Message Element (Version 2).
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.
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)
1679 /* First pass. Make sure all of the bytes we need are available */
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);
1688 if (tvb_memeql(tvb, offset, JXTA_MSGELEM_SIG, sizeof(JXTA_MSGELEM_SIG)) != 0) {
1689 /* It is not one of ours */
1693 offset += (int)sizeof(JXTA_MSGELEM_SIG);
1696 available = tvb_reported_length_remaining(tvb, offset);
1697 if (available < sizeof(guint8)) {
1698 needed = (gint) (sizeof(guint8) - available);
1701 flags = tvb_get_guint8(tvb, offset);
1702 offset += (int)sizeof(guint8);
1705 /* namespace id field */
1706 available = tvb_reported_length_remaining(tvb, offset);
1707 if (available < sizeof(guint16)) {
1708 needed = (gint) (sizeof(guint16) - available);
1712 offset += (int)sizeof(guint16);
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);
1722 offset += (int)sizeof(guint16);
1724 /* literal name field */
1725 available = tvb_reported_length_remaining(tvb, offset);
1726 if (available < sizeof(guint16)) {
1727 needed = (gint) (sizeof(guint16) - available);
1730 guint16 name_len = tvb_get_ntohs(tvb, offset);
1731 offset += (int)sizeof(guint16);
1733 available = tvb_reported_length_remaining(tvb, offset);
1734 if (available < name_len) {
1735 needed = (gint) (name_len - available);
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);
1751 offset += (int)sizeof(guint16);
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);
1762 offset += (int)sizeof(guint16);
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);
1773 guint64 content_len = tvb_get_ntoh64(tvb, offset);
1774 offset += (int)sizeof(guint64);
1776 available = tvb_reported_length_remaining(tvb, offset);
1777 if (available < content_len) {
1778 needed = (gint) (content_len - available);
1782 offset += (guint) content_len;
1785 available = tvb_reported_length_remaining(tvb, offset);
1786 if (available < sizeof(guint32)) {
1787 needed = (gint) (sizeof(guint32) - available);
1790 guint64 content_len = tvb_get_ntohl(tvb, offset);
1791 offset += (int)sizeof(guint32);
1793 available = tvb_reported_length_remaining(tvb, offset);
1794 if (available < content_len) {
1795 needed = (gint) (content_len - available);
1799 offset += (guint) content_len;
1803 /* signature element field */
1804 if ((flags & JXTAMSG2_ELMFLAG_SIGNATURE) != 0) {
1805 tvbuff_t *jxta_signature_element_tvb;
1808 jxta_signature_element_tvb = tvb_new_subset_remaining(tvb, offset);
1810 processed = dissect_jxta_message_element_2(jxta_signature_element_tvb, pinfo, NULL, 0, NULL);
1812 if (processed == 0) {
1816 if (processed < 0) {
1817 needed = -processed;
1821 offset += processed;
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;
1834 /* Second (optional) pass : build the proto tree */
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;
1844 proto_item *name_ti;
1845 guint64 content_len;
1846 const gchar *mediatype = NULL;
1847 tvbuff_t *element_content_tvb;
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);
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);
1864 namespaceID = tvb_get_ntohs(tvb, tree_offset);
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]);
1870 proto_item_append_text(namespace_ti, " * BAD *");
1872 tree_offset += (int)sizeof(guint16);
1875 if ((flags & JXTAMSG2_ELMFLAG_NAME_LITERAL) == 0) {
1876 nameID = tvb_get_ntohs(tvb, tree_offset);
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]);
1882 proto_item_append_text(name_ti, " * BAD *");
1884 tree_offset += (int)sizeof(guint16);
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;
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);
1899 if (mimeID < names_count) {
1900 proto_item_append_text(mime_ti, " (%s)", names_table[mimeID]);
1901 mediatype = ep_strdup( names_table[mimeID] );
1903 proto_item_append_text(mime_ti, " * BAD *");
1906 tree_offset += (int)sizeof(guint16);
1908 mediatype = "application/octet-stream";
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);
1917 if (encodingID < names_count) {
1918 proto_item_append_text(encoding_ti, " (%s)", names_table[encodingID]);
1920 proto_item_append_text(encoding_ti, " * BAD *");
1923 tree_offset += (int)sizeof(guint16);
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);
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);
1938 element_content_tvb = tvb_new_subset(tvb, tree_offset, (gint)content_len, (gint)content_len);
1940 tree_offset += dissect_media(mediatype, element_content_tvb, pinfo, jxta_elem_tree);
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);
1946 tree_offset += dissect_jxta_message_element_1(jxta_message_element_tvb, pinfo, jxta_elem_tree, names_count, names_table);
1949 proto_item_set_end(jxta_elem_tree_item, tvb, tree_offset);
1951 DISSECTOR_ASSERT(tree_offset == offset);
1958 * Dissect a tvbuff containing arbitrary typed data.
1960 * <p/>We provide special handling for type media types :
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>
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.
1976 static int dissect_media( const gchar* fullmediatype, tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) {
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;
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 );
1990 pinfo->private_data = NULL;
1993 /* Set the version that goes to packet-media.c before converting case */
1994 pinfo->match_string = ep_strdup(mediatype);
1996 /* force to lower case */
1997 ascii_strdown_inplace(mediatype);
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);
2005 } else if (0 == strcmp("application/gzip", mediatype)) {
2006 tvbuff_t *uncomp_tvb = tvb_child_uncompress(tvb, tvb, 0, tvb_length(tvb));
2008 if( NULL != uncomp_tvb ) {
2009 add_new_data_source(pinfo, uncomp_tvb, "Uncompressed Element Content");
2011 /* XXX bondolo 20060201 Force XML for uncompressed data. */
2012 dissected = dissect_media("text/xml;charset=\"UTF-8\"", uncomp_tvb, pinfo, tree);
2014 if( dissected > 0 ) {
2015 /* report back the uncompressed length. */
2016 dissected = tvb_length(tvb);
2020 dissected = dissector_try_string(media_type_dissector_table, mediatype, tvb, pinfo, tree) ? tvb_length(tvb) : 0;
2022 if( dissected != (int) tvb_length(tvb) ) {
2023 /* g_message( "%s : %d expected, %d dissected", mediatype, tvb_length(tvb), dissected ); */
2027 if (0 == dissected) {
2028 dissected = call_dissector(media_handle, tvb, pinfo, tree);
2031 pinfo->match_string = save_match_string;
2032 pinfo->private_data = save_private_data;
2035 if(0 == dissected) {
2036 /* display it as raw data */
2037 dissected = call_dissector_only(data_handle, tvb, pinfo, tree, NULL);
2044 * Register jxta protocol and jxta message protocol, header fields, subtree types, preferences.
2046 void proto_register_jxta(void)
2048 module_t *jxta_module;
2050 /** our header fields */
2051 static hf_register_info hf[] = {
2053 {"Address", "jxta.uri.addr", FT_STRING, BASE_NONE, NULL, 0x0,
2054 "URI Address (source or destination)", HFILL}
2057 {"Source", "jxta.uri.src", FT_STRING, BASE_NONE, NULL, 0x0,
2058 "URI Source", HFILL}
2061 {"Destination", "jxta.uri.dst", FT_STRING, BASE_NONE, NULL, 0x0,
2062 "URI Destination", HFILL}
2065 {"JXTA UDP", "jxta.udp", FT_NONE, BASE_NONE, NULL, 0x0,
2069 {"Signature", "jxta.udpsig", FT_STRING, BASE_NONE, NULL, 0x0,
2070 "JXTA UDP Signature", HFILL}
2073 {"Welcome", "jxta.welcome", FT_NONE, BASE_NONE, NULL, 0x00,
2074 "JXTA Connection Welcome Message", HFILL}
2076 {&hf_jxta_welcome_initiator,
2077 {"Initiator", "jxta.welcome.initiator", FT_BOOLEAN, BASE_NONE, NULL, 0x00,
2078 "JXTA Connection Welcome Message Initiator", HFILL}
2080 {&hf_jxta_welcome_sig,
2081 {"Signature", "jxta.welcome.signature", FT_STRING, BASE_NONE, NULL, 0x0,
2082 "JXTA Connection Welcome Message Signature", HFILL}
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}
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}
2092 {&hf_jxta_welcome_peerid,
2093 {"PeerID", "jxta.welcome.peerid", FT_STRING, BASE_NONE, NULL, 0x0,
2094 "JXTA Connection Welcome Message PeerID", HFILL}
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}
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}
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}
2108 {&hf_jxta_welcome_version,
2109 {"Version", "jxta.welcome.version", FT_STRING, BASE_NONE, NULL, 0x0,
2110 "JXTA Connection Welcome Message Version", HFILL}
2113 {"Framing", "jxta.framing", FT_NONE, BASE_NONE, NULL, 0x0,
2114 "JXTA Message Framing", HFILL}
2116 {&hf_jxta_framing_header,
2117 {"Header", "jxta.framing.header", FT_NONE, BASE_NONE, NULL, 0x0,
2118 "JXTA Message Framing Header", HFILL}
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}
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}
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}
2132 {&hf_jxta_message_address,
2133 {"Address", "jxta.message.address", FT_STRING, BASE_NONE, NULL, 0x0,
2134 "JXTA Message Address (source or destination)", HFILL}
2136 {&hf_jxta_message_src,
2137 {"Source", "jxta.message.source", FT_STRING, BASE_NONE, NULL, 0x0,
2138 "JXTA Message Source", HFILL}
2140 {&hf_jxta_message_dst,
2141 {"Destination", "jxta.message.destination", FT_STRING, BASE_NONE, NULL, 0x0,
2142 "JXTA Message Destination", HFILL}
2144 {&hf_jxta_message_sig,
2145 {"Signature", "jxta.message.signature", FT_STRING, BASE_NONE, NULL, 0x0,
2146 "JXTA Message Signature", HFILL}
2148 {&hf_jxta_message_version,
2149 {"Version", "jxta.message.version", FT_UINT8, BASE_DEC, NULL, 0x0,
2150 "JXTA Message Version", HFILL}
2152 {&hf_jxta_message_flags,
2153 {"Flags", "jxta.message.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
2154 "JXTA Message Flags", HFILL}
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}
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}
2164 {&hf_jxta_message_names_count,
2165 {"Names Count", "jxta.message.names", FT_UINT16, BASE_DEC, NULL, 0x0,
2166 "JXTA Message Names Table", HFILL}
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}
2172 {&hf_jxta_message_element_count,
2173 {"Element Count", "jxta.message.elements", FT_UINT16, BASE_DEC, NULL, 0x0,
2174 "JXTA Message Element Count", HFILL}
2177 {"JXTA Message Element", "jxta.message.element", FT_NONE, BASE_NONE, NULL, 0x0,
2180 {&hf_jxta_element_sig,
2181 {"Signature", "jxta.message.element.signature", FT_STRING, BASE_NONE, NULL, 0x0,
2182 "JXTA Message Element Signature", HFILL}
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}
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}
2192 {&hf_jxta_element_flags,
2193 {"Flags", "jxta.message.element.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
2194 "JXTA Message Element Flags", HFILL}
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}
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}
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}
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}
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}
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}
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}
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}
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}
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}
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}
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}
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}
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}
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}
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}
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}
2264 {&hf_jxta_element_content,
2265 {"Element Content", "jxta.message.element.content", FT_BYTES, BASE_NONE, NULL, 0x0,
2266 "JXTA Message Element Content", HFILL}
2270 proto_jxta = proto_register_protocol("JXTA P2P", "JXTA", "jxta");
2272 jxta_tap = register_tap("jxta");
2274 proto_message_jxta = proto_register_protocol("JXTA Message", "JXTA Message", "jxta.message");
2276 new_register_dissector("jxta.udp", dissect_jxta_udp, proto_jxta);
2277 new_register_dissector("jxta.stream", dissect_jxta_stream, proto_jxta);
2279 /* Register header fields */
2280 proto_register_field_array(proto_jxta, hf, array_length(hf));
2282 /* Register JXTA Sub-tree */
2283 proto_register_subtree_array(ett, array_length(ett));
2285 /* Register preferences */
2286 /* register re-init routine */
2287 jxta_module = prefs_register_protocol(proto_jxta, proto_reg_handoff_jxta);
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);
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.",
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);
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);
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);
2311 * Update registrations in response to preferences changes.
2313 void proto_reg_handoff_jxta(void)
2315 static gboolean init_done = FALSE;
2316 static dissector_handle_t message_jxta_handle;
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;
2324 message_jxta_handle = new_create_dissector_handle(dissect_jxta_message, proto_message_jxta);
2325 stream_jxta_handle = find_dissector("jxta.stream");
2327 media_type_dissector_table = find_dissector_table("media_type");
2329 data_handle = find_dissector("data");
2330 media_handle = find_dissector("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;
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;
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;
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;
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;
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;
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;
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;