Don't use GNodes for the protocol tree, put the sibling pointer, and
authorguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>
Thu, 4 Dec 2003 10:59:34 +0000 (10:59 +0000)
committerguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>
Thu, 4 Dec 2003 10:59:34 +0000 (10:59 +0000)
pointers to the first *and* last child, in the "proto_node" structure
itself.  That saves us one level of indirection and memory allocation,
and lets us append to a tree by appending to the last child directly,
rather than having to scan through the list of siblings of the first
child to find the end of that list.

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

epan/proto.c
epan/proto.h
file.c
gtk/proto_draw.c
gtk/rtp_analysis.c
print.c
proto_hier_stats.c
tap-protohierstat.c

index 52fb49f5c73e1c0fb1e3e3c1fdb0411209b5fbf8..7f5a0a382dc84c66d8b3bcf6f140e8dfcfff890f 100644 (file)
@@ -1,7 +1,7 @@
 /* proto.c
  * Routines for protocol tree
  *
- * $Id: proto.c,v 1.123 2003/12/03 09:50:40 sahlberg Exp $
+ * $Id: proto.c,v 1.124 2003/12/04 10:59:34 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
@@ -50,7 +50,7 @@
 #define cVALS(x) (const value_string*)(x)
 
 static gboolean
-proto_tree_free_node(GNode *node, gpointer data);
+proto_tree_free_node(proto_node *node, gpointer data);
 
 static void fill_label_boolean(field_info *fi, gchar *label_str);
 static void fill_label_uint(field_info *fi, gchar *label_str);
@@ -165,7 +165,11 @@ static field_info *field_info_tmp=NULL;
 /* Contains the space for proto_nodes. */
 static proto_node *proto_node_free_list=NULL;
 #define PROTO_NODE_NEW(node)                           \
-       SLAB_ALLOC(node, proto_node_free_list)
+       SLAB_ALLOC(node, proto_node_free_list)          \
+       node->first_child = NULL;                       \
+       node->last_child = NULL;                        \
+       node->next = NULL;
+
 #define PROTO_NODE_FREE(node)                          \
        SLAB_FREE(node, proto_node_free_list)
 
@@ -294,16 +298,101 @@ proto_cleanup(void)
 
 }
 
+typedef gboolean (*proto_tree_traverse_func)(proto_node *, gpointer);
+
+static gboolean
+proto_tree_traverse_pre_order(proto_tree *tree, proto_tree_traverse_func func,
+    gpointer data)
+{
+       proto_node *pnode = tree;
+       proto_node *child;
+       proto_node *current;
+
+       if (func(pnode, data))
+               return TRUE;
+
+       child = pnode->first_child;
+       while (child != NULL) {
+               /*
+                * The routine we call might modify the child, e.g. by
+                * freeing it, so we get the child's successor before
+                * calling that routine.
+                */
+               current = child;
+               child = current->next;
+               if (proto_tree_traverse_pre_order((proto_tree *)current, func,
+                   data))
+                       return TRUE;
+       }
+
+       return FALSE;
+}
+
+static gboolean
+proto_tree_traverse_in_order(proto_tree *tree, proto_tree_traverse_func func,
+    gpointer data)
+{
+       proto_node *pnode = tree;
+       proto_node *child;
+       proto_node *current;
+
+       child = pnode->first_child;
+       if (child != NULL) {
+               /*
+                * The routine we call might modify the child, e.g. by
+                * freeing it, so we get the child's successor before
+                * calling that routine.
+                */
+               current = child;
+               child = current->next;
+
+               if (proto_tree_traverse_in_order((proto_tree *)current, func,
+                   data))
+                       return TRUE;
+
+               if (func(pnode, data))
+                       return TRUE;
+
+               while (child != NULL) {
+                       /*
+                        * The routine we call might modify the child, e.g. by
+                        * freeing it, so we get the child's successor before
+                        * calling that routine.
+                        */
+                       current = child;
+                       child = current->next;
+                       if (proto_tree_traverse_in_order((proto_tree *)current,
+                           func, data))
+                               return TRUE;
+               }
+       } else {
+               if (func(pnode, data))
+                       return TRUE;
+       }
+
+       return FALSE;
+}
+
+void
+proto_tree_children_foreach(proto_tree *tree, proto_tree_foreach_func func,
+    gpointer data)
+{
+       proto_node *node = tree;
+       proto_node *current;
+
+       node = node->first_child;
+       while (node != NULL) {
+               current = node;
+               node = current->next;
+               func((proto_tree *)current, data);
+       }
+}
+
 /* frees the resources that the dissection a proto_tree uses */
 void
 proto_tree_free(proto_tree *tree)
 {
-       /* Free all the data pointed to by the tree. */
-       g_node_traverse((GNode*)tree, G_IN_ORDER, G_TRAVERSE_ALL, -1,
-               proto_tree_free_node, NULL);
-
-       /* Then free the tree. */
-       g_node_destroy((GNode*)tree);
+       proto_tree_traverse_in_order(tree, proto_tree_free_node, NULL);
 }
 
 static void
