diff options
author | Jörg Mayer <jmayer@loplof.de> | 2012-01-15 21:59:11 +0000 |
---|---|---|
committer | Jörg Mayer <jmayer@loplof.de> | 2012-01-15 21:59:11 +0000 |
commit | be706c63801fb98d42fb743b27b16cc36273651e (patch) | |
tree | 62ed0b552191eb0753d26a3edcbab73459a15f7f /ui/gtk/flow_graph.c | |
parent | 6d69ef093cd6868ab51f8b52477a510172033353 (diff) |
Move gtk to ui/gtk.
This looses the last checkin to gtk, will add this manually back.
svn path=/trunk/; revision=40518
Diffstat (limited to 'ui/gtk/flow_graph.c')
-rw-r--r-- | ui/gtk/flow_graph.c | 673 |
1 files changed, 673 insertions, 0 deletions
diff --git a/ui/gtk/flow_graph.c b/ui/gtk/flow_graph.c new file mode 100644 index 0000000000..f8b62adeae --- /dev/null +++ b/ui/gtk/flow_graph.c @@ -0,0 +1,673 @@ +/* flow_graph.c + * $Id$ + * Allows to display a flow graph of the currently displayed packets + * + * Copyright 2004, Ericsson , Spain + * By Francisco Alcoba <francisco.alcoba@ericsson.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 + * 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 <string.h> + +#include <gtk/gtk.h> + +#include <epan/epan.h> +#include <epan/packet.h> +#include <epan/filesystem.h> +#include <epan/stat_cmd_args.h> +#include <epan/to_str.h> +#include <epan/tap.h> +#include <epan/dissectors/packet-tcp.h> +#include <epan/strutil.h> + +#include "../stat_menu.h" +#include "../simple_dialog.h" + +#include "ui/gtk/graph_analysis.h" +#include "ui/gtk/gui_stat_menu.h" +#include "ui/gtk/dlg_utils.h" +#include "ui/gtk/gui_utils.h" +#include "ui/gtk/stock_icons.h" +#include "ui/gtk/gtkglobals.h" +#include "ui/gtk/main.h" + + + +#define TYPE_OF_PACKETS_DISPLAYED 0 +#define TYPE_OF_PACKETS_ALL 1 + +#define TYPE_OF_FLOW_GENERAL 0 +#define TYPE_OF_FLOW_TCP 1 + +#define NODE_ADDR_TYPE_SRCDST 0 +#define NODE_ADDR_TYPE_NET_SRCDST 1 + +static int type_of_packets = TYPE_OF_PACKETS_DISPLAYED; +static int type_of_flow = TYPE_OF_FLOW_GENERAL; +static int node_addr_type = NODE_ADDR_TYPE_SRCDST; + +static int tap_identifier; +static gboolean have_frame_tap_listener=FALSE; +static gboolean have_tcp_tap_listener=FALSE; +static graph_analysis_info_t *graph_analysis = NULL; +static graph_analysis_data_t *graph_analysis_data = NULL; + +static GtkWidget *flow_graph_dlg = NULL; + +static GtkWidget *select_all_rb; +static GtkWidget *select_displayed_rb; +static GtkWidget *select_general_rb; +static GtkWidget *select_tcp_rb; +static GtkWidget *src_dst_rb; +static GtkWidget *net_src_dst_rb; + +/****************************************************************************/ +/* free up memory and initialize the pointers */ + +static void +flow_graph_reset(void *ptr _U_) +{ + graph_analysis_item_t *graph_item; + + GList* list; + + if (graph_analysis !=NULL){ + + /* free the graph data items */ + list = g_list_first(graph_analysis->list); + while (list) + { + graph_item = list->data; + g_free(graph_item->frame_label); + g_free(graph_item->comment); + g_free(list->data); + list = g_list_next(list); + } + g_list_free(graph_analysis->list); + graph_analysis->nconv = 0; + graph_analysis->list = NULL; + } +} + +/****************************************************************************/ +static void +flow_graph_data_init(void) { + graph_analysis = g_malloc(sizeof(graph_analysis_info_t)); + graph_analysis->nconv = 0; + graph_analysis->list = NULL; +} + + +/****************************************************************************/ +static void +remove_tap_listener_flow_graph(void) +{ + protect_thread_critical_region(); + remove_tap_listener(&(tap_identifier)); + unprotect_thread_critical_region(); + + have_frame_tap_listener=FALSE; + have_tcp_tap_listener=FALSE; +} + + +/****************************************************************************/ +/* CALLBACKS */ +/****************************************************************************/ +static void +flow_graph_on_destroy(GObject *object _U_, gpointer user_data _U_) +{ + /* remove_tap_listeners */ + remove_tap_listener_flow_graph(); + + /* Clean up memory used by tap */ + flow_graph_reset(NULL); + + g_assert(graph_analysis != NULL); + g_assert(graph_analysis_data != NULL); + + g_free(graph_analysis); + graph_analysis = NULL; + + g_free(graph_analysis_data); + graph_analysis_data = NULL; + + /* Note that we no longer have a "Flow Graph" dialog box. */ + flow_graph_dlg = NULL; +} + + +/****************************************************************************/ +static void +toggle_select_all(GtkWidget *widget _U_, gpointer user_data _U_) +{ + /* is the button now active? */ + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(select_all_rb))) { + type_of_packets = TYPE_OF_PACKETS_ALL; + } +} + +/****************************************************************************/ +static void +toggle_select_displayed(GtkWidget *widget _U_, gpointer user_data _U_) +{ + /* is the button now active? */ + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(select_displayed_rb))) { + type_of_packets = TYPE_OF_PACKETS_DISPLAYED; + } +} + +/****************************************************************************/ +static void +toggle_select_general(GtkWidget *widget _U_, gpointer user_data _U_) +{ + /* is the button now active? */ + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(select_general_rb))) { + type_of_flow = TYPE_OF_FLOW_GENERAL; + } +} + +/****************************************************************************/ +static void +toggle_select_tcp(GtkWidget *widget _U_, gpointer user_data _U_) +{ + /* is the button now active? */ + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(select_tcp_rb))) { + type_of_flow = TYPE_OF_FLOW_TCP; + } +} + +/****************************************************************************/ +static void +toggle_select_srcdst(GtkWidget *widget _U_, gpointer user_data _U_) +{ + /* is the button now active? */ + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(src_dst_rb))) { + node_addr_type = NODE_ADDR_TYPE_SRCDST; + } +} + +/****************************************************************************/ +static void +toggle_select_netsrcdst(GtkWidget *widget _U_, gpointer user_data _U_) +{ + /* is the button now active? */ + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(net_src_dst_rb))) { + node_addr_type = NODE_ADDR_TYPE_NET_SRCDST; + } +} + +/****************************************************************************/ +/* Add a new frame into the graph */ +static int +flow_graph_frame_add_to_graph(packet_info *pinfo) +{ + graph_analysis_item_t *gai; + int i; + gchar *protocol; + gchar *colinfo; + + protocol=NULL; + colinfo=NULL; + + if (node_addr_type == NODE_ADDR_TYPE_NET_SRCDST) { + if (pinfo->net_src.type!=AT_NONE && pinfo->net_dst.type!=AT_NONE) { + gai = g_malloc(sizeof(graph_analysis_item_t)); + COPY_ADDRESS(&(gai->src_addr),&(pinfo->net_src)); + COPY_ADDRESS(&(gai->dst_addr),&(pinfo->net_dst)); + } + else return 0; + + } else { + if (pinfo->src.type!=AT_NONE && pinfo->dst.type!=AT_NONE) { + gai = g_malloc(sizeof(graph_analysis_item_t)); + COPY_ADDRESS(&(gai->src_addr),&(pinfo->src)); + COPY_ADDRESS(&(gai->dst_addr),&(pinfo->dst)); + } + else return 0; + } + + gai->fd = pinfo->fd; + + gai->port_src=pinfo->srcport; + gai->port_dst=pinfo->destport; + gai->comment=NULL; + gai->frame_label=NULL; + + /* this code doesn't make sense. + g_free(gai->comment); + g_free(gai->frame_label); + */ + + if(pinfo->cinfo) { + if (pinfo->cinfo->col_first[COL_INFO]>=0){ + + for (i = pinfo->cinfo->col_first[COL_INFO]; i <= pinfo->cinfo->col_last[COL_INFO]; i++) { + if (pinfo->cinfo->fmt_matx[i][COL_INFO]) { + colinfo = g_strdup(pinfo->cinfo->col_data[i]); + /* break; ? or g_free(colinfo); before g_strdup() */ + } + } + } + + if (pinfo->cinfo->col_first[COL_PROTOCOL]>=0){ + + for (i = pinfo->cinfo->col_first[COL_PROTOCOL]; i <= pinfo->cinfo->col_last[COL_PROTOCOL]; i++) { + if (pinfo->cinfo->fmt_matx[i][COL_PROTOCOL]) { + protocol = g_strdup(pinfo->cinfo->col_data[i]); + /* break; ? or g_free(protocol); before g_strdup() */ + } + } + } + } + + if (colinfo != NULL) { + if (protocol != NULL) { + gai->frame_label = g_strdup_printf("%.19s", colinfo); + gai->comment = g_strdup_printf("%s: %s", protocol, colinfo); + } else { + gai->frame_label = g_strdup_printf("%.19s", colinfo); + gai->comment = g_strdup_printf("%s", colinfo); + } + } else { + /* This will probably never happen...*/ + if (protocol != NULL) { + gai->frame_label = g_strdup_printf("%.19s", protocol); + gai->comment = g_strdup_printf("%s", protocol); + } + } + + g_free(protocol); + g_free(colinfo); + + gai->line_style=1; + gai->conv_num=0; + gai->display=TRUE; + + graph_analysis->list = g_list_append(graph_analysis->list, gai); + + return 1; +} + +/****************************************************************************/ +/* Add a new tcp frame into the graph */ +static int +flow_graph_tcp_add_to_graph(packet_info *pinfo, const struct tcpheader *tcph) +{ + graph_analysis_item_t *gai; + /* copied from packet-tcp */ + const gchar *fstr[] = {"FIN", "SYN", "RST", "PSH", "ACK", "URG", "ECN", "CWR" }; + guint i, bpos; + gboolean flags_found = FALSE; + gchar flags[64]; + + gai = g_malloc(sizeof(graph_analysis_item_t)); + gai->fd = pinfo->fd; + if (node_addr_type == NODE_ADDR_TYPE_NET_SRCDST) { + COPY_ADDRESS(&(gai->src_addr),&(pinfo->net_src)); + COPY_ADDRESS(&(gai->dst_addr),&(pinfo->net_dst)); + } else { + COPY_ADDRESS(&(gai->src_addr),&(pinfo->src)); + COPY_ADDRESS(&(gai->dst_addr),&(pinfo->dst)); + } + gai->port_src=pinfo->srcport; + gai->port_dst=pinfo->destport; + + flags[0] = '\0'; + for (i = 0; i < 8; i++) { + bpos = 1 << i; + if (tcph->th_flags & bpos) { + if (flags_found) { + g_strlcat(flags, ", ", sizeof(flags)); + } + g_strlcat(flags, fstr[i], sizeof(flags)); + flags_found = TRUE; + } + } + if (flags[0] == '\0') { + g_snprintf (flags, sizeof(flags), "<None>"); + } + + if ((tcph->th_have_seglen)&&(tcph->th_seglen!=0)){ + gai->frame_label = g_strdup_printf("%s - Len: %u",flags, tcph->th_seglen); + } + else{ + gai->frame_label = g_strdup(flags); + } + + if (tcph->th_flags & TH_ACK) + gai->comment = g_strdup_printf("Seq = %u Ack = %u",tcph->th_seq, tcph->th_ack); + else + gai->comment = g_strdup_printf("Seq = %u",tcph->th_seq); + + gai->line_style=1; + gai->conv_num=0; + gai->display=TRUE; + + graph_analysis->list = g_list_append(graph_analysis->list, gai); + + return 1; +} + + + +/****************************************************************************/ +/* whenever a frame packet is seen by the tap listener */ +static gboolean +flow_graph_frame_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *dummy _U_) +{ + if ((type_of_packets == TYPE_OF_PACKETS_ALL)||(pinfo->fd->flags.passed_dfilter==1)){ + flow_graph_frame_add_to_graph(pinfo); + } + + return TRUE; +} + +/****************************************************************************/ +/* whenever a TCP packet is seen by the tap listener */ +static gboolean +flow_graph_tcp_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *tcp_info) +{ + const struct tcpheader *tcph = tcp_info; + + if ((type_of_packets == TYPE_OF_PACKETS_ALL)||(pinfo->fd->flags.passed_dfilter==1)){ + flow_graph_tcp_add_to_graph(pinfo,tcph); + } + + return TRUE; +} + + +static void +flow_graph_packet_draw(void *prs _U_) +{ + return; +} + +/****************************************************************************/ +static void +flow_graph_on_ok (GtkButton *button _U_, + gpointer user_data) +{ + if ((have_frame_tap_listener==TRUE) + ||(have_tcp_tap_listener==TRUE)) + { + /* remove_tap_listeners */ + remove_tap_listener_flow_graph(); + } + + /* Scan for displayed packets (retap all packets) */ + + if (type_of_flow == TYPE_OF_FLOW_GENERAL){ + /* Register the tap listener */ + + if(have_frame_tap_listener==FALSE) + { + /* don't register tap listener, if we have it already */ + register_tap_listener("frame", &tap_identifier, NULL, + TL_REQUIRES_COLUMNS, + flow_graph_reset, + flow_graph_frame_packet, + flow_graph_packet_draw + ); + have_frame_tap_listener=TRUE; + } + + cf_retap_packets(&cfile); + } + else if (type_of_flow == TYPE_OF_FLOW_TCP){ + /* Register the tap listener */ + + if(have_tcp_tap_listener==FALSE) + { + /* don't register tap listener, if we have it already */ + register_tap_listener("tcp", &tap_identifier, NULL, + 0, + flow_graph_reset, + flow_graph_tcp_packet, + flow_graph_packet_draw + ); + have_tcp_tap_listener=TRUE; + } + + cf_retap_packets(&cfile); + } + + if (graph_analysis_data->dlg.window != NULL){ /* if we still have a window */ + graph_analysis_update(graph_analysis_data); /* refresh it xxx */ + } + else{ + graph_analysis_data->dlg.parent_w = user_data; + graph_analysis_create(graph_analysis_data); + } +} + + +/****************************************************************************/ +/* INTERFACE */ +/****************************************************************************/ + +static void +flow_graph_dlg_create (void) +{ + GtkWidget *flow_graph_dlg_w; + GtkWidget *main_vb; + GtkWidget *hbuttonbox; + GtkWidget *bt_cancel, *bt_ok; +#if 0 + GtkWidget *top_label = NULL; +#endif + GtkWidget *flow_type_fr, *range_fr, *range_tb, *flow_type_tb, *node_addr_fr, *node_addr_tb; + + flow_graph_dlg_w = dlg_window_new("Wireshark: Flow Graph"); /* transient_for top_level */ + gtk_window_set_destroy_with_parent (GTK_WINDOW(flow_graph_dlg_w), TRUE); + + gtk_window_set_default_size(GTK_WINDOW(flow_graph_dlg_w), 250, 150); + + main_vb = gtk_vbox_new (FALSE, 0); + gtk_container_add(GTK_CONTAINER(flow_graph_dlg_w), main_vb); + gtk_container_set_border_width (GTK_CONTAINER (main_vb), 7); + +#if 0 + top_label = gtk_label_new ("Choose packets to include in the graph"); + gtk_box_pack_start (GTK_BOX (main_vb), top_label, FALSE, FALSE, 8); +#endif + + gtk_widget_show(flow_graph_dlg_w); + + /*** Packet range frame ***/ + range_fr = gtk_frame_new("Choose packets"); + gtk_box_pack_start(GTK_BOX(main_vb), range_fr, FALSE, FALSE, 5); + + range_tb = gtk_table_new(4, 4, FALSE); + gtk_container_set_border_width(GTK_CONTAINER(range_tb), 5); + gtk_container_add(GTK_CONTAINER(range_fr), range_tb); + + /* Process all packets */ + select_all_rb = gtk_radio_button_new_with_mnemonic_from_widget(NULL, "_All packets"); + gtk_widget_set_tooltip_text (select_all_rb, ("Process all packets")); + g_signal_connect(select_all_rb, "toggled", G_CALLBACK(toggle_select_all), NULL); + gtk_table_attach_defaults(GTK_TABLE(range_tb), select_all_rb, 0, 1, 0, 1); + if (type_of_packets == TYPE_OF_PACKETS_ALL) { + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(select_all_rb),TRUE); + } + gtk_widget_show(select_all_rb); + + /* Process displayed packets */ + select_displayed_rb = gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(select_all_rb), + "_Displayed packets"); + gtk_widget_set_tooltip_text (select_displayed_rb, ("Process displayed packets")); + g_signal_connect(select_displayed_rb, "toggled", G_CALLBACK(toggle_select_displayed), NULL); + gtk_table_attach_defaults(GTK_TABLE(range_tb), select_displayed_rb, 0, 1, 1, 2); + if (type_of_packets == TYPE_OF_PACKETS_DISPLAYED) { + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(select_displayed_rb),TRUE); + } + gtk_widget_show(select_displayed_rb); + + gtk_widget_show(range_tb); + gtk_widget_show(range_fr); + + /*** Flow type frame ***/ + flow_type_fr = gtk_frame_new("Choose flow type"); + gtk_box_pack_start(GTK_BOX(main_vb), flow_type_fr, FALSE, FALSE, 5); + + flow_type_tb = gtk_table_new(4, 4, FALSE); + gtk_container_set_border_width(GTK_CONTAINER(flow_type_tb), 5); + gtk_container_add(GTK_CONTAINER(flow_type_fr), flow_type_tb); + + /* General information */ + select_general_rb = gtk_radio_button_new_with_mnemonic_from_widget(NULL, "_General flow"); + gtk_widget_set_tooltip_text (select_general_rb, ("Show all packets, with general information")); + g_signal_connect(select_general_rb, "toggled", G_CALLBACK(toggle_select_general), NULL); + gtk_table_attach_defaults(GTK_TABLE(flow_type_tb), select_general_rb, 0, 1, 0, 1); + if (type_of_flow == TYPE_OF_FLOW_GENERAL) { + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(select_general_rb),TRUE); + } + gtk_widget_show(select_general_rb); + + /* TCP specific information */ + select_tcp_rb = gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(select_general_rb), + "_TCP flow"); + gtk_widget_set_tooltip_text (select_tcp_rb, ("Show only TCP packets, with TCP specific information")); + g_signal_connect(select_tcp_rb, "toggled", G_CALLBACK(toggle_select_tcp), NULL); + gtk_table_attach_defaults(GTK_TABLE(flow_type_tb), select_tcp_rb, 0, 1, 1, 2); + if (type_of_flow == TYPE_OF_FLOW_TCP) { + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(select_tcp_rb),TRUE); + } + gtk_widget_show(select_tcp_rb); + + gtk_widget_show(flow_type_tb); + gtk_widget_show(flow_type_fr); + + /*** Node address type frame ***/ + node_addr_fr = gtk_frame_new("Choose node address type"); + gtk_box_pack_start(GTK_BOX(main_vb), node_addr_fr, FALSE, FALSE, 5); + + node_addr_tb = gtk_table_new(4, 4, FALSE); + gtk_container_set_border_width(GTK_CONTAINER(node_addr_tb), 5); + gtk_container_add(GTK_CONTAINER(node_addr_fr), node_addr_tb); + + /* Source / Dest address */ + src_dst_rb = gtk_radio_button_new_with_mnemonic_from_widget(NULL, "_Standard source/destination addresses"); + gtk_widget_set_tooltip_text (src_dst_rb, + ("Nodes in the diagram are identified with source and destination addresses")); + g_signal_connect(src_dst_rb, "toggled", G_CALLBACK(toggle_select_srcdst), NULL); + gtk_table_attach_defaults(GTK_TABLE(node_addr_tb), src_dst_rb, 0, 1, 0, 1); + if (node_addr_type == NODE_ADDR_TYPE_SRCDST) { + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(src_dst_rb),TRUE); + } + gtk_widget_show(src_dst_rb); + + /* Network source / dest address */ + net_src_dst_rb = gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(src_dst_rb), + "_Network source/destination addresses"); + gtk_widget_set_tooltip_text (net_src_dst_rb, + ("Nodes in the diagram are identified with network source and destination addresses")); + g_signal_connect(net_src_dst_rb, "toggled", G_CALLBACK(toggle_select_netsrcdst), NULL); + gtk_table_attach_defaults(GTK_TABLE(node_addr_tb), net_src_dst_rb, 0, 1, 1, 2); + if (node_addr_type == NODE_ADDR_TYPE_NET_SRCDST) { + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(net_src_dst_rb),TRUE); + } + gtk_widget_show(net_src_dst_rb); + + gtk_widget_show(node_addr_tb); + gtk_widget_show(node_addr_fr); + + /* button row */ + hbuttonbox = gtk_hbutton_box_new (); + gtk_box_pack_start (GTK_BOX (main_vb), hbuttonbox, FALSE, FALSE, 5); + gtk_button_box_set_layout (GTK_BUTTON_BOX (hbuttonbox), GTK_BUTTONBOX_SPREAD); + gtk_box_set_spacing (GTK_BOX (hbuttonbox), 30); + + bt_ok = gtk_button_new_from_stock(GTK_STOCK_OK); + gtk_container_add(GTK_CONTAINER(hbuttonbox), bt_ok); + gtk_widget_set_tooltip_text (bt_ok, "Show the flow graph"); + g_signal_connect(bt_ok, "clicked", G_CALLBACK(flow_graph_on_ok), flow_graph_dlg_w); + gtk_widget_show(bt_ok); + + bt_cancel = gtk_button_new_from_stock(GTK_STOCK_CANCEL); + gtk_container_add (GTK_CONTAINER (hbuttonbox), bt_cancel); +#if GTK_CHECK_VERSION(2,18,0) + gtk_widget_set_can_default(bt_cancel, TRUE); +#else + GTK_WIDGET_SET_FLAGS(bt_cancel, GTK_CAN_DEFAULT); +#endif + gtk_widget_set_tooltip_text (bt_cancel, "Cancel this dialog"); + window_set_cancel_button(flow_graph_dlg_w, bt_cancel, window_cancel_button_cb); + + g_signal_connect(flow_graph_dlg_w, "delete_event", G_CALLBACK(window_delete_event_cb), NULL); + g_signal_connect(flow_graph_dlg_w, "destroy", G_CALLBACK(flow_graph_on_destroy), NULL); + + gtk_widget_show_all(flow_graph_dlg_w); + window_present(flow_graph_dlg_w); + + flow_graph_dlg = flow_graph_dlg_w; +} + +/****************************************************************************/ +/* PUBLIC */ +/****************************************************************************/ + +/* init function for tap */ +static void +flow_graph_init_tap(const char *dummy _U_, void* userdata _U_) +{ + /* The storage allocated by flow_graph_data_init() and graph_analysis_init() */ + /* will be considered to be "associated with" the flow_graph_dlg dialog box. */ + /* It will be freed when the flow_graph_dlg dialog box is destroyed. */ + if (flow_graph_dlg != NULL) { + g_assert(graph_analysis != NULL); + g_assert(graph_analysis_data != NULL); + /* There's already a dialog box; reactivate it. */ + reactivate_window(flow_graph_dlg); + } else { + g_assert(graph_analysis == NULL); + g_assert(graph_analysis_data == NULL); + + /* initialize graph items store */ + flow_graph_data_init(); + + /* init the Graph Analysis */ + graph_analysis_data = graph_analysis_init(); + graph_analysis_data->graph_info = graph_analysis; + + flow_graph_dlg_create(); + } +} + + +/****************************************************************************/ +/* entry point when called via the GTK menu */ +void +flow_graph_launch(GtkAction *action _U_, gpointer user_data _U_) +{ + flow_graph_init_tap("",NULL); +} + +/****************************************************************************/ +void +register_tap_listener_flow_graph(void) +{ + register_stat_cmd_arg("flow_graph",flow_graph_init_tap,NULL); +} + |