"Fossies" - the Fresh Open Source Software Archive

Member "etherape-0.9.18/src/info_windows.c" (3 Jun 2018, 32183 Bytes) of package /linux/privat/etherape-0.9.18.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "info_windows.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 0.9.17_vs_0.9.18.

    1 /* EtherApe
    2  * Copyright (C) 2001 Juan Toledo, Riccardo Ghetta
    3  *
    4  * This program is free software; you can redistribute it and/or modify
    5  * it under the terms of the GNU General Public License as published by
    6  * the Free Software Foundation; either version 2 of the License, or
    7  * (at your option) any later version.
    8  *
    9  * This program is distributed in the hope that it will be useful,
   10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   12  * GNU General Public License for more details.
   13  *
   14  * You should have received a copy of the GNU General Public License
   15  * along with this program; if not, see <http://www.gnu.org/licenses/>.
   16  */
   17 
   18 #ifdef HAVE_CONFIG_H
   19 #include <config.h>
   20 #endif
   21 
   22 #include <math.h>
   23 #include <time.h>
   24 #include "appdata.h"
   25 #include "info_windows.h"
   26 #include "diagram.h"
   27 #include "stats/node.h"
   28 #include "datastructs.h"
   29 #include "stats/protocols.h"
   30 #include "capture/capctl.h"
   31 #include "preferences.h"
   32 #include "stats/prot_types.h"
   33 #include "ui_utils.h"
   34 #include "stats/util.h"
   35 #include "node_windows.h"
   36 
   37 #if !defined(G_SOURCE_CONTINUE)
   38 // RHEL6/CENTOS6, SLE11 etc don't have this macro
   39 #define G_SOURCE_CONTINUE TRUE
   40 #endif
   41 
   42 typedef enum
   43 {
   44   PROTO_COLUMN_COLOR = 0,
   45   PROTO_COLUMN_NAME,
   46   PROTO_COLUMN_PORT,
   47   PROTO_COLUMN_INSTANTANEOUS,
   48   PROTO_COLUMN_ACCUMULATED,
   49   PROTO_COLUMN_AVGSIZE,
   50   PROTO_COLUMN_LASTHEARD,
   51   PROTO_COLUMN_PACKETS,
   52   PROTO_COLUMN_N        /* must be the last entry */
   53 } PROTO_COLUMN;
   54 
   55 typedef struct
   56 {
   57   gchar *prot_name;
   58   GtkWidget *window;
   59 }
   60 prot_info_window_t;
   61 
   62 typedef struct protocol_list_item_t_tag
   63 {
   64   gchar *name; /* protocol name */
   65   uint port;     /* protocol port */
   66   GdkRGBA color; /* protocol color */
   67   basic_stats_t rowstats;
   68 } protocol_list_item_t;
   69 
   70 
   71 /* list of active node/link info windows */
   72 static GList *stats_info_windows = NULL;
   73 
   74 /* list of active protocol info windows */
   75 static GList *prot_info_windows = NULL;
   76 
   77 /* private functions */
   78 static void update_prot_info_windows (void);
   79 static void update_prot_info_window (prot_info_window_t * prot_info_window);
   80 static gint node_info_window_compare (gconstpointer a, gconstpointer b);
   81 static gint prot_info_compare (gconstpointer a, gconstpointer b);
   82 static void update_stats_info_windows (void);
   83 static void update_node_protocols_window (GtkWidget *node_window);
   84 static void update_link_info_window (GtkWidget *window);
   85 
   86 /* ----------------------------------------------------------
   87 
   88    Generic Protocol Info Detail window functions (prot_info_windows)
   89    Used to display nodes and links detail data (and protos)
   90 
   91    ---------------------------------------------------------- */
   92 /* Comparison function used to compare prot_info_windows */
   93 static gint
   94 prot_info_compare (gconstpointer a, gconstpointer b)
   95 {
   96   g_assert (a != NULL);
   97   g_assert (b != NULL);
   98   return strcmp (((prot_info_window_t *) a)->prot_name, (gchar *) b);
   99 }               /* prot_info_compare */
  100 
  101 
  102 static GtkBuilder *new_bldr_instance(const gchar *id)
  103 {
  104   GtkBuilder *bldr;
  105   gchar *ids[2];
  106 
  107   ids[0] = id;
  108   ids[1] = NULL;
  109 
  110   bldr = gtk_builder_new();
  111   if (!bldr)
  112     {
  113       g_error(_("We could not load the interface! (%s)"),
  114                appdata.itf_file);
  115       return NULL;
  116     }
  117 
  118   if (!gtk_builder_add_objects_from_file(bldr, appdata.itf_file, ids, NULL)) {
  119       g_error(_("Cannot create widget %s from file %s!"),
  120                id,
  121                appdata.itf_file);
  122       g_object_unref(bldr);
  123       return NULL;
  124   }
  125 
  126   gtk_builder_connect_signals(bldr, NULL);
  127   return bldr;
  128 }
  129 
  130 
  131 static void create_prot_info_window(protocol_t * protocol)
  132 {
  133   GtkWidget *window;
  134   prot_info_window_t *prot_info_window;
  135   GtkWidget *widget;
  136   GList *list_item;
  137 
  138   /* If there is already a window, we don't need to create it again */
  139   if (!(list_item =
  140     g_list_find_custom (prot_info_windows,
  141                 protocol->name, prot_info_compare)))
  142     {
  143 /*     GtkWidget *protwin;
  144      protwin =
  145             GTK_WIDGET(gtk_builder_get_object(appdata.xml, "prot_info"));*/
  146 /*      guint err;
  147       GError *gerror = NULL;
  148       static gchar *objs[] = {"prot_info", NULL};
  149       err = gtk_builder_add_objects_from_file(GtkBuilder *builder,
  150                                               const gchar *filename,
  151                                               objs,
  152                                               &gerror);
  153      xml_info_window =
  154             GTK_WIDGET(glade_xml_new(appdata.itf_file, "prot_info", NULL));
  155       if (!xml_info_window)
  156         {
  157           g_error (_("We could not load the interface! (%s)"),
  158                appdata.itf_file);
  159           return;
  160         }
  161       glade_xml_signal_autoconnect (xml_info_window);
  162 */
  163       window = GTK_WIDGET(gtk_builder_get_object(appdata.xml, "prot_info"));
  164 
  165       gtk_widget_show (window);
  166       widget = GTK_WIDGET(gtk_builder_get_object(appdata.xml, "prot_info_name_label"));
  167       g_object_set_data(G_OBJECT(window), "name_label", widget);
  168       widget =
  169             GTK_WIDGET(gtk_builder_get_object(appdata.xml, "prot_info_last_heard_label"));
  170       g_object_set_data(G_OBJECT(window), "last_heard_label", widget);
  171       widget = GTK_WIDGET(gtk_builder_get_object(appdata.xml, "prot_info_average"));
  172       g_object_set_data(G_OBJECT(window), "average", widget);
  173       widget =
  174             GTK_WIDGET(gtk_builder_get_object(appdata.xml, "prot_info_accumulated"));
  175       g_object_set_data(G_OBJECT (window), "accumulated", widget);
  176 
  177       prot_info_window = g_malloc (sizeof (prot_info_window_t));
  178       prot_info_window->prot_name = g_strdup (protocol->name);
  179       g_object_set_data(G_OBJECT (window), "prot_name",
  180              prot_info_window->prot_name);
  181       prot_info_window->window = window;
  182       prot_info_windows =
  183     g_list_prepend (prot_info_windows, prot_info_window);
  184 
  185     }
  186   else
  187     prot_info_window = (prot_info_window_t *) list_item->data;
  188 
  189   update_prot_info_window (prot_info_window);
  190 
  191 }               /* create_prot_info_window */
  192 
  193 
  194 /* It's called when a prot info window is closed by the user
  195  * It has to free memory and delete the window from the list
  196  * of windows */
  197 gboolean
  198 on_prot_info_delete_event (GtkWidget * prot_info, GdkEvent * evt,
  199                gpointer user_data)
  200 {
  201   GList *item = NULL;
  202   gchar *prot_name = NULL;
  203   prot_info_window_t *prot_info_window = NULL;
  204 
  205   prot_name = g_object_get_data (G_OBJECT (prot_info), "prot_name");
  206   if (!prot_name)
  207     {
  208       g_my_critical (_("No prot_name in on_prot_info_delete_event"));
  209       return TRUE;      /* ignore event */
  210     }
  211 
  212   if (!(item =
  213     g_list_find_custom (prot_info_windows, prot_name, prot_info_compare)))
  214     {
  215       g_my_critical (_("No prot_info_window in on_prot_info_delete_event"));
  216       return TRUE;      /* ignore event */
  217     }
  218 
  219   prot_info_window = item->data;
  220   g_free (prot_info_window->prot_name);
  221   gtk_widget_destroy (GTK_WIDGET (prot_info_window->window));
  222   prot_info_windows = g_list_remove_link (prot_info_windows, item);
  223 
  224   return FALSE;
  225 }               /* on_prot_info_delete_event */
  226 
  227 /* updates a single proto detail window */
  228 static void
  229 update_prot_info_window (prot_info_window_t * prot_info_window)
  230 {
  231   const protocol_t *prot;
  232   GtkWidget *window;
  233   GtkWidget *widget;
  234   gchar *str;
  235 
  236   window = prot_info_window->window;
  237   if (!window)
  238     return;
  239 
  240   prot = protocol_summary_find(pref.stack_level, prot_info_window->prot_name);
  241   if (!prot)
  242     {
  243       /* protocol expired */
  244       widget = g_object_get_data (G_OBJECT (window), "average");
  245       gtk_label_set_text (GTK_LABEL (widget), "X");
  246       widget = g_object_get_data (G_OBJECT (window), "accumulated");
  247       gtk_label_set_text (GTK_LABEL (widget), "X");
  248       gtk_widget_queue_resize (GTK_WIDGET (prot_info_window->window));
  249       return;
  250     }
  251 
  252   gtk_window_set_title (GTK_WINDOW (window), prot_info_window->prot_name);
  253   widget = g_object_get_data (G_OBJECT (window), "name_label");
  254   gtk_label_set_text (GTK_LABEL (widget), prot_info_window->prot_name);
  255   widget = g_object_get_data (G_OBJECT (window), "last_heard_label");
  256   str = timeval_to_str(prot->stats.last_time);
  257   gtk_label_set_text (GTK_LABEL (widget), str);
  258   g_free(str);
  259   widget = g_object_get_data (G_OBJECT (window), "average");
  260   str = traffic_to_str (prot->stats.average, TRUE);
  261   gtk_label_set_text (GTK_LABEL (widget), str);
  262   g_free(str);
  263   widget = g_object_get_data (G_OBJECT (window), "accumulated");
  264   str = traffic_to_str (prot->stats.accumulated, FALSE);
  265   gtk_label_set_text (GTK_LABEL (widget), str);
  266   g_free(str);
  267   gtk_widget_queue_resize (GTK_WIDGET (prot_info_window->window));
  268 
  269 }               /* update_prot_info_window */
  270 
  271 /* cycles on all proto detail windows updating them */
  272 void
  273 update_prot_info_windows (void)
  274 {
  275   GList *list_item = NULL, *remove_item;
  276   prot_info_window_t *prot_info_window = NULL;
  277   capstatus_t status;
  278 
  279   status = get_capture_status();
  280 
  281   list_item = prot_info_windows;
  282   while (list_item)
  283     {
  284       prot_info_window = (prot_info_window_t *) list_item->data;
  285       if (status == STOP)
  286     {
  287       g_free (prot_info_window->prot_name);
  288       gtk_widget_destroy (GTK_WIDGET (prot_info_window->window));
  289       remove_item = list_item;
  290       list_item = list_item->next;
  291       prot_info_windows =
  292         g_list_remove_link (prot_info_windows, remove_item);
  293     }
  294       else
  295     {
  296       update_prot_info_window (prot_info_window);
  297       list_item = list_item->next;
  298     }
  299     }
  300 
  301 }               /* update_prot_info_windows */
  302 
  303 
  304 /***************************************************************
  305  *
  306  * protocol table handling functions
  307  *
  308  ***************************************************************/
  309 #define MAX_C(a,b) ((a) > (b) ? (a) : (b))
  310 #define MIN_C(a,b) ((a) > (b) ? (a) : (b))
  311 #define LUMINANCE(r,g,b) ((MAX_C( (double)(r)/0xFFFF, MAX_C( (double)(g)/0xFFFF, \
  312                                   (double)(b)/0xFFFF)) + \
  313                           MIN_C( (double)(r)/0xFFFF, MIN_C( (double)(g)/0xFFFF, \
  314                                   (double)(b)/0xFFFF))) / 2.0)
  315 
  316 /* Comparison functions used to sort the clist */
  317 static gint
  318 protocols_table_compare (GtkTreeModel * gs, GtkTreeIter * a, GtkTreeIter * b,
  319              gpointer userdata)
  320 {
  321   gint ret = 0;
  322   gdouble t1, t2;
  323   gdouble diffms;
  324   gint idcol;
  325   GtkSortType order;
  326 
  327   /* reads the proto ptr from 6th columns */
  328   const protocol_list_item_t *prot1, *prot2;
  329   gtk_tree_model_get (gs, a, PROTO_COLUMN_N, &prot1, -1);
  330   gtk_tree_model_get (gs, b, PROTO_COLUMN_N, &prot2, -1);
  331   if (!prot1 || !prot2)
  332     return 0;           /* error */
  333 
  334   /* gets sort info */
  335   gtk_tree_sortable_get_sort_column_id (GTK_TREE_SORTABLE (gs), &idcol,
  336                     &order);
  337 
  338   switch (idcol)
  339     {
  340     case PROTO_COLUMN_COLOR: /* color */
  341     case PROTO_COLUMN_PORT: /* port */
  342     case PROTO_COLUMN_NAME: /* name */
  343     default:
  344       ret = strcmp (prot1->name, prot2->name);
  345       break;
  346     case PROTO_COLUMN_INSTANTANEOUS:
  347       t1 = prot1->rowstats.average;
  348       t2 = prot2->rowstats.average;
  349       if (t1 == t2)
  350     ret = 0;
  351       else if (t1 < t2)
  352     ret = -1;
  353       else
  354     ret = 1;
  355       break;
  356     case PROTO_COLUMN_ACCUMULATED:
  357       t1 = prot1->rowstats.accumulated;
  358       t2 = prot2->rowstats.accumulated;
  359       if (t1 == t2)
  360     ret = 0;
  361       else if (t1 < t2)
  362     ret = -1;
  363       else
  364     ret = 1;
  365       break;
  366     case PROTO_COLUMN_AVGSIZE:
  367       t1 = prot1->rowstats.avg_size;
  368       t2 = prot2->rowstats.avg_size;
  369       if (t1 == t2)
  370     ret = 0;
  371       else if (t1 < t2)
  372     ret = -1;
  373       else
  374     ret = 1;
  375       break;
  376     case PROTO_COLUMN_LASTHEARD:
  377       diffms = subtract_times_ms(&prot1->rowstats.last_time,
  378                                   &prot2->rowstats.last_time);
  379       if (diffms == 0)
  380     ret = 0;
  381       else if (diffms < 0)
  382     ret = -1;
  383       else
  384     ret = 1;
  385       break;
  386     case PROTO_COLUMN_PACKETS:
  387       if (prot1->rowstats.accu_packets == prot2->rowstats.accu_packets)
  388     ret = 0;
  389       else if (prot1->rowstats.accu_packets < prot2->rowstats.accu_packets)
  390     ret = -1;
  391       else
  392     ret = 1;
  393       break;
  394     }
  395 
  396   return ret;
  397 }
  398 
  399 static GtkListStore *create_protocols_table (GtkWidget *window)
  400 {
  401   GtkTreeView *gv;
  402   GtkListStore *gs;
  403   GtkTreeViewColumn *gc;
  404   int i;
  405 
  406   /* get the treeview, if present */
  407   gv = retrieve_treeview(window);
  408   if (!gv)
  409     return NULL;
  410 
  411   gs = GTK_LIST_STORE (gtk_tree_view_get_model (gv));
  412   if (gs)
  413     return gs;
  414 
  415   /* create the store  - it uses 9 values, 7 displayable, one proto color
  416      and the data pointer */
  417   gs = gtk_list_store_new (9, GDK_TYPE_RGBA, G_TYPE_STRING, G_TYPE_STRING,
  418                G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
  419                G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER);
  420   gtk_tree_view_set_model (gv, GTK_TREE_MODEL (gs));
  421 
  422   /* the view columns and cell renderers must be also created ...
  423      the first column is the proto color; is a text column wich renders
  424      only a space with a colored background. We must set some special properties
  425    */
  426 
  427   gc = gtk_tree_view_column_new_with_attributes
  428     (" ", gtk_cell_renderer_text_new(), "background-rgba", PROTO_COLUMN_COLOR,
  429      NULL);
  430   g_object_set (G_OBJECT (gc), "resizable", TRUE,
  431                                "reorderable", TRUE,
  432                                NULL);
  433 //  gtk_tree_view_column_set_sort_column_id(gc, PROTO_COLUMN_COLOR);
  434   gtk_tree_view_append_column (gv, gc);
  435 
  436 
  437   create_add_text_column(gv, "Protocol", PROTO_COLUMN_NAME, FALSE);
  438   create_add_text_column(gv, "Port", PROTO_COLUMN_PORT, TRUE);
  439   create_add_text_column(gv, "Inst Traffic", PROTO_COLUMN_INSTANTANEOUS, FALSE);
  440   create_add_text_column(gv, "Accum Traffic", PROTO_COLUMN_ACCUMULATED, FALSE);
  441   create_add_text_column(gv, "Avg Size", PROTO_COLUMN_AVGSIZE, FALSE);
  442   create_add_text_column(gv, "Last Heard", PROTO_COLUMN_LASTHEARD, FALSE);
  443   create_add_text_column(gv, "Packets", PROTO_COLUMN_PACKETS, FALSE);
  444 
  445   /* the sort functions ... */
  446   for (i = 0 ; i < PROTO_COLUMN_N ; ++i)
  447     gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (gs), i,
  448                                     protocols_table_compare, gs, NULL);
  449 
  450   /* initial sort order is by protocol */
  451   gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (gs),
  452                                         PROTO_COLUMN_NAME,
  453                     GTK_SORT_ASCENDING);
  454 
  455   return gs;
  456 }
  457 
  458 static void protocols_table_clear(GtkListStore *gs)
  459 {
  460   gboolean res;
  461   GtkTreeIter it;
  462 
  463   res = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (gs), &it);
  464   while (res)
  465     {
  466       protocol_list_item_t *row_proto = NULL;
  467       gtk_tree_model_get (GTK_TREE_MODEL (gs), &it, PROTO_COLUMN_N,
  468                           &row_proto, -1);
  469       if (row_proto)
  470         {
  471           g_free(row_proto->name);
  472           g_free(row_proto);
  473           res = gtk_list_store_remove (gs, &it);
  474         }
  475     }
  476 }
  477 
  478 static void update_protocols_row(GtkListStore *gs, GtkTreeIter *it,
  479                                  const protocol_list_item_t *row_proto)
  480 {
  481   gchar *ga, *gb, *gc, *gd, *ge, *gf;
  482   const port_service_t *ps;
  483 
  484   ga = traffic_to_str (row_proto->rowstats.accumulated, FALSE);
  485   gb = g_strdup_printf ("%lu", row_proto->rowstats.accu_packets);
  486   ps = services_port_find(row_proto->name);
  487   if (ps)
  488     gc = g_strdup_printf ("%d", ps->port);
  489   else
  490     gc = g_strdup("-");
  491   gd = traffic_to_str (row_proto->rowstats.average, TRUE);
  492   ge = timeval_to_str (row_proto->rowstats.last_time);
  493   gf = traffic_to_str (row_proto->rowstats.avg_size, FALSE);
  494 
  495   gtk_list_store_set (gs, it,
  496                       PROTO_COLUMN_ACCUMULATED, ga,
  497                       PROTO_COLUMN_PACKETS, gb,
  498                       PROTO_COLUMN_PORT, gc,
  499                       PROTO_COLUMN_INSTANTANEOUS, gd,
  500                       PROTO_COLUMN_LASTHEARD, ge,
  501                       PROTO_COLUMN_AVGSIZE, gf,
  502                       -1);
  503 
  504   g_free(ga);
  505   g_free(gb);
  506   g_free(gc);
  507   g_free(gd);
  508   g_free(ge);
  509   g_free(gf);
  510 }
  511 
  512 static void update_protocols_table(GtkWidget *window, const protostack_t *pstk)
  513 {
  514   GtkListStore *gs;
  515   GList *item;
  516   gboolean res;
  517   GtkTreeIter it;
  518 
  519   gs = create_protocols_table (window);
  520   if (!gs)
  521     return; /* nothing to do */
  522 
  523   if (pstk)
  524     item = pstk->protostack[pref.stack_level];
  525   else
  526     item = NULL;
  527 
  528   res = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (gs), &it);
  529   while (res || item)
  530     {
  531       const protocol_t *stack_proto = NULL;
  532       protocol_list_item_t *row_proto = NULL;
  533 
  534       /* retrieve current row proto (if present) */
  535       if (res)
  536         gtk_tree_model_get (GTK_TREE_MODEL (gs), &it, PROTO_COLUMN_N,
  537                             &row_proto, -1);
  538 
  539       if ( !item )
  540         {
  541           /* no more protos on stack, del current row (remove moves to next) */
  542           if (res)
  543             {
  544               g_free(row_proto->name);
  545               g_free(row_proto);
  546               res = gtk_list_store_remove (gs, &it);
  547             }
  548           continue;
  549         }
  550 
  551       /* retrieve current stack proto */
  552       stack_proto = item->data;
  553 
  554       if (!res)
  555         {
  556           /* current protocol missing on list, create a new row */
  557       row_proto = g_malloc(sizeof(protocol_list_item_t));
  558           g_assert(row_proto);
  559 
  560           row_proto->name = g_strdup(stack_proto->name);
  561       row_proto->color = *protohash_color(stack_proto->name);
  562 
  563       gtk_list_store_append(gs, &it);
  564       gtk_list_store_set (gs, &it,
  565                               PROTO_COLUMN_NAME, row_proto->name,
  566                               PROTO_COLUMN_COLOR, &row_proto->color,
  567                               PROTO_COLUMN_N, row_proto,
  568                               -1);
  569         }
  570       else
  571         {
  572           /* we have both items, check names */
  573           if (strcmp(row_proto->name, stack_proto->name))
  574             {
  575               /* names not identical, delete current row  (remove moves to next) */
  576               g_free(row_proto->name);
  577               g_free(row_proto);
  578               res = gtk_list_store_remove (gs, &it);
  579               continue;
  580             }
  581         }
  582 
  583       /* everything ok, update stats */
  584       row_proto->rowstats = stack_proto->stats;
  585       update_protocols_row(gs, &it, row_proto);
  586 
  587       if (res)
  588         res = gtk_tree_model_iter_next (GTK_TREE_MODEL (gs), &it);
  589 
  590       item = item->next;
  591     }
  592 }
  593 
  594 /* ----------------------------------------------------------
  595 
  596    General Protocol Info window functions (protocols_window)
  597    Displays the global protocol table
  598 
  599    ---------------------------------------------------------- */
  600 
  601 static void
  602 update_protocols_window (void)
  603 {
  604   GtkWidget *window;
  605   GtkTreeView *gv;
  606 
  607   window = GTK_WIDGET(gtk_builder_get_object(appdata.xml, "protocols_window"));
  608   gv = retrieve_treeview(window);
  609   if (!gv)
  610     {
  611       /* register gv */
  612       gv = GTK_TREE_VIEW (gtk_builder_get_object (appdata.xml, "prot_clist"));
  613       if (!gv)
  614         {
  615           g_critical("can't find prot_clist");
  616           return;
  617         }
  618       register_treeview(window, gv);
  619     }
  620 
  621   update_protocols_table(window, protocol_summary_stack());
  622 }               /* update_protocols_window */
  623 
  624 void
  625 toggle_protocols_window (void)
  626 {
  627   GtkWidget *protocols_check = GTK_WIDGET(gtk_builder_get_object(appdata.xml, "protocols_check"));
  628   if (!protocols_check)
  629     return;
  630   gtk_menu_item_activate (GTK_MENU_ITEM (protocols_check));
  631 }               /* toggle_protocols_window */
  632 
  633 gboolean
  634 on_delete_protocol_window (GtkWidget * wdg, GdkEvent * evt, gpointer ud)
  635 {
  636   toggle_protocols_window ();
  637   return TRUE;          /* ignore signal */
  638 }
  639 
  640 void
  641 on_protocols_check_activate (GtkCheckMenuItem * menuitem, gpointer user_data)
  642 {
  643   GtkWidget *protocols_window = GTK_WIDGET(gtk_builder_get_object(appdata.xml, "protocols_window"));
  644   if (!protocols_window)
  645     return;
  646   if (gtk_check_menu_item_get_active (menuitem))
  647     {
  648       gtk_widget_show(protocols_window);
  649       gdk_window_raise(gtk_widget_get_window(protocols_window));
  650       update_protocols_window ();
  651     }
  652   else
  653     {
  654       /* retrieve view and model (store) */
  655       GtkListStore *gs;
  656       GtkTreeView *gv = GTK_TREE_VIEW(gtk_builder_get_object(appdata.xml, "prot_clist"));
  657       if (gv)
  658         {
  659           gs = GTK_LIST_STORE (gtk_tree_view_get_model (gv));
  660           if (gs)
  661              protocols_table_clear(gs);
  662         }
  663       gtk_widget_hide (protocols_window);
  664     }
  665 }               /* on_protocols_check_activate */
  666 
  667 /* opens a protocol detail window when the user clicks a proto row */
  668 gboolean
  669 on_prot_list_select_row (GtkTreeView * gv, gboolean arg1, gpointer user_data)
  670 {
  671   protocol_t *protocol = NULL;
  672   GtkListStore *gs;
  673   GtkTreePath *gpath = NULL;
  674   GtkTreeViewColumn *gcol = NULL;
  675   GtkTreeIter it;
  676 
  677   /* retrieve the model (store) */
  678   gs = GTK_LIST_STORE (gtk_tree_view_get_model (gv));
  679   if (!gs)
  680     return FALSE;
  681 
  682   /* gets the row (path) at cursor */
  683   gtk_tree_view_get_cursor (gv, &gpath, &gcol);
  684   if (!gpath)
  685     return FALSE;       /* no row selected */
  686 
  687   /* get iterator from path  and removes from store */
  688   if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (gs), &it, gpath))
  689     return FALSE;       /* path not found */
  690 
  691   gtk_tree_model_get (GTK_TREE_MODEL (gs), &it, PROTO_COLUMN_N, &protocol, -1);
  692   create_prot_info_window (protocol);
  693 
  694   return TRUE;
  695 }               /* on_prot_clist_select_row */
  696 
  697 
  698 
  699 
  700 /* ----------------------------------------------------------
  701 
  702    Node Info window functions
  703 
  704    ---------------------------------------------------------- */
  705 /* Comparison function used to compare stats_info_windows */
  706 static gint
  707 node_info_window_compare(gconstpointer a, gconstpointer b)
  708 {
  709   const node_id_t *id_a;
  710   g_assert (a != NULL);
  711   g_assert (b != NULL);
  712 
  713   id_a = g_object_get_data (G_OBJECT (a), "node_id");
  714   if (!id_a)
  715     return -1; /* not a node window */
  716 
  717   return node_id_compare( id_a, b);
  718 }
  719 
  720 gboolean update_info_windows(gpointer dummy)
  721 {
  722   capstatus_t status;
  723 
  724   status = get_capture_status();
  725   if (status != PLAY && status != STOP)
  726     return TRUE;
  727 
  728   update_protocols_window ();
  729   update_stats_info_windows ();
  730   update_prot_info_windows ();
  731   nodes_wnd_update();
  732 
  733   return G_SOURCE_CONTINUE; /* Keep on calling this function */
  734 }
  735 
  736 /* It's called when a node info window is closed by the user
  737  * It has to free memory and delete the window from the list
  738  * of windows */
  739 gboolean
  740 on_node_info_delete_event (GtkWidget * node_info, GdkEvent * evt,
  741                gpointer user_data)
  742 {
  743   stats_info_windows = g_list_remove(stats_info_windows, node_info);
  744 
  745   g_free(g_object_get_data (G_OBJECT (node_info), "node_id"));
  746   g_free(g_object_get_data (G_OBJECT (node_info), "link_id"));
  747 
  748   gtk_widget_destroy (node_info);
  749 
  750   return FALSE;
  751 }               /* on_node_info_delete_event */
  752 
  753 
  754 void
  755 update_stats_info_windows (void)
  756 {
  757   GList *list_item;
  758   GtkWidget *window;
  759   capstatus_t status;
  760   double diffms;
  761   static struct timeval last_update_time = {
  762     0, 0
  763   };
  764 
  765   status = get_capture_status();
  766 
  767   /* Update info windows at most twice a second */
  768   diffms = subtract_times_ms(&appdata.now, &last_update_time);
  769   if (pref.refresh_period < 500)
  770     if (diffms >= 0 && diffms < 500)
  771       return;
  772 
  773   list_item = stats_info_windows;
  774   while (list_item)
  775     {
  776       window = list_item->data;
  777       if (status == STOP)
  778     {
  779           GList *remove_item = list_item;
  780       list_item = list_item->next;
  781       stats_info_windows =
  782         g_list_delete_link (stats_info_windows, remove_item);
  783           g_free(g_object_get_data (G_OBJECT (window), "node_id"));
  784           g_free(g_object_get_data (G_OBJECT (window), "link_id"));
  785       gtk_widget_destroy (GTK_WIDGET (window));
  786     }
  787       else
  788     {
  789           if (g_object_get_data (G_OBJECT (window), "node_id"))
  790             {
  791               /* is a node info window */
  792               update_node_protocols_window (window);
  793             }
  794           else
  795             update_link_info_window (window);
  796       list_item = list_item->next;
  797     }
  798     }
  799 
  800   last_update_time = appdata.now;
  801 }               /* update_stats_info_windows */
  802 
  803 
  804 
  805 /****************************************************************************
  806  *
  807  * node protocols display
  808  *
  809  ***************************************************************************/
  810 static GtkWidget *stats_info_create(const gchar *idkey, gpointer key)
  811 {
  812   GtkBuilder *bldr;
  813   GtkWidget *window;
  814   GtkTreeView *gv;
  815 
  816   bldr = new_bldr_instance("node_proto_info");
  817   if (!bldr)
  818     {
  819       g_error(_("We could not load the interface! (%s)"),
  820                appdata.itf_file);
  821       return NULL;
  822     }
  823   window = GTK_WIDGET(gtk_builder_get_object(bldr, "node_proto_info"));
  824   if (!window)
  825     {
  826       g_error(_("We could not load the interface! (%s)"),
  827                appdata.itf_file);
  828       g_object_unref(bldr);
  829       return NULL;
  830     }
  831 
  832   gtk_widget_show(window);
  833 
  834   /* register the widgets in the window */
  835   register_glade_widget(bldr, window, "src_label");
  836   register_glade_widget(bldr, window, "dst_label");
  837   register_glade_widget(bldr, window, "node_iproto_name");
  838   register_glade_widget(bldr, window, "node_iproto_numeric_name");
  839   register_glade_widget(bldr, window, "node_iproto_name_b");
  840   register_glade_widget(bldr, window, "node_iproto_numeric_name_b");
  841   register_glade_widget(bldr, window, "total_label");
  842   register_glade_widget(bldr, window, "inbound_label");
  843   register_glade_widget(bldr, window, "outbound_label");
  844   register_glade_widget(bldr, window, "node_iproto_avg");
  845   register_glade_widget(bldr, window, "node_iproto_avg_in");
  846   register_glade_widget(bldr, window, "node_iproto_avg_out");
  847   register_glade_widget(bldr, window, "node_iproto_accum");
  848   register_glade_widget(bldr, window, "node_iproto_accum_in");
  849   register_glade_widget(bldr, window, "node_iproto_accum_out");
  850   register_glade_widget(bldr, window, "node_iproto_avgsize");
  851   register_glade_widget(bldr, window, "node_iproto_avgsize_in");
  852   register_glade_widget(bldr, window, "node_iproto_avgsize_out");
  853 
  854   /* get and register the tree view */
  855   gv = GTK_TREE_VIEW(gtk_builder_get_object(bldr, "node_iproto_proto"));
  856   register_treeview(window, gv);
  857 
  858   /* create columns of proto list */
  859   create_protocols_table(window);
  860 
  861   // builder is not needed anymore
  862   g_object_unref(bldr);
  863 
  864   /* register key info */
  865   g_object_set_data(G_OBJECT (window), idkey, key);
  866 
  867   /* insert into list */
  868   stats_info_windows = g_list_prepend (stats_info_windows, window);
  869 
  870   return window;
  871 }
  872 
  873 
  874 static void
  875 stats_info_update(GtkWidget *window, const traffic_stats_t *stats)
  876 {
  877   if (!stats)
  878     {
  879       update_gtklabel(window, "node_iproto_avg", "X");
  880       update_gtklabel(window, "node_iproto_accum", "X");
  881       update_gtklabel(window, "node_iproto_avgsize", "X");
  882       update_gtklabel(window, "node_iproto_avg_in", "X");
  883       update_gtklabel(window, "node_iproto_avg_out", "X");
  884       update_gtklabel(window, "node_iproto_accum_in", "X");
  885       update_gtklabel(window, "node_iproto_accum_out", "X");
  886       update_gtklabel(window, "node_iproto_avgsize_in", "X");
  887       update_gtklabel(window, "node_iproto_avgsize_out", "X");
  888       update_protocols_table(window, NULL);
  889       gtk_widget_queue_resize (GTK_WIDGET (window));
  890     }
  891   else
  892     {
  893       gchar *str;
  894       str = traffic_to_str (stats->stats.average, TRUE);
  895       update_gtklabel(window, "node_iproto_avg", str);
  896       g_free(str);
  897       str = traffic_to_str (stats->stats.accumulated, FALSE);
  898       update_gtklabel(window, "node_iproto_accum", str);
  899       g_free(str);
  900       str = traffic_to_str (stats->stats.avg_size, FALSE);
  901       update_gtklabel(window, "node_iproto_avgsize", str);
  902       g_free(str);
  903       str = traffic_to_str (stats->stats_in.average, TRUE);
  904       update_gtklabel(window, "node_iproto_avg_in", str);
  905       g_free(str);
  906       str = traffic_to_str (stats->stats_out.average, TRUE);
  907       update_gtklabel(window, "node_iproto_avg_out", str);
  908       g_free(str);
  909       str = traffic_to_str (stats->stats_in.accumulated, FALSE);
  910       update_gtklabel(window, "node_iproto_accum_in", str);
  911       g_free(str);
  912       str = traffic_to_str (stats->stats_out.accumulated, FALSE);
  913       update_gtklabel(window, "node_iproto_accum_out", str);
  914       g_free(str);
  915       str = traffic_to_str (stats->stats_in.avg_size, FALSE);
  916       update_gtklabel(window, "node_iproto_avgsize_in", str);
  917       g_free(str);
  918       str = traffic_to_str (stats->stats_out.avg_size, FALSE);
  919       update_gtklabel(window, "node_iproto_avgsize_out", str);
  920       g_free(str);
  921       /* update protocol table */
  922       update_protocols_table(window, &stats->stats_protos);
  923     }
  924 }
  925 
  926 
  927 void
  928 node_protocols_window_create(const node_id_t * node_id)
  929 {
  930   GtkWidget *window;
  931   GList *list_item;
  932 
  933   /* If there is already a window, we don't need to create it again */
  934   list_item = g_list_find_custom (stats_info_windows,
  935                                   node_id, node_info_window_compare);
  936   if (!list_item)
  937     {
  938       window = stats_info_create("node_id", g_memdup(node_id, sizeof(node_id_t)));
  939       if (!window)
  940         return; /* creation failed */
  941 
  942       /* nodes don't need secondary names */
  943       update_gtklabel(window, "node_iproto_name_b", "");
  944       update_gtklabel(window, "node_iproto_numeric_name_b", "");
  945     }
  946   else
  947     window = list_item->data;
  948   update_node_protocols_window (window);
  949 }               /* node_protocols_window_create */
  950 
  951 static void
  952 update_node_protocols_window (GtkWidget *window)
  953 {
  954   const node_id_t *node_id;
  955   const node_t *node;
  956 
  957   node_id = g_object_get_data (G_OBJECT (window), "node_id");
  958   node = nodes_catalog_find(node_id);
  959   if (!node)
  960     {
  961       /* node expired, clear stats */
  962       update_gtklabel(window, "node_iproto_numeric_name", _("Node timed out"));
  963       stats_info_update(window, NULL);
  964       return;
  965     }
  966 
  967   gtk_window_set_title (GTK_WINDOW (window), node->name->str);
  968 
  969   update_gtklabel(window, "node_iproto_name", node->name->str);
  970   update_gtklabel(window, "node_iproto_numeric_name", node->numeric_name->str);
  971 
  972   stats_info_update(window, &node->node_stats);
  973 }
  974 
  975 /****************************************************************************
  976  *
  977  * link protocols display
  978  *
  979  ***************************************************************************/
  980 /* Comparison function used to compare stats_info_windows */
  981 static gint
  982 link_info_window_compare(gconstpointer a, gconstpointer b)
  983 {
  984   const link_id_t *id_a;
  985   g_assert (a != NULL);
  986   g_assert (b != NULL);
  987 
  988   id_a = g_object_get_data (G_OBJECT (a), "link_id");
  989   if (!id_a)
  990     return -1; /* not a link window */
  991 
  992   return link_id_compare( id_a, b);
  993 }
  994 
  995 void
  996 link_info_window_create(const link_id_t * link_id)
  997 {
  998   GtkWidget *window;
  999   GList *list_item;
 1000 
 1001   /* If there is already a window, we don't need to create it again */
 1002   list_item = g_list_find_custom (stats_info_windows,
 1003                                   link_id, link_info_window_compare);
 1004   if (!list_item)
 1005     {
 1006       window = stats_info_create("link_id", g_memdup(link_id, sizeof(link_id_t)));
 1007       if (!window)
 1008         return; /* creation failed */
 1009     }
 1010   else
 1011     window = list_item->data;
 1012   update_link_info_window (window);
 1013 }
 1014 
 1015 static void
 1016 update_link_info_window(GtkWidget *window)
 1017 {
 1018   const link_id_t *link_id;
 1019   const link_t *link;
 1020   const node_t *node;
 1021   gchar *linkname;
 1022 
 1023   /* updates column descriptions */
 1024   show_widget(window, "src_label");
 1025   show_widget(window, "dst_label");
 1026   update_gtklabel(window, "inbound_label", _("B->A"));
 1027   update_gtklabel(window, "outbound_label", _("A->B"));
 1028 
 1029   link_id = g_object_get_data (G_OBJECT (window), "link_id");
 1030   link = links_catalog_find(link_id);
 1031   if (!link)
 1032     {
 1033       /* node expired, clear stats */
 1034       update_gtklabel(window, "node_iproto_numeric_name", _("Link timed out"));
 1035       update_gtklabel(window, "node_iproto_numeric_name_b", "");
 1036       stats_info_update(window, NULL);
 1037       return;
 1038     }
 1039 
 1040   linkname = link_id_node_names(link_id);
 1041   gtk_window_set_title (GTK_WINDOW (window), linkname);
 1042   g_free(linkname);
 1043 
 1044   node = nodes_catalog_find(&link_id->src);
 1045   if (node)
 1046   {
 1047     update_gtklabel(window, "node_iproto_name", node->name->str);
 1048     update_gtklabel(window, "node_iproto_numeric_name", node->numeric_name->str);
 1049   }
 1050   else
 1051   {
 1052     update_gtklabel(window, "node_iproto_name", _("Node timed out"));
 1053     update_gtklabel(window, "node_iproto_numeric_name", _("Node timed out"));
 1054   }
 1055 
 1056   node = nodes_catalog_find(&link_id->dst);
 1057   if (node)
 1058   {
 1059     update_gtklabel(window, "node_iproto_name_b", node->name->str);
 1060     update_gtklabel(window, "node_iproto_numeric_name_b", node->numeric_name->str);
 1061   }
 1062   else
 1063   {
 1064     update_gtklabel(window, "node_iproto_name_b", _("Node timed out"));
 1065     update_gtklabel(window, "node_iproto_numeric_name_b", _("Node timed out"));
 1066   }
 1067 
 1068   stats_info_update(window, &link->link_stats);
 1069 }