@@ -336,25 +425,25 @@ free_node_tree_data(tree_data_t *tree_data)
        FIELD_INFO_FREE(finfo);
 
 static gboolean
-proto_tree_free_node(GNode *node, gpointer data _U_)
+proto_tree_free_node(proto_node *node, gpointer data _U_)
 {
        field_info *finfo = PITEM_FINFO(node);
 
        if (finfo == NULL) {
-               /* This is the root GNode. Destroy the per-tree data.
+               /* This is the root node. Destroy the per-tree data.
                 * There is no field_info to destroy. */
                free_node_tree_data(PTREE_DATA(node));
        }
        else {
-               /* This is a child GNode. Don't free the per-tree data, but
+               /* This is a child node. Don't free the per-tree data, but
                 * do free the field_info data. */
                FREE_NODE_FIELD_INFO(finfo);
        }
 
        /* Free the proto_node. */
-       PROTO_NODE_FREE(GNODE_PNODE(node));
+       PROTO_NODE_FREE(node);
 
-       return FALSE; /* FALSE = do not end traversal of GNode tree */
+       return FALSE; /* FALSE = do not end traversal of protocol tree */
 }
 
 /* Is the parsing being done for a visible proto_tree or an invisible one?
@@ -1740,12 +1829,11 @@ proto_tree_set_int(field_info *fi, gint32 value)
 }
 
 
-/* Add a field_info struct to the proto_tree, encapsulating it in a GNode (proto_item) */
+/* Add a field_info struct to the proto_tree, encapsulating it in a proto_node */
 static proto_item *
 proto_tree_add_node(proto_tree *tree, field_info *fi)
 {
-       GNode *new_gnode;
-       proto_node *pnode, *tnode;
+       proto_node *pnode, *tnode, *sibling;
        field_info *tfi;
 
        /*
@@ -1757,7 +1845,7 @@ proto_tree_add_node(proto_tree *tree, field_info *fi)
         * so it doesn't need an ett_ value to remember whether it
         * was expanded.
         */
-       tnode = GNODE_PNODE(tree);
+       tnode = tree;
        tfi = tnode->finfo;
        g_assert(tfi == NULL ||
            (tfi->tree_type >= 0 && tfi->tree_type < num_tree_types));
@@ -1766,10 +1854,15 @@ proto_tree_add_node(proto_tree *tree, field_info *fi)
        pnode->finfo = fi;
        pnode->tree_data = PTREE_DATA(tree);
 
-       new_gnode = g_node_new(pnode);
-       g_node_append((GNode*)tree, new_gnode);
+       if (tnode->last_child != NULL) {
+               sibling = tnode->last_child;
+               g_assert(sibling->next == NULL);
+               sibling->next = pnode;
+       } else
+               tnode->first_child = pnode;
+       tnode->last_child = pnode;
 
-       return (proto_item*) new_gnode;
+       return (proto_item*)pnode;
 }
 
 
@@ -2030,7 +2123,7 @@ proto_tree_create_root(void)
         * changed, then we'll find out very quickly. */
        pnode->tree_data->visible = FALSE;
 
-       return (proto_tree*) g_node_new(pnode);
+       return (proto_tree*) pnode;
 }
 
 
@@ -3224,7 +3317,7 @@ typedef struct {
 } offset_search_t;
 
 static gboolean
-check_for_offset(GNode *node, gpointer data)
+check_for_offset(proto_node *node, gpointer data)
 {
        field_info          *fi = PITEM_FINFO(node);
        offset_search_t         *offsearch = data;
@@ -3258,8 +3351,7 @@ proto_find_field_from_offset(proto_tree *tree, guint offset, tvbuff_t *tvb)
        offsearch.finfo = NULL;
        offsearch.tvb = tvb;
 
-       g_node_traverse((GNode*)tree, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
-                       check_for_offset, &offsearch);
+       proto_tree_traverse_pre_order(tree, check_for_offset, &offsearch);
 
        return offsearch.finfo;
 }
