When reading MIME-encapsulated files, read the entire file at once,
authorguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>
Tue, 31 Dec 2013 23:47:24 +0000 (23:47 +0000)
committerguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>
Tue, 31 Dec 2013 23:47:24 +0000 (23:47 +0000)
don't break it into chunks.

This means we don't need to do reassembly in the MIME-encapsulated-data
dissector.

git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@54524 f5534014-38df-0310-8fa8-9805f1628bb7

epan/dissectors/packet-mime-encap.c
wiretap/mpeg.c

index 29c0902ab7326df78e9a6aace2a9e03061bd0ab1..58b44f383788e6a1fa86813ba795875b48ec962f 100644 (file)
@@ -26,9 +26,8 @@
 #include <glib.h>
 
 #include <epan/packet.h>
-#include <wiretap/wtap.h>
 
-#include "tvbuff-int.h"
+#include <wiretap/wtap.h>
 
 void proto_register_mime_encap(void);
 void proto_reg_handoff_mime_encap(void);
@@ -38,72 +37,19 @@ static int proto_mime_encap = -1;
 static heur_dissector_list_t heur_subdissector_list;
 static dissector_handle_t data_handle;
 
-static tvbuff_t *file_tvbs;
-static tvbuff_t *whole_tvb;
-
-static void
-mime_encap_init(void)
-{
-       if (file_tvbs) {
-               tvb_free_chain(file_tvbs);
-               file_tvbs = NULL;
-               whole_tvb = NULL;
-       }
-}
-
 static void
 dissect_mime_encap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 {
        proto_item* item;
-       guint len;
 
        /* XXX, COL_INFO */
 
        col_set_str(pinfo->cinfo, COL_PROTOCOL, "MIME_FILE");
        item = proto_tree_add_item(tree, proto_mime_encap, tvb, 0, -1, ENC_NA);
 
-       /* frames with nsec >= 1000000000 means errors :) */
-       if (pinfo->fd->abs_ts.nsecs >= 1000000000) {
-               proto_item_append_text(item, " (Error)");
-               /* return; */ /* dissect what we have */
-       }
-
-       len = tvb_length(tvb);
-       if (!pinfo->fd->flags.visited) {
-               if (len) {
-                       tvbuff_t *cloned_tvb = tvb_clone(tvb);
-
-                       if (!file_tvbs) {
-                               file_tvbs = cloned_tvb;
-                               whole_tvb = tvb_new_composite();
-                       } else
-                               tvb_add_to_chain(file_tvbs, 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)
-                */
-               tvbuff_t *tmp_tvb = tvb_new_chain(tvb, whole_tvb);
-
-               proto_item_append_text(item, " (Final)");
-
-               add_new_data_source(pinfo, tmp_tvb, "Whole file");
-
-               if (!dissector_try_heuristic(heur_subdissector_list, tmp_tvb, pinfo, tree, NULL)) {
-                       proto_item_append_text(item, " (Unhandled)");
-                       call_dissector(data_handle, tmp_tvb, pinfo, tree);
-               }
+       if (!dissector_try_heuristic(heur_subdissector_list, tvb, pinfo, tree, NULL)) {
+               proto_item_append_text(item, " (Unhandled)");
+               call_dissector(data_handle, tvb, pinfo, tree);
        }
 }
 
@@ -113,7 +59,6 @@ proto_register_mime_encap(void)
        proto_mime_encap = proto_register_protocol("MIME file", "MIME_FILE", "mime_dlt");
 
        register_dissector("mime_dlt", dissect_mime_encap, proto_mime_encap);
-       register_init_routine(mime_encap_init);
        register_heur_dissector_list("wtap_file", &heur_subdissector_list);
 }
 
index 3767978747a52324d128d3cd9b9847c1b86977bf..62d929af836ed9481f54339260307f131d4fd6ca 100644 (file)
@@ -52,41 +52,41 @@ typedef struct {
 } mpeg_t;
 
 static int
-mpeg_resync(wtap *wth, int *err, gchar **err_info _U_)
+mpeg_resync(FILE_T fh, int *err)
 {
-       gint64 offset = file_tell(wth->fh);
+       gint64 offset = file_tell(fh);
        int count = 0;
-       int byte = file_getc(wth->fh);
+       int byte = file_getc(fh);
 
        while (byte != EOF) {
                if (byte == 0xff && count > 0) {
-                       byte = file_getc(wth->fh);
+                       byte = file_getc(fh);
                        if (byte != EOF && (byte & 0xe0) == 0xe0)
                                break;
                } else
-                       byte = file_getc(wth->fh);
+                       byte = file_getc(fh);
                count++;
        }
-       if (file_seek(wth->fh, offset, SEEK_SET, err) == -1)
+       if (file_seek(fh, offset, SEEK_SET, err) == -1)
                return 0;
        return count;
 }
 
 static int
-mpeg_read_header(wtap *wth, int *err, gchar **err_info, guint32 *n)
+mpeg_read_header(FILE_T fh, int *err, gchar **err_info, guint32 *n)
 {
        int bytes_read;
 
        errno = WTAP_ERR_CANT_READ;
-       bytes_read = file_read(n, sizeof *n, wth->fh);
+       bytes_read = file_read(n, sizeof *n, fh);
        if (bytes_read != sizeof *n) {
-               *err = file_error(wth->fh, err_info);
+               *err = file_error(fh, err_info);
                if (*err == 0 && bytes_read != 0)
                        *err = WTAP_ERR_SHORT_READ;
                return -1;
        }
        *n = g_ntohl(*n);
-       if (file_seek(wth->fh, -(gint64)(sizeof *n), SEEK_CUR, err) == -1)
+       if (file_seek(fh, -(gint64)(sizeof *n), SEEK_CUR, err) == -1)
                return -1;
        return bytes_read;
 }
@@ -94,28 +94,28 @@ mpeg_read_header(wtap *wth, int *err, gchar **err_info, guint32 *n)
 #define SCRHZ 27000000
 
 static gboolean
-mpeg_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
+mpeg_read_packet(wtap *wth, FILE_T fh, struct wtap_pkthdr *phdr, Buffer *buf,
+    gboolean is_random, int *err, gchar **err_info)
 {
        mpeg_t *mpeg = (mpeg_t *)wth->priv;
        guint32 n;
-       int bytes_read = mpeg_read_header(wth, err, err_info, &n);
+       int bytes_read;
        unsigned int packet_size;
        nstime_t ts = mpeg->now;
 
+       bytes_read = mpeg_read_header(fh, err, err_info, &n);
        if (bytes_read == -1)
                return FALSE;
        if (PES_VALID(n)) {
-               gint64 offset = file_tell(wth->fh);
+               gint64 offset = file_tell(fh);
                guint8 stream;
 
-               if (offset == -1)
-                       return -1;
-               if (file_seek(wth->fh, 3, SEEK_CUR, err) == -1)
+               if (file_seek(fh, 3, SEEK_CUR, err) == -1)
                        return FALSE;
 
-               bytes_read = file_read(&stream, sizeof stream, wth->fh);
+               bytes_read = file_read(&stream, sizeof stream, fh);
                if (bytes_read != sizeof stream) {
-                       *err = file_error(wth->fh, err_info);
+                       *err = file_error(fh, err_info);
                        return FALSE;
                }
 
@@ -125,16 +125,16 @@ mpeg_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
                        guint64 pack;
                        guint8 stuffing;
 
-                       bytes_read = file_read(&pack1, sizeof pack1, wth->fh);
+                       bytes_read = file_read(&pack1, sizeof pack1, fh);
                        if (bytes_read != sizeof pack1) {
-                               *err = file_error(wth->fh, err_info);
+                               *err = file_error(fh, err_info);
                                if (*err == 0 && bytes_read != 0)
                                        *err = WTAP_ERR_SHORT_READ;
                                return FALSE;
                        }
-                       bytes_read = file_read(&pack0, sizeof pack0, wth->fh);
+                       bytes_read = file_read(&pack0, sizeof pack0, fh);
                        if (bytes_read != sizeof pack0) {
-                               *err = file_error(wth->fh, err_info);
+                               *err = file_error(fh, err_info);
                                if (*err == 0 && bytes_read != 0)
                                        *err = WTAP_ERR_SHORT_READ;
                                return FALSE;
@@ -143,18 +143,18 @@ mpeg_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
 
                        switch (pack >> 62) {
                                case 1:
-                                       if (file_seek(wth->fh, 1, SEEK_CUR, err) == -1)
+                                       if (file_seek(fh, 1, SEEK_CUR, err) == -1)
                                                return FALSE;
                                        bytes_read = file_read(&stuffing,
-                                                       sizeof stuffing, wth->fh);
+                                                       sizeof stuffing, fh);
                                        if (bytes_read != sizeof stuffing) {
-                                               *err = file_error(wth->fh, err_info);
+                                               *err = file_error(fh, err_info);
                                                return FALSE;
                                        }
                                        stuffing &= 0x07;
                                        packet_size = 14 + stuffing;
 
-                                       {
+                                       if (!is_random) {
                                                guint64 bytes = pack >> 16;
                                                guint64 ts_val =
                                                        (bytes >> 43 & 0x0007) << 30 |
@@ -175,9 +175,9 @@ mpeg_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
                        }
                } else {
                        guint16 length;
-                       bytes_read = file_read(&length, sizeof length, wth->fh);
+                       bytes_read = file_read(&length, sizeof length, fh);
                        if (bytes_read != sizeof length) {
-                               *err = file_error(wth->fh, err_info);
+                               *err = file_error(fh, err_info);
                                if (*err == 0 && bytes_read != 0)
                                        *err = WTAP_ERR_SHORT_READ;
                                return FALSE;
@@ -186,7 +186,7 @@ mpeg_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
                        packet_size = 6 + length;
                }
 
-               if (file_seek(wth->fh, offset, SEEK_SET, err) == -1)
+               if (file_seek(fh, offset, SEEK_SET, err) == -1)
                        return FALSE;
        } else {
                struct mpa mpa;
@@ -194,38 +194,58 @@ mpeg_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
                MPA_UNMARSHAL(&mpa, n);
                if (MPA_VALID(&mpa)) {
                        packet_size = MPA_BYTES(&mpa);
-                       mpeg->now.nsecs += MPA_DURATION_NS(&mpa);
-                       if (mpeg->now.nsecs >= 1000000000) {
-                               mpeg->now.secs++;
-                               mpeg->now.nsecs -= 1000000000;
+                       if (!is_random) {
+                               mpeg->now.nsecs += MPA_DURATION_NS(&mpa);
+                               if (mpeg->now.nsecs >= 1000000000) {
+                                       mpeg->now.secs++;
+                                       mpeg->now.nsecs -= 1000000000;
+                               }
                        }
                } else {
-                       packet_size = mpeg_resync(wth, err, err_info);
+                       packet_size = mpeg_resync(fh, err);
                        if (packet_size == 0)
                                return FALSE;
                }
        }
-       *data_offset = file_tell(wth->fh);
 
-       if (!wtap_read_packet_bytes(wth->fh, wth->frame_buffer,
-                               packet_size, err, err_info))
+       if (!wtap_read_packet_bytes(fh, buf, packet_size, err, err_info))
                return FALSE;
+
        /* XXX - relative, not absolute, time stamps */
-       wth->phdr.presence_flags = WTAP_HAS_TS;
-       wth->phdr.ts = ts;
-       wth->phdr.caplen = packet_size;
-       wth->phdr.len = packet_size;
+       if (!is_random) {
+               phdr->presence_flags = WTAP_HAS_TS;
+               phdr->ts = ts;
+       }
+       phdr->caplen = packet_size;
+       phdr->len = packet_size;
+
        return TRUE;
 }
 
+static gboolean 
+mpeg_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
+{
+       *data_offset = file_tell(wth->fh);
+
+       return mpeg_read_packet(wth, wth->fh, &wth->phdr, wth->frame_buffer,
+           FALSE, err, err_info);
+}
+
 static gboolean
 mpeg_seek_read(wtap *wth, gint64 seek_off,
-               struct wtap_pkthdr *phdr _U_, Buffer *buf, int length,
+               struct wtap_pkthdr *phdr, Buffer *buf, int length _U_,
                int *err, gchar **err_info)
 {
        if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
                return FALSE;
-       return wtap_read_packet_bytes(wth->random_fh, buf, length, err, err_info);
+
+       if (!mpeg_read_packet(wth, wth->random_fh, phdr, buf, TRUE, err,
+           err_info)) {
+               if (*err == 0)
+                       *err = WTAP_ERR_SHORT_READ;
+               return FALSE;
+       }
+       return TRUE;
 }
 
 struct _mpeg_magic {