summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Zawadzki <darkjames-ws@darkjames.pl>2013-07-14 08:41:04 +0000
committerJakub Zawadzki <darkjames-ws@darkjames.pl>2013-07-14 08:41:04 +0000
commit2131f2250837f40595968c5fb52f6bcc3e165064 (patch)
tree168f28b3cbe6a7c1cfa36912771fefa94d98c70c
parentb3e0623e5ca3661404db30e9a702b1c11ad6e5d9 (diff)
downloadwireshark-2131f2250837f40595968c5fb52f6bcc3e165064.tar.gz
Rewrite packet-mime-encap to use composite tvbs + cloning
svn path=/trunk/; revision=50571
-rw-r--r--epan/dissectors/packet-mime-encap.c60
-rw-r--r--epan/tvbuff-int.h2
-rw-r--r--epan/tvbuff_subset.c13
3 files changed, 56 insertions, 19 deletions
diff --git a/epan/dissectors/packet-mime-encap.c b/epan/dissectors/packet-mime-encap.c
index 071c4ce160..46000e440f 100644
--- a/epan/dissectors/packet-mime-encap.c
+++ b/epan/dissectors/packet-mime-encap.c
@@ -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);
+
+ if (!whole_tvb) {
+ whole_tvb = tvb_new_composite();
+ first_tvb = cloned_tvb;
+ }
- /* eof? */
- if (!(len = tvb_length(tvb))) {
- tvbuff_t *comp_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);
}
}
}
diff --git a/epan/tvbuff-int.h b/epan/tvbuff-int.h
index 2fdb2caa1f..890138f8d4 100644
--- a/epan/tvbuff-int.h
+++ b/epan/tvbuff-int.h
@@ -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);
diff --git a/epan/tvbuff_subset.c b/epan/tvbuff_subset.c
index fe327fecbe..a06d60ea09 100644
--- a/epan/tvbuff_subset.c
+++ b/epan/tvbuff_subset.c
@@ -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);
+}