1 /* hostlist_table.c 2004 Ian Schorr
2 * modified from endpoint_talkers_table.c 2003 Ronnie Sahlberg
3 * Helper routines common to all host list taps.
7 * Ethereal - Network traffic analyzer
8 * By Gerald Combs <gerald@ethereal.com>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
37 #include <epan/packet_info.h>
38 #include <epan/to_str.h>
39 #include <epan/addr_resolv.h>
42 #include "compat_macros.h"
43 #include "hostlist_table.h"
44 #include "image/clist_ascend.xpm"
45 #include "image/clist_descend.xpm"
46 #include "simple_dialog.h"
50 #include "gtk/color_dlg.h"
51 #include "gtkglobals.h"
53 #include "gui_utils.h"
54 #include "dlg_utils.h"
58 #define GTK_MENU_FUNC(a) ((GtkItemFactoryCallback)(a))
63 /* convert a port number into a string */
65 hostlist_port_to_str(int port_type, guint32 port)
68 static gchar *strp, str[4][12];
79 g_snprintf(strp, 11, "%d", port);
86 #define FN_ANY_ADDRESS 0
89 /* given an address (to distinguish between ipv4 and ipv6 for tcp/udp
90 a port_type and a name_type (FN_...)
91 return a string for the filter name
93 some addresses, like AT_ETHER may actually be any of multiple types
94 of protocols, either ethernet, tokenring, fddi etc so we must be more
95 specific there thats why we need specific_addr_type
98 hostlist_get_filter_name(address *addr, int specific_addr_type, int port_type, int name_type)
104 switch(specific_addr_type){
124 switch(specific_addr_type){
126 return "jxta.message.address";
144 g_assert_not_reached();
149 typedef struct column_arrows {
151 GtkWidget *ascend_pm;
152 GtkWidget *descend_pm;
157 reset_hostlist_table_data(hostlist_table *hosts)
162 /* Allow clist to update */
163 gtk_clist_thaw(hosts->table);
166 g_snprintf(title, 255, "Endpoints: %s", cf_get_display_name(&cfile));
167 gtk_window_set_title(GTK_WINDOW(hosts->win), title);
168 g_snprintf(title, 255, "%s", hosts->name);
169 gtk_label_set_text(GTK_LABEL(hosts->page_lb), title);
170 gtk_widget_set_sensitive(hosts->page_lb, FALSE);
172 g_snprintf(title, 255, "%s Endpoints: %s", hosts->name, cf_get_display_name(&cfile));
173 gtk_window_set_title(GTK_WINDOW(hosts->win), title);
176 /* remove all entries from the clist */
177 gtk_clist_clear(hosts->table);
179 /* delete all hosts */
180 for(i=0;i<hosts->num_hosts;i++){
181 g_free((gpointer)hosts->hosts[i].address.data);
183 g_free(hosts->hosts);
189 reset_hostlist_table_data_cb(void *arg)
191 reset_hostlist_table_data(arg);
194 void protect_thread_critical_region(void);
195 void unprotect_thread_critical_region(void);
197 hostlist_win_destroy_cb(GtkWindow *win _U_, gpointer data)
199 hostlist_table *hosts=(hostlist_table *)data;
201 protect_thread_critical_region();
202 remove_tap_listener(hosts);
203 unprotect_thread_critical_region();
205 reset_hostlist_table_data(hosts);
210 hostlist_sort_column(GtkCList *clist, gconstpointer ptr1, gconstpointer ptr2)
216 const GtkCListRow *row1 = ptr1;
217 const GtkCListRow *row2 = ptr2;
219 text1 = GTK_CELL_TEXT (row1->cell[clist->sort_column])->text;
220 text2 = GTK_CELL_TEXT (row2->cell[clist->sort_column])->text;
222 switch(clist->sort_column){
225 return strcmp (text1, text2);
232 sscanf(text1, "%" PRIu64, &i1);
233 sscanf(text2, "%" PRIu64, &i2);
234 /* XXX - this might cause trouble because of overflow problems */
235 /* XXX - is this correct anyway? Subtracting two unsigned values will still be an unsigned value, which will never become negative */
236 return (gint) (i1-i2);
238 g_assert_not_reached();
240 /* Allow clist to redraw */
242 gtk_clist_thaw(clist);
243 gtk_clist_freeze(clist);
249 hostlist_click_column_cb(GtkCList *clist, gint column, gpointer data)
251 column_arrows *col_arrows = (column_arrows *) data;
254 for (i = 0; i < NUM_COLS; i++) {
255 gtk_widget_hide(col_arrows[i].ascend_pm);
256 gtk_widget_hide(col_arrows[i].descend_pm);
259 if (column == clist->sort_column) {
260 if (clist->sort_type == GTK_SORT_ASCENDING) {
261 clist->sort_type = GTK_SORT_DESCENDING;
262 gtk_widget_show(col_arrows[column].descend_pm);
264 clist->sort_type = GTK_SORT_ASCENDING;
265 gtk_widget_show(col_arrows[column].ascend_pm);
268 clist->sort_type = GTK_SORT_DESCENDING;
269 gtk_widget_show(col_arrows[column].descend_pm);
270 gtk_clist_set_sort_column(clist, column);
273 gtk_clist_sort(clist);
275 /* Allow update of clist */
276 gtk_clist_thaw(clist);
277 gtk_clist_freeze(clist);
281 /* action is encoded as
282 filter_action*256+filter_type
290 5: Colorize Host Traffic
300 hostlist_select_filter_cb(GtkWidget *widget _U_, gpointer callback_data, guint callback_action)
304 hostlist_table *hl=(hostlist_table *)callback_data;
307 const char *current_filter;
310 action = (callback_action>>8)&0xff;
311 type = callback_action&0xff;
313 selection=GPOINTER_TO_INT(g_list_nth_data(GTK_CLIST(hl->table)->selection, 0));
314 if(selection>=(int)hl->num_hosts){
315 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "No hostlist selected");
318 /* translate it back from row index to index in hostlist array */
319 selection=GPOINTER_TO_INT(gtk_clist_get_row_data(hl->table, selection));
321 sport=hostlist_port_to_str(hl->hosts[selection].port_type, hl->hosts[selection].port);
323 g_snprintf(dirstr, 127, "%s==%s %s%s%s%s",
324 hostlist_get_filter_name(&hl->hosts[selection].address,
325 hl->hosts[selection].sat, hl->hosts[selection].port_type, FN_ANY_ADDRESS),
326 address_to_str(&hl->hosts[selection].address),
328 sport?hostlist_get_filter_name(&hl->hosts[selection].address, hl->hosts[selection].sat, hl->hosts[selection].port_type, FN_ANY_PORT):"",
332 current_filter=gtk_entry_get_text(GTK_ENTRY(main_display_filter_widget));
336 g_snprintf(str, 255, "%s", dirstr);
340 g_snprintf(str, 255, "!(%s)", dirstr);
344 g_snprintf(str, 255, "(%s) && (%s)", current_filter, dirstr);
348 g_snprintf(str, 255, "(%s) || (%s)", current_filter, dirstr);
351 /* and not selected */
352 g_snprintf(str, 255, "(%s) && !(%s)", current_filter, dirstr);
355 /* or not selected */
356 g_snprintf(str, 255, "(%s) || !(%s)", current_filter, dirstr);
363 gtk_entry_set_text(GTK_ENTRY(main_display_filter_widget), str);
364 main_filter_packets(&cfile, str, FALSE);
365 gdk_window_raise(top_level->window);
369 gtk_entry_set_text(GTK_ENTRY(main_display_filter_widget), str);
373 find_frame_with_filter(str);
377 find_previous_next_frame_with_filter(str, FALSE);
381 find_previous_next_frame_with_filter(str, TRUE);
384 /* colorize host traffic */
385 color_display_with_filter(str);
390 hostlist_show_popup_menu_cb(void *widg _U_, GdkEvent *event, hostlist_table *et)
392 GdkEventButton *bevent = (GdkEventButton *)event;
396 /* To qoute the "Gdk Event Structures" doc:
397 * "Normally button 1 is the left mouse button, 2 is the middle button, and 3 is the right button" */
398 if(event->type==GDK_BUTTON_PRESS && bevent->button==3){
399 /* if this is a right click on one of our columns, select it and popup the context menu */
400 if(gtk_clist_get_selection_info(et->table,
401 (gint) (((GdkEventButton *)event)->x),
402 (gint) (((GdkEventButton *)event)->y),
404 gtk_clist_unselect_all(et->table);
405 gtk_clist_select_row(et->table, row, -1);
407 gtk_menu_popup(GTK_MENU(et->menu), NULL, NULL, NULL, NULL,
408 bevent->button, bevent->time);
415 static GtkItemFactoryEntry hostlist_list_menu_items[] =
418 ITEM_FACTORY_ENTRY("/Apply as Filter", NULL, NULL, 0, "<Branch>", NULL),
419 ITEM_FACTORY_ENTRY("/Apply as Filter/Selected", NULL,
420 hostlist_select_filter_cb, 0*256+0, NULL, NULL),
421 ITEM_FACTORY_ENTRY("/Apply as Filter/Not Selected", NULL,
422 hostlist_select_filter_cb, 0*256+1, NULL, NULL),
423 ITEM_FACTORY_ENTRY("/Apply as Filter/... and Selected", NULL,
424 hostlist_select_filter_cb, 0*256+2, NULL, NULL),
425 ITEM_FACTORY_ENTRY("/Apply as Filter/... or Selected", NULL,
426 hostlist_select_filter_cb, 0*256+3, NULL, NULL),
427 ITEM_FACTORY_ENTRY("/Apply as Filter/... and not Selected", NULL,
428 hostlist_select_filter_cb, 0*256+4, NULL, NULL),
429 ITEM_FACTORY_ENTRY("/Apply as Filter/... or not Selected", NULL,
430 hostlist_select_filter_cb, 0*256+5, NULL, NULL),
433 ITEM_FACTORY_ENTRY("/Prepare a Filter", NULL, NULL, 0, "<Branch>", NULL),
434 ITEM_FACTORY_ENTRY("/Prepare a Filter/Selected", NULL,
435 hostlist_select_filter_cb, 1*256+0, NULL, NULL),
436 ITEM_FACTORY_ENTRY("/Prepare a Filter/Not Selected", NULL,
437 hostlist_select_filter_cb, 1*256+1, NULL, NULL),
438 ITEM_FACTORY_ENTRY("/Prepare a Filter/... and Selected", NULL,
439 hostlist_select_filter_cb, 1*256+2, NULL, NULL),
440 ITEM_FACTORY_ENTRY("/Prepare a Filter/... or Selected", NULL,
441 hostlist_select_filter_cb, 1*256+3, NULL, NULL),
442 ITEM_FACTORY_ENTRY("/Prepare a Filter/... and not Selected", NULL,
443 hostlist_select_filter_cb, 1*256+4, NULL, NULL),
444 ITEM_FACTORY_ENTRY("/Prepare a Filter/... or not Selected", NULL,
445 hostlist_select_filter_cb, 1*256+5, NULL, NULL),
448 ITEM_FACTORY_ENTRY("/Find Frame", NULL, NULL, 0, "<Branch>", NULL),
449 ITEM_FACTORY_ENTRY("/Find Frame/Find Frame", NULL,
450 hostlist_select_filter_cb, 2*256+0, NULL, NULL),
452 ITEM_FACTORY_ENTRY("/Find Frame/Find Next", NULL,
453 hostlist_select_filter_cb, 3*256+0, NULL, NULL),
455 ITEM_FACTORY_ENTRY("/Find Frame/Find Previous", NULL,
456 hostlist_select_filter_cb, 4*256+0, NULL, NULL),
457 /* Colorize Host Traffic */
458 ITEM_FACTORY_ENTRY("/Colorize Host Traffic", NULL,
459 hostlist_select_filter_cb, 5*256+0, NULL, NULL),
464 hostlist_create_popup_menu(hostlist_table *hl)
466 GtkItemFactory *item_factory;
468 item_factory = gtk_item_factory_new(GTK_TYPE_MENU, "<main>", NULL);
470 gtk_item_factory_create_items_ac(item_factory, sizeof(hostlist_list_menu_items)/sizeof(hostlist_list_menu_items[0]), hostlist_list_menu_items, hl, 2);
472 hl->menu = gtk_item_factory_get_widget(item_factory, "<main>");
473 SIGNAL_CONNECT(hl->table, "button_press_event", hostlist_show_popup_menu_cb, hl);
477 /* Draw/refresh the address field of a single entry at the specified index */
479 draw_hostlist_table_address(hostlist_table *hl, int hostlist_idx)
486 rownum=gtk_clist_find_row_from_data(hl->table, (gpointer)hostlist_idx);
488 if (!hl->resolve_names)
489 entry=address_to_str(&hl->hosts[hostlist_idx].address);
491 entry=get_addr_name(&hl->hosts[hostlist_idx].address);
493 gtk_clist_set_text(hl->table, rownum, 0, entry);
495 pt = hl->hosts[hostlist_idx].port_type;
496 if(!hl->resolve_names) pt = PT_NONE;
499 entry=get_tcp_port(hl->hosts[hostlist_idx].port);
502 entry=get_udp_port(hl->hosts[hostlist_idx].port);
505 port=hostlist_port_to_str(hl->hosts[hostlist_idx].port_type, hl->hosts[hostlist_idx].port);
508 gtk_clist_set_text(hl->table, rownum, 1, entry);
511 /* Refresh the address fields of all entries in the list */
513 draw_hostlist_table_addresses(hostlist_table *hl)
517 for(i=0;i<hl->num_hosts;i++){
518 draw_hostlist_table_address(hl, i);
524 draw_hostlist_table_data(hostlist_table *hl)
532 g_snprintf(title, 255, "%s: %u", hl->name, hl->num_hosts);
534 g_snprintf(title, 255, "%s", hl->name);
536 gtk_label_set_text(GTK_LABEL(hl->page_lb), title);
537 gtk_widget_set_sensitive(hl->page_lb, hl->num_hosts);
540 for(i=0;i<hl->num_hosts;i++){
543 j=gtk_clist_find_row_from_data(hl->table, (gpointer)i);
545 g_snprintf(str, 16, "%" PRIu64, hl->hosts[i].tx_frames+hl->hosts[i].rx_frames);
546 gtk_clist_set_text(hl->table, j, 2, str);
547 g_snprintf(str, 16, "%" PRIu64, hl->hosts[i].tx_bytes+hl->hosts[i].rx_bytes);
548 gtk_clist_set_text(hl->table, j, 3, str);
551 g_snprintf(str, 16, "%" PRIu64, hl->hosts[i].tx_frames);
552 gtk_clist_set_text(hl->table, j, 4, str);
553 g_snprintf(str, 16, "%" PRIu64, hl->hosts[i].tx_bytes);
554 gtk_clist_set_text(hl->table, j, 5, str);
557 g_snprintf(str, 16, "%" PRIu64, hl->hosts[i].rx_frames);
558 gtk_clist_set_text(hl->table, j, 6, str);
559 g_snprintf(str, 16, "%" PRIu64, hl->hosts[i].rx_bytes);
560 gtk_clist_set_text(hl->table, j, 7, str);
564 draw_hostlist_table_addresses(hl);
566 gtk_clist_sort(hl->table);
568 /* Allow table to redraw. */
569 gtk_clist_thaw(hl->table);
570 gtk_clist_freeze(hl->table);
574 draw_hostlist_table_data_cb(void *arg)
576 draw_hostlist_table_data(arg);
579 #if (GTK_MAJOR_VERSION >= 2)
581 copy_as_csv_cb(GtkWindow *win _U_, gpointer data)
586 GString *CSV_str = g_string_new("");
588 hostlist_table *hosts=(hostlist_table *)data;
590 /* Add the column headers to the CSV data */
591 for(i=0;i<hosts->num_columns;i++){ /* all columns */
592 if(i==1 && !hosts->has_ports) continue; /* Don't add the port column if it's empty */
593 g_string_append(CSV_str,hosts->default_titles[i]);/* add the column heading to the CSV string */
594 if(i!=hosts->num_columns-1)
595 g_string_append(CSV_str,",");
597 g_string_append(CSV_str,"\n"); /* new row */
599 /* Add the column values to the CSV data */
600 for(i=0;i<hosts->num_hosts;i++){ /* all rows */
601 for(j=0;j<hosts->num_columns;j++){ /* all columns */
602 if(j==1 && !hosts->has_ports) continue; /* Don't add the port column if it's empty */
603 gtk_clist_get_text(hosts->table,i,j,&table_entry);/* copy table item into string */
604 g_string_append(CSV_str,table_entry); /* add the table entry to the CSV string */
605 if(j!=hosts->num_columns-1)
606 g_string_append(CSV_str,",");
608 g_string_append(CSV_str,"\n"); /* new row */
611 /* Now that we have the CSV data, copy it into the default clipboard */
612 cb = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD); /* Get the default clipboard */
613 gtk_clipboard_set_text(cb, CSV_str->str, -1); /* Copy the CSV data into the clipboard */
614 g_string_free(CSV_str, TRUE); /* Free the memory */
620 init_hostlist_table_page(hostlist_table *hosttable, GtkWidget *vbox, gboolean hide_ports, const char *table_name, const char *tap_name, const char *filter, tap_packet_cb packet_func)
623 column_arrows *col_arrows;
625 GtkWidget *column_lb;
626 GString *error_string;
628 #if (GTK_MAJOR_VERSION >= 2)
630 GtkTooltips *tooltips = gtk_tooltips_new();
634 hosttable->num_columns=NUM_COLS;
635 hosttable->default_titles[0] = "Address";
636 hosttable->default_titles[1] = "Port";
637 hosttable->default_titles[2] = "Packets";
638 hosttable->default_titles[3] = "Bytes";
639 hosttable->default_titles[4] = "Tx Packets";
640 hosttable->default_titles[5] = "Tx Bytes";
641 hosttable->default_titles[6] = "Rx Packets";
642 hosttable->default_titles[7] = "Rx Bytes";
643 hosttable->has_ports=!hide_ports;
644 hosttable->num_hosts = 0;
645 hosttable->resolve_names=TRUE;
647 g_snprintf(title, 255, "%s Endpoints", table_name);
648 hosttable->page_lb = gtk_label_new(title);
649 gtk_box_pack_start(GTK_BOX(vbox), hosttable->page_lb, FALSE, FALSE, 0);
651 hosttable->scrolled_window=scrolled_window_new(NULL, NULL);
652 gtk_box_pack_start(GTK_BOX(vbox), hosttable->scrolled_window, TRUE, TRUE, 0);
654 hosttable->table=(GtkCList *)gtk_clist_new(NUM_COLS);
656 col_arrows = (column_arrows *) g_malloc(sizeof(column_arrows) * NUM_COLS);
657 win_style = gtk_widget_get_style(hosttable->scrolled_window);
658 for (i = 0; i < NUM_COLS; i++) {
659 col_arrows[i].table = gtk_table_new(2, 2, FALSE);
660 gtk_table_set_col_spacings(GTK_TABLE(col_arrows[i].table), 5);
661 column_lb = gtk_label_new(hosttable->default_titles[i]);
662 gtk_table_attach(GTK_TABLE(col_arrows[i].table), column_lb, 0, 1, 0, 2, GTK_SHRINK, GTK_SHRINK, 0, 0);
663 gtk_widget_show(column_lb);
665 col_arrows[i].ascend_pm = xpm_to_widget((const char **) clist_ascend_xpm);
666 gtk_table_attach(GTK_TABLE(col_arrows[i].table), col_arrows[i].ascend_pm, 1, 2, 1, 2, GTK_SHRINK, GTK_SHRINK, 0, 0);
667 col_arrows[i].descend_pm = xpm_to_widget((const char **) clist_descend_xpm);
668 gtk_table_attach(GTK_TABLE(col_arrows[i].table), col_arrows[i].descend_pm, 1, 2, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0);
669 /* make total frames be the default sort order */
671 gtk_widget_show(col_arrows[i].descend_pm);
673 gtk_clist_set_column_widget(GTK_CLIST(hosttable->table), i, col_arrows[i].table);
674 gtk_widget_show(col_arrows[i].table);
676 gtk_clist_column_titles_show(GTK_CLIST(hosttable->table));
678 gtk_clist_set_compare_func(hosttable->table, hostlist_sort_column);
679 gtk_clist_set_sort_column(hosttable->table, 4);
680 gtk_clist_set_sort_type(hosttable->table, GTK_SORT_DESCENDING);
682 gtk_clist_set_column_auto_resize(hosttable->table, 0, TRUE);
683 gtk_clist_set_column_auto_resize(hosttable->table, 1, TRUE);
684 gtk_clist_set_column_auto_resize(hosttable->table, 2, TRUE);
685 gtk_clist_set_column_auto_resize(hosttable->table, 3, TRUE);
686 gtk_clist_set_column_auto_resize(hosttable->table, 4, TRUE);
687 gtk_clist_set_column_auto_resize(hosttable->table, 5, TRUE);
688 gtk_clist_set_column_auto_resize(hosttable->table, 6, TRUE);
689 gtk_clist_set_column_auto_resize(hosttable->table, 7, TRUE);
691 gtk_clist_set_shadow_type(hosttable->table, GTK_SHADOW_IN);
692 gtk_clist_column_titles_show(hosttable->table);
693 gtk_container_add(GTK_CONTAINER(hosttable->scrolled_window), (GtkWidget *)hosttable->table);
695 SIGNAL_CONNECT(hosttable->table, "click-column", hostlist_click_column_cb, col_arrows);
697 hosttable->num_hosts=0;
698 hosttable->hosts=NULL;
700 /* hide srcport and dstport if we don't use ports */
702 gtk_clist_set_column_visibility(hosttable->table, 1, FALSE);
705 /* create popup menu for this table */
706 hostlist_create_popup_menu(hosttable);
708 #if (GTK_MAJOR_VERSION >= 2)
709 /* XXX - maybe we want to have a "Copy as CSV" stock button here? */
710 /*copy_bt = gtk_button_new_with_label ("Copy content to clipboard as CSV");*/
711 copy_bt = BUTTON_NEW_FROM_STOCK(GTK_STOCK_COPY);
712 gtk_tooltips_set_tip(tooltips, copy_bt,
713 "Copy all statistical values of this page to the clipboard in CSV (Comma Seperated Values) format.", NULL);
714 SIGNAL_CONNECT(copy_bt, "clicked", copy_as_csv_cb,(gpointer *) hosttable);
715 gtk_box_pack_start(GTK_BOX(vbox), copy_bt, FALSE, FALSE, 0);
718 /* register the tap and rerun the taps on the packet list */
719 error_string=register_tap_listener(tap_name, hosttable, filter, reset_hostlist_table_data_cb, packet_func, draw_hostlist_table_data_cb);
721 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, error_string->str);
722 g_string_free(error_string, TRUE);
732 init_hostlist_table(gboolean hide_ports, const char *table_name, const char *tap_name, const char *filter, tap_packet_cb packet_func)
734 hostlist_table *hosttable;
738 GtkWidget *close_bt, *help_bt;
742 hosttable=g_malloc(sizeof(hostlist_table));
744 hosttable->name=table_name;
745 g_snprintf(title, 255, "%s Endpoints: %s", table_name, cf_get_display_name(&cfile));
746 hosttable->win=window_new(GTK_WINDOW_TOPLEVEL, title);
748 gtk_window_set_default_size(GTK_WINDOW(hosttable->win), 750, 400);
750 vbox=gtk_vbox_new(FALSE, 3);
751 gtk_container_add(GTK_CONTAINER(hosttable->win), vbox);
752 gtk_container_set_border_width(GTK_CONTAINER(vbox), 12);
754 ret = init_hostlist_table_page(hosttable, vbox, hide_ports, table_name, tap_name, filter, packet_func);
761 if(topic_available(HELP_STATS_ENDPOINTS_DIALOG)) {
762 bbox = dlg_button_row_new(GTK_STOCK_CLOSE, GTK_STOCK_HELP, NULL);
764 bbox = dlg_button_row_new(GTK_STOCK_CLOSE, NULL);
766 gtk_box_pack_end(GTK_BOX(vbox), bbox, FALSE, FALSE, 0);
768 close_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_CLOSE);
769 window_set_cancel_button(hosttable->win, close_bt, window_cancel_button_cb);
771 if(topic_available(HELP_STATS_ENDPOINTS_DIALOG)) {
772 help_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_HELP);
773 SIGNAL_CONNECT(help_bt, "clicked", topic_cb, HELP_STATS_ENDPOINTS_DIALOG);
776 SIGNAL_CONNECT(hosttable->win, "delete_event", window_delete_event_cb, NULL);
777 SIGNAL_CONNECT(hosttable->win, "destroy", hostlist_win_destroy_cb, hosttable);
779 gtk_widget_show_all(hosttable->win);
780 window_present(hosttable->win);
782 cf_retap_packets(&cfile, FALSE);
784 /* Keep clist frozen to cause modifications to the clist (inserts, appends, others that are extremely slow
785 in GTK2) to not be drawn, allow refreshes to occur at strategic points for performance */
786 gtk_clist_freeze(hosttable->table);
789 /* after retapping, redraw table */
790 draw_hostlist_table_data(hosttable);
795 hostlist_win_destroy_notebook_cb(GtkWindow *win _U_, gpointer data)
797 void ** pages = data;
800 /* first "page" contains the number of pages */
801 for (page=1; page<=GPOINTER_TO_INT(pages[0]); page++) {
802 hostlist_win_destroy_cb(NULL, pages[page]);
809 static hostlist_table *
810 init_hostlist_notebook_page_cb(gboolean hide_ports, char *table_name, char *tap_name, char *filter, tap_packet_cb packet_func)
813 GtkWidget *page_vbox;
814 hostlist_table *hosttable;
816 hosttable=g_malloc(sizeof(hostlist_table));
817 hosttable->name=table_name;
818 hosttable->resolve_names=TRUE;
820 page_vbox=gtk_vbox_new(FALSE, 6);
821 hosttable->win = page_vbox;
822 gtk_container_set_border_width(GTK_CONTAINER(page_vbox), 6);
824 ret = init_hostlist_table_page(hosttable, page_vbox, hide_ports, table_name, tap_name, filter, packet_func);
835 gboolean hide_ports; /* hide TCP / UDP port columns */
836 char *table_name; /* GUI output name */
837 char *tap_name; /* internal name */
838 char *filter; /* display filter string (unused) */
839 tap_packet_cb packet_func; /* function to be called for new incoming packets */
840 } register_hostlist_t;
843 static GSList *registered_hostlist_tables = NULL;
846 register_hostlist_table(gboolean hide_ports, char *table_name, char *tap_name, char *filter, tap_packet_cb packet_func)
848 register_hostlist_t *table;
850 table = g_malloc(sizeof(register_hostlist_t));
852 table->hide_ports = hide_ports;
853 table->table_name = table_name;
854 table->tap_name = tap_name;
855 table->filter = filter;
856 table->packet_func = packet_func;
858 registered_hostlist_tables = g_slist_append(registered_hostlist_tables, table);
863 hostlist_resolve_toggle_dest(GtkWidget *widget, gpointer data)
866 void ** pages = data;
867 gboolean resolve_names;
868 hostlist_table *hosttable;
871 resolve_names = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget));
873 for (page=1; page<=GPOINTER_TO_INT(pages[0]); page++) {
874 hosttable = pages[page];
875 hosttable->resolve_names = resolve_names;
877 draw_hostlist_table_addresses(hosttable);
879 gtk_clist_thaw(hosttable->table);
880 gtk_clist_freeze(hosttable->table);
886 init_hostlist_notebook_cb(GtkWidget *w _U_, gpointer d _U_)
888 hostlist_table *hosttable;
893 GtkWidget *close_bt, *help_bt;
895 GtkWidget *resolv_cb;
900 GSList *current_table;
901 register_hostlist_t *registered;
902 GtkTooltips *tooltips = gtk_tooltips_new();
905 pages = g_malloc(sizeof(void *) * (g_slist_length(registered_hostlist_tables) + 1));
907 win=window_new(GTK_WINDOW_TOPLEVEL, "hostlist");
908 g_snprintf(title, 255, "Endpoints: %s", cf_get_display_name(&cfile));
909 gtk_window_set_title(GTK_WINDOW(win), title);
910 gtk_window_set_default_size(GTK_WINDOW(win), 750, 400);
912 vbox=gtk_vbox_new(FALSE, 6);
913 gtk_container_add(GTK_CONTAINER(win), vbox);
914 gtk_container_set_border_width(GTK_CONTAINER(vbox), 12);
916 nb = gtk_notebook_new();
917 gtk_container_add(GTK_CONTAINER(vbox), nb);
921 current_table = registered_hostlist_tables;
922 while(current_table) {
923 registered = current_table->data;
924 page_lb = gtk_label_new("");
925 hosttable = init_hostlist_notebook_page_cb(registered->hide_ports, registered->table_name, registered->tap_name,
926 registered->filter, registered->packet_func);
927 gtk_notebook_append_page(GTK_NOTEBOOK(nb), hosttable->win, page_lb);
928 hosttable->win = win;
929 hosttable->page_lb = page_lb;
930 pages[++page] = hosttable;
932 current_table = g_slist_next(current_table);
935 pages[0] = GINT_TO_POINTER(page);
937 hbox = gtk_hbox_new(FALSE, 3);
938 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
940 resolv_cb = CHECK_BUTTON_NEW_WITH_MNEMONIC("Name resolution", NULL);
941 gtk_container_add(GTK_CONTAINER(hbox), resolv_cb);
942 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(resolv_cb), TRUE);
943 gtk_tooltips_set_tip(tooltips, resolv_cb, "Show results of name resolutions rather than the \"raw\" values. "
944 "Please note: The corresponding name resolution must be enabled.", NULL);
946 SIGNAL_CONNECT(resolv_cb, "toggled", hostlist_resolve_toggle_dest, pages);
949 if(topic_available(HELP_STATS_ENDPOINTS_DIALOG)) {
950 bbox = dlg_button_row_new(GTK_STOCK_CLOSE, GTK_STOCK_HELP, NULL);
952 bbox = dlg_button_row_new(GTK_STOCK_CLOSE, NULL);
954 gtk_box_pack_end(GTK_BOX(vbox), bbox, FALSE, FALSE, 0);
956 close_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_CLOSE);
957 window_set_cancel_button(win, close_bt, window_cancel_button_cb);
959 if(topic_available(HELP_STATS_ENDPOINTS_DIALOG)) {
960 help_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_HELP);
961 SIGNAL_CONNECT(help_bt, "clicked", topic_cb, HELP_STATS_ENDPOINTS_DIALOG);
964 SIGNAL_CONNECT(win, "delete_event", window_delete_event_cb, NULL);
965 SIGNAL_CONNECT(win, "destroy", hostlist_win_destroy_notebook_cb, pages);
967 gtk_widget_show_all(win);
970 cf_retap_packets(&cfile, FALSE);
972 /* after retapping, redraw table */
973 for (page=1; page<=GPOINTER_TO_INT(pages[0]); page++) {
974 draw_hostlist_table_data(pages[page]);
981 add_hostlist_table_data(hostlist_table *hl, const address *addr, guint32 port, gboolean sender, int num_frames, int num_bytes, SAT_E sat, int port_type)
983 hostlist_talker_t *talker=NULL;
988 /* XXX should be optimized to allocate n extra entries at a time
989 instead of just one */
990 /* if we dont have any entries at all yet */
992 hl->hosts=g_malloc(sizeof(hostlist_talker_t));
994 talker=&hl->hosts[0];
999 /* try to find it among the existing known hosts */
1002 for(i=0;i<hl->num_hosts;i++){
1003 if( (!CMP_ADDRESS(&hl->hosts[i].address, addr))&&(hl->hosts[i].port==port) ){
1004 talker=&hl->hosts[i];
1011 /* if we still dont know what talker this is it has to be a new one
1012 and we have to allocate it and append it to the end of the list */
1016 hl->hosts=g_realloc(hl->hosts, hl->num_hosts*sizeof(hostlist_talker_t));
1017 talker=&hl->hosts[hl->num_hosts-1];
1018 talker_idx=hl->num_hosts-1;
1021 /* if this is a new talker we need to initialize the struct */
1023 COPY_ADDRESS(&talker->address, addr);
1025 talker->port_type=port_type;
1027 talker->rx_frames=0;
1028 talker->tx_frames=0;
1033 /* update the talker struct */
1035 talker->tx_frames+=num_frames;
1036 talker->tx_bytes+=num_bytes;
1038 talker->rx_frames+=num_frames;
1039 talker->rx_bytes+=num_bytes;
1042 /* if this was a new talker we have to create a clist row for it */
1044 char *entries[NUM_COLS];
1045 char frames[16],bytes[16],txframes[16],txbytes[16],rxframes[16],rxbytes[16];
1047 /* these values will be filled by call to draw_hostlist_table_addresses() below */
1051 g_snprintf(frames, 16, "%" PRIu64, talker->tx_frames+talker->rx_frames);
1053 g_snprintf(bytes, 16, "%" PRIu64, talker->tx_bytes+talker->rx_bytes);
1056 g_snprintf(txframes, 16, "%" PRIu64, talker->tx_frames);
1057 entries[4]=txframes;
1058 g_snprintf(txbytes, 16, "%" PRIu64, talker->tx_bytes);
1061 g_snprintf(rxframes, 16, "%" PRIu64, talker->rx_frames);
1062 entries[6]=rxframes;
1063 g_snprintf(rxbytes, 16, "%" PRIu64, talker->rx_bytes);
1066 gtk_clist_insert(hl->table, talker_idx, entries);
1067 gtk_clist_set_row_data(hl->table, talker_idx, (gpointer) talker_idx);
1069 draw_hostlist_table_address(hl, talker_idx);