Create a new frame_data_sequence data type; it represents a dense

sequence of frame_data structures, indexed by the frame number.  Extract
the relevant bits of the capture_file data structure and move them to
the frame_data_sequence, and move the relevant code from cfile.c and
tweak it to handle frame_data_sequence structures.

Have a possibly-null pointer to a frame_data_sequence structure in the
capture_file structure; if it's null, we aren't keeping a sequence of
frame_data structures (we don't keep that sequence when we're doing
one-pass processing in TShark).

Nothing in libwireshark should care about a capture_file structure; get
rid of some unnecessary includes of cfile.h.

svn path=/trunk/; revision=36881
This commit is contained in:
Guy Harris 2011-04-27 02:54:44 +00:00
parent 6c09e1cf95
commit c9b9dd690b
13 changed files with 405 additions and 307 deletions

View File

@ -51,6 +51,7 @@ WIRESHARK_COMMON_SRC = \
cfile.c \ cfile.c \
clopts_common.c \ clopts_common.c \
disabled_protos.c \ disabled_protos.c \
frame_data_sequence.c \
packet-range.c \ packet-range.c \
print.c \ print.c \
ps.c \ ps.c \
@ -74,6 +75,7 @@ WIRESHARK_COMMON_INCLUDES = \
disabled_protos.h \ disabled_protos.h \
file.h \ file.h \
fileset.h \ fileset.h \
frame_data_sequence.h \
isprint.h \ isprint.h \
packet-range.h \ packet-range.h \
print.h \ print.h \

268
cfile.c
View File

