Create stats_tree Makefile to allow manual builds
[obnox/wireshark/wip.git] / proto_hier_stats.c
index 146dfe8c7244331fb8ff336825f30dec4c06e3e5..8974e52ac1ca59275887c73ef4d6398a3f0d7be8 100644 (file)
@@ -1,7 +1,7 @@
 /* proto_hier_stats.c
  * Routines for calculating statistics based on protocol.
  *
- * $Id: proto_hier_stats.c,v 1.8 2001/12/18 19:09:02 gram Exp $
+ * $Id$
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
@@ -22,7 +22,6 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
-
 #ifdef HAVE_CONFIG_H
 # include "config.h"
 #endif
@@ -30,7 +29,8 @@
 #include "globals.h"
 #include "proto_hier_stats.h"
 #include "progress_dlg.h"
-#include "epan_dissect.h"
+#include "simple_dialog.h"
+#include <epan/epan_dissect.h>
 #include <wtap.h>
 
 #include <stdio.h>
 /* Update the progress bar this many times when scanning the packet list. */
 #define N_PROGBAR_UPDATES      100
 
+#define STAT_NODE_STATS(n)   ((ph_stats_node_t*)(n)->data)
+#define STAT_NODE_HFINFO(n)  (STAT_NODE_STATS(n)->hfinfo)
+
+static double
+secs_usecs(guint32 s, guint32 us)
+{
+  return (us / 1000000.0) + (double)s;
+}
+
 static GNode*
-find_stat_node(GNode *parent_node, header_field_info *needle_hfinfo)
+find_stat_node(GNode *parent_stat_node, header_field_info *needle_hfinfo)
 {
-       GNode                   *needle_node;
-       field_info              *finfo;
-       ph_stats_node_t *stats;
+       GNode                   *needle_stat_node;
+       header_field_info       *hfinfo;
+       ph_stats_node_t         *stats;
 
-       needle_node = g_node_first_child(parent_node);
+       needle_stat_node = g_node_first_child(parent_stat_node);
 
-       while (needle_node) {
-               finfo = PITEM_FINFO(needle_node);
-               if (finfo && finfo->hfinfo && finfo->hfinfo->id == needle_hfinfo->id) {
-                       return needle_node;
+       while (needle_stat_node) {
+               hfinfo = STAT_NODE_HFINFO(needle_stat_node);
+               if (hfinfo &&  hfinfo->id == needle_hfinfo->id) {
+                       return needle_stat_node;
                }
-               needle_node = g_node_next_sibling(needle_node);
+               needle_stat_node = g_node_next_sibling(needle_stat_node);
        }
 
        /* None found. Create one. */
@@ -66,33 +75,33 @@ find_stat_node(GNode *parent_node, header_field_info *needle_hfinfo)
        stats->num_bytes_total = 0;
        stats->num_bytes_last = 0;
 
-       needle_node = g_node_new(stats);
-       g_node_append(parent_node, needle_node);
-       return needle_node;
+       needle_stat_node = g_node_new(stats);
+       g_node_append(parent_stat_node, needle_stat_node);
+       return needle_stat_node;
 }
 
 
 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);
 
        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->data;
+       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);
@@ -108,9 +117,9 @@ process_node(proto_item *ptree_node, GNode *parent_stat_node, ph_stats_t *ps, gu
 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;
        }
@@ -118,29 +127,45 @@ process_tree(proto_tree *protocol_tree, ph_stats_t* ps, guint pkt_len)
        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 */
-       wtap_seek_read(cfile.wth, frame->file_off, &phdr,
-                       pd, frame->cap_len);
+       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 */
        edt = epan_dissect_new(TRUE, FALSE);
-    epan_dissect_run(edt, &phdr, pd, frame, cinfo);
+       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 = secs_usecs(frame->abs_secs, frame->abs_usecs);
+       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)
@@ -148,17 +173,22 @@ ph_stats_new(void)
        ph_stats_t      *ps;
        frame_data      *frame;
        guint           tot_packets, tot_bytes;
-       progdlg_t       *progbar;
+       progdlg_t       *progbar = NULL;
        gboolean        stop_flag;
-       guint32         progbar_quantum;
-       guint32         progbar_nextstep;
-       unsigned int    count;
+       int             count;
+       float           prog_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. */
        progbar_nextstep = 0;
@@ -169,8 +199,7 @@ ph_stats_new(void)
        count = 0;
 
        stop_flag = FALSE;
-       progbar = create_progress_dlg("Computing protocol statistics", "Stop",
-           &stop_flag);
+       g_get_current_time(&start_time);
 
        tot_packets = 0;
        tot_bytes = 0;
@@ -188,8 +217,19 @@ ph_stats_new(void)
                         */
                        g_assert(cfile.count > 0);
 
-                       update_progress_dlg(progbar,
-                           (gfloat) count / cfile.count);
+                       prog_val = (gfloat) count / cfile.count;
+
+                       if (progbar == NULL)
+                               /* Create the progress bar if necessary */
+                               progbar = delayed_create_progress_dlg(
+                                   "Computing", "protocol hierarchy statistics", 
+                                   &stop_flag, &start_time, prog_val);
+
+                       if (progbar != NULL) {
+                               g_snprintf(status_str, sizeof(status_str),
+                                       "%4u of %u frames", count, cfile.count);
+                               update_progress_dlg(progbar, prog_val, status_str);
+                       }
 
                        progbar_nextstep += progbar_quantum;
                }
@@ -206,7 +246,23 @@ ph_stats_new(void)
                   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 = secs_usecs(frame->abs_secs,
+                                                            frame->abs_usecs);
+                               ps->first_time = cur_time;
+                               ps->last_time = cur_time;
+                       }
+
+                       if (!process_frame(frame, &cfile.cinfo, 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;
@@ -215,8 +271,10 @@ ph_stats_new(void)
                count++;
        }
 
-       /* We're done calculating the statistics; destroy the progress bar. */
-       destroy_progress_dlg(progbar);
+       /* We're done calculating the statistics; destroy the progress bar
+           if it was created. */
+       if (progbar != NULL)
+               destroy_progress_dlg(progbar);
 
        if (stop_flag) {
                /*
@@ -235,7 +293,7 @@ ph_stats_new(void)
 }
 
 static gboolean
-stat_node_free(GNode *node, gpointer data)
+stat_node_free(GNode *node, gpointer data _U_)
 {
        ph_stats_node_t *stats = node->data;