index 9c0d3fa55edd7d4153ab9f396bfb2fe5c4384a7f..7422945748df7e0f08af5056b45ae47bc3b8a536 100644 (file)
@@ -1,7 +1,7 @@
 /* proto.h
  * Definitions for protocol display
  *
- * $Id: proto.h,v 1.51 2003/12/03 09:28:22 guy Exp $
+ * $Id: proto.h,v 1.52 2003/12/04 10:59:34 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
@@ -126,24 +126,28 @@ typedef struct {
     gboolean    visible;
 } tree_data_t;
 
-/* Each GNode (proto_tree, proto_item) points to one of
- * these. */
+/* Each proto_tree, proto_item is one of these. */
 typedef struct _proto_node {
+       struct _proto_node *first_child;
+       struct _proto_node *last_child;
+       struct _proto_node *next;
        field_info  *finfo;
        tree_data_t *tree_data;
 } proto_node;
 
-typedef GNode proto_tree;
-typedef GNode proto_item;
+typedef proto_node proto_tree;
+typedef proto_node proto_item;
 
-/* Retrieve the proto_node from a GNode. */
-#define GNODE_PNODE(t)  ((proto_node*)((GNode*)(t))->data)
+typedef void (*proto_tree_foreach_func)(proto_node *, gpointer);
+
+extern void proto_tree_children_foreach(proto_tree *tree,
+    proto_tree_foreach_func func, gpointer data);
 
 /* Retrieve the field_info from a proto_item */
-#define PITEM_FINFO(t)  (GNODE_PNODE(t)->finfo)
+#define PITEM_FINFO(t)  ((t)->finfo)
 
 /* Retrieve the tree_data_t from a proto_tree */
-#define PTREE_DATA(t)   (GNODE_PNODE(t)->tree_data)
+#define PTREE_DATA(t)   ((t)->tree_data)
 
 /* Sets up memory used by proto routines. Called at program startup */
 extern void proto_init(const char *plugin_dir,
diff --git a/file.c b/file.c
index 19253ed686ae542c9d07a5c60d4f54ced0ac1df9..fef4ed5c50aa8babdd02f29c0630bfebb21da041 100644 (file)
--- a/file.c
+++ b/file.c
@@ -1,7 +1,7 @@
 /* file.c
  * File I/O routines
  *
- * $Id: file.c,v 1.325 2003/12/02 23:14:30 guy Exp $
+ * $Id: file.c,v 1.326 2003/12/04 10:59:33 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
@@ -96,7 +96,7 @@ static void rescan_packets(capture_file *cf, const char *action, const char *act
 
 static gboolean match_protocol_tree(capture_file *cf, frame_data *fdata,
        void *criterion);
-static void match_subtree_text(GNode *node, gpointer data);
+static void match_subtree_text(proto_node *node, gpointer data);
 static gboolean match_summary_line(capture_file *cf, frame_data *fdata,
        void *criterion);
 static gboolean match_ascii_and_unicode(capture_file *cf, frame_data *fdata,
@@ -1623,14 +1623,13 @@ match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
   /* Iterate through all the nodes, seeing if they have text that matches. */
   mdata->cf = cf;
   mdata->frame_matched = FALSE;
-  g_node_children_foreach((GNode*) edt->tree, G_TRAVERSE_ALL,
-                         match_subtree_text, mdata);
+  proto_tree_children_foreach(edt->tree, match_subtree_text, mdata);
   epan_dissect_free(edt);
   return mdata->frame_matched;
 }
 
 static void
-match_subtree_text(GNode *node, gpointer data)
+match_subtree_text(proto_node *node, gpointer data)
 {
   match_data   *mdata = (match_data*) data;
   const gchar  *string = mdata->string;
@@ -1680,8 +1679,8 @@ match_subtree_text(GNode *node, gpointer data)
   }
   
   /* Recurse into the subtree, if it exists */
-  if (g_node_n_children(node) > 0)
-    g_node_children_foreach(node, G_TRAVERSE_ALL, match_subtree_text, mdata);
+  if (node->first_child != NULL)
+    proto_tree_children_foreach(node, match_subtree_text, mdata);
 }
 
 gboolean
index a580b79a0adc470e85aa32c36a9f46b777bac090..90b168c7225e5d71773f854bd8248dbed8191319 100644 (file)
@@ -1,7 +1,7 @@
 /* proto_draw.c
  * Routines for GTK+ packet display
  *
- * $Id: proto_draw.c,v 1.70 2003/12/01 02:01:56 guy Exp $
+ * $Id: proto_draw.c,v 1.71 2003/12/04 10:59:34 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
@@ -116,7 +116,7 @@ add_byte_tab(GtkWidget *byte_nb, const char *name, tvbuff_t *tvb,
     proto_tree *tree, GtkWidget *tree_view);
 
 static void
-proto_tree_draw_node(GNode *node, gpointer data);
+proto_tree_draw_node(proto_node *node, gpointer data);
 
 /* Get the current text window for the notebook. */
 GtkWidget *
