Rewrite packet-mime-encap to use composite tvbs + cloning

svn path=/trunk/; revision=50571
This commit is contained in:
Jakub Zawadzki 2013-07-14 08:41:04 +00:00
parent b3e0623e5c
commit 2131f22508
3 changed files with 56 additions and 19 deletions

View File

@ -26,19 +26,25 @@
#include <glib.h>
#include <epan/packet.h>
#include "tvbuff-int.h"
static int proto_mime_encap = -1;
static heur_dissector_list_t heur_subdissector_list;
static dissector_handle_t data_handle;
static GString *whole_file;
static tvbuff_t *whole_tvb;
static tvbuff_t *first_tvb;
static void
mime_encap_init(void)
{
if (whole_file) {
g_string_free(whole_file, TRUE);
whole_file = NULL;
if (whole_tvb) {
/* hacky, tvb_free_chain() requires that we'll pass first tvb in chain,
* and tvb composite chains up with first tvb appended */
tvb_free_chain(first_tvb);
whole_tvb = NULL;
first_tvb = NULL;
}
}
@ -59,26 +65,44 @@ dissect_mime_encap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
/* return; */ /* dissect what we have */
}
if (!whole_file)
whole_file = g_string_new("");
len = tvb_length(tvb);
if (!pinfo->fd->flags.visited) {
if (len) {
tvbuff_t *cloned_tvb = tvb_clone(tvb);
/* eof? */
if (!(len = tvb_length(tvb))) {
tvbuff_t *comp_tvb;
if (!whole_tvb) {
whole_tvb = tvb_new_composite();
first_tvb = cloned_tvb;
}
tvb_composite_append(whole_tvb, cloned_tvb);
} else
tvb_composite_finalize(whole_tvb);
}
/* End of file? */
if (!len && whole_tvb) {
/*
* Here we're doing some trick.
*
* We don't want to call dissectors with composite tvb, cause dissectors can create subsets or real data child
* on it, which would append to whole_tvb chain and would be freed only in mime_encap_init.
*
* So we create some tvb which pass all calls to whole_tvb, but chain with tvb (which is freed in dissection cleanup)
*
* BIG FAT NOTE: YOU NORMALLY DON'T WANT TO DO IT, SO DON'T COPY THIS CODE!!!!!111
*/
tvbuff_t *tmp_tvb = tvb_new_temporary(whole_tvb);
tvb_add_to_chain(tvb, tmp_tvb);
proto_item_append_text(item, " (Final)");
comp_tvb = tvb_new_child_real_data(tvb, whole_file->str, (guint) whole_file->len, (gint) whole_file->len);
add_new_data_source(pinfo, comp_tvb, "Whole file");
add_new_data_source(pinfo, tmp_tvb, "Whole file");
if (!dissector_try_heuristic(heur_subdissector_list, comp_tvb, pinfo, tree, NULL)) {
if (!dissector_try_heuristic(heur_subdissector_list, tmp_tvb, pinfo, tree, NULL)) {
proto_item_append_text(item, " (Unhandled)");
call_dissector(data_handle, comp_tvb, pinfo, tree);
}
} else {
if (!pinfo->fd->flags.visited) {
g_string_set_size(whole_file, (gsize) pinfo->fd->file_off + len);
tvb_memcpy(tvb, whole_file->str + pinfo->fd->file_off, 0, len);
call_dissector(data_handle, tmp_tvb, pinfo, tree);
}
}
}

View File

@ -94,6 +94,8 @@ struct tvb_composite {
WS_DLL_PUBLIC tvbuff_t *tvb_new(const struct tvb_ops *ops);
tvbuff_t *tvb_new_temporary(tvbuff_t *backing);
void tvb_add_to_chain(tvbuff_t *parent, tvbuff_t *child);
guint tvb_offset_from_real_beginning_counter(const tvbuff_t *tvb, const guint counter);

View File

@ -131,7 +131,6 @@ tvb_new_with_subset(tvbuff_t *backing, const gint reported_length,
tvb->reported_length = reported_length;
}
tvb->initialized = TRUE;
tvb_add_to_chain(backing, tvb);
/* Optimization. If the backing buffer has a pointer to contiguous, real data,
* then we can point directly to our starting offset in that buffer */
@ -166,6 +165,8 @@ tvb_new_subset(tvbuff_t *backing, const gint backing_offset, const gint backing_
tvb = tvb_new_with_subset(backing, reported_length,
subset_tvb_offset, subset_tvb_length);
tvb_add_to_chain(backing, tvb);
return tvb;
}
@ -196,6 +197,8 @@ tvb_new_subset_length(tvbuff_t *backing, const gint backing_offset, const gint b
tvb = tvb_new_with_subset(backing, backing_length,
subset_tvb_offset, subset_tvb_length);
tvb_add_to_chain(backing, tvb);
return tvb;
}
@ -213,5 +216,13 @@ tvb_new_subset_remaining(tvbuff_t *backing, const gint backing_offset)
tvb = tvb_new_with_subset(backing, -1 /* reported_length */,
subset_tvb_offset, subset_tvb_length);
tvb_add_to_chain(backing, tvb);
return tvb;
}
tvbuff_t *
tvb_new_temporary(tvbuff_t *backing)
{
return tvb_new_with_subset(backing, backing->reported_length, 0, backing->length);
}