aboutsummaryrefslogtreecommitdiffstats
path: root/epan
diff options
context:
space:
mode:
authorJeff Morriss <jeff.morriss.ws@gmail.com>2013-07-11 23:57:11 +0000
committerJeff Morriss <jeff.morriss.ws@gmail.com>2013-07-11 23:57:11 +0000
commit45449ce1a8f3d287dc4afe1106e5ad05608487fe (patch)
treebe7810a7b1a590ce37fc7410ef8119ef8745face /epan
parentd7466120c9b961cf6f44eb418672ea302dbf4362 (diff)
Move some more modules into epan.
svn path=/trunk/; revision=50517
Diffstat (limited to 'epan')
-rw-r--r--epan/CMakeLists.txt2
-rw-r--r--epan/Makefile.common4
-rw-r--r--epan/frame_data_sequence.c338
-rw-r--r--epan/frame_data_sequence.h57
-rw-r--r--epan/packet-range.c368
-rw-r--r--epan/packet-range.h120
6 files changed, 889 insertions, 0 deletions
diff --git a/epan/CMakeLists.txt b/epan/CMakeLists.txt
index f4b73b2138..1e3678ba6c 100644
--- a/epan/CMakeLists.txt
+++ b/epan/CMakeLists.txt
@@ -1441,6 +1441,7 @@ set(LIBWIRESHARK_FILES
filter_expressions.c
follow.c
frame_data.c
+ frame_data_sequence.c
frequency-utils.c
funnel.c
gcp.c
@@ -1454,6 +1455,7 @@ set(LIBWIRESHARK_FILES
next_tvb.c
oids.c
osi-utils.c
+ packet-range.c
packet.c
plugins.c
prefs.c
diff --git a/epan/Makefile.common b/epan/Makefile.common
index 446bdead58..3b93b38073 100644
--- a/epan/Makefile.common
+++ b/epan/Makefile.common
@@ -54,6 +54,7 @@ LIBWIRESHARK_SRC = \
filter_expressions.c \
follow.c \
frame_data.c \
+ frame_data_sequence.c \
frequency-utils.c \
funnel.c \
gcp.c \
@@ -67,6 +68,7 @@ LIBWIRESHARK_SRC = \
next_tvb.c \
oids.c \
osi-utils.c \
+ packet-range.c \
packet.c \
plugins.c \
prefs.c \
@@ -184,6 +186,7 @@ LIBWIRESHARK_INCLUDES = \
filesystem.h \
follow.h \
frame_data.h \
+ frame_data_sequence.h \
frequency-utils.h \
funnel.h \
garrayfix.h \
@@ -207,6 +210,7 @@ LIBWIRESHARK_INCLUDES = \
oids.h \
osi-utils.h \
oui.h \
+ packet-range.h \
packet.h \
packet_info.h \
params.h \
diff --git a/epan/frame_data_sequence.c b/epan/frame_data_sequence.c
new file mode 100644
index 0000000000..8748038fb7
--- /dev/null
+++ b/epan/frame_data_sequence.c
@@ -0,0 +1,338 @@
+/* frame_data_sequence.c
+ * Implements a sequence of frame_data structures
+ *
+ * $Id$
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <glib.h>
+
+#include <epan/packet.h>
+
+#include "frame_data_sequence.h"
+
+/*
+ * We store the frame_data structures in a radix tree, with 1024
+ * elements per level. The leaf nodes are arrays of 1024 frame_data
+ * structures; the nodes above them are arrays of 1024 pointers to
+ * the nodes below them. The capture_file structure has a pointer
+ * to the root node.
+ *
+ * As frame numbers are 32 bits, and as 1024 is 2^10, that gives us
+ * up to 4 levels of tree.
+ */
+#define LOG2_NODES_PER_LEVEL 10
+#define NODES_PER_LEVEL (1<<LOG2_NODES_PER_LEVEL)
+
+struct _frame_data_sequence {
+ guint32 count; /* Total number of frames */
+ void *ptree_root; /* Pointer to the root node */
+};
+
+/*
+ * For a given frame number, calculate the indices into a level 3
+ * node, a level 2 node, a level 1 node, and a leaf node.
+ */
+#define LEVEL_3_INDEX(framenum) \
+ ((framenum) >> (3*LOG2_NODES_PER_LEVEL))
+#define LEVEL_2_INDEX(framenum) \
+ (((framenum) >> (2*LOG2_NODES_PER_LEVEL)) & (NODES_PER_LEVEL - 1))
+#define LEVEL_1_INDEX(framenum) \
+ (((framenum) >> (1*LOG2_NODES_PER_LEVEL)) & (NODES_PER_LEVEL - 1))
+#define LEAF_INDEX(framenum) \
+ (((framenum) >> (0*LOG2_NODES_PER_LEVEL)) & (NODES_PER_LEVEL - 1))
+
+frame_data_sequence *
+new_frame_data_sequence(void)
+{
+ frame_data_sequence *fds;
+
+ fds = (frame_data_sequence *)g_malloc(sizeof *fds);
+ fds->count = 0;
+ fds->ptree_root = NULL;
+ return fds;
+}
+
+/*
+ * Add a new frame_data structure to a frame_data_sequence.
+ */
+frame_data *
+frame_data_sequence_add(frame_data_sequence *fds, frame_data *fdata)
+{
+ frame_data *leaf;
+ frame_data **level1;
+ frame_data ***level2;
+ frame_data ****level3;
+ frame_data *node;
+
+ /*
+ * The current value of fds->count is the index value for the new frame,
+ * because the index value for a frame is the frame number - 1, and
+ * if we currently have fds->count frames, the the frame number of
+ * the last frame in the collection is fds->count, so its index value
+ * is fds->count - 1.
+ */
+ if (fds->count == 0) {
+ /* The tree is empty; allocate the first leaf node, which will be
+ the root node. */
+ leaf = (frame_data *)g_malloc((sizeof *leaf)*NODES_PER_LEVEL);
+ node = &leaf[0];
+ fds->ptree_root = leaf;
+ } else if (fds->count < NODES_PER_LEVEL) {
+ /* It's a 1-level tree, and is going to stay that way for now. */
+ leaf = (frame_data *)fds->ptree_root;
+ node = &leaf[fds->count];
+ } else if (fds->count == NODES_PER_LEVEL) {
+ /* It's a 1-level tree that will turn into a 2-level tree. */
+ level1 = (frame_data **)g_malloc0((sizeof *level1)*NODES_PER_LEVEL);
+ level1[0] = (frame_data *)fds->ptree_root;
+ leaf = (frame_data *)g_malloc((sizeof *leaf)*NODES_PER_LEVEL);
+ level1[1] = leaf;
+ node = &leaf[0];
+ fds->ptree_root = level1;
+ } else if (fds->count < NODES_PER_LEVEL*NODES_PER_LEVEL) {
+ /* It's a 2-level tree, and is going to stay that way for now. */
+ level1 = (frame_data **)fds->ptree_root;
+ leaf = level1[fds->count >> LOG2_NODES_PER_LEVEL];
+ if (leaf == NULL) {
+ leaf = (frame_data *)g_malloc((sizeof *leaf)*NODES_PER_LEVEL);
+ level1[fds->count >> LOG2_NODES_PER_LEVEL] = leaf;
+ }
+ node = &leaf[LEAF_INDEX(fds->count)];
+ } else if (fds->count == NODES_PER_LEVEL*NODES_PER_LEVEL) {
+ /* It's a 2-level tree that will turn into a 3-level tree */
+ level2 = (frame_data ***)g_malloc0((sizeof *level2)*NODES_PER_LEVEL);
+ level2[0] = (frame_data **)fds->ptree_root;
+ level1 = (frame_data **)g_malloc0((sizeof *level1)*NODES_PER_LEVEL);
+ level2[1] = level1;
+ leaf = (frame_data *)g_malloc((sizeof *leaf)*NODES_PER_LEVEL);
+ level1[0] = leaf;
+ node = &leaf[0];
+ fds->ptree_root = level2;
+ } else if (fds->count < NODES_PER_LEVEL*NODES_PER_LEVEL*NODES_PER_LEVEL) {
+ /* It's a 3-level tree, and is going to stay that way for now. */
+ level2 = (frame_data ***)fds->ptree_root;
+ level1 = level2[fds->count >> (LOG2_NODES_PER_LEVEL+LOG2_NODES_PER_LEVEL)];
+ if (level1 == NULL) {
+ level1 = (frame_data **)g_malloc0((sizeof *level1)*NODES_PER_LEVEL);
+ level2[fds->count >> (LOG2_NODES_PER_LEVEL+LOG2_NODES_PER_LEVEL)] = level1;
+ }
+ leaf = level1[LEVEL_1_INDEX(fds->count)];
+ if (leaf == NULL) {
+ leaf = (frame_data *)g_malloc((sizeof *leaf)*NODES_PER_LEVEL);
+ level1[LEVEL_1_INDEX(fds->count)] = leaf;
+ }
+ node = &leaf[LEAF_INDEX(fds->count)];
+ } else if (fds->count == NODES_PER_LEVEL*NODES_PER_LEVEL*NODES_PER_LEVEL) {
+ /* It's a 3-level tree that will turn into a 4-level tree */
+ level3 = (frame_data ****)g_malloc0((sizeof *level3)*NODES_PER_LEVEL);
+ level3[0] = (frame_data ***)fds->ptree_root;
+ level2 = (frame_data ***)g_malloc0((sizeof *level2)*NODES_PER_LEVEL);
+ level3[1] = level2;
+ level1 = (frame_data **)g_malloc0((sizeof *level1)*NODES_PER_LEVEL);
+ level2[0] = level1;
+ leaf = (frame_data *)g_malloc((sizeof *leaf)*NODES_PER_LEVEL);
+ level1[0] = leaf;
+ node = &leaf[0];
+ fds->ptree_root = level3;
+ } else {
+ /* fds->count is 2^32-1 at most, and NODES_PER_LEVEL^4
+ 2^(LOG2_NODES_PER_LEVEL*4), and LOG2_NODES_PER_LEVEL is 10,
+ so fds->count is always less < NODES_PER_LEVEL^4.
+
+ XXX - we should fail if fds->count is 2^31-1, or should
+ make the frame numbers 64-bit and just let users run
+ themselves out of address space or swap space. :-) */
+ /* It's a 4-level tree, and is going to stay that way forever. */
+ level3 = (frame_data ****)fds->ptree_root;
+ level2 = level3[LEVEL_3_INDEX(fds->count)];
+ if (level2 == NULL) {
+ level2 = (frame_data ***)g_malloc0((sizeof *level2)*NODES_PER_LEVEL);
+ level3[LEVEL_3_INDEX(fds->count)] = level2;
+ }
+ level1 = level2[LEVEL_2_INDEX(fds->count)];
+ if (level1 == NULL) {
+ level1 = (frame_data **)g_malloc0((sizeof *level1)*NODES_PER_LEVEL);
+ level2[LEVEL_2_INDEX(fds->count)] = level1;
+ }
+ leaf = level1[LEVEL_1_INDEX(fds->count)];
+ if (leaf == NULL) {
+ leaf = (frame_data *)g_malloc((sizeof *leaf)*NODES_PER_LEVEL);
+ level1[LEVEL_1_INDEX(fds->count)] = leaf;
+ }
+ node = &leaf[LEAF_INDEX(fds->count)];
+ }
+ *node = *fdata;
+ fds->count++;
+ return node;
+}
+
+/*
+ * Find the frame_data for the specified frame number.
+ */
+frame_data *
+frame_data_sequence_find(frame_data_sequence *fds, guint32 num)
+{
+ frame_data *leaf;
+ frame_data **level1;
+ frame_data ***level2;
+ frame_data ****level3;
+
+ if (num == 0) {
+ /* There is no frame number 0 */
+ return NULL;
+ }
+
+ /* Convert it into an index number. */
+ num--;
+ if (num >= fds->count) {
+ /* There aren't that many frames. */
+ return NULL;
+ }
+
+ if (fds->count <= NODES_PER_LEVEL) {
+ /* It's a 1-level tree. */
+ leaf = (frame_data *)fds->ptree_root;
+ return &leaf[num];
+ }
+ if (fds->count <= NODES_PER_LEVEL*NODES_PER_LEVEL) {
+ /* It's a 2-level tree. */
+ level1 = (frame_data **)fds->ptree_root;
+ leaf = level1[num >> LOG2_NODES_PER_LEVEL];
+ return &leaf[LEAF_INDEX(num)];
+ }
+ if (fds->count <= NODES_PER_LEVEL*NODES_PER_LEVEL*NODES_PER_LEVEL) {
+ /* It's a 3-level tree. */
+ level2 = (frame_data ***)fds->ptree_root;
+ level1 = level2[num >> (LOG2_NODES_PER_LEVEL+LOG2_NODES_PER_LEVEL)];
+ leaf = level1[(num >> LOG2_NODES_PER_LEVEL) & (NODES_PER_LEVEL - 1)];
+ return &leaf[LEAF_INDEX(num)];
+ }
+ /* fds->count is 2^32-1 at most, and NODES_PER_LEVEL^4
+ 2^(LOG2_NODES_PER_LEVEL*4), and LOG2_NODES_PER_LEVEL is 10,
+ so fds->count is always less < NODES_PER_LEVEL^4. */
+ /* It's a 4-level tree, and is going to stay that way forever. */
+ level3 = (frame_data ****)fds->ptree_root;
+ level2 = level3[num >> (LOG2_NODES_PER_LEVEL+LOG2_NODES_PER_LEVEL+LOG2_NODES_PER_LEVEL)];
+ level1 = level2[(num >> (LOG2_NODES_PER_LEVEL+LOG2_NODES_PER_LEVEL)) & (NODES_PER_LEVEL - 1)];
+ leaf = level1[(num >> LOG2_NODES_PER_LEVEL) & (NODES_PER_LEVEL - 1)];
+ return &leaf[LEAF_INDEX(num)];
+}
+
+/* recursively frees a frame_data radix level */
+static void
+free_frame_data_array(void *array, guint count, guint level, gboolean last)
+{
+ guint i, level_count;
+
+ if (last) {
+ /* if we are the last in our given parent's row, we may not have
+ * exactly a full row, so do the bit twiddling to figure out exactly
+ * how many fields we have */
+ level_count = (count >> ((level - 1) * LOG2_NODES_PER_LEVEL)) &
+ (NODES_PER_LEVEL - 1);
+ /* the above calculation rounds down, so make sure we count correctly
+ * if count is not an even multiple of NODES_PER_LEVEL */
+ if (count & ((1 << ((level - 1) * LOG2_NODES_PER_LEVEL)) - 1)) {
+ level_count++;
+ }
+ }
+ else {
+ /* if we're not the last in our parent, then we're guaranteed to have
+ * a full array */
+ level_count = NODES_PER_LEVEL;
+ }
+
+
+ if (level > 1) {
+ /* recurse on every sub-array, passing on our own 'last' value
+ * specially to our last child */
+ frame_data **real_array = (frame_data **) array;
+
+ for (i=0; i < level_count-1; i++) {
+ free_frame_data_array(real_array[i], count, level-1, FALSE);
+ }
+
+ free_frame_data_array(real_array[level_count-1], count, level-1, last);
+ }
+ else if (level == 1) {
+ /* bottom level, so just clean up all the frame data */
+ frame_data *real_array = (frame_data *) array;
+
+ for (i=0; i < level_count; i++) {
+ frame_data_destroy(&real_array[i]);
+ }
+ }
+
+ /* free the array itself */
+ g_free(array);
+}
+
+/*
+ * Free a frame_data_sequence and all the frame_data structures in it.
+ */
+void
+free_frame_data_sequence(frame_data_sequence *fds)
+{
+ guint32 count = fds->count;
+ guint levels = 0;
+
+ /* calculate how many levels we have */
+ while (count) {
+ levels++;
+ count >>= LOG2_NODES_PER_LEVEL;
+ }
+
+ /* call the recursive free function */
+ if (levels > 0) {
+ free_frame_data_array(fds->ptree_root, fds->count, levels, TRUE);
+ }
+
+ /* free the header struct */
+ g_free(fds);
+}
+
+void
+find_and_mark_frame_depended_upon(gpointer data, gpointer user_data)
+{
+ frame_data *dependent_fd;
+ guint32 dependent_frame = GPOINTER_TO_UINT(data);
+ frame_data_sequence *frames = (frame_data_sequence *)user_data;
+
+ if (dependent_frame && frames) {
+ dependent_fd = frame_data_sequence_find(frames, dependent_frame);
+ dependent_fd->flags.dependent_of_displayed = 1;
+ }
+}
+
+/*
+ * Editor modelines - http://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 2
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vi: set shiftwidth=2 tabstop=8 expandtab:
+ * :indentSize=2:tabSize=8:noTabs=true:
+ */
diff --git a/epan/frame_data_sequence.h b/epan/frame_data_sequence.h
new file mode 100644
index 0000000000..bf3611a16f
--- /dev/null
+++ b/epan/frame_data_sequence.h
@@ -0,0 +1,57 @@
+/* frame_data_sequence.h
+ * Implements a sequence of frame_data structures
+ *
+ * $Id$
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __FRAME_DATA_SEQUENCE_H__
+#define __FRAME_DATA_SEQUENCE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct _frame_data_sequence frame_data_sequence;
+
+WS_DLL_PUBLIC frame_data_sequence *new_frame_data_sequence(void);
+
+WS_DLL_PUBLIC frame_data *frame_data_sequence_add(frame_data_sequence *fds,
+ frame_data *fdata);
+
+/*
+ * Find the frame_data for the specified frame number.
+ */
+WS_DLL_PUBLIC frame_data *frame_data_sequence_find(frame_data_sequence *fds,
+ guint32 num);
+
+/*
+ * Free a frame_data_sequence and all the frame_data structures in it.
+ */
+WS_DLL_PUBLIC void free_frame_data_sequence(frame_data_sequence *fds);
+
+WS_DLL_PUBLIC void find_and_mark_frame_depended_upon(gpointer data, gpointer user_data);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __FRAME_DATA_SEQUENCE_H__ */
diff --git a/epan/packet-range.c b/epan/packet-range.c
new file mode 100644
index 0000000000..dc3391b3da
--- /dev/null
+++ b/epan/packet-range.c
@@ -0,0 +1,368 @@
+/* packet-range.c
+ * Packet range routines (save, print, ...)
+ *
+ * $Id$
+ *
+ * Dick Gooris <gooris@lucent.com>
+ * Ulf Lamping <ulf.lamping@web.de>
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <glib.h>
+
+#include <epan/frame_data.h>
+
+#include "packet-range.h"
+
+/* (re-)calculate the packet counts (except the user specified range) */
+static void packet_range_calc(packet_range_t *range) {
+ guint32 framenum;
+ guint32 mark_low;
+ guint32 mark_high;
+ guint32 displayed_mark_low;
+ guint32 displayed_mark_high;
+ frame_data *packet;
+
+
+ range->selected_packet = 0L;
+
+ mark_low = 0L;
+ mark_high = 0L;
+ range->mark_range_cnt = 0L;
+ range->ignored_cnt = 0L;
+ range->ignored_marked_cnt = 0L;
+ range->ignored_mark_range_cnt = 0L;
+ range->ignored_user_range_cnt = 0L;
+
+ displayed_mark_low = 0L;
+ displayed_mark_high = 0L;
+ range->displayed_cnt = 0L;
+ range->displayed_marked_cnt = 0L;
+ range->displayed_mark_range_cnt=0L;
+ range->displayed_plus_dependents_cnt = 0L;
+ range->displayed_ignored_cnt = 0L;
+ range->displayed_ignored_marked_cnt = 0L;
+ range->displayed_ignored_mark_range_cnt = 0L;
+ range->displayed_ignored_user_range_cnt = 0L;
+
+ g_assert(range->cf != NULL);
+
+ /* XXX - this doesn't work unless you have a full set of frame_data
+ * structures for all packets in the capture, which is not,
+ * for example, the case when TShark is doing a one-pass
+ * read of a file or a live capture.
+ *
+ * It's also horribly slow on large captures, causing it to
+ * take a long time for the Save As dialog to pop up, for
+ * example. We should really keep these statistics in
+ * the capture_file structure, updating them whenever we
+ * filter the display, etc..
+ */
+ if (range->cf->frames != NULL) {
+ /* The next for-loop is used to obtain the amount of packets
+ * to be processed and is used to present the information in
+ * the Save/Print As widget.
+ * We have different types of ranges: All the packets, the number
+ * of packets of a marked range, a single packet, and a user specified
+ * packet range. The last one is not calculated here since this
+ * data must be entered in the widget by the user.
+ */
+
+ for(framenum = 1; framenum <= range->cf->count; framenum++) {
+ packet = frame_data_sequence_find(range->cf->frames, framenum);
+
+ if (range->cf->current_frame == packet) {
+ range->selected_packet = framenum;
+ }
+ if (packet->flags.passed_dfilter) {
+ range->displayed_cnt++;
+ }
+ if (packet->flags.passed_dfilter ||
+ packet->flags.dependent_of_displayed) {
+ range->displayed_plus_dependents_cnt++;
+ }
+ if (packet->flags.marked) {
+ if (packet->flags.ignored) {
+ range->ignored_marked_cnt++;
+ }
+ if (packet->flags.passed_dfilter) {
+ range->displayed_marked_cnt++;
+ if (packet->flags.ignored) {
+ range->displayed_ignored_marked_cnt++;
+ }
+ if (displayed_mark_low == 0) {
+ displayed_mark_low = framenum;
+ }
+ if (framenum > displayed_mark_high) {
+ displayed_mark_high = framenum;
+ }
+ }
+
+ if (mark_low == 0) {
+ mark_low = framenum;
+ }
+ if (framenum > mark_high) {
+ mark_high = framenum;
+ }
+ }
+ if (packet->flags.ignored) {
+ range->ignored_cnt++;
+ if (packet->flags.passed_dfilter) {
+ range->displayed_ignored_cnt++;
+ }
+ }
+ }
+
+ for(framenum = 1; framenum <= range->cf->count; framenum++) {
+ packet = frame_data_sequence_find(range->cf->frames, framenum);
+
+ if (framenum >= mark_low &&
+ framenum <= mark_high)
+ {
+ range->mark_range_cnt++;
+ if (packet->flags.ignored) {
+ range->ignored_mark_range_cnt++;
+ }
+ }
+
+ if (framenum >= displayed_mark_low &&
+ framenum <= displayed_mark_high)
+ {
+ if (packet->flags.passed_dfilter) {
+ range->displayed_mark_range_cnt++;
+ if (packet->flags.ignored) {
+ range->displayed_ignored_mark_range_cnt++;
+ }
+ }
+ }
+ }
+
+#if 0
+ /* in case we marked just one packet, we add 1. */
+ if (range->cf->marked_count != 0) {
+ range->mark_range = mark_high - mark_low + 1;
+ }
+
+ /* in case we marked just one packet, we add 1. */
+ if (range->displayed_marked_cnt != 0) {
+ range->displayed_mark_range = displayed_mark_high - displayed_mark_low + 1;
+ }
+#endif
+ }
+}
+
+
+/* (re-)calculate the user specified packet range counts */
+static void packet_range_calc_user(packet_range_t *range) {
+ guint32 framenum;
+ frame_data *packet;
+
+ range->user_range_cnt = 0L;
+ range->ignored_user_range_cnt = 0L;
+ range->displayed_user_range_cnt = 0L;
+ range->displayed_ignored_user_range_cnt = 0L;
+
+ g_assert(range->cf != NULL);
+
+ /* XXX - this doesn't work unless you have a full set of frame_data
+ * structures for all packets in the capture, which is not,
+ * for example, the case when TShark is doing a one-pass
+ * read of a file or a live capture.
+ *
+ * It's also horribly slow on large captures, causing it to
+ * take a long time for the Save As dialog to pop up, for
+ * example. This obviously can't be kept in the capture_file
+ * structure and recalculated whenever we filter the display
+ * or mark frames as ignored, as the results of this depend
+ * on what the user specifies. In some cases, limiting the
+ * frame_data structures at which we look to the ones specified
+ * by the user might help, but if most of the frames are in
+ * the range, that won't help. In that case, if we could
+ * examine the *complement* of the range, and *subtract* them
+ * from the statistics for the capture as a whole, that might
+ * help, but if the user specified about *half* the packets in
+ * the range, that won't help, either.
+ */
+ if (range->cf->frames != NULL) {
+ for(framenum = 1; framenum <= range->cf->count; framenum++) {
+ packet = frame_data_sequence_find(range->cf->frames, framenum);
+
+ if (value_is_in_range(range->user_range, framenum)) {
+ range->user_range_cnt++;
+ if (packet->flags.ignored) {
+ range->ignored_user_range_cnt++;
+ }
+ if (packet->flags.passed_dfilter) {
+ range->displayed_user_range_cnt++;
+ if (packet->flags.ignored) {
+ range->displayed_ignored_user_range_cnt++;
+ }
+ }
+ }
+ }
+ }
+}
+
+
+/* init the range struct */
+void packet_range_init(packet_range_t *range, capture_file *cf) {
+
+ memset(range, 0, sizeof(packet_range_t));
+ range->process = range_process_all;
+ range->user_range = range_empty();
+ range->cf = cf;
+
+ /* calculate all packet range counters */
+ packet_range_calc(range);
+ packet_range_calc_user(range);
+}
+
+/* check whether the packet range is OK */
+convert_ret_t packet_range_check(packet_range_t *range) {
+ if (range->process == range_process_user_range && range->user_range == NULL) {
+ /* Not valid - return the error. */
+ return range->user_range_status;
+ }
+ return CVT_NO_ERROR;
+}
+
+/* init the processing run */
+void packet_range_process_init(packet_range_t *range) {
+ /* Check that, if an explicit range was selected, it's valid. */
+ /* "enumeration" values */
+ range->marked_range_active = FALSE;
+ range->selected_done = FALSE;
+
+ if (range->process_filtered == FALSE) {
+ range->marked_range_left = range->mark_range_cnt;
+ } else {
+ range->marked_range_left = range->displayed_mark_range_cnt;
+ }
+}
+
+/* do we have to process all packets? */
+gboolean packet_range_process_all(packet_range_t *range) {
+ return range->process == range_process_all && !range->process_filtered && !range->remove_ignored;
+}
+
+/* do we have to process this packet? */
+range_process_e packet_range_process_packet(packet_range_t *range, frame_data *fdata) {
+
+ if (range->remove_ignored && fdata->flags.ignored) {
+ return range_process_next;
+ }
+
+ g_assert(range->cf != NULL);
+
+ switch(range->process) {
+ case(range_process_all):
+ break;
+ case(range_process_selected):
+ if (range->selected_done) {
+ return range_processing_finished;
+ }
+ if (fdata->num != range->cf->current_frame->num) {
+ return range_process_next;
+ }
+ range->selected_done = TRUE;
+ break;
+ case(range_process_marked):
+ if (fdata->flags.marked == FALSE) {
+ return range_process_next;
+ }
+ break;
+ case(range_process_marked_range):
+ if (range->marked_range_left == 0) {
+ return range_processing_finished;
+ }
+ if (fdata->flags.marked == TRUE) {
+ range->marked_range_active = TRUE;
+ }
+ if (range->marked_range_active == FALSE ) {
+ return range_process_next;
+ }
+ if (!range->process_filtered ||
+ (range->process_filtered && fdata->flags.passed_dfilter == TRUE))
+ {
+ range->marked_range_left--;
+ }
+ break;
+ case(range_process_user_range):
+ if (value_is_in_range(range->user_range, fdata->num) == FALSE) {
+ return range_process_next;
+ }
+ break;
+ default:
+ g_assert_not_reached();
+ }
+
+ /* This packet has to pass the display filter but didn't?
+ * Try next, but only if we're not including dependent packets and this
+ * packet happens to be a dependency on something that is displayed.
+ */
+ if ((range->process_filtered && fdata->flags.passed_dfilter == FALSE) &&
+ !(range->include_dependents && fdata->flags.dependent_of_displayed)) {
+ return range_process_next;
+ }
+
+ /* We fell through the conditions above, so we accept this packet */
+ return range_process_this;
+}
+
+
+/******************** Range Entry Parser *********************************/
+
+/* Converts a range string to a user range.
+ * The parameter 'es' points to the string to be converted, and is defined in
+ * the Save/Print-As widget.
+ */
+
+void packet_range_convert_str(packet_range_t *range, const gchar *es)
+{
+ range_t *new_range;
+ convert_ret_t ret;
+
+ if (range->user_range != NULL)
+ g_free(range->user_range);
+
+ g_assert(range->cf != NULL);
+
+ ret = range_convert_str(&new_range, es, range->cf->count);
+ if (ret != CVT_NO_ERROR) {
+ /* range isn't valid */
+ range->user_range = NULL;
+ range->user_range_status = ret;
+ range->user_range_cnt = 0L;
+ range->ignored_user_range_cnt = 0L;
+ range->displayed_user_range_cnt = 0L;
+ range->displayed_ignored_user_range_cnt = 0L;
+ return;
+ }
+ range->user_range = new_range;
+
+ /* calculate new user specified packet range counts */
+ packet_range_calc_user(range);
+} /* packet_range_convert_str */
diff --git a/epan/packet-range.h b/epan/packet-range.h
new file mode 100644
index 0000000000..a1e5d9337c
--- /dev/null
+++ b/epan/packet-range.h
@@ -0,0 +1,120 @@
+/* packet-range.h
+ * Packet range routines (save, print, ...)
+ *
+ * $Id$
+ *
+ * Dick Gooris <gooris@lucent.com>
+ * Ulf Lamping <ulf.lamping@web.de>
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __PACKET_RANGE_H__
+#define __PACKET_RANGE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include <glib.h>
+
+#include <epan/range.h>
+
+#include "cfile.h"
+
+
+extern guint32 curr_selected_frame;
+
+typedef enum {
+ range_process_all,
+ range_process_selected,
+ range_process_marked,
+ range_process_marked_range,
+ range_process_user_range
+} packet_range_e;
+
+typedef struct packet_range_tag {
+ /* values coming from the UI */
+ packet_range_e process; /* which range to process */
+ gboolean process_filtered; /* captured or filtered packets */
+ gboolean remove_ignored; /* remove ignored packets */
+ gboolean include_dependents; /* True if packets which are dependents of others should be processed */
+
+ /* user specified range(s) and, if null, error status */
+ range_t *user_range;
+ convert_ret_t user_range_status;
+
+ /* calculated values */
+ guint32 selected_packet; /* the currently selected packet */
+
+ /* current packet counts (captured) */
+ capture_file *cf; /* Associated capture file. */
+ guint32 mark_range_cnt; /* packets in marked range */
+ guint32 user_range_cnt; /* packets in user specified range */
+ guint32 ignored_cnt; /* packets ignored */
+ guint32 ignored_marked_cnt; /* packets ignored and marked */
+ guint32 ignored_mark_range_cnt; /* packets ignored in marked range */
+ guint32 ignored_user_range_cnt; /* packets ignored in user specified range */
+
+ /* current packet counts (displayed) */
+ guint32 displayed_cnt;
+ guint32 displayed_plus_dependents_cnt;
+ guint32 displayed_marked_cnt;
+ guint32 displayed_mark_range_cnt;
+ guint32 displayed_user_range_cnt;
+ guint32 displayed_ignored_cnt;
+ guint32 displayed_ignored_marked_cnt;
+ guint32 displayed_ignored_mark_range_cnt;
+ guint32 displayed_ignored_user_range_cnt;
+
+ /* "enumeration" values */
+ gboolean marked_range_active; /* marked range is currently processed */
+ guint32 marked_range_left; /* marked range packets left to do */
+ gboolean selected_done; /* selected packet already processed */
+} packet_range_t;
+
+typedef enum {
+ range_process_this, /* process this packet */
+ range_process_next, /* skip this packet, process next */
+ range_processing_finished /* stop processing, required packets done */
+} range_process_e;
+
+/* init the range structure */
+WS_DLL_PUBLIC void packet_range_init(packet_range_t *range, capture_file *cf);
+
+/* check whether the packet range is OK */
+WS_DLL_PUBLIC convert_ret_t packet_range_check(packet_range_t *range);
+
+/* init the processing run */
+WS_DLL_PUBLIC void packet_range_process_init(packet_range_t *range);
+
+/* do we have to process all packets? */
+WS_DLL_PUBLIC gboolean packet_range_process_all(packet_range_t *range);
+
+/* do we have to process this packet? */
+WS_DLL_PUBLIC range_process_e packet_range_process_packet(packet_range_t *range, frame_data *fdata);
+
+/* convert user given string to the internal user specified range representation */
+WS_DLL_PUBLIC void packet_range_convert_str(packet_range_t *range, const gchar *es);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __PACKET_RANGE_H__ */