@@ -1603,8 +1603,7 @@ proto_tree_draw(proto_tree *protocol_tree, GtkWidget *tree_view)
     gtk_tree_store_clear(store);
 #endif
 
-    g_node_children_foreach((GNode*) protocol_tree, G_TRAVERSE_ALL,
-                            proto_tree_draw_node, &info);
+    proto_tree_children_foreach(protocol_tree, proto_tree_draw_node, &info);
 
 #if GTK_MAJOR_VERSION < 2
     gtk_clist_thaw(GTK_CLIST(tree_view));
@@ -1612,7 +1611,7 @@ proto_tree_draw(proto_tree *protocol_tree, GtkWidget *tree_view)
 }
 
 static void
-proto_tree_draw_node(GNode *node, gpointer data)
+proto_tree_draw_node(proto_node *node, gpointer data)
 {
     struct proto_tree_draw_info        info;
     struct proto_tree_draw_info        *parent_info = (struct proto_tree_draw_info*) data;
@@ -1641,7 +1640,7 @@ proto_tree_draw_node(GNode *node, gpointer data)
         proto_item_fill_label(fi, label_str);
     }
 
-    if (g_node_n_children(node) > 0) {
+    if (node->first_child != NULL) {
         is_leaf = FALSE;
         g_assert(fi->tree_type >= 0 && fi->tree_type < num_tree_types);
         if (tree_is_expanded[fi->tree_type]) {
@@ -1676,8 +1675,7 @@ proto_tree_draw_node(GNode *node, gpointer data)
 #else
         info.iter = &iter;
 #endif
-        g_node_children_foreach(node, G_TRAVERSE_ALL,
-                                proto_tree_draw_node, &info);
+        proto_tree_children_foreach(node, proto_tree_draw_node, &info);
 #if GTK_MAJOR_VERSION >= 2
         path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &iter);
         if (is_expanded)
index de4b0d8ecfe7cd3bf42f0a572ba3497fccb83098..03257a94682512e776d6ad2966ccfad08a1c0d11 100644 (file)
@@ -1,7 +1,7 @@
 /* rtp_analysis.c
  * RTP analysis addition for ethereal
  *
- * $Id: rtp_analysis.c,v 1.12 2003/12/03 09:28:26 guy Exp $
+ * $Id: rtp_analysis.c,v 1.13 2003/12/04 10:59:34 guy Exp $
  *
  * Copyright 2003, Alcatel Business Systems
  * By Lars Ruoff <lars.ruoff@gmx.net>
@@ -1770,11 +1770,11 @@ void create_rtp_dialog(user_data_t* user_data)
 
 
 /****************************************************************************/
-static gboolean process_node(proto_item *ptree_node, header_field_info *hfinformation,
+static gboolean process_node(proto_node *ptree_node, header_field_info *hfinformation,
                                                        const gchar* proto_field, guint32* p_result)
 {
        field_info            *finfo;
-       proto_item            *proto_sibling_node;
+       proto_node            *proto_sibling_node;
        header_field_info     *hfssrc;
        ipv4_addr             *ipv4;
 
@@ -1784,8 +1784,8 @@ static gboolean process_node(proto_item *ptree_node, header_field_info *hfinform
                hfssrc = proto_registrar_get_byname((gchar*) proto_field);
                if (hfssrc == NULL)
                        return FALSE;
-               for(ptree_node=g_node_first_child(ptree_node); ptree_node!=NULL; 
-                                       ptree_node=g_node_next_sibling(ptree_node)) {
+               for(ptree_node=ptree_node->first_child; ptree_node!=NULL; 
+                                       ptree_node=ptree_node->next) {
                        finfo=PITEM_FINFO(ptree_node);
                        if (hfssrc==finfo->hfinfo) {
                                if (hfinformation->type==FT_IPv4) {
@@ -1800,7 +1800,7 @@ static gboolean process_node(proto_item *ptree_node, header_field_info *hfinform
                }
        }
 
-       proto_sibling_node = g_node_next_sibling(ptree_node);
+       proto_sibling_node = ptree_node->next;
 
        if (proto_sibling_node) {
                return process_node(proto_sibling_node, hfinformation, proto_field, p_result);
@@ -1815,14 +1815,14 @@ static gboolean get_int_value_from_proto_tree(proto_tree *protocol_tree,
                                                                                         const gchar* proto_field,
                                                                                         guint32* p_result)
 {
-       proto_item      *ptree_node;
+       proto_node      *ptree_node;
        header_field_info     *hfinformation;
 
        hfinformation = proto_registrar_get_byname((gchar*) proto_name);
        if (hfinformation == NULL)
                return FALSE;
 
-       ptree_node = g_node_first_child(protocol_tree);
+       ptree_node = ((proto_node *)protocol_tree)->first_child;
        if (!ptree_node)
                return FALSE;
 
diff --git a/print.c b/print.c
index 553febb42b52817450d47ad8e8a29d815d6498a2..07ab81d62805254cbeea522b463f54c494950147 100644 (file)
--- a/print.c
+++ b/print.c
@@ -1,7 +1,7 @@
 /* print.c
  * Routines for printing packet analysis trees.
  *
- * $Id: print.c,v 1.62 2003/12/03 09:28:19 guy Exp $
+ * $Id: print.c,v 1.63 2003/12/04 10:59:33 guy Exp $
  *
  * Gilbert Ramirez <gram@alumni.rice.edu>
  *
@@ -41,7 +41,7 @@
 #include "util.h"
 #include "packet-data.h"
 
-static void proto_tree_print_node(GNode *node, gpointer data);
+static void proto_tree_print_node(proto_node *node, gpointer data);
 static void print_hex_data_buffer(FILE *fh, register const guchar *cp,
     register guint length, char_enc encoding, gint format);
 static void ps_clean_string(unsigned char *out, const unsigned char *in,
@@ -95,8 +95,7 @@ void proto_tree_print(print_args_t *print_args, epan_dissect_t *edt,
               print uninterpreted data fields in hex as well. */
        data.format = print_args->format;
 
-       g_node_children_foreach((GNode*) edt->tree, G_TRAVERSE_ALL,
-               proto_tree_print_node, &data);
+       proto_tree_children_foreach(edt->tree, proto_tree_print_node, &data);
 }
 
 /*
@@ -130,7 +129,7 @@ get_field_data(GSList *src_list, field_info *fi)
 
 /* Print a tree's data, and any child nodes. */
 static
-void proto_tree_print_node(GNode *node, gpointer data)
+void proto_tree_print_node(proto_node *node, gpointer data)
 {
        field_info      *fi = PITEM_FINFO(node);
        print_data      *pdata = (print_data*) data;
@@ -170,9 +169,9 @@ void proto_tree_print_node(GNode *node, gpointer data)
        g_assert(fi->tree_type >= -1 && fi->tree_type < num_tree_types);
        if (pdata->print_all_levels ||
            (fi->tree_type >= 0 && tree_is_expanded[fi->tree_type])) {
-               if (g_node_n_children(node) > 0) {
+               if (node->first_child != NULL) {
                        pdata->level++;
-                       g_node_children_foreach(node, G_TRAVERSE_ALL,
+                       proto_tree_children_foreach(node,
                                proto_tree_print_node, pdata);
                        pdata->level--;
                }
index 266c7dd070b6593de729d643bb5c3526e2e7d824..641ee0d24c7001c1c07df13bfa42db04849058a7 100644 (file)
@@ -1,7 +1,7 @@
 /* proto_hier_stats.c
  * Routines for calculating statistics based on protocol.
  *
- * $Id: proto_hier_stats.c,v 1.19 2003/12/03 09:28:19 guy Exp $
+ * $Id: proto_hier_stats.c,v 1.20 2003/12/04 10:59:33 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
@@ -76,11 +76,11 @@ 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);
@@ -95,7 +95,7 @@ process_node(proto_item *ptree_node, GNode *parent_stat_node, ph_stats_t *ps, gu
        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);
@@ -111,9 +111,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;
        }
index dfe648170514f8f2becc1a4957b9598c7395169f..532ebcc343298c069fcfd47de5d47d374d89904d 100644 (file)
@@ -1,7 +1,7 @@
 /* tap-protohierstat.c
  * protohierstat   2002 Ronnie Sahlberg
  *
- * $Id: tap-protohierstat.c,v 1.5 2003/12/03 09:28:19 guy Exp $
+ * $Id: tap-protohierstat.c,v 1.6 2003/12/04 10:59:33 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
@@ -84,11 +84,11 @@ protohierstat_packet(void *prs, packet_info *pinfo, epan_dissect_t *edt, void *d
        if(!edt->tree){
                return 0;
        }
-       if(!edt->tree->children){
+       if(!edt->tree->first_child){
                return 0;
        }
 
-       for(tree=edt->tree->children;tree;tree=tree->next){
+       for(tree=edt->tree->first_child;tree;tree=tree->next){
                fi=PITEM_FINFO(tree);
 
                /* first time we saw a protocol at this leaf */