Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(216)

Unified Diff: net/tools/spdyshark/packet-spdy.c

Issue 68013005: Remove net/tools/spdyshark (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/tools/spdyshark/packet-spdy.h ('k') | net/tools/spdyshark/plugin.rc.in » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/tools/spdyshark/packet-spdy.c
diff --git a/net/tools/spdyshark/packet-spdy.c b/net/tools/spdyshark/packet-spdy.c
deleted file mode 100644
index becc585c0cb7a3e6115ae6feae9a146d8888f0dc..0000000000000000000000000000000000000000
--- a/net/tools/spdyshark/packet-spdy.c
+++ /dev/null
@@ -1,1532 +0,0 @@
-/* packet-spdy.c
- * Routines for SPDY packet disassembly
- * For now, the protocol spec can be found at
- * http://dev.chromium.org/spdy/spdy-protocol
- *
- * Copyright 2010, Google Inc.
- * Eric Shienbrood <ers@google.com>
- *
- * $Id$
- *
- * Wireshark - Network traffic analyzer
- * By Gerald Combs <gerald@wireshark.org>
- * Copyright 1998 Gerald Combs
- *
- * Originally based on packet-http.c
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <string.h>
-#include <ctype.h>
-
-#include <glib.h>
-#include <epan/conversation.h>
-#include <epan/packet.h>
-#include <epan/strutil.h>
-#include <epan/base64.h>
-#include <epan/emem.h>
-#include <epan/stats_tree.h>
-
-#include <epan/req_resp_hdrs.h>
-#include "packet-spdy.h"
-#include <epan/dissectors/packet-tcp.h>
-#include <epan/dissectors/packet-ssl.h>
-#include <epan/prefs.h>
-#include <epan/expert.h>
-#include <epan/uat.h>
-
-#define SPDY_FIN 0x01
-
-/* The types of SPDY control frames */
-typedef enum _spdy_type {
- SPDY_DATA,
- SPDY_SYN_STREAM,
- SPDY_SYN_REPLY,
- SPDY_FIN_STREAM,
- SPDY_HELLO,
- SPDY_NOOP,
- SPDY_PING,
- SPDY_INVALID
-} spdy_frame_type_t;
-
-static const char *frame_type_names[] = {
- "DATA", "SYN_STREAM", "SYN_REPLY", "FIN_STREAM", "HELLO", "NOOP",
- "PING", "INVALID"
-};
-
-/*
- * This structure will be tied to each SPDY frame.
- * Note that there may be multiple SPDY frames
- * in one packet.
- */
-typedef struct _spdy_frame_info_t {
- guint32 stream_id;
- guint8 *header_block;
- guint header_block_len;
- guint16 frame_type;
-} spdy_frame_info_t;
-
-/*
- * This structures keeps track of all the data frames
- * associated with a stream, so that they can be
- * reassembled into a single chunk.
- */
-typedef struct _spdy_data_frame_t {
- guint8 *data;
- guint32 length;
- guint32 framenum;
-} spdy_data_frame_t;
-
-typedef struct _spdy_stream_info_t {
- gchar *content_type;
- gchar *content_type_parameters;
- gchar *content_encoding;
- GSList *data_frames;
- tvbuff_t *assembled_data;
- guint num_data_frames;
-} spdy_stream_info_t;
-
-#include <epan/tap.h>
-
-
-static int spdy_tap = -1;
-static int spdy_eo_tap = -1;
-
-static int proto_spdy = -1;
-static int hf_spdy_syn_stream = -1;
-static int hf_spdy_syn_reply = -1;
-static int hf_spdy_control_bit = -1;
-static int hf_spdy_version = -1;
-static int hf_spdy_type = -1;
-static int hf_spdy_flags = -1;
-static int hf_spdy_flags_fin = -1;
-static int hf_spdy_length = -1;
-static int hf_spdy_header = -1;
-static int hf_spdy_header_name = -1;
-static int hf_spdy_header_name_text = -1;
-static int hf_spdy_header_value = -1;
-static int hf_spdy_header_value_text = -1;
-static int hf_spdy_streamid = -1;
-static int hf_spdy_associated_streamid = -1;
-static int hf_spdy_priority = -1;
-static int hf_spdy_num_headers = -1;
-static int hf_spdy_num_headers_string = -1;
-
-static gint ett_spdy = -1;
-static gint ett_spdy_syn_stream = -1;
-static gint ett_spdy_syn_reply = -1;
-static gint ett_spdy_fin_stream = -1;
-static gint ett_spdy_flags = -1;
-static gint ett_spdy_header = -1;
-static gint ett_spdy_header_name = -1;
-static gint ett_spdy_header_value = -1;
-
-static gint ett_spdy_encoded_entity = -1;
-
-static dissector_handle_t data_handle;
-static dissector_handle_t media_handle;
-static dissector_handle_t spdy_handle;
-
-/* Stuff for generation/handling of fields for custom HTTP headers */
-typedef struct _header_field_t {
- gchar* header_name;
- gchar* header_desc;
-} header_field_t;
-
-/*
- * desegmentation of SPDY control frames
- * (when we are over TCP or another protocol providing the desegmentation API)
- */
-static gboolean spdy_desegment_control_frames = TRUE;
-
-/*
- * desegmentation of SPDY data frames bodies
- * (when we are over TCP or another protocol providing the desegmentation API)
- * TODO let the user filter on content-type the bodies he wants desegmented
- */
-static gboolean spdy_desegment_data_frames = TRUE;
-
-static gboolean spdy_assemble_entity_bodies = TRUE;
-
-/*
- * Decompression of zlib encoded entities.
- */
-#ifdef HAVE_LIBZ
-static gboolean spdy_decompress_body = TRUE;
-static gboolean spdy_decompress_headers = TRUE;
-#else
-static gboolean spdy_decompress_body = FALSE;
-static gboolean spdy_decompress_headers = FALSE;
-#endif
-static gboolean spdy_debug = FALSE;
-
-#define TCP_PORT_DAAP 3689
-
-/*
- * SSDP is implemented atop HTTP (yes, it really *does* run over UDP).
- */
-#define TCP_PORT_SSDP 1900
-#define UDP_PORT_SSDP 1900
-
-/*
- * tcp and ssl ports
- */
-
-#define TCP_DEFAULT_RANGE "80,8080"
-#define SSL_DEFAULT_RANGE "443"
-
-static range_t *global_spdy_tcp_range = NULL;
-static range_t *global_spdy_ssl_range = NULL;
-
-static range_t *spdy_tcp_range = NULL;
-static range_t *spdy_ssl_range = NULL;
-
-static const value_string vals_status_code[] = {
- { 100, "Continue" },
- { 101, "Switching Protocols" },
- { 102, "Processing" },
- { 199, "Informational - Others" },
-
- { 200, "OK"},
- { 201, "Created"},
- { 202, "Accepted"},
- { 203, "Non-authoritative Information"},
- { 204, "No Content"},
- { 205, "Reset Content"},
- { 206, "Partial Content"},
- { 207, "Multi-Status"},
- { 299, "Success - Others"},
-
- { 300, "Multiple Choices"},
- { 301, "Moved Permanently"},
- { 302, "Found"},
- { 303, "See Other"},
- { 304, "Not Modified"},
- { 305, "Use Proxy"},
- { 307, "Temporary Redirect"},
- { 399, "Redirection - Others"},
-
- { 400, "Bad Request"},
- { 401, "Unauthorized"},
- { 402, "Payment Required"},
- { 403, "Forbidden"},
- { 404, "Not Found"},
- { 405, "Method Not Allowed"},
- { 406, "Not Acceptable"},
- { 407, "Proxy Authentication Required"},
- { 408, "Request Time-out"},
- { 409, "Conflict"},
- { 410, "Gone"},
- { 411, "Length Required"},
- { 412, "Precondition Failed"},
- { 413, "Request Entity Too Large"},
- { 414, "Request-URI Too Long"},
- { 415, "Unsupported Media Type"},
- { 416, "Requested Range Not Satisfiable"},
- { 417, "Expectation Failed"},
- { 418, "I'm a teapot"}, /* RFC 2324 */
- { 422, "Unprocessable Entity"},
- { 423, "Locked"},
- { 424, "Failed Dependency"},
- { 499, "Client Error - Others"},
-
- { 500, "Internal Server Error"},
- { 501, "Not Implemented"},
- { 502, "Bad Gateway"},
- { 503, "Service Unavailable"},
- { 504, "Gateway Time-out"},
- { 505, "HTTP Version not supported"},
- { 507, "Insufficient Storage"},
- { 599, "Server Error - Others"},
-
- { 0, NULL}
-};
-
-static const char spdy_dictionary[] =
- "optionsgetheadpostputdeletetraceacceptaccept-charsetaccept-encodingaccept-"
- "languageauthorizationexpectfromhostif-modified-sinceif-matchif-none-matchi"
- "f-rangeif-unmodifiedsincemax-forwardsproxy-authorizationrangerefererteuser"
- "-agent10010120020120220320420520630030130230330430530630740040140240340440"
- "5406407408409410411412413414415416417500501502503504505accept-rangesageeta"
- "glocationproxy-authenticatepublicretry-afterservervarywarningwww-authentic"
- "ateallowcontent-basecontent-encodingcache-controlconnectiondatetrailertran"
- "sfer-encodingupgradeviawarningcontent-languagecontent-lengthcontent-locati"
- "oncontent-md5content-rangecontent-typeetagexpireslast-modifiedset-cookieMo"
- "ndayTuesdayWednesdayThursdayFridaySaturdaySundayJanFebMarAprMayJunJulAugSe"
- "pOctNovDecchunkedtext/htmlimage/pngimage/jpgimage/gifapplication/xmlapplic"
- "ation/xhtmltext/plainpublicmax-agecharset=iso-8859-1utf-8gzipdeflateHTTP/1"
- ".1statusversionurl";
-
-static void reset_decompressors(void)
-{
- if (spdy_debug) printf("Should reset SPDY decompressors\n");
-}
-
-static spdy_conv_t *
-get_spdy_conversation_data(packet_info *pinfo)
-{
- conversation_t *conversation;
- spdy_conv_t *conv_data;
- int retcode;
-
- conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
- if (spdy_debug) {
- printf("\n===========================================\n\n");
- printf("Conversation for frame #%d is %p\n", pinfo->fd->num, conversation);
- if (conversation)
- printf(" conv_data=%p\n", conversation_get_proto_data(conversation, proto_spdy));
- }
-
- if(!conversation) /* Conversation does not exist yet - create it */
- conversation = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
-
- /* Retrieve information from conversation
- */
- conv_data = conversation_get_proto_data(conversation, proto_spdy);
- if(!conv_data) {
- /* Setup the conversation structure itself */
- conv_data = se_alloc0(sizeof(spdy_conv_t));
-
- conv_data->streams = NULL;
- if (spdy_decompress_headers) {
- conv_data->rqst_decompressor = se_alloc0(sizeof(z_stream));
- conv_data->rply_decompressor = se_alloc0(sizeof(z_stream));
- retcode = inflateInit(conv_data->rqst_decompressor);
- if (retcode == Z_OK)
- retcode = inflateInit(conv_data->rply_decompressor);
- if (retcode != Z_OK)
- printf("frame #%d: inflateInit() failed: %d\n", pinfo->fd->num, retcode);
- else if (spdy_debug)
- printf("created decompressor\n");
- conv_data->dictionary_id = adler32(0L, Z_NULL, 0);
- conv_data->dictionary_id = adler32(conv_data->dictionary_id,
- spdy_dictionary,
- sizeof(spdy_dictionary));
- }
-
- conversation_add_proto_data(conversation, proto_spdy, conv_data);
- register_postseq_cleanup_routine(reset_decompressors);
- }
- return conv_data;
-}
-
-static void
-spdy_save_stream_info(spdy_conv_t *conv_data,
- guint32 stream_id,
- gchar *content_type,
- gchar *content_type_params,
- gchar *content_encoding)
-{
- spdy_stream_info_t *si;
-
- if (conv_data->streams == NULL)
- conv_data->streams = g_array_new(FALSE, TRUE, sizeof(spdy_stream_info_t *));
- if (stream_id < conv_data->streams->len)
- DISSECTOR_ASSERT(g_array_index(conv_data->streams, spdy_stream_info_t*, stream_id) == NULL);
- else
- g_array_set_size(conv_data->streams, stream_id+1);
- si = se_alloc(sizeof(spdy_stream_info_t));
- si->content_type = content_type;
- si->content_type_parameters = content_type_params;
- si->content_encoding = content_encoding;
- si->data_frames = NULL;
- si->num_data_frames = 0;
- si->assembled_data = NULL;
- g_array_index(conv_data->streams, spdy_stream_info_t*, stream_id) = si;
- if (spdy_debug)
- printf("Saved stream info for ID %u, content type %s\n", stream_id, content_type);
-}
-
-static spdy_stream_info_t *
-spdy_get_stream_info(spdy_conv_t *conv_data, guint32 stream_id)
-{
- if (conv_data->streams == NULL || stream_id >= conv_data->streams->len)
- return NULL;
- else
- return g_array_index(conv_data->streams, spdy_stream_info_t*, stream_id);
-}
-
-static void
-spdy_add_data_chunk(spdy_conv_t *conv_data, guint32 stream_id, guint32 frame,
- guint8 *data, guint32 length)
-{
- spdy_stream_info_t *si = spdy_get_stream_info(conv_data, stream_id);
-
- if (si == NULL) {
- if (spdy_debug) printf("No stream_info found for stream %d\n", stream_id);
- } else {
- spdy_data_frame_t *df = g_malloc(sizeof(spdy_data_frame_t));
- df->data = data;
- df->length = length;
- df->framenum = frame;
- si->data_frames = g_slist_append(si->data_frames, df);
- ++si->num_data_frames;
- if (spdy_debug)
- printf("Saved %u bytes of data for stream %u frame %u\n",
- length, stream_id, df->framenum);
- }
-}
-
-static void
-spdy_increment_data_chunk_count(spdy_conv_t *conv_data, guint32 stream_id)
-{
- spdy_stream_info_t *si = spdy_get_stream_info(conv_data, stream_id);
- if (si != NULL)
- ++si->num_data_frames;
-}
-
-/*
- * Return the number of data frames saved so far for the specified stream.
- */
-static guint
-spdy_get_num_data_frames(spdy_conv_t *conv_data, guint32 stream_id)
-{
- spdy_stream_info_t *si = spdy_get_stream_info(conv_data, stream_id);
-
- return si == NULL ? 0 : si->num_data_frames;
-}
-
-static spdy_stream_info_t *
-spdy_assemble_data_frames(spdy_conv_t *conv_data, guint32 stream_id)
-{
- spdy_stream_info_t *si = spdy_get_stream_info(conv_data, stream_id);
- tvbuff_t *tvb;
-
- if (si == NULL)
- return NULL;
-
- /*
- * Compute the total amount of data and concatenate the
- * data chunks, if it hasn't already been done.
- */
- if (si->assembled_data == NULL) {
- spdy_data_frame_t *df;
- guint8 *data;
- guint32 datalen;
- guint32 offset;
- guint32 framenum;
- GSList *dflist = si->data_frames;
- if (dflist == NULL)
- return si;
- dflist = si->data_frames;
- datalen = 0;
- /*
- * I'd like to use a composite tvbuff here, but since
- * only a real-data tvbuff can be the child of another
- * tvb, I can't. It would be nice if this limitation
- * could be fixed.
- */
- while (dflist != NULL) {
- df = dflist->data;
- datalen += df->length;
- dflist = g_slist_next(dflist);
- }
- if (datalen != 0) {
- data = se_alloc(datalen);
- dflist = si->data_frames;
- offset = 0;
- framenum = 0;
- while (dflist != NULL) {
- df = dflist->data;
- memcpy(data+offset, df->data, df->length);
- offset += df->length;
- dflist = g_slist_next(dflist);
- }
- tvb = tvb_new_real_data(data, datalen, datalen);
- si->assembled_data = tvb;
- }
- }
- return si;
-}
-
-static void
-spdy_discard_data_frames(spdy_stream_info_t *si)
-{
- GSList *dflist = si->data_frames;
- spdy_data_frame_t *df;
-
- if (dflist == NULL)
- return;
- while (dflist != NULL) {
- df = dflist->data;
- if (df->data != NULL) {
- g_free(df->data);
- df->data = NULL;
- }
- dflist = g_slist_next(dflist);
- }
- /*g_slist_free(si->data_frames);
- si->data_frames = NULL; */
-}
-
-// TODO(cbentzel): tvb_child_uncompress should be exported by wireshark.
-static tvbuff_t* spdy_tvb_child_uncompress(tvbuff_t *parent _U_, tvbuff_t *tvb,
- int offset, int comprlen)
-{
- tvbuff_t *new_tvb = tvb_uncompress(tvb, offset, comprlen);
- if (new_tvb)
- tvb_set_child_real_data_tvbuff (parent, new_tvb);
- return new_tvb;
-}
-
-static int
-dissect_spdy_data_frame(tvbuff_t *tvb, int offset,
- packet_info *pinfo,
- proto_tree *top_level_tree,
- proto_tree *spdy_tree,
- proto_item *spdy_proto,
- spdy_conv_t *conv_data)
-{
- guint32 stream_id;
- guint8 flags;
- guint32 frame_length;
- proto_item *ti;
- proto_tree *flags_tree;
- guint32 reported_datalen;
- guint32 datalen;
- dissector_table_t media_type_subdissector_table;
- dissector_table_t port_subdissector_table;
- dissector_handle_t handle;
- guint num_data_frames;
- gboolean dissected;
-
- stream_id = tvb_get_bits32(tvb, (offset << 3) + 1, 31, FALSE);
- flags = tvb_get_guint8(tvb, offset+4);
- frame_length = tvb_get_ntoh24(tvb, offset+5);
-
- if (spdy_debug)
- printf("Data frame [stream_id=%u flags=0x%x length=%d]\n",
- stream_id, flags, frame_length);
- if (spdy_tree) proto_item_append_text(spdy_tree, ", data frame");
- col_add_fstr(pinfo->cinfo, COL_INFO, "DATA[%u] length=%d",
- stream_id, frame_length);
-
- proto_item_append_text(spdy_proto, ":%s stream=%d length=%d",
- flags & SPDY_FIN ? " [FIN]" : "",
- stream_id, frame_length);
-
- proto_tree_add_boolean(spdy_tree, hf_spdy_control_bit, tvb, offset, 1, 0);
- proto_tree_add_uint(spdy_tree, hf_spdy_streamid, tvb, offset, 4, stream_id);
- ti = proto_tree_add_uint_format(spdy_tree, hf_spdy_flags, tvb, offset+4, 1, flags,
- "Flags: 0x%02x%s", flags, flags&SPDY_FIN ? " (FIN)" : "");
-
- flags_tree = proto_item_add_subtree(ti, ett_spdy_flags);
- proto_tree_add_boolean(flags_tree, hf_spdy_flags_fin, tvb, offset+4, 1, flags);
- proto_tree_add_uint(spdy_tree, hf_spdy_length, tvb, offset+5, 3, frame_length);
-
- datalen = tvb_length_remaining(tvb, offset);
- if (datalen > frame_length)
- datalen = frame_length;
-
- reported_datalen = tvb_reported_length_remaining(tvb, offset);
- if (reported_datalen > frame_length)
- reported_datalen = frame_length;
-
- num_data_frames = spdy_get_num_data_frames(conv_data, stream_id);
- if (datalen != 0 || num_data_frames != 0) {
- /*
- * There's stuff left over; process it.
- */
- tvbuff_t *next_tvb = NULL;
- tvbuff_t *data_tvb = NULL;
- spdy_stream_info_t *si = NULL;
- void *save_private_data = NULL;
- guint8 *copied_data;
- gboolean private_data_changed = FALSE;
- gboolean is_single_chunk = FALSE;
- gboolean have_entire_body;
-
- /*
- * Create a tvbuff for the payload.
- */
- if (datalen != 0) {
- next_tvb = tvb_new_subset(tvb, offset+8, datalen,
- reported_datalen);
- is_single_chunk = num_data_frames == 0 && (flags & SPDY_FIN) != 0;
- if (!pinfo->fd->flags.visited) {
- if (!is_single_chunk) {
- if (spdy_assemble_entity_bodies) {
- copied_data = tvb_memdup(next_tvb, 0, datalen);
- spdy_add_data_chunk(conv_data, stream_id, pinfo->fd->num,
- copied_data, datalen);
- } else
- spdy_increment_data_chunk_count(conv_data, stream_id);
- }
- }
- } else
- is_single_chunk = (num_data_frames == 1);
-
- if (!(flags & SPDY_FIN)) {
- col_set_fence(pinfo->cinfo, COL_INFO);
- col_add_fstr(pinfo->cinfo, COL_INFO, " (partial entity)");
- proto_item_append_text(spdy_proto, " (partial entity body)");
- /* would like the proto item to say */
- /* " (entity body fragment N of M)" */
- goto body_dissected;
- }
- have_entire_body = is_single_chunk;
- /*
- * On seeing the last data frame in a stream, we can
- * reassemble the frames into one data block.
- */
- si = spdy_assemble_data_frames(conv_data, stream_id);
- if (si == NULL)
- goto body_dissected;
- data_tvb = si->assembled_data;
- if (spdy_assemble_entity_bodies)
- have_entire_body = TRUE;
-
- if (!have_entire_body)
- goto body_dissected;
-
- if (data_tvb == NULL)
- data_tvb = next_tvb;
- else
- add_new_data_source(pinfo, data_tvb, "Assembled entity body");
-
- if (have_entire_body && si->content_encoding != NULL &&
- g_ascii_strcasecmp(si->content_encoding, "identity") != 0) {
- /*
- * We currently can't handle, for example, "compress";
- * just handle them as data for now.
- *
- * After July 7, 2004 the LZW patent expires, so support
- * might be added then. However, I don't think that
- * anybody ever really implemented "compress", due to
- * the aforementioned patent.
- */
- tvbuff_t *uncomp_tvb = NULL;
- proto_item *e_ti = NULL;
- proto_item *ce_ti = NULL;
- proto_tree *e_tree = NULL;
-
- if (spdy_decompress_body &&
- (g_ascii_strcasecmp(si->content_encoding, "gzip") == 0 ||
- g_ascii_strcasecmp(si->content_encoding, "deflate")
- == 0)) {
- uncomp_tvb = spdy_tvb_child_uncompress(tvb, data_tvb, 0,
- tvb_length(data_tvb));
- }
- /*
- * Add the encoded entity to the protocol tree
- */
- e_ti = proto_tree_add_text(top_level_tree, data_tvb,
- 0, tvb_length(data_tvb),
- "Content-encoded entity body (%s): %u bytes",
- si->content_encoding,
- tvb_length(data_tvb));
- e_tree = proto_item_add_subtree(e_ti, ett_spdy_encoded_entity);
- if (si->num_data_frames > 1) {
- GSList *dflist;
- spdy_data_frame_t *df;
- guint32 framenum;
- ce_ti = proto_tree_add_text(e_tree, data_tvb, 0,
- tvb_length(data_tvb),
- "Assembled from %d frames in packet(s)", si->num_data_frames);
- dflist = si->data_frames;
- framenum = 0;
- while (dflist != NULL) {
- df = dflist->data;
- if (framenum != df->framenum) {
- proto_item_append_text(ce_ti, " #%u", df->framenum);
- framenum = df->framenum;
- }
- dflist = g_slist_next(dflist);
- }
- }
-
- if (uncomp_tvb != NULL) {
- /*
- * Decompression worked
- */
-
- /* XXX - Don't free this, since it's possible
- * that the data was only partially
- * decompressed, such as when desegmentation
- * isn't enabled.
- *
- tvb_free(next_tvb);
- */
- proto_item_append_text(e_ti, " -> %u bytes", tvb_length(uncomp_tvb));
- data_tvb = uncomp_tvb;
- add_new_data_source(pinfo, data_tvb, "Uncompressed entity body");
- } else {
- if (spdy_decompress_body)
- proto_item_append_text(e_ti, " [Error: Decompression failed]");
- call_dissector(data_handle, data_tvb, pinfo, e_tree);
-
- goto body_dissected;
- }
- }
- if (si != NULL)
- spdy_discard_data_frames(si);
- /*
- * Do subdissector checks.
- *
- * First, check whether some subdissector asked that they
- * be called if something was on some particular port.
- */
-
- port_subdissector_table = find_dissector_table("http.port");
- media_type_subdissector_table = find_dissector_table("media_type");
- if (have_entire_body && port_subdissector_table != NULL)
- handle = dissector_get_port_handle(port_subdissector_table,
- pinfo->match_port);
- else
- handle = NULL;
- if (handle == NULL && have_entire_body && si->content_type != NULL &&
- media_type_subdissector_table != NULL) {
- /*
- * We didn't find any subdissector that
- * registered for the port, and we have a
- * Content-Type value. Is there any subdissector
- * for that content type?
- */
- save_private_data = pinfo->private_data;
- private_data_changed = TRUE;
-
- if (si->content_type_parameters)
- pinfo->private_data = ep_strdup(si->content_type_parameters);
- else
- pinfo->private_data = NULL;
- /*
- * Calling the string handle for the media type
- * dissector table will set pinfo->match_string
- * to si->content_type for us.
- */
- pinfo->match_string = si->content_type;
- handle = dissector_get_string_handle(
- media_type_subdissector_table,
- si->content_type);
- }
- if (handle != NULL) {
- /*
- * We have a subdissector - call it.
- */
- dissected = call_dissector(handle, data_tvb, pinfo, top_level_tree);
- } else
- dissected = FALSE;
-
- if (dissected) {
- /*
- * The subdissector dissected the body.
- * Fix up the top-level item so that it doesn't
- * include the stuff for that protocol.
- */
- if (ti != NULL)
- proto_item_set_len(ti, offset);
- } else if (have_entire_body && si->content_type != NULL) {
- /*
- * Calling the default media handle if there is a content-type that
- * wasn't handled above.
- */
- call_dissector(media_handle, next_tvb, pinfo, top_level_tree);
- } else {
- /* Call the default data dissector */
- call_dissector(data_handle, next_tvb, pinfo, top_level_tree);
- }
-
-body_dissected:
- /*
- * Do *not* attempt at freeing the private data;
- * it may be in use by subdissectors.
- */
- if (private_data_changed) /*restore even NULL value*/
- pinfo->private_data = save_private_data;
- /*
- * We've processed "datalen" bytes worth of data
- * (which may be no data at all); advance the
- * offset past whatever data we've processed.
- */
- }
- return frame_length + 8;
-}
-
-static guint8 *
-spdy_decompress_header_block(tvbuff_t *tvb, z_streamp decomp,
- guint32 dictionary_id, int offset,
- guint32 length, guint *uncomp_length)
-{
- int retcode;
- size_t bufsize = 16384;
- const guint8 *hptr = tvb_get_ptr(tvb, offset, length);
- guint8 *uncomp_block = ep_alloc(bufsize);
- decomp->next_in = (Bytef *)hptr;
- decomp->avail_in = length;
- decomp->next_out = uncomp_block;
- decomp->avail_out = bufsize;
- retcode = inflate(decomp, Z_SYNC_FLUSH);
- if (retcode == Z_NEED_DICT) {
- if (decomp->adler != dictionary_id) {
- printf("decompressor wants dictionary %#x, but we have %#x\n",
- (guint)decomp->adler, dictionary_id);
- } else {
- retcode = inflateSetDictionary(decomp,
- spdy_dictionary,
- sizeof(spdy_dictionary));
- if (retcode == Z_OK)
- retcode = inflate(decomp, Z_SYNC_FLUSH);
- }
- }
-
- if (retcode != Z_OK) {
- return NULL;
- } else {
- *uncomp_length = bufsize - decomp->avail_out;
- if (spdy_debug)
- printf("Inflation SUCCEEDED. uncompressed size=%d\n", *uncomp_length);
- if (decomp->avail_in != 0)
- if (spdy_debug)
- printf(" but there were %d input bytes left over\n", decomp->avail_in);
- }
- return se_memdup(uncomp_block, *uncomp_length);
-}
-
-/*
- * Try to determine heuristically whether the header block is
- * compressed. For an uncompressed block, the first two bytes
- * gives the number of headers. Each header name and value is
- * a two-byte length followed by ASCII characters.
- */
-static gboolean
-spdy_check_header_compression(tvbuff_t *tvb,
- int offset,
- guint32 frame_length)
-{
- guint16 length;
- if (!tvb_bytes_exist(tvb, offset, 6))
- return 1;
- length = tvb_get_ntohs(tvb, offset);
- if (length > frame_length)
- return 1;
- length = tvb_get_ntohs(tvb, offset+2);
- if (length > frame_length)
- return 1;
- if (spdy_debug) printf("Looks like the header block is not compressed\n");
- return 0;
-}
-
-// TODO(cbentzel): Change wireshark to export p_remove_proto_data, rather
-// than duplicating code here.
-typedef struct _spdy_frame_proto_data {
- int proto;
- void *proto_data;
-} spdy_frame_proto_data;
-
-static gint spdy_p_compare(gconstpointer a, gconstpointer b)
-{
- const spdy_frame_proto_data *ap = (const spdy_frame_proto_data *)a;
- const spdy_frame_proto_data *bp = (const spdy_frame_proto_data *)b;
-
- if (ap -> proto > bp -> proto)
- return 1;
- else if (ap -> proto == bp -> proto)
- return 0;
- else
- return -1;
-
-}
-
-static void spdy_p_remove_proto_data(frame_data *fd, int proto)
-{
- spdy_frame_proto_data temp;
- GSList *item;
-
- temp.proto = proto;
- temp.proto_data = NULL;
-
- item = g_slist_find_custom(fd->pfd, (gpointer *)&temp, spdy_p_compare);
-
- if (item) {
- fd->pfd = g_slist_remove(fd->pfd, item->data);
- }
-}
-
-static spdy_frame_info_t *
-spdy_save_header_block(frame_data *fd,
- guint32 stream_id,
- guint frame_type,
- guint8 *header,
- guint length)
-{
- GSList *filist = p_get_proto_data(fd, proto_spdy);
- spdy_frame_info_t *frame_info = se_alloc(sizeof(spdy_frame_info_t));
- if (filist != NULL)
- spdy_p_remove_proto_data(fd, proto_spdy);
- frame_info->stream_id = stream_id;
- frame_info->header_block = header;
- frame_info->header_block_len = length;
- frame_info->frame_type = frame_type;
- filist = g_slist_append(filist, frame_info);
- p_add_proto_data(fd, proto_spdy, filist);
- return frame_info;
- /* TODO(ers) these need to get deleted when no longer needed */
-}
-
-static spdy_frame_info_t *
-spdy_find_saved_header_block(frame_data *fd,
- guint32 stream_id,
- guint16 frame_type)
-{
- GSList *filist = p_get_proto_data(fd, proto_spdy);
- while (filist != NULL) {
- spdy_frame_info_t *fi = filist->data;
- if (fi->stream_id == stream_id && fi->frame_type == frame_type)
- return fi;
- filist = g_slist_next(filist);
- }
- return NULL;
-}
-
-/*
- * Given a content type string that may contain optional parameters,
- * return the parameter string, if any, otherwise return NULL. This
- * also has the side effect of null terminating the content type
- * part of the original string.
- */
-static gchar *
-spdy_parse_content_type(gchar *content_type)
-{
- gchar *cp = content_type;
-
- while (*cp != '\0' && *cp != ';' && !isspace(*cp)) {
- *cp = tolower(*cp);
- ++cp;
- }
- if (*cp == '\0')
- cp = NULL;
-
- if (cp != NULL) {
- *cp++ = '\0';
- while (*cp == ';' || isspace(*cp))
- ++cp;
- if (*cp != '\0')
- return cp;
- }
- return NULL;
-}
-
-static int
-dissect_spdy_message(tvbuff_t *tvb, int offset, packet_info *pinfo,
- proto_tree *tree, spdy_conv_t *conv_data)
-{
- guint8 control_bit;
- guint16 version;
- guint16 frame_type;
- guint8 flags;
- guint32 frame_length;
- guint32 stream_id;
- guint32 associated_stream_id;
- gint priority;
- guint16 num_headers;
- guint32 fin_status;
- guint8 *frame_header;
- const char *proto_tag;
- const char *frame_type_name;
- proto_tree *spdy_tree = NULL;
- proto_item *ti = NULL;
- proto_item *spdy_proto = NULL;
- int orig_offset;
- int hoffset;
- int hdr_offset = 0;
- spdy_frame_type_t spdy_type;
- proto_tree *sub_tree;
- proto_tree *flags_tree;
- tvbuff_t *header_tvb = NULL;
- gboolean headers_compressed;
- gchar *hdr_verb = NULL;
- gchar *hdr_url = NULL;
- gchar *hdr_version = NULL;
- gchar *content_type = NULL;
- gchar *content_encoding = NULL;
-
- /*
- * Minimum size for a SPDY frame is 8 bytes.
- */
- if (tvb_reported_length_remaining(tvb, offset) < 8)
- return -1;
-
- proto_tag = "SPDY";
-
- if (check_col(pinfo->cinfo, COL_PROTOCOL))
- col_set_str(pinfo->cinfo, COL_PROTOCOL, proto_tag);
-
- /*
- * Is this a control frame or a data frame?
- */
- orig_offset = offset;
- control_bit = tvb_get_bits8(tvb, offset << 3, 1);
- if (control_bit) {
- version = tvb_get_bits16(tvb, (offset << 3) + 1, 15, FALSE);
- frame_type = tvb_get_ntohs(tvb, offset+2);
- if (frame_type >= SPDY_INVALID) {
- return -1;
- }
- frame_header = ep_tvb_memdup(tvb, offset, 16);
- } else {
- version = 1; /* avoid gcc warning */
- frame_type = SPDY_DATA;
- frame_header = NULL; /* avoid gcc warning */
- }
- frame_type_name = frame_type_names[frame_type];
- offset += 4;
- flags = tvb_get_guint8(tvb, offset);
- frame_length = tvb_get_ntoh24(tvb, offset+1);
- offset += 4;
- /*
- * Make sure there's as much data as the frame header says there is.
- */
- if ((guint)tvb_reported_length_remaining(tvb, offset) < frame_length) {
- if (spdy_debug)
- printf("Not enough header data: %d vs. %d\n",
- frame_length, tvb_reported_length_remaining(tvb, offset));
- return -1;
- }
- if (tree) {
- spdy_proto = proto_tree_add_item(tree, proto_spdy, tvb, orig_offset, frame_length+8, FALSE);
- spdy_tree = proto_item_add_subtree(spdy_proto, ett_spdy);
- }
-
- if (control_bit) {
- if (spdy_debug)
- printf("Control frame [version=%d type=%d flags=0x%x length=%d]\n",
- version, frame_type, flags, frame_length);
- if (tree) proto_item_append_text(spdy_tree, ", control frame");
- } else {
- return dissect_spdy_data_frame(tvb, orig_offset, pinfo, tree,
- spdy_tree, spdy_proto, conv_data);
- }
- num_headers = 0;
- sub_tree = NULL; /* avoid gcc warning */
- switch (frame_type) {
- case SPDY_SYN_STREAM:
- case SPDY_SYN_REPLY:
- if (tree) {
- int hf;
- hf = frame_type == SPDY_SYN_STREAM ? hf_spdy_syn_stream : hf_spdy_syn_reply;
- ti = proto_tree_add_bytes(spdy_tree, hf, tvb,
- orig_offset, 16, frame_header);
- sub_tree = proto_item_add_subtree(ti, ett_spdy_syn_stream);
- }
- stream_id = tvb_get_bits32(tvb, (offset << 3) + 1, 31, FALSE);
- offset += 4;
- if (frame_type == SPDY_SYN_STREAM) {
- associated_stream_id = tvb_get_bits32(tvb, (offset << 3) + 1, 31, FALSE);
- offset += 4;
- priority = tvb_get_bits8(tvb, offset << 3, 2);
- offset += 2;
- } else {
- // The next two bytes have no meaning in SYN_REPLY
- offset += 2;
- }
- if (tree) {
- proto_tree_add_boolean(sub_tree, hf_spdy_control_bit, tvb, orig_offset, 1, control_bit);
- proto_tree_add_uint(sub_tree, hf_spdy_version, tvb, orig_offset, 2, version);
- proto_tree_add_uint(sub_tree, hf_spdy_type, tvb, orig_offset+2, 2, frame_type);
- ti = proto_tree_add_uint_format(sub_tree, hf_spdy_flags, tvb, orig_offset+4, 1, flags,
- "Flags: 0x%02x%s", flags, flags&SPDY_FIN ? " (FIN)" : "");
- flags_tree = proto_item_add_subtree(ti, ett_spdy_flags);
- proto_tree_add_boolean(flags_tree, hf_spdy_flags_fin, tvb, orig_offset+4, 1, flags);
- proto_tree_add_uint(sub_tree, hf_spdy_length, tvb, orig_offset+5, 3, frame_length);
- proto_tree_add_uint(sub_tree, hf_spdy_streamid, tvb, orig_offset+8, 4, stream_id);
- if (frame_type == SPDY_SYN_STREAM) {
- proto_tree_add_uint(sub_tree, hf_spdy_associated_streamid, tvb, orig_offset+12, 4, associated_stream_id);
- proto_tree_add_uint(sub_tree, hf_spdy_priority, tvb, orig_offset+16, 1, priority);
- }
- proto_item_append_text(spdy_proto, ": %s%s stream=%d length=%d",
- frame_type_name,
- flags & SPDY_FIN ? " [FIN]" : "",
- stream_id, frame_length);
- if (spdy_debug)
- printf(" stream ID=%u priority=%d\n", stream_id, priority);
- }
- break;
-
- case SPDY_FIN_STREAM:
- stream_id = tvb_get_bits32(tvb, (offset << 3) + 1, 31, FALSE);
- fin_status = tvb_get_ntohl(tvb, offset);
- // TODO(ers) fill in tree and summary
- offset += 8;
- break;
-
- case SPDY_HELLO:
- // TODO(ers) fill in tree and summary
- stream_id = 0; /* avoid gcc warning */
- break;
-
- default:
- stream_id = 0; /* avoid gcc warning */
- return -1;
- break;
- }
-
- /*
- * Process the name-value pairs one at a time, after possibly
- * decompressing the header block.
- */
- if (frame_type == SPDY_SYN_STREAM || frame_type == SPDY_SYN_REPLY) {
- headers_compressed = spdy_check_header_compression(tvb, offset, frame_length);
- if (!spdy_decompress_headers || !headers_compressed) {
- header_tvb = tvb;
- hdr_offset = offset;
- } else {
- spdy_frame_info_t *per_frame_info =
- spdy_find_saved_header_block(pinfo->fd,
- stream_id,
- frame_type == SPDY_SYN_REPLY);
- if (per_frame_info == NULL) {
- guint uncomp_length;
- z_streamp decomp = frame_type == SPDY_SYN_STREAM ?
- conv_data->rqst_decompressor : conv_data->rply_decompressor;
- guint8 *uncomp_ptr =
- spdy_decompress_header_block(tvb, decomp,
- conv_data->dictionary_id,
- offset,
- frame_length + 8 - (offset - orig_offset),
- &uncomp_length);
- if (uncomp_ptr == NULL) { /* decompression failed */
- if (spdy_debug)
- printf("Frame #%d: Inflation failed\n", pinfo->fd->num);
- proto_item_append_text(spdy_proto, " [Error: Header decompression failed]");
- // Should we just bail here?
- } else {
- if (spdy_debug)
- printf("Saving %u bytes of uncomp hdr\n", uncomp_length);
- per_frame_info =
- spdy_save_header_block(pinfo->fd, stream_id, frame_type == SPDY_SYN_REPLY,
- uncomp_ptr, uncomp_length);
- }
- } else if (spdy_debug) {
- printf("Found uncompressed header block len %u for stream %u frame_type=%d\n",
- per_frame_info->header_block_len,
- per_frame_info->stream_id,
- per_frame_info->frame_type);
- }
- if (per_frame_info != NULL) {
- header_tvb = tvb_new_child_real_data(tvb,
- per_frame_info->header_block,
- per_frame_info->header_block_len,
- per_frame_info->header_block_len);
- add_new_data_source(pinfo, header_tvb, "Uncompressed headers");
- hdr_offset = 0;
- }
- }
- offset = orig_offset + 8 + frame_length;
- num_headers = tvb_get_ntohs(header_tvb, hdr_offset);
- hdr_offset += 2;
- if (header_tvb == NULL ||
- (headers_compressed && !spdy_decompress_headers)) {
- num_headers = 0;
- ti = proto_tree_add_string(sub_tree, hf_spdy_num_headers_string,
- tvb,
- frame_type == SPDY_SYN_STREAM ? orig_offset+18 : orig_offset + 14,
- 2,
- "Unknown (header block is compressed)");
- } else
- ti = proto_tree_add_uint(sub_tree, hf_spdy_num_headers,
- tvb,
- frame_type == SPDY_SYN_STREAM ? orig_offset+18 : orig_offset +14,
- 2, num_headers);
- }
- spdy_type = SPDY_INVALID; /* type not known yet */
- if (spdy_debug)
- printf(" %d Headers:\n", num_headers);
- if (num_headers > frame_length) {
- printf("Number of headers is greater than frame length!\n");
- proto_item_append_text(ti, " [Error: Number of headers is larger than frame length]");
- col_add_fstr(pinfo->cinfo, COL_INFO, "%s[%d]", frame_type_name, stream_id);
- return frame_length+8;
- }
- hdr_verb = hdr_url = hdr_version = content_type = content_encoding = NULL;
- while (num_headers-- && tvb_reported_length_remaining(header_tvb, hdr_offset) != 0) {
- gchar *header_name;
- gchar *header_value;
- proto_tree *header_tree;
- proto_tree *name_tree;
- proto_tree *value_tree;
- proto_item *header;
- gint16 length;
- gint header_length = 0;
-
- hoffset = hdr_offset;
-
- header = proto_tree_add_item(spdy_tree, hf_spdy_header, header_tvb,
- hdr_offset, frame_length, FALSE);
- header_tree = proto_item_add_subtree(header, ett_spdy_header);
-
- length = tvb_get_ntohs(header_tvb, hdr_offset);
- hdr_offset += 2;
- header_name = (gchar *)tvb_get_ephemeral_string(header_tvb, hdr_offset, length);
- hdr_offset += length;
- header_length += hdr_offset - hoffset;
- if (tree) {
- ti = proto_tree_add_text(header_tree, header_tvb, hoffset, length+2, "Name: %s",
- header_name);
- name_tree = proto_item_add_subtree(ti, ett_spdy_header_name);
- proto_tree_add_uint(name_tree, hf_spdy_length, header_tvb, hoffset, 2, length);
- proto_tree_add_string_format(name_tree, hf_spdy_header_name_text, header_tvb, hoffset+2, length,
- header_name, "Text: %s", format_text(header_name, length));
- }
-
- hoffset = hdr_offset;
- length = tvb_get_ntohs(header_tvb, hdr_offset);
- hdr_offset += 2;
- header_value = (gchar *)tvb_get_ephemeral_string(header_tvb, hdr_offset, length);
- hdr_offset += length;
- header_length += hdr_offset - hoffset;
- if (tree) {
- ti = proto_tree_add_text(header_tree, header_tvb, hoffset, length+2, "Value: %s",
- header_value);
- value_tree = proto_item_add_subtree(ti, ett_spdy_header_value);
- proto_tree_add_uint(value_tree, hf_spdy_length, header_tvb, hoffset, 2, length);
- proto_tree_add_string_format(value_tree, hf_spdy_header_value_text, header_tvb, hoffset+2, length,
- header_value, "Text: %s", format_text(header_value, length));
- proto_item_append_text(header, ": %s: %s", header_name, header_value);
- proto_item_set_len(header, header_length);
- }
- if (spdy_debug) printf(" %s: %s\n", header_name, header_value);
- /*
- * TODO(ers) check that the header name contains only legal characters.
- */
- if (g_ascii_strcasecmp(header_name, "method") == 0 ||
- g_ascii_strcasecmp(header_name, "status") == 0) {
- hdr_verb = header_value;
- } else if (g_ascii_strcasecmp(header_name, "url") == 0) {
- hdr_url = header_value;
- } else if (g_ascii_strcasecmp(header_name, "version") == 0) {
- hdr_version = header_value;
- } else if (g_ascii_strcasecmp(header_name, "content-type") == 0) {
- content_type = se_strdup(header_value);
- } else if (g_ascii_strcasecmp(header_name, "content-encoding") == 0) {
- content_encoding = se_strdup(header_value);
- }
- }
- if (hdr_version != NULL) {
- if (hdr_url != NULL) {
- col_add_fstr(pinfo->cinfo, COL_INFO, "%s[%d]: %s %s %s",
- frame_type_name, stream_id, hdr_verb, hdr_url, hdr_version);
- } else {
- col_add_fstr(pinfo->cinfo, COL_INFO, "%s[%d]: %s %s",
- frame_type_name, stream_id, hdr_verb, hdr_version);
- }
- } else {
- col_add_fstr(pinfo->cinfo, COL_INFO, "%s[%d]", frame_type_name, stream_id);
- }
- /*
- * If we expect data on this stream, we need to remember the content
- * type and content encoding.
- */
- if (content_type != NULL && !pinfo->fd->flags.visited) {
- gchar *content_type_params = spdy_parse_content_type(content_type);
- spdy_save_stream_info(conv_data, stream_id, content_type,
- content_type_params, content_encoding);
- }
-
- return offset - orig_offset;
-}
-
-static int
-dissect_spdy(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
-{
- spdy_conv_t *conv_data;
- int offset = 0;
- int len;
- int firstpkt = 1;
-
- /*
- * The first byte of a SPDY packet must be either 0 or
- * 0x80. If it's not, assume that this is not SPDY.
- * (In theory, a data frame could have a stream ID
- * >= 2^24, in which case it won't have 0 for a first
- * byte, but this is a pretty reliable heuristic for
- * now.)
- */
- guint8 first_byte = tvb_get_guint8(tvb, 0);
- if (first_byte != 0x80 && first_byte != 0x0)
- return 0;
-
- conv_data = get_spdy_conversation_data(pinfo);
-
- while (tvb_reported_length_remaining(tvb, offset) != 0) {
- if (!firstpkt) {
- col_add_fstr(pinfo->cinfo, COL_INFO, " >> ");
- col_set_fence(pinfo->cinfo, COL_INFO);
- }
- len = dissect_spdy_message(tvb, offset, pinfo, tree, conv_data);
- if (len <= 0)
- return 0;
- offset += len;
- /*
- * OK, we've set the Protocol and Info columns for the
- * first SPDY message; set a fence so that subsequent
- * SPDY messages don't overwrite the Info column.
- */
- col_set_fence(pinfo->cinfo, COL_INFO);
- firstpkt = 0;
- }
- return 1;
-}
-
-static gboolean
-dissect_spdy_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
-{
- if (!value_is_in_range(global_spdy_tcp_range, pinfo->destport) &&
- !value_is_in_range(global_spdy_tcp_range, pinfo->srcport))
- return FALSE;
- return dissect_spdy(tvb, pinfo, tree) != 0;
-}
-
-static void reinit_spdy(void)
-{
-}
-
-// NMAKE complains about flags_set_truth not being constant. Duplicate
-// the values inside of it.
-static const true_false_string tfs_spdy_set_notset = { "Set", "Not set" };
-
-void
-proto_register_spdy(void)
-{
- static hf_register_info hf[] = {
- { &hf_spdy_syn_stream,
- { "Syn Stream", "spdy.syn_stream",
- FT_BYTES, BASE_NONE, NULL, 0x0,
- "", HFILL }},
- { &hf_spdy_syn_reply,
- { "Syn Reply", "spdy.syn_reply",
- FT_BYTES, BASE_NONE, NULL, 0x0,
- "", HFILL }},
- { &hf_spdy_control_bit,
- { "Control bit", "spdy.control_bit",
- FT_BOOLEAN, BASE_NONE, NULL, 0x0,
- "TRUE if SPDY control frame", HFILL }},
- { &hf_spdy_version,
- { "Version", "spdy.version",
- FT_UINT16, BASE_DEC, NULL, 0x0,
- "", HFILL }},
- { &hf_spdy_type,
- { "Type", "spdy.type",
- FT_UINT16, BASE_DEC, NULL, 0x0,
- "", HFILL }},
- { &hf_spdy_flags,
- { "Flags", "spdy.flags",
- FT_UINT8, BASE_HEX, NULL, 0x0,
- "", HFILL }},
- { &hf_spdy_flags_fin,
- { "Fin", "spdy.flags.fin",
- FT_BOOLEAN, 8, TFS(&tfs_spdy_set_notset),
- SPDY_FIN, "", HFILL }},
- { &hf_spdy_length,
- { "Length", "spdy.length",
- FT_UINT24, BASE_DEC, NULL, 0x0,
- "", HFILL }},
- { &hf_spdy_header,
- { "Header", "spdy.header",
- FT_NONE, BASE_NONE, NULL, 0x0,
- "", HFILL }},
- { &hf_spdy_header_name,
- { "Name", "spdy.header.name",
- FT_NONE, BASE_NONE, NULL, 0x0,
- "", HFILL }},
- { &hf_spdy_header_name_text,
- { "Text", "spdy.header.name.text",
- FT_STRING, BASE_NONE, NULL, 0x0,
- "", HFILL }},
- { &hf_spdy_header_value,
- { "Value", "spdy.header.value",
- FT_NONE, BASE_NONE, NULL, 0x0,
- "", HFILL }},
- { &hf_spdy_header_value_text,
- { "Text", "spdy.header.value.text",
- FT_STRING, BASE_NONE, NULL, 0x0,
- "", HFILL }},
- { &hf_spdy_streamid,
- { "Stream ID", "spdy.streamid",
- FT_UINT32, BASE_DEC, NULL, 0x0,
- "", HFILL }},
- { &hf_spdy_associated_streamid,
- { "Associated Stream ID", "spdy.associated.streamid",
- FT_UINT32, BASE_DEC, NULL, 0x0,
- "", HFILL }},
- { &hf_spdy_priority,
- { "Priority", "spdy.priority",
- FT_UINT8, BASE_DEC, NULL, 0x0,
- "", HFILL }},
- { &hf_spdy_num_headers,
- { "Number of headers", "spdy.numheaders",
- FT_UINT16, BASE_DEC, NULL, 0x0,
- "", HFILL }},
- { &hf_spdy_num_headers_string,
- { "Number of headers", "spdy.numheaders",
- FT_STRING, BASE_NONE, NULL, 0x0,
- "", HFILL }},
- };
- static gint *ett[] = {
- &ett_spdy,
- &ett_spdy_syn_stream,
- &ett_spdy_syn_reply,
- &ett_spdy_fin_stream,
- &ett_spdy_flags,
- &ett_spdy_header,
- &ett_spdy_header_name,
- &ett_spdy_header_value,
- &ett_spdy_encoded_entity,
- };
-
- module_t *spdy_module;
-
- proto_spdy = proto_register_protocol("SPDY", "SPDY", "spdy");
- proto_register_field_array(proto_spdy, hf, array_length(hf));
- proto_register_subtree_array(ett, array_length(ett));
- new_register_dissector("spdy", dissect_spdy, proto_spdy);
- spdy_module = prefs_register_protocol(proto_spdy, reinit_spdy);
- prefs_register_bool_preference(spdy_module, "desegment_headers",
- "Reassemble SPDY control frames spanning multiple TCP segments",
- "Whether the SPDY dissector should reassemble control frames "
- "spanning multiple TCP segments. "
- "To use this option, you must also enable "
- "\"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
- &spdy_desegment_control_frames);
- prefs_register_bool_preference(spdy_module, "desegment_body",
- "Reassemble SPDY bodies spanning multiple TCP segments",
- "Whether the SPDY dissector should reassemble "
- "data frames spanning multiple TCP segments. "
- "To use this option, you must also enable "
- "\"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
- &spdy_desegment_data_frames);
- prefs_register_bool_preference(spdy_module, "assemble_data_frames",
- "Assemble SPDY bodies that consist of multiple DATA frames",
- "Whether the SPDY dissector should reassemble multiple "
- "data frames into an entity body.",
- &spdy_assemble_entity_bodies);
-#ifdef HAVE_LIBZ
- prefs_register_bool_preference(spdy_module, "decompress_headers",
- "Uncompress SPDY headers",
- "Whether to uncompress SPDY headers.",
- &spdy_decompress_headers);
- prefs_register_bool_preference(spdy_module, "decompress_body",
- "Uncompress entity bodies",
- "Whether to uncompress entity bodies that are compressed "
- "using \"Content-Encoding: \"",
- &spdy_decompress_body);
-#endif
- prefs_register_bool_preference(spdy_module, "debug_output",
- "Print debug info on stdout",
- "Print debug info on stdout",
- &spdy_debug);
-#if 0
- prefs_register_string_preference(ssl_module, "debug_file", "SPDY debug file",
- "Redirect SPDY debug to file name; "
- "leave empty to disable debugging, "
- "or use \"" SPDY_DEBUG_USE_STDOUT "\""
- " to redirect output to stdout\n",
- (const gchar **)&sdpy_debug_file_name);
-#endif
- prefs_register_obsolete_preference(spdy_module, "tcp_alternate_port");
-
- range_convert_str(&global_spdy_tcp_range, TCP_DEFAULT_RANGE, 65535);
- spdy_tcp_range = range_empty();
- prefs_register_range_preference(spdy_module, "tcp.port", "TCP Ports",
- "TCP Ports range",
- &global_spdy_tcp_range, 65535);
-
- range_convert_str(&global_spdy_ssl_range, SSL_DEFAULT_RANGE, 65535);
- spdy_ssl_range = range_empty();
- prefs_register_range_preference(spdy_module, "ssl.port", "SSL/TLS Ports",
- "SSL/TLS Ports range",
- &global_spdy_ssl_range, 65535);
-
- spdy_handle = new_create_dissector_handle(dissect_spdy, proto_spdy);
- /*
- * Register for tapping
- */
- spdy_tap = register_tap("spdy"); /* SPDY statistics tap */
- spdy_eo_tap = register_tap("spdy_eo"); /* SPDY Export Object tap */
-}
-
-void
-proto_reg_handoff_spdy(void)
-{
- data_handle = find_dissector("data");
- media_handle = find_dissector("media");
- heur_dissector_add("tcp", dissect_spdy_heur, proto_spdy);
-}
-
-/*
- * Content-Type: message/http
- */
-
-static gint proto_message_spdy = -1;
-static gint ett_message_spdy = -1;
-
-static void
-dissect_message_spdy(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
-{
- proto_tree *subtree;
- proto_item *ti;
- gint offset = 0, next_offset;
- gint len;
-
- if (check_col(pinfo->cinfo, COL_INFO))
- col_append_str(pinfo->cinfo, COL_INFO, " (message/spdy)");
- if (tree) {
- ti = proto_tree_add_item(tree, proto_message_spdy,
- tvb, 0, -1, FALSE);
- subtree = proto_item_add_subtree(ti, ett_message_spdy);
- while (tvb_reported_length_remaining(tvb, offset) != 0) {
- len = tvb_find_line_end(tvb, offset,
- tvb_ensure_length_remaining(tvb, offset),
- &next_offset, FALSE);
- if (len == -1)
- break;
- proto_tree_add_text(subtree, tvb, offset, next_offset - offset,
- "%s", tvb_format_text(tvb, offset, len));
- offset = next_offset;
- }
- }
-}
-
-void
-proto_register_message_spdy(void)
-{
- static gint *ett[] = {
- &ett_message_spdy,
- };
-
- proto_message_spdy = proto_register_protocol(
- "Media Type: message/spdy",
- "message/spdy",
- "message-spdy"
- );
- proto_register_subtree_array(ett, array_length(ett));
-}
-
-void
-proto_reg_handoff_message_spdy(void)
-{
- dissector_handle_t message_spdy_handle;
-
- message_spdy_handle = create_dissector_handle(dissect_message_spdy,
- proto_message_spdy);
-
- dissector_add_string("media_type", "message/spdy", message_spdy_handle);
-
- reinit_spdy();
-}
« no previous file with comments | « net/tools/spdyshark/packet-spdy.h ('k') | net/tools/spdyshark/plugin.rc.in » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698