/* proto_hier_stats.c
* Routines for calculating statistics based on protocol.
*
- * $Id: proto_hier_stats.c,v 1.14 2002/07/30 10:13:14 guy Exp $
+ * $Id$
*
- * Ethereal - Network traffic analyzer
- * By Gerald Combs <gerald@ethereal.com>
+ * 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
#include "globals.h"
#include "proto_hier_stats.h"
#include "progress_dlg.h"
+#include "simple_dialog.h"
#include <epan/epan_dissect.h>
#include <wtap.h>
#define STAT_NODE_STATS(n) ((ph_stats_node_t*)(n)->data)
#define STAT_NODE_HFINFO(n) (STAT_NODE_STATS(n)->hfinfo)
+
static GNode*
find_stat_node(GNode *parent_stat_node, header_field_info *needle_hfinfo)
{
static void
-process_node(proto_item *ptree_node, GNode *parent_stat_node, ph_stats_t *ps, guint pkt_len)
+process_node(proto_node *ptree_node, GNode *parent_stat_node, ph_stats_t *ps, guint pkt_len)
{
field_info *finfo;
- ph_stats_node_t *stats;
- proto_item *proto_sibling_node;
+ ph_stats_node_t *stats;
+ proto_node *proto_sibling_node;
GNode *stat_node;
finfo = PITEM_FINFO(ptree_node);
g_assert(finfo);
+ /* if the field info isn't related to a protocol but to a field, don't count them,
+ * as they don't belong to any protocol.
+ * (happens e.g. for toplevel tree item of desegmentation "[Reassembled TCP Segments]") */
+ if(finfo->hfinfo->parent != -1) {
+ /* there are some cases where helpful generated items are added
+ * to the decode tree so do not test for it any more
+ *g_assert(PROTO_ITEM_IS_GENERATED(ptree_node));
+ */
+ return;
+ }
+
stat_node = find_stat_node(parent_stat_node, finfo->hfinfo);
-
- /* Assert that the finfo is related to a protocol, not a field. */
- g_assert(finfo->hfinfo->parent == -1);
stats = STAT_NODE_STATS(stat_node);
stats->num_pkts_total++;
stats->num_bytes_total += pkt_len;
- proto_sibling_node = g_node_next_sibling(ptree_node);
+ proto_sibling_node = ptree_node->next;
if (proto_sibling_node) {
process_node(proto_sibling_node, stat_node, ps, pkt_len);
static void
process_tree(proto_tree *protocol_tree, ph_stats_t* ps, guint pkt_len)
{
- proto_item *ptree_node;
+ proto_node *ptree_node;
- ptree_node = g_node_first_child(protocol_tree);
+ ptree_node = ((proto_node *)protocol_tree)->first_child;
if (!ptree_node) {
return;
}
process_node(ptree_node, ps->stats_tree, ps, pkt_len);
}
-static void
+static gboolean
process_frame(frame_data *frame, column_info *cinfo, ph_stats_t* ps)
{
epan_dissect_t *edt;
union wtap_pseudo_header phdr;
guint8 pd[WTAP_MAX_PACKET_SIZE];
int err;
+ gchar *err_info;
+ double cur_time;
/* Load the frame from the capture file */
- /* XX - do something with "err" */
- wtap_seek_read(cfile.wth, frame->file_off, &phdr,
- pd, frame->cap_len, &err);
+ if (!wtap_seek_read(cfile.wth, frame->file_off, &phdr, pd,
+ frame->cap_len, &err, &err_info)) {
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+ cf_read_error_message(err, err_info), cfile.filename);
+ return FALSE; /* failure */
+ }
- /* Dissect the frame */
+ /* Dissect the frame tree not visible */
edt = epan_dissect_new(TRUE, FALSE);
epan_dissect_run(edt, &phdr, pd, frame, cinfo);
/* Get stats from this protocol tree */
process_tree(edt->tree, ps, frame->pkt_len);
+ /* Update times */
+ cur_time = nstime_to_sec(&frame->abs_ts);
+ if (cur_time < ps->first_time) {
+ ps->first_time = cur_time;
+ }
+ if (cur_time > ps->last_time){
+ ps->last_time = cur_time;
+ }
+
/* Free our memory. */
epan_dissect_free(edt);
-}
-
+ return TRUE; /* success */
+}
ph_stats_t*
ph_stats_new(void)
guint tot_packets, tot_bytes;
progdlg_t *progbar = NULL;
gboolean stop_flag;
- long count;
- float prog_val;
+ int count;
+ float progbar_val;
GTimeVal start_time;
+ gchar status_str[100];
+ int progbar_nextstep;
+ int progbar_quantum;
/* Initialize the data */
ps = g_new(ph_stats_t, 1);
ps->tot_packets = 0;
ps->tot_bytes = 0;
ps->stats_tree = g_node_new(NULL);
+ ps->first_time = 0.0;
+ ps->last_time = 0.0;
/* Update the progress bar when it gets to this value. */
- cfile.progbar_nextstep = 0;
+ progbar_nextstep = 0;
/* When we reach the value that triggers a progress bar update,
bump that value by this amount. */
- cfile.progbar_quantum = cfile.count/N_PROGBAR_UPDATES;
+ progbar_quantum = cfile.count/N_PROGBAR_UPDATES;
/* Count of packets at which we've looked. */
count = 0;
+ /* Progress so far. */
+ progbar_val = 0.0;
stop_flag = FALSE;
g_get_current_time(&start_time);
tot_bytes = 0;
for (frame = cfile.plist; frame != NULL; frame = frame->next) {
+ /* Create the progress bar if necessary.
+ We check on every iteration of the loop, so that
+ it takes no longer than the standard time to create
+ it (otherwise, for a large file, we might take
+ considerably longer than that standard time in order
+ to get to the next progress bar step). */
+ if (progbar == NULL)
+ progbar = delayed_create_progress_dlg(
+ "Computing", "protocol hierarchy statistics",
+ TRUE, &stop_flag, &start_time, progbar_val);
+
/* Update the progress bar, but do it only N_PROGBAR_UPDATES
times; when we update it, we have to run the GTK+ main
loop to get it to repaint what's pending, and doing so
may involve an "ioctl()" to see if there's any pending
input from an X server, and doing that for every packet
can be costly, especially on a big file. */
- if (count >= cfile.progbar_nextstep) {
+ if (count >= progbar_nextstep) {
/* let's not divide by zero. I should never be started
* with count == 0, so let's assert that
*/
g_assert(cfile.count > 0);
- prog_val = (gfloat) count / cfile.count;
-
- if (progbar == NULL)
- /* Create the progress bar if necessary */
- progbar = delayed_create_progress_dlg(
- "Computing protocol statistics", "Stop",
- &stop_flag, &start_time, prog_val);
+ progbar_val = (gfloat) count / cfile.count;
- if (progbar != NULL)
- update_progress_dlg(progbar, prog_val);
+ if (progbar != NULL) {
+ g_snprintf(status_str, sizeof(status_str),
+ "%4u of %u frames", count, cfile.count);
+ update_progress_dlg(progbar, progbar_val, status_str);
+ }
- cfile.progbar_nextstep += cfile.progbar_quantum;
+ progbar_nextstep += progbar_quantum;
}
if (stop_flag) {
probably do so for other loops (see "file.c") that
look only at those packets. */
if (frame->flags.passed_dfilter) {
- process_frame(frame, &cfile.cinfo, ps);
+
+ if (tot_packets == 0) {
+ double cur_time = nstime_to_sec(&frame->abs_ts);
+ ps->first_time = cur_time;
+ ps->last_time = cur_time;
+ }
+
+ /* we don't care about colinfo */
+ if (!process_frame(frame, NULL, ps)) {
+ /*
+ * Give up, and set "stop_flag" so we
+ * just abort rather than popping up
+ * the statistics window.
+ */
+ stop_flag = TRUE;
+ break;
+ }
tot_packets++;
tot_bytes += frame->pkt_len;