@ -37,260 +37,16 @@ void
cap_file_init(capture_file *cf) cap_file_init(capture_file *cf)
{ {
/* Initialize the capture file struct */ /* Initialize the capture file struct */
cf->ptree_root = NULL; cf->filename = NULL;
cf->wth = NULL; cf->source = NULL;
cf->filename = NULL; cf->is_tempfile = FALSE;
cf->source = NULL; cf->user_saved = FALSE;
cf->user_saved = FALSE; cf->count = 0;
cf->is_tempfile = FALSE; cf->has_snap = FALSE;
cf->rfcode = NULL; cf->snap = WTAP_MAX_PACKET_SIZE;
cf->dfilter = NULL; cf->wth = NULL;
cf->has_snap = FALSE; cf->rfcode = NULL;
cf->snap = WTAP_MAX_PACKET_SIZE; cf->dfilter = NULL;
cf->count = 0; cf->redissecting = FALSE;
cf->redissecting = FALSE; cf->frames = NULL;
}
/*
* 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))
/*
* Add a new frame_data structure to the capture_file's collection.
*/
frame_data *
cap_file_add_fdata(capture_file *cf, frame_data *fdata)
{
frame_data *leaf;
frame_data **level1;
frame_data ***level2;
frame_data ****level3;
frame_data *node;
/*
* The current value of cf->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 cf->count frames, the the frame number of
* the last frame in the collection is cf->count, so its index value
* is cf->count - 1.
*/
if (cf->count == 0) {
/* The tree is empty; allocate the first leaf node, which will be
the root node. */
leaf = g_malloc((sizeof *leaf)*NODES_PER_LEVEL);
node = &leaf[0];
cf->ptree_root = leaf;
} else if (cf->count < NODES_PER_LEVEL) {
/* It's a 1-level tree, and is going to stay that way for now. */
leaf = cf->ptree_root;
node = &leaf[cf->count];
} else if (cf->count == NODES_PER_LEVEL) {
/* It's a 1-level tree that will turn into a 2-level tree. */
level1 = g_malloc((sizeof *level1)*NODES_PER_LEVEL);
memset(level1, 0, (sizeof *level1)*NODES_PER_LEVEL);
level1[0] = cf->ptree_root;
leaf = g_malloc((sizeof *leaf)*NODES_PER_LEVEL);
level1[1] = leaf;
node = &leaf[0];
cf->ptree_root = level1;
} else if (cf->count < NODES_PER_LEVEL*NODES_PER_LEVEL) {
/* It's a 2-level tree, and is going to stay that way for now. */
level1 = cf->ptree_root;
leaf = level1[cf->count >> LOG2_NODES_PER_LEVEL];
if (leaf == NULL) {
leaf = g_malloc((sizeof *leaf)*NODES_PER_LEVEL);
level1[cf->count >> LOG2_NODES_PER_LEVEL] = leaf;
}
node = &leaf[LEAF_INDEX(cf->count)];
} else if (cf->count == NODES_PER_LEVEL*NODES_PER_LEVEL) {
/* It's a 2-level tree that will turn into a 3-level tree */
level2 = g_malloc((sizeof *level2)*NODES_PER_LEVEL);
memset(level2, 0, (sizeof *level2)*NODES_PER_LEVEL);
level2[0] = cf->ptree_root;
level1 = g_malloc((sizeof *level1)*NODES_PER_LEVEL);
memset(level1, 0, (sizeof *level1)*NODES_PER_LEVEL);
level2[1] = level1;
leaf = g_malloc((sizeof *leaf)*NODES_PER_LEVEL);
level1[0] = leaf;
node = &leaf[0];
cf->ptree_root = level2;
} else if (cf->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 = cf->ptree_root;
level1 = level2[cf->count >> (LOG2_NODES_PER_LEVEL+LOG2_NODES_PER_LEVEL)];
if (level1 == NULL) {
level1 = g_malloc((sizeof *level1)*NODES_PER_LEVEL);
memset(level1, 0, (sizeof *level1)*NODES_PER_LEVEL);
level2[cf->count >> (LOG2_NODES_PER_LEVEL+LOG2_NODES_PER_LEVEL)] = level1;
}
leaf = level1[LEVEL_1_INDEX(cf->count)];
if (leaf == NULL) {
leaf = g_malloc((sizeof *leaf)*NODES_PER_LEVEL);
level1[LEVEL_1_INDEX(cf->count)] = leaf;
}
node = &leaf[LEAF_INDEX(cf->count)];
} else if (cf->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 = g_malloc((sizeof *level3)*NODES_PER_LEVEL);
memset(level3, 0, (sizeof *level3)*NODES_PER_LEVEL);
level3[0] = cf->ptree_root;
level2 = g_malloc((sizeof *level2)*NODES_PER_LEVEL);
memset(level2, 0, (sizeof *level2)*NODES_PER_LEVEL);
level3[1] = level2;
level1 = g_malloc((sizeof *level1)*NODES_PER_LEVEL);
memset(level1, 0, (sizeof *level1)*NODES_PER_LEVEL);
level2[0] = level1;
leaf = g_malloc((sizeof *leaf)*NODES_PER_LEVEL);
level1[0] = leaf;
node = &leaf[0];
cf->ptree_root = level3;
} else {
/* cf->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 cf->count is always less < NODES_PER_LEVEL^4.
XXX - we should fail if cf->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 = cf->ptree_root;
level2 = level3[LEVEL_3_INDEX(cf->count)];
if (level2 == NULL) {
level2 = g_malloc((sizeof *level2)*NODES_PER_LEVEL);
memset(level2, 0, (sizeof *level2)*NODES_PER_LEVEL);
level3[LEVEL_3_INDEX(cf->count)] = level2;
}
level1 = level2[LEVEL_2_INDEX(cf->count)];
if (level1 == NULL) {
level1 = g_malloc((sizeof *level1)*NODES_PER_LEVEL);
memset(level1, 0, (sizeof *level1)*NODES_PER_LEVEL);
level2[LEVEL_2_INDEX(cf->count)] = level1;
}
leaf = level1[LEVEL_1_INDEX(cf->count)];
if (leaf == NULL) {
leaf = g_malloc((sizeof *leaf)*NODES_PER_LEVEL);
level1[LEVEL_1_INDEX(cf->count)] = leaf;
}
node = &leaf[LEAF_INDEX(cf->count)];
}
*node = *fdata;
cf->count++;
return node;
}
/*
* Find the frame_data for the specified frame number.
*/
frame_data *
cap_file_find_fdata(capture_file *cf, 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 >= cf->count) {
/* There aren't that many frames. */
return NULL;
}
if (cf->count <= NODES_PER_LEVEL) {
/* It's a 1-level tree. */
leaf = cf->ptree_root;
return &leaf[num];
}
if (cf->count <= NODES_PER_LEVEL*NODES_PER_LEVEL) {
/* It's a 2-level tree. */
level1 = cf->ptree_root;
leaf = level1[num >> LOG2_NODES_PER_LEVEL];
return &leaf[LEAF_INDEX(num)];
}
if (cf->count <= NODES_PER_LEVEL*NODES_PER_LEVEL*NODES_PER_LEVEL) {
/* It's a 3-level tree. */
level2 = cf->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)];
}
/* cf->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 cf->count is always less < NODES_PER_LEVEL^4. */
/* It's a 4-level tree, and is going to stay that way forever. */
level3 = cf->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)];
}
/*
* Free up all the frame information for a capture file.
*/
void
cap_file_free_frames(capture_file *cf)
{
frame_data **level1;
frame_data ***level2;
frame_data ****level3;
guint i, j, k;
if (cf->count == 0) {
/* Nothing to free. */
return;
}
if (cf->count <= NODES_PER_LEVEL) {
/* It's a 1-level tree. */
g_free(cf->ptree_root);
} else if (cf->count <= NODES_PER_LEVEL*NODES_PER_LEVEL) {
/* It's a 2-level tree. */
level1 = cf->ptree_root;
for (i = 0; i < NODES_PER_LEVEL && level1[i] != NULL; i++)
g_free(level1[i]);
g_free(level1);
} else if (cf->count <= NODES_PER_LEVEL*NODES_PER_LEVEL*NODES_PER_LEVEL) {
/* It's a 3-level tree. */
level2 = cf->ptree_root;
for (i = 0; i < NODES_PER_LEVEL && level2[i] != NULL; i++) {
level1 = level2[i];
for (j = 0; j < NODES_PER_LEVEL && level1[i] != NULL; j++)
g_free(level1[j]);
g_free(level1);
}
g_free(level2);
return;
} else {
/* cf->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 cf->count is always less < NODES_PER_LEVEL^4. */
/* It's a 4-level tree, and is going to stay that way forever. */
level3 = cf->ptree_root;
for (i = 0; i < NODES_PER_LEVEL && level3[i] != NULL; i++) {
level2 = level3[i];
for (j = 0; j < NODES_PER_LEVEL && level2[i] != NULL; j++) {
level1 = level2[j];
for (k = 0; k < NODES_PER_LEVEL && level1[k] != NULL; k++)
g_free(level1[k]);
}
g_free(level2);
}
g_free(level3);
}
cf->ptree_root = NULL;
cf->count = 0;
} }

