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 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
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){
126 switch(specific_addr_type){
128 return "jxta.message.address";
148 g_assert_not_reached();
153 typedef struct column_arrows {
155 GtkWidget *ascend_pm;
156 GtkWidget *descend_pm;
161 reset_hostlist_table_data(hostlist_table *hosts)
166 /* Allow clist to update */
167 gtk_clist_thaw(hosts->table);
170 g_snprintf(title, 255, "Endpoints: %s", cf_get_display_name(&cfile));
171 gtk_window_set_title(GTK_WINDOW(hosts->win), title);
172 g_snprintf(title, 255, "%s", hosts->name);
173 gtk_label_set_text(GTK_LABEL(hosts->page_lb), title);
174 gtk_widget_set_sensitive(hosts->page_lb, FALSE);
176 g_snprintf(title, 255, "%s Endpoints: %s", hosts->name, cf_get_display_name(&cfile));
177 gtk_window_set_title(GTK_WINDOW(hosts->win), title);
180 /* remove all entries from the clist */
181 gtk_clist_clear(hosts->table);
183 /* delete all hosts */
184 for(i=0;i<hosts->num_hosts;i++){
185 g_free((gpointer)hosts->hosts[i].address.data);
187 g_free(hosts->hosts);
193 reset_hostlist_table_data_cb(void *arg)
195 reset_hostlist_table_data(arg);
198 void protect_thread_critical_region(void);
199 void unprotect_thread_critical_region(void);
201 hostlist_win_destroy_cb(GtkWindow *win _U_, gpointer data)
203 hostlist_table *hosts=(hostlist_table *)data;
205 protect_thread_critical_region();
206 remove_tap_listener(hosts);
207 unprotect_thread_critical_region();
209 reset_hostlist_table_data(hosts);
214 hostlist_sort_column(GtkCList *clist, gconstpointer ptr1, gconstpointer ptr2)
220 const GtkCListRow *row1 = ptr1;
221 const GtkCListRow *row2 = ptr2;
223 text1 = GTK_CELL_TEXT (row1->cell[clist->sort_column])->text;
224 text2 = GTK_CELL_TEXT (row2->cell[clist->sort_column])->text;
226 switch(clist->sort_column){
227 case 0: /* Address */
229 return strcmp (text1, text2);
230 case 2: /* Packets */
232 case 4: /* Tx Packets */
233 case 5: /* Tx Bytes */
234 case 6: /* Rx Packets */
235 case 7: /* Rx Bytes */
236 sscanf(text1, "%" PRIu64, &i1);
237 sscanf(text2, "%" PRIu64, &i2);
238 /* XXX - this might cause trouble because of overflow problems */
239 /* XXX - is this correct anyway? Subtracting two unsigned values will still be an unsigned value, which will never become negative */
240 return (gint) (i1-i2);
242 g_assert_not_reached();
244 /* Allow clist to redraw */
246 gtk_clist_thaw(clist);
247 gtk_clist_freeze(clist);
253 hostlist_click_column_cb(GtkCList *clist, gint column, gpointer data)
255 column_arrows *col_arrows = (column_arrows *) data;
258 for (i = 0; i < NUM_COLS; i++) {
259 gtk_widget_hide(col_arrows[i].ascend_pm);
260 gtk_widget_hide(col_arrows[i].descend_pm);
263 if (column == clist->sort_column) {
264 if (clist->sort_type == GTK_SORT_ASCENDING) {
265 clist->sort_type = GTK_SORT_DESCENDING;
266 gtk_widget_show(col_arrows[column].descend_pm);
268 clist->sort_type = GTK_SORT_ASCENDING;
269 gtk_widget_show(col_arrows[column].ascend_pm);
272 clist->sort_type = GTK_SORT_DESCENDING;
273 gtk_widget_show(col_arrows[column].descend_pm);
274 gtk_clist_set_sort_column(clist, column);
277 gtk_clist_sort(clist);
279 /* Allow update of clist */
280 gtk_clist_thaw(clist);
281 gtk_clist_freeze(clist);
285 /* action is encoded as
286 filter_action*256+filter_type
294 5: Colorize Host Traffic
304 hostlist_select_filter_cb(GtkWidget *widget _U_, gpointer callback_data, guint callback_action)
308 hostlist_table *hl=(hostlist_table *)callback_data;
311 const char *current_filter;
314 action = (callback_action>>8)&0xff;
315 type = callback_action&0xff;
317 selection=GPOINTER_TO_INT(g_list_nth_data(GTK_CLIST(hl->table)->selection, 0));
318 if(selection>=(int)hl->num_hosts){
319 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "No hostlist selected");
322 /* translate it back from row index to index in hostlist array */
323 selection=GPOINTER_TO_INT(gtk_clist_get_row_data(hl->table, selection));
325 sport=hostlist_port_to_str(hl->hosts[selection].port_type, hl->hosts[selection].port);
327 g_snprintf(dirstr, 127, "%s==%s %s%s%s%s",
328 hostlist_get_filter_name(&hl->hosts[selection].address,
329 hl->hosts[selection].sat, hl->hosts[selection].port_type, FN_ANY_ADDRESS),
330 address_to_str(&hl->hosts[selection].address),
332 sport?hostlist_get_filter_name(&hl->hosts[selection].address, hl->hosts[selection].sat, hl->hosts[selection].port_type, FN_ANY_PORT):"",
336 current_filter=gtk_entry_get_text(GTK_ENTRY(main_display_filter_widget));
340 g_snprintf(str, 255, "%s", dirstr);
344 g_snprintf(str, 255, "!(%s)", dirstr);
348 g_snprintf(str, 255, "(%s) && (%s)", current_filter, dirstr);
352 g_snprintf(str, 255, "(%s) || (%s)", current_filter, dirstr);
355 /* and not selected */
356 g_snprintf(str, 255, "(%s) && !(%s)", current_filter, dirstr);
359 /* or not selected */
360 g_snprintf(str, 255, "(%s) || !(%s)", current_filter, dirstr);
367 gtk_entry_set_text(GTK_ENTRY(main_display_filter_widget), str);
368 main_filter_packets(&cfile, str, FALSE);
369 gdk_window_raise(top_level->window);
373 gtk_entry_set_text(GTK_ENTRY(main_display_filter_widget), str);
377 find_frame_with_filter(str);
381 find_previous_next_frame_with_filter(str, FALSE);
385 find_previous_next_frame_with_filter(str, TRUE);
388 /* colorize host traffic */
389 color_display_with_filter(str);
394 hostlist_show_popup_menu_cb(void *widg _U_, GdkEvent *event, hostlist_table *et)
396 GdkEventButton *bevent = (GdkEventButton *)event;
400 /* To qoute the "Gdk Event Structures" doc:
401 * "Normally button 1 is the left mouse button, 2 is the middle button, and 3 is the right button" */
402 if(event->type==GDK_BUTTON_PRESS && bevent->button==3){
403 /* if this is a right click on one of our columns, select it and popup the context menu */
404 if(gtk_clist_get_selection_info(et->table,
405 (gint) (((GdkEventButton *)event)->x),
406 (gint) (((GdkEventButton *)event)->y),
408 gtk_clist_unselect_all(et->table);
409 gtk_clist_select_row(et->table, row, -1);
411 gtk_menu_popup(GTK_MENU(et->menu), NULL, NULL, NULL, NULL,
412 bevent->button, bevent->time);
419 static GtkItemFactoryEntry hostlist_list_menu_items[] =
422 ITEM_FACTORY_ENTRY("/Apply as Filter", NULL, NULL, 0, "<Branch>", NULL),
423 ITEM_FACTORY_ENTRY("/Apply as Filter/Selected", NULL,
424 hostlist_select_filter_cb, 0*256+0, NULL, NULL),
425 ITEM_FACTORY_ENTRY("/Apply as Filter/Not Selected", NULL,
426 hostlist_select_filter_cb, 0*256+1, NULL, NULL),
427 ITEM_FACTORY_ENTRY("/Apply as Filter/... and Selected", NULL,
428 hostlist_select_filter_cb, 0*256+2, NULL, NULL),
429 ITEM_FACTORY_ENTRY("/Apply as Filter/... or Selected", NULL,
430 hostlist_select_filter_cb, 0*256+3, NULL, NULL),
431 ITEM_FACTORY_ENTRY("/Apply as Filter/... and not Selected", NULL,
432 hostlist_select_filter_cb, 0*256+4, NULL, NULL),
433 ITEM_FACTORY_ENTRY("/Apply as Filter/... or not Selected", NULL,
434 hostlist_select_filter_cb, 0*256+5, NULL, NULL),
437 ITEM_FACTORY_ENTRY("/Prepare a Filter", NULL, NULL, 0, "<Branch>", NULL),
438 ITEM_FACTORY_ENTRY("/Prepare a Filter/Selected", NULL,
439 hostlist_select_filter_cb, 1*256+0, NULL, NULL),
440 ITEM_FACTORY_ENTRY("/Prepare a Filter/Not Selected", NULL,
441 hostlist_select_filter_cb, 1*256+1, NULL, NULL),
442 ITEM_FACTORY_ENTRY("/Prepare a Filter/... and Selected", NULL,
443 hostlist_select_filter_cb, 1*256+2, NULL, NULL),
444 ITEM_FACTORY_ENTRY("/Prepare a Filter/... or Selected", NULL,
445 hostlist_select_filter_cb, 1*256+3, NULL, NULL),
446 ITEM_FACTORY_ENTRY("/Prepare a Filter/... and not Selected", NULL,
447 hostlist_select_filter_cb, 1*256+4, NULL, NULL),
448 ITEM_FACTORY_ENTRY("/Prepare a Filter/... or not Selected", NULL,
449 hostlist_select_filter_cb, 1*256+5, NULL, NULL),
452 ITEM_FACTORY_ENTRY("/Find Frame", NULL, NULL, 0, "<Branch>", NULL),
453 ITEM_FACTORY_ENTRY("/Find Frame/Find Frame", NULL,
454 hostlist_select_filter_cb, 2*256+0, NULL, NULL),
456 ITEM_FACTORY_ENTRY("/Find Frame/Find Next", NULL,
457 hostlist_select_filter_cb, 3*256+0, NULL, NULL),
459 ITEM_FACTORY_ENTRY("/Find Frame/Find Previous", NULL,
460 hostlist_select_filter_cb, 4*256+0, NULL, NULL),
461 /* Colorize Host Traffic */
462 ITEM_FACTORY_ENTRY("/Colorize Host Traffic", NULL,
463 hostlist_select_filter_cb, 5*256+0, NULL, NULL),
468 hostlist_create_popup_menu(hostlist_table *hl)
470 GtkItemFactory *item_factory;
472 item_factory = gtk_item_factory_new(GTK_TYPE_MENU, "<main>", NULL);
474 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);
476 hl->menu = gtk_item_factory_get_widget(item_factory, "<main>");
477 SIGNAL_CONNECT(hl->table, "button_press_event", hostlist_show_popup_menu_cb, hl);
481 /* Draw/refresh the address field of a single entry at the specified index */
483 draw_hostlist_table_address(hostlist_table *hl, int hostlist_idx)
490 rownum=gtk_clist_find_row_from_data(hl->table, (gpointer)hostlist_idx);
492 if (!hl->resolve_names)
493 entry=address_to_str(&hl->hosts[hostlist_idx].address);
495 entry=get_addr_name(&hl->hosts[hostlist_idx].address);
497 gtk_clist_set_text(hl->table, rownum, 0, entry);
499 pt = hl->hosts[hostlist_idx].port_type;
500 if(!hl->resolve_names) pt = PT_NONE;
503 entry=get_tcp_port(hl->hosts[hostlist_idx].port);
506 entry=get_udp_port(hl->hosts[hostlist_idx].port);
509 port=hostlist_port_to_str(hl->hosts[hostlist_idx].port_type, hl->hosts[hostlist_idx].port);
512 gtk_clist_set_text(hl->table, rownum, 1, entry);
515 /* Refresh the address fields of all entries in the list */
517 draw_hostlist_table_addresses(hostlist_table *hl)
521 for(i=0;i<hl->num_hosts;i++){
522 draw_hostlist_table_address(hl, i);
528 draw_hostlist_table_data(hostlist_table *hl)
536 g_snprintf(title, 255, "%s: %u", hl->name, hl->num_hosts);
538 g_snprintf(title, 255, "%s", hl->name);
540 gtk_label_set_text(GTK_LABEL(hl->page_lb), title);
541 gtk_widget_set_sensitive(hl->page_lb, hl->num_hosts);
544 for(i=0;i<hl->num_hosts;i++){
547 j=gtk_clist_find_row_from_data(hl->table, (gpointer)i);
549 g_snprintf(str, 16, "%" PRIu64, hl->hosts[i].tx_frames+hl->hosts[i].rx_frames);
550 gtk_clist_set_text(hl->table, j, 2, str);
551 g_snprintf(str, 16, "%" PRIu64, hl->hosts[i].tx_bytes+hl->hosts[i].rx_bytes);
552 gtk_clist_set_text(hl->table, j, 3, str);
555 g_snprintf(str, 16, "%" PRIu64, hl->hosts[i].tx_frames);
556 gtk_clist_set_text(hl->table, j, 4, str);
557 g_snprintf(str, 16, "%" PRIu64, hl->hosts[i].tx_bytes);
558 gtk_clist_set_text(hl->table, j, 5, str);
561 g_snprintf(str, 16, "%" PRIu64, hl->hosts[i].rx_frames);
562 gtk_clist_set_text(hl->table, j, 6, str);
563 g_snprintf(str, 16, "%" PRIu64, hl->hosts[i].rx_bytes);
564 gtk_clist_set_text(hl->table, j, 7, str);
568 draw_hostlist_table_addresses(hl);
570 gtk_clist_sort(hl->table);
572 /* Allow table to redraw. */
573 gtk_clist_thaw(hl->table);
574 gtk_clist_freeze(hl->table);
578 draw_hostlist_table_data_cb(void *arg)
580 draw_hostlist_table_data(arg);
583 #if (GTK_MAJOR_VERSION >= 2)
585 copy_as_csv_cb(GtkWindow *win _U_, gpointer data)
590 GString *CSV_str = g_string_new("");
592 hostlist_table *hosts=(hostlist_table *)data;
594 /* Add the column headers to the CSV data */
595 for(i=0;i<hosts->num_columns;i++){ /* all columns */
596 if(i==1 && !hosts->has_ports) continue; /* Don't add the port column if it's empty */
597 g_string_append(CSV_str,hosts->default_titles[i]);/* add the column heading to the CSV string */
598 if(i!=hosts->num_columns-1)
599 g_string_append(CSV_str,",");
601 g_string_append(CSV_str,"\n"); /* new row */
603 /* Add the column values to the CSV data */
604 for(i=0;i<hosts->num_hosts;i++){ /* all rows */
605 for(j=0;j<hosts->num_columns;j++){ /* all columns */
606 if(j==1 && !hosts->has_ports) continue; /* Don't add the port column if it's empty */
607 gtk_clist_get_text(hosts->table,i,j,&table_entry);/* copy table item into string */
608 g_string_append(CSV_str,table_entry); /* add the table entry to the CSV string */
609 if(j!=hosts->num_columns-1)
610 g_string_append(CSV_str,",");
612 g_string_append(CSV_str,"\n"); /* new row */
615 /* Now that we have the CSV data, copy it into the default clipboard */
616 cb = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD); /* Get the default clipboard */
617 gtk_clipboard_set_text(cb, CSV_str->str, -1); /* Copy the CSV data into the clipboard */
618 g_string_free(CSV_str, TRUE); /* Free the memory */
624 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)
627 column_arrows *col_arrows;
629 GtkWidget *column_lb;
630 GString *error_string;
632 #if (GTK_MAJOR_VERSION >= 2)
634 GtkTooltips *tooltips = gtk_tooltips_new();
638 hosttable->num_columns=NUM_COLS;
639 hosttable->default_titles[0] = "Address";
640 hosttable->default_titles[1] = "Port";
641 hosttable->default_titles[2] = "Packets";
642 hosttable->default_titles[3] = "Bytes";
643 hosttable->default_titles[4] = "Tx Packets";
644 hosttable->default_titles[5] = "Tx Bytes";
645 hosttable->default_titles[6] = "Rx Packets";
646 hosttable->default_titles[7] = "Rx Bytes";
647 hosttable->has_ports=!hide_ports;
648 hosttable->num_hosts = 0;
649 hosttable->resolve_names=TRUE;
651 g_snprintf(title, 255, "%s Endpoints", table_name);
652 hosttable->page_lb = gtk_label_new(title);
653 gtk_box_pack_start(GTK_BOX(vbox), hosttable->page_lb, FALSE, FALSE, 0);
655 hosttable->scrolled_window=scrolled_window_new(NULL, NULL);
656 gtk_box_pack_start(GTK_BOX(vbox), hosttable->scrolled_window, TRUE, TRUE, 0);
658 hosttable->table=(GtkCList *)gtk_clist_new(NUM_COLS);
660 col_arrows = (column_arrows *) g_malloc(sizeof(column_arrows) * NUM_COLS);
661 win_style = gtk_widget_get_style(hosttable->scrolled_window);
662 for (i = 0; i < NUM_COLS; i++) {
663 col_arrows[i].table = gtk_table_new(2, 2, FALSE);
664 gtk_table_set_col_spacings(GTK_TABLE(col_arrows[i].table), 5);
665 column_lb = gtk_label_new(hosttable->default_titles[i]);
666 gtk_table_attach(GTK_TABLE(col_arrows[i].table), column_lb, 0, 1, 0, 2, GTK_SHRINK, GTK_SHRINK, 0, 0);
667 gtk_widget_show(column_lb);
669 col_arrows[i].ascend_pm = xpm_to_widget((const char **) clist_ascend_xpm);
670 gtk_table_attach(GTK_TABLE(col_arrows[i].table), col_arrows[i].ascend_pm, 1, 2, 1, 2, GTK_SHRINK, GTK_SHRINK, 0, 0);
671 col_arrows[i].descend_pm = xpm_to_widget((const char **) clist_descend_xpm);
672 gtk_table_attach(GTK_TABLE(col_arrows[i].table), col_arrows[i].descend_pm, 1, 2, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0);
673 /* make total frames be the default sort order */
675 gtk_widget_show(col_arrows[i].descend_pm);
677 gtk_clist_set_column_widget(GTK_CLIST(hosttable->table), i, col_arrows[i].table);
678 gtk_widget_show(col_arrows[i].table);
680 gtk_clist_column_titles_show(GTK_CLIST(hosttable->table));
682 gtk_clist_set_compare_func(hosttable->table, hostlist_sort_column);
683 gtk_clist_set_sort_column(hosttable->table, 4);
684 gtk_clist_set_sort_type(hosttable->table, GTK_SORT_DESCENDING);
686 gtk_clist_set_column_auto_resize(hosttable->table, 0, TRUE);
687 gtk_clist_set_column_auto_resize(hosttable->table, 1, TRUE);
688 gtk_clist_set_column_auto_resize(hosttable->table, 2, TRUE);
689 gtk_clist_set_column_auto_resize(hosttable->table, 3, TRUE);
690 gtk_clist_set_column_auto_resize(hosttable->table, 4, TRUE);
691 gtk_clist_set_column_auto_resize(hosttable->table, 5, TRUE);
692 gtk_clist_set_column_auto_resize(hosttable->table, 6, TRUE);
693 gtk_clist_set_column_auto_resize(hosttable->table, 7, TRUE);
695 gtk_clist_set_shadow_type(hosttable->table, GTK_SHADOW_IN);
696 gtk_clist_column_titles_show(hosttable->table);
697 gtk_container_add(GTK_CONTAINER(hosttable->scrolled_window), (GtkWidget *)hosttable->table);
699 SIGNAL_CONNECT(hosttable->table, "click-column", hostlist_click_column_cb, col_arrows);
701 hosttable->num_hosts=0;
702 hosttable->hosts=NULL;
704 /* hide srcport and dstport if we don't use ports */
706 gtk_clist_set_column_visibility(hosttable->table, 1, FALSE);
709 /* create popup menu for this table */
710 hostlist_create_popup_menu(hosttable);
712 #if (GTK_MAJOR_VERSION >= 2)
713 /* XXX - maybe we want to have a "Copy as CSV" stock button here? */
714 /*copy_bt = gtk_button_new_with_label ("Copy content to clipboard as CSV");*/
715 copy_bt = BUTTON_NEW_FROM_STOCK(GTK_STOCK_COPY);
716 gtk_tooltips_set_tip(tooltips, copy_bt,
717 "Copy all statistical values of this page to the clipboard in CSV (Comma Seperated Values) format.", NULL);
718 SIGNAL_CONNECT(copy_bt, "clicked", copy_as_csv_cb,(gpointer *) hosttable);
719 gtk_box_pack_start(GTK_BOX(vbox), copy_bt, FALSE, FALSE, 0);
722 /* register the tap and rerun the taps on the packet list */
723 error_string=register_tap_listener(tap_name, hosttable, filter, reset_hostlist_table_data_cb, packet_func, draw_hostlist_table_data_cb);
725 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, error_string->str);
726 g_string_free(error_string, TRUE);
736 init_hostlist_table(gboolean hide_ports, const char *table_name, const char *tap_name, const char *filter, tap_packet_cb packet_func)
738 hostlist_table *hosttable;
742 GtkWidget *close_bt, *help_bt;
746 hosttable=g_malloc(sizeof(hostlist_table));
748 hosttable->name=table_name;
749 g_snprintf(title, 255, "%s Endpoints: %s", table_name, cf_get_display_name(&cfile));
750 hosttable->win=window_new(GTK_WINDOW_TOPLEVEL, title);
752 gtk_window_set_default_size(GTK_WINDOW(hosttable->win), 750, 400);
754 vbox=gtk_vbox_new(FALSE, 3);
755 gtk_container_add(GTK_CONTAINER(hosttable->win), vbox);
756 gtk_container_set_border_width(GTK_CONTAINER(vbox), 12);
758 ret = init_hostlist_table_page(hosttable, vbox, hide_ports, table_name, tap_name, filter, packet_func);
765 if(topic_available(HELP_STATS_ENDPOINTS_DIALOG)) {
766 bbox = dlg_button_row_new(GTK_STOCK_CLOSE, GTK_STOCK_HELP, NULL);
768 bbox = dlg_button_row_new(GTK_STOCK_CLOSE, NULL);
770 gtk_box_pack_end(GTK_BOX(vbox), bbox, FALSE, FALSE, 0);
772 close_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_CLOSE);
773 window_set_cancel_button(hosttable->win, close_bt, window_cancel_button_cb);
775 if(topic_available(HELP_STATS_ENDPOINTS_DIALOG)) {
776 help_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_HELP);
777 SIGNAL_CONNECT(help_bt, "clicked", topic_cb, HELP_STATS_ENDPOINTS_DIALOG);
780 SIGNAL_CONNECT(hosttable->win, "delete_event", window_delete_event_cb, NULL);
781 SIGNAL_CONNECT(hosttable->win, "destroy", hostlist_win_destroy_cb, hosttable);
783 gtk_widget_show_all(hosttable->win);
784 window_present(hosttable->win);
786 cf_retap_packets(&cfile, FALSE);
788 /* Keep clist frozen to cause modifications to the clist (inserts, appends, others that are extremely slow
789 in GTK2) to not be drawn, allow refreshes to occur at strategic points for performance */
790 gtk_clist_freeze(hosttable->table);
793 /* after retapping, redraw table */
794 draw_hostlist_table_data(hosttable);
799 hostlist_win_destroy_notebook_cb(GtkWindow *win _U_, gpointer data)
801 void ** pages = data;
804 /* first "page" contains the number of pages */
805 for (page=1; page<=GPOINTER_TO_INT(pages[0]); page++) {
806 hostlist_win_destroy_cb(NULL, pages[page]);
813 static hostlist_table *
814 init_hostlist_notebook_page_cb(gboolean hide_ports, char *table_name, char *tap_name, char *filter, tap_packet_cb packet_func)
817 GtkWidget *page_vbox;
818 hostlist_table *hosttable;
820 hosttable=g_malloc(sizeof(hostlist_table));
821 hosttable->name=table_name;
822 hosttable->resolve_names=TRUE;
824 page_vbox=gtk_vbox_new(FALSE, 6);
825 hosttable->win = page_vbox;
826 gtk_container_set_border_width(GTK_CONTAINER(page_vbox), 6);
828 ret = init_hostlist_table_page(hosttable, page_vbox, hide_ports, table_name, tap_name, filter, packet_func);
839 gboolean hide_ports; /* hide TCP / UDP port columns */
840 char *table_name; /* GUI output name */
841 char *tap_name; /* internal name */
842 char *filter; /* display filter string (unused) */
843 tap_packet_cb packet_func; /* function to be called for new incoming packets */
844 } register_hostlist_t;
847 static GSList *registered_hostlist_tables = NULL;
850 register_hostlist_table(gboolean hide_ports, char *table_name, char *tap_name, char *filter, tap_packet_cb packet_func)
852 register_hostlist_t *table;
854 table = g_malloc(sizeof(register_hostlist_t));
856 table->hide_ports = hide_ports;
857 table->table_name = table_name;
858 table->tap_name = tap_name;
859 table->filter = filter;
860 table->packet_func = packet_func;
862 registered_hostlist_tables = g_slist_append(registered_hostlist_tables, table);
867 hostlist_resolve_toggle_dest(GtkWidget *widget, gpointer data)
870 void ** pages = data;
871 gboolean resolve_names;
872 hostlist_table *hosttable;
875 resolve_names = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget));
877 for (page=1; page<=GPOINTER_TO_INT(pages[0]); page++) {
878 hosttable = pages[page];
879 hosttable->resolve_names = resolve_names;
881 draw_hostlist_table_addresses(hosttable);
883 gtk_clist_thaw(hosttable->table);
884 gtk_clist_freeze(hosttable->table);
890 init_hostlist_notebook_cb(GtkWidget *w _U_, gpointer d _U_)
892 hostlist_table *hosttable;
897 GtkWidget *close_bt, *help_bt;
899 GtkWidget *resolv_cb;
904 GSList *current_table;
905 register_hostlist_t *registered;
906 GtkTooltips *tooltips = gtk_tooltips_new();
909 pages = g_malloc(sizeof(void *) * (g_slist_length(registered_hostlist_tables) + 1));
911 win=window_new(GTK_WINDOW_TOPLEVEL, "hostlist");
912 g_snprintf(title, 255, "Endpoints: %s", cf_get_display_name(&cfile));
913 gtk_window_set_title(GTK_WINDOW(win), title);
914 gtk_window_set_default_size(GTK_WINDOW(win), 750, 400);
916 vbox=gtk_vbox_new(FALSE, 6);
917 gtk_container_add(GTK_CONTAINER(win), vbox);
918 gtk_container_set_border_width(GTK_CONTAINER(vbox), 12);
920 nb = gtk_notebook_new();
921 gtk_container_add(GTK_CONTAINER(vbox), nb);
925 current_table = registered_hostlist_tables;
926 while(current_table) {
927 registered = current_table->data;
928 page_lb = gtk_label_new("");
929 hosttable = init_hostlist_notebook_page_cb(registered->hide_ports, registered->table_name, registered->tap_name,
930 registered->filter, registered->packet_func);
931 gtk_notebook_append_page(GTK_NOTEBOOK(nb), hosttable->win, page_lb);
932 hosttable->win = win;
933 hosttable->page_lb = page_lb;
934 pages[++page] = hosttable;
936 current_table = g_slist_next(current_table);
939 pages[0] = GINT_TO_POINTER(page);
941 hbox = gtk_hbox_new(FALSE, 3);
942 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
944 resolv_cb = CHECK_BUTTON_NEW_WITH_MNEMONIC("Name resolution", NULL);
945 gtk_container_add(GTK_CONTAINER(hbox), resolv_cb);
946 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(resolv_cb), TRUE);
947 gtk_tooltips_set_tip(tooltips, resolv_cb, "Show results of name resolutions rather than the \"raw\" values. "
948 "Please note: The corresponding name resolution must be enabled.", NULL);
950 SIGNAL_CONNECT(resolv_cb, "toggled", hostlist_resolve_toggle_dest, pages);
953 if(topic_available(HELP_STATS_ENDPOINTS_DIALOG)) {
954 bbox = dlg_button_row_new(GTK_STOCK_CLOSE, GTK_STOCK_HELP, NULL);
956 bbox = dlg_button_row_new(GTK_STOCK_CLOSE, NULL);
958 gtk_box_pack_end(GTK_BOX(vbox), bbox, FALSE, FALSE, 0);
960 close_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_CLOSE);
961 window_set_cancel_button(win, close_bt, window_cancel_button_cb);
963 if(topic_available(HELP_STATS_ENDPOINTS_DIALOG)) {
964 help_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_HELP);
965 SIGNAL_CONNECT(help_bt, "clicked", topic_cb, HELP_STATS_ENDPOINTS_DIALOG);
968 SIGNAL_CONNECT(win, "delete_event", window_delete_event_cb, NULL);
969 SIGNAL_CONNECT(win, "destroy", hostlist_win_destroy_notebook_cb, pages);
971 gtk_widget_show_all(win);
974 cf_retap_packets(&cfile, FALSE);
976 /* after retapping, redraw table */
977 for (page=1; page<=GPOINTER_TO_INT(pages[0]); page++) {
978 draw_hostlist_table_data(pages[page]);
985 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)
987 hostlist_talker_t *talker=NULL;
992 /* XXX should be optimized to allocate n extra entries at a time
993 instead of just one */
994 /* if we dont have any entries at all yet */
996 hl->hosts=g_malloc(sizeof(hostlist_talker_t));
998 talker=&hl->hosts[0];
1003 /* try to find it among the existing known hosts */
1006 for(i=0;i<hl->num_hosts;i++){
1007 if( (!CMP_ADDRESS(&hl->hosts[i].address, addr))&&(hl->hosts[i].port==port) ){
1008 talker=&hl->hosts[i];
1015 /* if we still dont know what talker this is it has to be a new one
1016 and we have to allocate it and append it to the end of the list */
1020 hl->hosts=g_realloc(hl->hosts, hl->num_hosts*sizeof(hostlist_talker_t));
1021 talker=&hl->hosts[hl->num_hosts-1];
1022 talker_idx=hl->num_hosts-1;
1025 /* if this is a new talker we need to initialize the struct */
1027 COPY_ADDRESS(&talker->address, addr);
1029 talker->port_type=port_type;
1031 talker->rx_frames=0;
1032 talker->tx_frames=0;
1037 /* update the talker struct */
1039 talker->tx_frames+=num_frames;
1040 talker->tx_bytes+=num_bytes;
1042 talker->rx_frames+=num_frames;
1043 talker->rx_bytes+=num_bytes;
1046 /* if this was a new talker we have to create a clist row for it */
1048 char *entries[NUM_COLS];
1049 char frames[16],bytes[16],txframes[16],txbytes[16],rxframes[16],rxbytes[16];
1051 /* these values will be filled by call to draw_hostlist_table_addresses() below */
1055 g_snprintf(frames, 16, "%" PRIu64, talker->tx_frames+talker->rx_frames);
1057 g_snprintf(bytes, 16, "%" PRIu64, talker->tx_bytes+talker->rx_bytes);
1060 g_snprintf(txframes, 16, "%" PRIu64, talker->tx_frames);
1061 entries[4]=txframes;
1062 g_snprintf(txbytes, 16, "%" PRIu64, talker->tx_bytes);
1065 g_snprintf(rxframes, 16, "%" PRIu64, talker->rx_frames);
1066 entries[6]=rxframes;
1067 g_snprintf(rxbytes, 16, "%" PRIu64, talker->rx_bytes);
1070 gtk_clist_insert(hl->table, talker_idx, entries);
1071 gtk_clist_set_row_data(hl->table, talker_idx, (gpointer) talker_idx);
1073 draw_hostlist_table_address(hl, talker_idx);