18
cfile.h
View File

@ -25,6 +25,8 @@
#ifndef __CFILE_H__ #ifndef __CFILE_H__
#define __CFILE_H__ #define __CFILE_H__
#include "frame_data_sequence.h"
/* Current state of file. */ /* Current state of file. */
typedef enum { typedef enum {
FILE_CLOSED, /* No file open */ FILE_CLOSED, /* No file open */
@ -98,7 +100,7 @@ typedef struct _capture_file {
union wtap_pseudo_header pseudo_header; /* Packet pseudo_header */ union wtap_pseudo_header pseudo_header; /* Packet pseudo_header */
guint8 pd[WTAP_MAX_PACKET_SIZE]; /* Packet data */ guint8 pd[WTAP_MAX_PACKET_SIZE]; /* Packet data */
/* frames */ /* frames */
void *ptree_root; /* Pointer to the root node */ frame_data_sequence *frames; /* Sequence of frames, if we're keeping that information */
guint32 first_displayed; /* Frame number of first frame displayed */ guint32 first_displayed; /* Frame number of first frame displayed */
guint32 last_displayed; /* Frame number of last frame displayed */ guint32 last_displayed; /* Frame number of last frame displayed */
column_info cinfo; /* Column formatting information */ column_info cinfo; /* Column formatting information */
@ -110,18 +112,4 @@ typedef struct _capture_file {
extern void cap_file_init(capture_file *cf); extern void cap_file_init(capture_file *cf);
extern frame_data *cap_file_add_fdata(capture_file *cf, frame_data *fdata);
/*
* Find the frame_data for the specified frame number.
* Do some caching to make this work reasonably fast for
* forward and backward sequential passes through the packets.
*/
extern frame_data *cap_file_find_fdata(capture_file *cf, guint32 num);
/*
* Free up all the frame information for a capture file.
*/
extern void cap_file_free_frames(capture_file *cf);
#endif /* cfile.h */ #endif /* cfile.h */

View File

@ -32,7 +32,6 @@
#include <epan/packet.h> #include <epan/packet.h>
#include <epan/emem.h> #include <epan/emem.h>
#include <epan/timestamp.h> #include <epan/timestamp.h>
#include "cfile.h"
#include <glib.h> #include <glib.h>

View File

@ -46,7 +46,6 @@
#include <epan/prefs.h> #include <epan/prefs.h>
#include <epan/proto.h> #include <epan/proto.h>
#include <epan/strutil.h> #include <epan/strutil.h>
#include "cfile.h"
#include <epan/column.h> #include <epan/column.h>
#include "print.h" #include "print.h"
#include <wsutil/file_util.h> #include <wsutil/file_util.h>

25
file.c
View File

@ -331,6 +331,9 @@ cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
} else } else
cf->has_snap = TRUE; cf->has_snap = TRUE;
/* Allocate a frame_data_sequence for the frames in this file */
cf->frames = new_frame_data_sequence();
nstime_set_zero(&cf->elapsed_time); nstime_set_zero(&cf->elapsed_time);
nstime_set_unset(&first_ts); nstime_set_unset(&first_ts);
nstime_set_unset(&prev_dis_ts); nstime_set_unset(&prev_dis_ts);
@ -389,7 +392,8 @@ cf_reset_state(capture_file *cf)
dfilter_free(cf->rfcode); dfilter_free(cf->rfcode);
cf->rfcode = NULL; cf->rfcode = NULL;
cap_file_free_frames(cf); free_frame_data_sequence(cf->frames);
cf->frames = NULL;
cf_unselect_packet(cf); /* nothing to select */ cf_unselect_packet(cf); /* nothing to select */
cf->first_displayed = 0; cf->first_displayed = 0;
cf->last_displayed = 0; cf->last_displayed = 0;
@ -642,7 +646,7 @@ cf_read(capture_file *cf, gboolean from_save)
WTAP_ENCAP_PER_PACKET). */ WTAP_ENCAP_PER_PACKET). */
cf->lnk_t = wtap_file_encap(cf->wth); cf->lnk_t = wtap_file_encap(cf->wth);
cf->current_frame = cap_file_find_fdata(cf, cf->first_displayed); cf->current_frame = frame_data_sequence_find(cf->frames, cf->first_displayed);
cf->current_row = 0; cf->current_row = 0;
new_packet_list_thaw(); new_packet_list_thaw();
@ -1182,8 +1186,9 @@ read_packet(capture_file *cf, dfilter_t *dfcode,
if (passed) { if (passed) {
/* This does a shallow copy of fdlocal, which is good enough. */ /* This does a shallow copy of fdlocal, which is good enough. */
fdata = cap_file_add_fdata(cf, &fdlocal); fdata = frame_data_sequence_add(cf->frames, &fdlocal);
cf->count++;
cf->f_datalen = offset + fdlocal.cap_len; cf->f_datalen = offset + fdlocal.cap_len;
if (!cf->redissecting) { if (!cf->redissecting) {
@ -1683,7 +1688,7 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item,
selected_frame_seen = FALSE; selected_frame_seen = FALSE;
for (framenum = 1; framenum <= cf->count; framenum++) { for (framenum = 1; framenum <= cf->count; framenum++) {
fdata = cap_file_find_fdata(cf, framenum); fdata = frame_data_sequence_find(cf->frames, framenum);
/* Create the progress bar if necessary. /* Create the progress bar if necessary.
We check on every iteration of the loop, so that it takes no We check on every iteration of the loop, so that it takes no
@ -1798,7 +1803,7 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item,
would leave the user stuck with an Wireshark grinding on would leave the user stuck with an Wireshark grinding on
until it finishes. Should we just stick them with that? */ until it finishes. Should we just stick them with that? */
for (; framenum <= cf->count; framenum++) { for (; framenum <= cf->count; framenum++) {
fdata = cap_file_find_fdata(cf, framenum); fdata = frame_data_sequence_find(cf->frames, framenum);
fdata->flags.visited = 0; fdata->flags.visited = 0;
frame_data_cleanup(fdata); frame_data_cleanup(fdata);
} }
@ -1899,7 +1904,7 @@ ref_time_packets(capture_file *cf)
cum_bytes = 0; cum_bytes = 0;
for (framenum = 1; framenum <= cf->count; framenum++) { for (framenum = 1; framenum <= cf->count; framenum++) {
fdata = cap_file_find_fdata(cf, framenum); fdata = frame_data_sequence_find(cf->frames, framenum);
/* just add some value here until we know if it is being displayed or not */ /* just add some value here until we know if it is being displayed or not */
fdata->cum_bytes = cum_bytes + fdata->pkt_len; fdata->cum_bytes = cum_bytes + fdata->pkt_len;
@ -2011,7 +2016,7 @@ process_specified_packets(capture_file *cf, packet_range_t *range,
/* Iterate through all the packets, printing the packets that /* Iterate through all the packets, printing the packets that
were selected by the current display filter. */ were selected by the current display filter. */
for (framenum = 1; framenum <= cf->count; framenum++) { for (framenum = 1; framenum <= cf->count; framenum++) {
fdata = cap_file_find_fdata(cf, framenum); fdata = frame_data_sequence_find(cf->frames, framenum);
/* Create the progress bar if necessary. /* Create the progress bar if necessary.
We check on every iteration of the loop, so that it takes no We check on every iteration of the loop, so that it takes no
@ -3280,7 +3285,7 @@ find_packet(capture_file *cf,
} else } else
framenum++; framenum++;
} }
fdata = cap_file_find_fdata(cf, framenum); fdata = frame_data_sequence_find(cf->frames, framenum);
count++; count++;
@ -3339,7 +3344,7 @@ cf_goto_frame(capture_file *cf, guint fnumber)
{ {
frame_data *fdata; frame_data *fdata;
fdata = cap_file_find_fdata(cf, fnumber); fdata = frame_data_sequence_find(cf->frames, fnumber);
if (fdata == NULL) { if (fdata == NULL) {
/* we didn't find a packet with that packet number */ /* we didn't find a packet with that packet number */
@ -3441,7 +3446,7 @@ cf_select_packet(capture_file *cf, int row)
GtkCList; see the comment in "add_packet_to_packet_list()". */ GtkCList; see the comment in "add_packet_to_packet_list()". */
if (row == 0 && cf->first_displayed == cf->last_displayed) if (row == 0 && cf->first_displayed == cf->last_displayed)
fdata = cap_file_find_fdata(cf, cf->first_displayed); fdata = frame_data_sequence_find(cf->frames, cf->first_displayed);
} }
/* If fdata _still_ isn't set simply give up. */ /* If fdata _still_ isn't set simply give up. */

287
frame_data_sequence.c Normal file
View File

@ -0,0 +1,287 @@
/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <glib.h>
#include <epan/packet.h>
#include "frame_data_sequence.h"
frame_data_sequence *
new_frame_data_sequence(void)
{
frame_data_sequence *fds;
fds = g_malloc(sizeof *fds);
fds->count = 0;
fds->ptree_root = NULL;
return fds;
}
/*
* 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))
/*
* 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 = 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 = 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 = g_malloc((sizeof *level1)*NODES_PER_LEVEL);
memset(level1, 0, (sizeof *level1)*NODES_PER_LEVEL);
level1[0] = fds->ptree_root;
leaf = 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 = fds->ptree_root;
leaf = level1[fds->count >> LOG2_NODES_PER_LEVEL];
if (leaf == NULL) {
leaf = 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 = g_malloc((sizeof *level2)*NODES_PER_LEVEL);
memset(level2, 0, (sizeof *level2)*NODES_PER_LEVEL);
level2[0] = fds->ptree_root;
level1 = g_malloc((sizeof *level1)*NODES_PER_LEVEL);
memset(level1, 0, (sizeof *level1)*NODES_PER_LEVEL);
level2[1] = level1;
leaf = 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 = fds->ptree_root;
level1 = level2[fds->count >> (LOG2_NODES_PER_LEVEL+LOG2_NODES_PER_LEVEL)];
if (level1 == NULL) {
level1 = g_malloc((sizeof *level1)*NODES_PER_LEVEL);
memset(level1, 0, (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 = 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 = g_malloc((sizeof *level3)*NODES_PER_LEVEL);
memset(level3, 0, (sizeof *level3)*NODES_PER_LEVEL);
level3[0] = fds->ptree_root;
level2 = g_malloc((sizeof *level2)*NODES_PER_LEVEL);
memset(level2, 0, (sizeof *level2)*NODES_PER_LEVEL);
level3[1] = level2;
level1 = g_malloc((sizeof *level1)*NODES_PER_LEVEL);
memset(level1, 0, (sizeof *level1)*NODES_PER_LEVEL);
level2[0] = level1;
leaf = 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 = fds->ptree_root;
level2 = level3[LEVEL_3_INDEX(fds->count)];
if (level2 == NULL) {
level2 = g_malloc((sizeof *level2)*NODES_PER_LEVEL);
memset(level2, 0, (sizeof *level2)*NODES_PER_LEVEL);
level3[LEVEL_3_INDEX(fds->count)] = level2;
}
level1 = level2[LEVEL_2_INDEX(fds->count)];
if (level1 == NULL) {
level1 = g_malloc((sizeof *level1)*NODES_PER_LEVEL);
memset(level1, 0, (sizeof *level1)*NODES_PER_LEVEL);
level2[LEVEL_2_INDEX(fds->count)] = level1;
}
leaf = level1[LEVEL_1_INDEX(fds->count)];
if (leaf == NULL) {
leaf = 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 = fds->ptree_root;
return &leaf[num];
}
if (fds->count <= NODES_PER_LEVEL*NODES_PER_LEVEL) {
/* It's a 2-level tree. */
level1 = 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 = 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 = 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)];
}
/*
* Free a frame_data_sequence and all the frame_data structures in it.
*/
void
free_frame_data_sequence(frame_data_sequence *fds)
{
frame_data **level1;
frame_data ***level2;
frame_data ****level3;
guint i, j, k;
if (fds->count == 0) {
/* Nothing to free. */
return;
}
if (fds->count <= NODES_PER_LEVEL) {
/* It's a 1-level tree. */
g_free(fds->ptree_root);
} else if (fds->count <= NODES_PER_LEVEL*NODES_PER_LEVEL) {
/* It's a 2-level tree. */
level1 = fds->ptree_root;
for (i = 0; i < NODES_PER_LEVEL && level1[i] != NULL; i++)
g_free(level1[i]);
g_free(level1);
} else if (fds->count <= NODES_PER_LEVEL*NODES_PER_LEVEL*NODES_PER_LEVEL) {
/* It's a 3-level tree. */
level2 = fds->ptree_root;
for (i = 0; i < NODES_PER_LEVEL && level2[i] != NULL; i++) {
level1 = level2[i];
for (j = 0; j < NODES_PER_LEVEL && level1[i] != NULL; j++)
g_free(level1[j]);
g_free(level1);
}
g_free(level2);
return;
} 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. */
/* It's a 4-level tree, and is going to stay that way forever. */
level3 = fds->ptree_root;
for (i = 0; i < NODES_PER_LEVEL && level3[i] != NULL; i++) {
level2 = level3[i];
for (j = 0; j < NODES_PER_LEVEL && level2[i] != NULL; j++) {
level1 = level2[j];
for (k = 0; k < NODES_PER_LEVEL && level1[k] != NULL; k++)
g_free(level1[k]);
}
g_free(level2);
}
g_free(level3);
}
g_free(fds);
}

62
frame_data_sequence.h Normal file
View File

@ -0,0 +1,62 @@
/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __FRAME_DATA_SEQUENCE_H__
#define __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)
typedef struct {
guint32 count; /* Total number of frames */
void *ptree_root; /* Pointer to the root node */
} frame_data_sequence;
extern frame_data_sequence *new_frame_data_sequence(void);
extern frame_data *frame_data_sequence_add(frame_data_sequence *fds,
frame_data *fdata);
/*
* Find the frame_data for the specified frame number.
*/
extern 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.
*/
extern void free_frame_data_sequence(frame_data_sequence *fds);
#endif /* frame_data_sequence.h */

View File

@ -1495,7 +1495,7 @@ mark_all_displayed_frames(gboolean set)
guint32 framenum; guint32 framenum;
frame_data *fdata; frame_data *fdata;
for (framenum = 1; framenum <= cfile.count; framenum++) { for (framenum = 1; framenum <= cfile.count; framenum++) {
fdata = cap_file_find_fdata(&cfile, framenum); fdata = frame_data_sequence_find(cfile.frames, framenum);
if( fdata->flags.passed_dfilter ) if( fdata->flags.passed_dfilter )
set_frame_mark(set, fdata); set_frame_mark(set, fdata);
} }
@ -1522,7 +1522,7 @@ toggle_mark_all_displayed_frames()
guint32 framenum; guint32 framenum;
frame_data *fdata; frame_data *fdata;
for (framenum = 1; framenum <= cfile.count; framenum++) { for (framenum = 1; framenum <= cfile.count; framenum++) {
fdata = cap_file_find_fdata(&cfile, framenum); fdata = frame_data_sequence_find(cfile.frames, framenum);
if( fdata->flags.passed_dfilter ) if( fdata->flags.passed_dfilter )
set_frame_mark(!fdata->flags.marked, fdata); set_frame_mark(!fdata->flags.marked, fdata);
} }
@ -1571,7 +1571,7 @@ ignore_all_displayed_frames(gboolean set)
/* XXX: we might need a progressbar here */ /* XXX: we might need a progressbar here */
for (framenum = 1; framenum <= cfile.count; framenum++) { for (framenum = 1; framenum <= cfile.count; framenum++) {
fdata = cap_file_find_fdata(&cfile, framenum); fdata = frame_data_sequence_find(cfile.frames, framenum);
if( fdata->flags.passed_dfilter ) if( fdata->flags.passed_dfilter )
set_frame_ignore(set, fdata); set_frame_ignore(set, fdata);
} }
@ -1586,7 +1586,7 @@ new_packet_list_ignore_all_displayed_frames_cb(GtkWidget *w _U_, gpointer data _
/* Due to performance impact with large captures, don't check the filtered list for /* Due to performance impact with large captures, don't check the filtered list for
an ignored frame; just check the first. If a ignored frame exists but isn't first and an ignored frame; just check the first. If a ignored frame exists but isn't first and
the user wants to unignore all the displayed frames, they will just re-exec the shortcut. */ the user wants to unignore all the displayed frames, they will just re-exec the shortcut. */
fdata = cap_file_find_fdata(&cfile, cfile.first_displayed); fdata = frame_data_sequence_find(cfile.frames, cfile.first_displayed);
if (fdata->flags.ignored==TRUE) { if (fdata->flags.ignored==TRUE) {
ignore_all_displayed_frames(FALSE); ignore_all_displayed_frames(FALSE);
} else { } else {
@ -1603,7 +1603,7 @@ unignore_all_frames(void)
/* XXX: we might need a progressbar here */ /* XXX: we might need a progressbar here */
for (framenum = 1; framenum <= cfile.count; framenum++) { for (framenum = 1; framenum <= cfile.count; framenum++) {
fdata = cap_file_find_fdata(&cfile, framenum); fdata = frame_data_sequence_find(cfile.frames, framenum);
set_frame_ignore(FALSE, fdata); set_frame_ignore(FALSE, fdata);
} }
redissect_packets(); redissect_packets();
@ -1623,7 +1623,7 @@ untime_reference_all_frames()
guint32 framenum; guint32 framenum;
frame_data *fdata; frame_data *fdata;
for (framenum = 1; framenum <= cfile.count && cfile.ref_time_count > 0; framenum++) { for (framenum = 1; framenum <= cfile.count && cfile.ref_time_count > 0; framenum++) {
fdata = cap_file_find_fdata(&cfile, framenum); fdata = frame_data_sequence_find(cfile.frames, framenum);
if (fdata->flags.ref_time == 1) { if (fdata->flags.ref_time == 1) {
set_frame_reftime(FALSE, fdata, cfile.current_row); set_frame_reftime(FALSE, fdata, cfile.current_row);
} }

View File

@ -76,7 +76,7 @@ static void packet_range_calc(packet_range_t *range) {
* for example, the case when TShark is doing a one-pass * for example, the case when TShark is doing a one-pass
* read of a file or a live capture. * read of a file or a live capture.
*/ */
if (cfile.ptree_root != NULL) { if (cfile.frames != NULL) {
/* The next for-loop is used to obtain the amount of packets /* The next for-loop is used to obtain the amount of packets
* to be processed and is used to present the information in * to be processed and is used to present the information in
* the Save/Print As widget. * the Save/Print As widget.
@ -87,7 +87,7 @@ static void packet_range_calc(packet_range_t *range) {
*/ */
for(framenum = 1; framenum <= cfile.count; framenum++) { for(framenum = 1; framenum <= cfile.count; framenum++) {
packet = cap_file_find_fdata(&cfile, framenum); packet = frame_data_sequence_find(cfile.frames, framenum);
if (cfile.current_frame == packet) { if (cfile.current_frame == packet) {
range->selected_packet = framenum; range->selected_packet = framenum;
@ -128,7 +128,7 @@ static void packet_range_calc(packet_range_t *range) {
} }
for(framenum = 1; framenum <= cfile.count; framenum++) { for(framenum = 1; framenum <= cfile.count; framenum++) {
packet = cap_file_find_fdata(&cfile, framenum); packet = frame_data_sequence_find(cfile.frames, framenum);
if (framenum >= mark_low && if (framenum >= mark_low &&
framenum <= mark_high) framenum <= mark_high)
@ -181,9 +181,9 @@ static void packet_range_calc_user(packet_range_t *range) {
* for example, the case when TShark is doing a one-pass * for example, the case when TShark is doing a one-pass
* read of a file or a live capture. * read of a file or a live capture.
*/ */
if (cfile.ptree_root != NULL) { if (cfile.frames != NULL) {
for(framenum = 1; framenum <= cfile.count; framenum++) { for(framenum = 1; framenum <= cfile.count; framenum++) {
packet = cap_file_find_fdata(&cfile, framenum); packet = frame_data_sequence_find(cfile.frames, framenum);
if (value_is_in_range(range->user_range, framenum)) { if (value_is_in_range(range->user_range, framenum)) {
range->user_range_cnt++; range->user_range_cnt++;

View File

@ -214,7 +214,7 @@ ph_stats_new(void)
tot_bytes = 0; tot_bytes = 0;
for (framenum = 1; framenum <= cfile.count; framenum++) { for (framenum = 1; framenum <= cfile.count; framenum++) {
frame = cap_file_find_fdata(&cfile, framenum); frame = frame_data_sequence_find(cfile.frames, framenum);
/* Create the progress bar if necessary. /* Create the progress bar if necessary.
We check on every iteration of the loop, so that We check on every iteration of the loop, so that

View File

@ -109,12 +109,12 @@ summary_fill_in(capture_file *cf, summary_tally *st)
/* initialize the tally */ /* initialize the tally */
if (cf->count != 0) { if (cf->count != 0) {
first_frame = cap_file_find_fdata(cf, 1); first_frame = frame_data_sequence_find(cf->frames, 1);
st->start_time = nstime_to_sec(&first_frame->abs_ts); st->start_time = nstime_to_sec(&first_frame->abs_ts);
st->stop_time = nstime_to_sec(&first_frame->abs_ts); st->stop_time = nstime_to_sec(&first_frame->abs_ts);
for (framenum = 1; framenum <= cf->count; framenum++) { for (framenum = 1; framenum <= cf->count; framenum++) {
cur_frame = cap_file_find_fdata(cf, framenum); cur_frame = frame_data_sequence_find(cf->frames, framenum);
tally_frame_data(cur_frame, st); tally_frame_data(cur_frame, st);
} }
} }

View File

@ -1816,14 +1816,10 @@ main(int argc, char *argv[])
g_free(cf_name); g_free(cf_name);
/* XXX - hack to avoid a crash in one-pass mode, where we update if (cfile.frames != NULL) {
cfile.count but don't allocate any frame_data structures. free_frame_data_sequence(cfile.frames);
We may want to more cleanly separate the "capture file" and cfile.frames = NULL;
"collection of frames" stuff, to handle cases such as TShark }
one-pass mode where we care about the former but don't care
about the latter. */
if (cfile.ptree_root != NULL)
cap_file_free_frames(&cfile);
draw_tap_listeners(TRUE); draw_tap_listeners(TRUE);
funnel_dump_all_text_windows(); funnel_dump_all_text_windows();
@ -2441,7 +2437,8 @@ process_packet_first_pass(capture_file *cf,
if (passed) { if (passed) {
frame_data_set_after_dissect(&fdlocal, &cum_bytes, &prev_dis_ts); frame_data_set_after_dissect(&fdlocal, &cum_bytes, &prev_dis_ts);
cap_file_add_fdata(cf, &fdlocal); frame_data_sequence_add(cf->frames, &fdlocal);
cf->count++;
} }
if (do_dissection) if (do_dissection)
@ -2650,6 +2647,9 @@ load_cap_file(capture_file *cf, char *save_file, int out_file_type,
frame_data *fdata; frame_data *fdata;
int old_max_packet_count = max_packet_count; int old_max_packet_count = max_packet_count;
/* Allocate a frame_data_sequence for all the frames. */
cf->frames = new_frame_data_sequence();
while (wtap_read(cf->wth, &err, &err_info, &data_offset)) { while (wtap_read(cf->wth, &err, &err_info, &data_offset)) {
if (process_packet_first_pass(cf, data_offset, wtap_phdr(cf->wth), if (process_packet_first_pass(cf, data_offset, wtap_phdr(cf->wth),
wtap_pseudoheader(cf->wth), wtap_buf_ptr(cf->wth))) { wtap_pseudoheader(cf->wth), wtap_buf_ptr(cf->wth))) {
@ -2675,7 +2675,7 @@ load_cap_file(capture_file *cf, char *save_file, int out_file_type,
max_packet_count = old_max_packet_count; max_packet_count = old_max_packet_count;
for (framenum = 1; err == 0 && framenum <= cf->count; framenum++) { for (framenum = 1; err == 0 && framenum <= cf->count; framenum++) {
fdata = cap_file_find_fdata(cf, framenum); fdata = frame_data_sequence_find(cf->frames, framenum);
if (wtap_seek_read(cf->wth, fdata->file_off, &cf->pseudo_header, if (wtap_seek_read(cf->wth, fdata->file_off, &cf->pseudo_header,
cf->pd, fdata->cap_len, &err, &err_info)) { cf->pd, fdata->cap_len, &err, &err_info)) {
if (process_packet_second_pass(cf, fdata, if (process_packet_second_pass(cf, fdata,