From dfb104544f3eba323167b74a8fbe058455cc2a70 Mon Sep 17 00:00:00 2001 From: Gerald Combs Date: Tue, 20 Nov 2007 18:35:41 +0000 Subject: [PATCH] Add relative start time, duration, and average data rate (bps) columns to the conversation lists. Move the "copy" button down to the button bar in order to free up some real estate. Add an nstime_cmp() function. Clean up code in a few places. svn path=/trunk/; revision=23516 --- epan/libwireshark.def | 1 + epan/nstime.c | 39 +++++- epan/nstime.h | 8 ++ gtk/conversations_eth.c | 2 +- gtk/conversations_fc.c | 2 +- gtk/conversations_fddi.c | 2 +- gtk/conversations_ip.c | 2 +- gtk/conversations_ipx.c | 2 +- gtk/conversations_jxta.c | 19 +-- gtk/conversations_ncp.c | 2 +- gtk/conversations_rsvp.c | 10 +- gtk/conversations_sctp.c | 17 +-- gtk/conversations_table.c | 260 +++++++++++++++++++++++++++++--------- gtk/conversations_table.h | 39 +++--- gtk/conversations_tcpip.c | 2 +- gtk/conversations_tr.c | 2 +- gtk/conversations_udpip.c | 2 +- gtk/conversations_usb.c | 2 +- gtk/conversations_wlan.c | 2 +- gtk/dlg_utils.c | 30 +++-- 20 files changed, 317 insertions(+), 128 deletions(-) diff --git a/epan/libwireshark.def b/epan/libwireshark.def index 74bb1b4ab9..7b55ca4547 100644 --- a/epan/libwireshark.def +++ b/epan/libwireshark.def @@ -514,6 +514,7 @@ mtp3_service_indicator_code_short_vals DATA new_create_dissector_handle new_register_dissector npf_sys_is_running +nstime_cmp nstime_delta nstime_is_unset nstime_is_zero diff --git a/epan/nstime.c b/epan/nstime.c index e1b27f6759..b913947bdf 100644 --- a/epan/nstime.c +++ b/epan/nstime.c @@ -2,7 +2,7 @@ * Routines for manipulating nstime_t structures * * Copyright (c) 2005 MX Telecom Ltd. - * + * * $Id$ * * Wireshark - Network traffic analyzer @@ -13,12 +13,12 @@ * 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. @@ -127,7 +127,24 @@ void nstime_sum(nstime_t *sum, const nstime_t *a, const nstime_t *b) } else if(sum->nsecs<=-NS_PER_S || (sum->nsecs<0 && sum->secs>0)) { sum->nsecs+=NS_PER_S; sum->secs--; - } + } +} + +/* + * function: nstime_cmp + * + * a > b : > 0 + * a = b : 0 + * a < b : < 0 + */ + +int nstime_cmp (nstime_t *a, const nstime_t *b ) +{ + if (a->secs == b->secs) { + return a->nsecs - b->nsecs; + } else { + return (int) (a->secs - b->secs); + } } /* @@ -159,3 +176,17 @@ double wtap_nstime_to_sec(const struct wtap_nstime *time) { return ((double)time->secs + (double)time->nsecs/1000000000); } + +/* + * Editor modelines + * + * Local Variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * ex: set shiftwidth=4 tabstop=8 expandtab + * :indentSize=4:tabSize=8:noTabs=true: + */ + diff --git a/epan/nstime.h b/epan/nstime.h index 853e3adc9c..ea97ea5924 100644 --- a/epan/nstime.h +++ b/epan/nstime.h @@ -72,6 +72,14 @@ extern void nstime_sum(nstime_t *sum, const nstime_t *b, const nstime_t *a ); /* sum += a */ #define nstime_add(sum, a) nstime_sum(sum, sum, a) +/* compare two times are return a value similar to memcmp() or strcmp(). + * + * a > b : > 0 + * a = b : 0 + * a < b : < 0 + */ +extern int nstime_cmp(nstime_t *a, const nstime_t *b ); + /* converts nstime to double, time base is milli seconds */ extern double nstime_to_msec(const nstime_t *time); diff --git a/gtk/conversations_eth.c b/gtk/conversations_eth.c index f8a690d5ab..d25c5e2994 100644 --- a/gtk/conversations_eth.c +++ b/gtk/conversations_eth.c @@ -47,7 +47,7 @@ eth_conversation_packet(void *pct, packet_info *pinfo, epan_dissect_t *edt _U_, { const eth_hdr *ehdr=vip; - add_conversation_table_data((conversations_table *)pct, &ehdr->src, &ehdr->dst, 0, 0, 1, pinfo->fd->pkt_len, SAT_ETHER, PT_NONE); + add_conversation_table_data((conversations_table *)pct, &ehdr->src, &ehdr->dst, 0, 0, 1, pinfo->fd->pkt_len, &pinfo->fd->rel_ts, SAT_ETHER, PT_NONE); return 1; } diff --git a/gtk/conversations_fc.c b/gtk/conversations_fc.c index 66ad8f77ef..cf34e91ba9 100644 --- a/gtk/conversations_fc.c +++ b/gtk/conversations_fc.c @@ -49,7 +49,7 @@ fc_conversation_packet(void *pct, packet_info *pinfo, epan_dissect_t *edt _U_, c { const fc_hdr *fchdr=vip; - add_conversation_table_data((conversations_table *)pct, &fchdr->s_id, &fchdr->d_id, 0, 0, 1, pinfo->fd->pkt_len, SAT_NONE, PT_NONE); + add_conversation_table_data((conversations_table *)pct, &fchdr->s_id, &fchdr->d_id, 0, 0, 1, pinfo->fd->pkt_len, &pinfo->fd->rel_ts, SAT_NONE, PT_NONE); return 1; } diff --git a/gtk/conversations_fddi.c b/gtk/conversations_fddi.c index ac9784ee65..0f95870b7d 100644 --- a/gtk/conversations_fddi.c +++ b/gtk/conversations_fddi.c @@ -47,7 +47,7 @@ fddi_conversation_packet(void *pct, packet_info *pinfo, epan_dissect_t *edt _U_, { const fddi_hdr *ehdr=vip; - add_conversation_table_data((conversations_table *)pct, &ehdr->src, &ehdr->dst, 0, 0, 1, pinfo->fd->pkt_len, SAT_FDDI, PT_NONE); + add_conversation_table_data((conversations_table *)pct, &ehdr->src, &ehdr->dst, 0, 0, 1, pinfo->fd->pkt_len, &pinfo->fd->rel_ts, SAT_FDDI, PT_NONE); return 1; } diff --git a/gtk/conversations_ip.c b/gtk/conversations_ip.c index 2ae005d8c1..68454f3c37 100644 --- a/gtk/conversations_ip.c +++ b/gtk/conversations_ip.c @@ -47,7 +47,7 @@ ip_conversation_packet(void *pct, packet_info *pinfo, epan_dissect_t *edt _U_, c { const e_ip *iph=vip; - add_conversation_table_data((conversations_table *)pct, &iph->ip_src, &iph->ip_dst, 0, 0, 1, pinfo->fd->pkt_len, SAT_NONE, PT_NONE); + add_conversation_table_data((conversations_table *)pct, &iph->ip_src, &iph->ip_dst, 0, 0, 1, pinfo->fd->pkt_len, &pinfo->fd->rel_ts, SAT_NONE, PT_NONE); return 1; } diff --git a/gtk/conversations_ipx.c b/gtk/conversations_ipx.c index 2b0718ddc5..53f288cb09 100644 --- a/gtk/conversations_ipx.c +++ b/gtk/conversations_ipx.c @@ -47,7 +47,7 @@ ipx_conversation_packet(void *pct, packet_info *pinfo, epan_dissect_t *edt _U_, { const ipxhdr_t *ipxh=vip; - add_conversation_table_data((conversations_table *)pct, &ipxh->ipx_src, &ipxh->ipx_dst, 0, 0, 1, pinfo->fd->pkt_len, SAT_NONE, PT_NONE); + add_conversation_table_data((conversations_table *)pct, &ipxh->ipx_src, &ipxh->ipx_dst, 0, 0, 1, pinfo->fd->pkt_len, &pinfo->fd->rel_ts, SAT_NONE, PT_NONE); return 1; } diff --git a/gtk/conversations_jxta.c b/gtk/conversations_jxta.c index 12166fc032..a6ac37c818 100644 --- a/gtk/conversations_jxta.c +++ b/gtk/conversations_jxta.c @@ -1,7 +1,7 @@ /* conversations_jxta.c * conversations_jxta copyright (c) 2005 Mike Duigou * copied from conversations_sctp.c - * + * * $Id$ * * Wireshark - Network traffic analyzer @@ -48,14 +48,15 @@ jxta_conversation_packet(void *pct, packet_info *pinfo _U_, epan_dissect_t *edt { const jxta_tap_header *jxtahdr = (const jxta_tap_header *) vip; - add_conversation_table_data((conversations_table *)pct, - &jxtahdr->src_address, - &jxtahdr->dest_address, - 0, - 0, - 1, - jxtahdr->size, - SAT_JXTA, + add_conversation_table_data((conversations_table *)pct, + &jxtahdr->src_address, + &jxtahdr->dest_address, + 0, + 0, + 1, + jxtahdr->size, + NULL, + SAT_JXTA, PT_NONE); diff --git a/gtk/conversations_ncp.c b/gtk/conversations_ncp.c index 8c1475c4e1..5479f57f13 100644 --- a/gtk/conversations_ncp.c +++ b/gtk/conversations_ncp.c @@ -50,7 +50,7 @@ ncp_conversation_packet(void *pct, packet_info *pinfo, epan_dissect_t *edt _U_, connection = (ncph->conn_high * 256)+ncph->conn_low; if (connection < 65535) { - add_conversation_table_data((conversations_table *)pct, &pinfo->src, &pinfo->dst, connection, connection, 1, pinfo->fd->pkt_len, SAT_NONE, PT_NCP); + add_conversation_table_data((conversations_table *)pct, &pinfo->src, &pinfo->dst, connection, connection, 1, pinfo->fd->pkt_len, &pinfo->fd->rel_ts, SAT_NONE, PT_NCP); } return 1; diff --git a/gtk/conversations_rsvp.c b/gtk/conversations_rsvp.c index c6fd7f08d0..8e8772c621 100644 --- a/gtk/conversations_rsvp.c +++ b/gtk/conversations_rsvp.c @@ -45,9 +45,9 @@ rsvp_conversation_packet(void *pct, packet_info *pinfo, epan_dissect_t *edt _U_, { const rsvp_conversation_info *rsvph = vip; - add_conversation_table_data((conversations_table *)pct, - &rsvph->source, &rsvph->destination, 0, 0, 1, - pinfo->fd->pkt_len, SAT_NONE, PT_NONE); + add_conversation_table_data((conversations_table *)pct, + &rsvph->source, &rsvph->destination, 0, 0, 1, + pinfo->fd->pkt_len, &pinfo->fd->rel_ts, SAT_NONE, PT_NONE); return 1; } @@ -63,7 +63,7 @@ rsvp_conversation_init(const char *optarg, void* userdata _U_) filter=NULL; } - init_conversation_table(TRUE, "RSVP", "rsvp", filter, + init_conversation_table(TRUE, "RSVP", "rsvp", filter, rsvp_conversation_packet); } @@ -84,6 +84,6 @@ register_tap_listener_rsvp_conversation(void) register_stat_menu_item("RSVP", REGISTER_STAT_GROUP_CONVERSATION_LIST, rsvp_endpoints_cb, NULL, NULL, NULL); - register_conversation_table(TRUE, "RSVP", "rsvp", NULL /*filter*/, + register_conversation_table(TRUE, "RSVP", "rsvp", NULL /*filter*/, rsvp_conversation_packet); } diff --git a/gtk/conversations_sctp.c b/gtk/conversations_sctp.c index 6b04702038..87fc13468f 100644 --- a/gtk/conversations_sctp.c +++ b/gtk/conversations_sctp.c @@ -47,14 +47,15 @@ sctp_conversation_packet(void *pct, packet_info *pinfo, epan_dissect_t *edt _U_, { const struct _sctp_info *sctphdr=vip; - add_conversation_table_data((conversations_table *)pct, - &sctphdr->ip_src, - &sctphdr->ip_dst, - sctphdr->sport, - sctphdr->dport, - 1, - pinfo->fd->pkt_len, - SAT_NONE, + add_conversation_table_data((conversations_table *)pct, + &sctphdr->ip_src, + &sctphdr->ip_dst, + sctphdr->sport, + sctphdr->dport, + 1, + pinfo->fd->pkt_len, + &pinfo->fd->rel_ts, + SAT_NONE, PT_SCTP); diff --git a/gtk/conversations_table.c b/gtk/conversations_table.c index 0ce70a3fee..eaddc27d18 100644 --- a/gtk/conversations_table.c +++ b/gtk/conversations_table.c @@ -42,6 +42,7 @@ #include #include #include +#include #include "compat_macros.h" #include "sat.h" @@ -62,13 +63,16 @@ #define GTK_MENU_FUNC(a) ((GtkItemFactoryCallback)(a)) -#define NUM_COLS 10 +#define NUM_COLS 14 +#define COL_STR_LEN 16 #define CONV_PTR_KEY "conversations-pointer" +#define NB_PAGES_KEY "notebook-pages" +#define NO_BPS_STR "N/A" -#define CMP_INT(i1, i2) \ - if ((i1) > (i2)) \ +#define CMP_NUM(n1, n2) \ + if ((n1) > (n2)) \ return 1; \ - else if ((i1) < (i2)) \ + else if ((n1) < (n2)) \ return -1; \ else \ return 0; @@ -343,6 +347,7 @@ ct_sort_column(GtkCList *clist, gconstpointer ptr1, gconstpointer ptr2) conversations_table *ct = OBJECT_GET_DATA(clist, CONV_PTR_KEY); conv_t *conv1 = NULL; conv_t *conv2 = NULL; + double duration1, duration2; const GtkCListRow *row1 = ptr1; const GtkCListRow *row2 = ptr2; @@ -356,29 +361,48 @@ ct_sort_column(GtkCList *clist, gconstpointer ptr1, gconstpointer ptr2) conv1 = &ct->conversations[idx1]; conv2 = &ct->conversations[idx2]; + duration1 = nstime_to_sec(&conv1->stop_time) - nstime_to_sec(&conv1->start_time); + duration2 = nstime_to_sec(&conv2->stop_time) - nstime_to_sec(&conv2->start_time); + switch(clist->sort_column){ case 0: /* Source address */ return(CMP_ADDRESS(&conv1->src_address, &conv2->src_address)); case 2: /* Destination address */ return(CMP_ADDRESS(&conv1->dst_address, &conv2->dst_address)); case 1: /* Source port */ - CMP_INT(conv1->src_port, conv2->src_port); + CMP_NUM(conv1->src_port, conv2->src_port); case 3: /* Destination port */ - CMP_INT(conv1->dst_port, conv2->dst_port); + CMP_NUM(conv1->dst_port, conv2->dst_port); case 4: /* Packets */ - CMP_INT(conv1->tx_frames+conv1->rx_frames, + CMP_NUM(conv1->tx_frames+conv1->rx_frames, conv2->tx_frames+conv2->rx_frames); case 5: /* Bytes */ - CMP_INT(conv1->tx_bytes+conv1->rx_bytes, + CMP_NUM(conv1->tx_bytes+conv1->rx_bytes, conv2->tx_bytes+conv2->rx_bytes); case 6: /* Packets A->B */ - CMP_INT(conv1->tx_frames, conv2->tx_frames); + CMP_NUM(conv1->tx_frames, conv2->tx_frames); case 7: /* Bytes A->B */ - CMP_INT(conv1->tx_bytes, conv2->tx_bytes); + CMP_NUM(conv1->tx_bytes, conv2->tx_bytes); case 8: /* Packets A<-B */ - CMP_INT(conv1->rx_frames, conv2->rx_frames); + CMP_NUM(conv1->rx_frames, conv2->rx_frames); case 9: /* Bytes A<-B */ - CMP_INT(conv1->rx_bytes, conv2->rx_bytes); + CMP_NUM(conv1->rx_bytes, conv2->rx_bytes); + case 10: /* Start time */ + return nstime_cmp(&conv1->start_time, &conv2->start_time); + case 11: /* Duration */ + CMP_NUM(duration1, duration2); + case 12: /* bps A->B */ + if (duration1 > 0 && conv1->tx_frames > 1 && duration2 > 0 && conv2->tx_frames > 1) { + CMP_NUM((gint64) conv1->tx_bytes / duration1, (gint64) conv2->tx_bytes / duration2); + } else { + CMP_NUM(conv1->tx_bytes, conv2->tx_bytes); + } + case 13: /* bps A<-B */ + if (duration1 > 0 && conv1->rx_frames > 1 && duration2 > 0 && conv2->rx_frames > 1) { + CMP_NUM((gint64) conv1->rx_bytes / duration1, (gint64) conv2->rx_bytes / duration2); + } else { + CMP_NUM(conv1->rx_bytes, conv2->rx_bytes); + } default: g_assert_not_reached(); } @@ -1101,6 +1125,7 @@ draw_ct_table_data(conversations_table *ct) guint32 i; int j; char title[256]; + double duration_s; if (ct->page_lb) { if(ct->num_conversations) { @@ -1113,27 +1138,46 @@ draw_ct_table_data(conversations_table *ct) } for(i=0;inum_conversations;i++){ - char str[16]; + char str[COL_STR_LEN]; j=gtk_clist_find_row_from_data(ct->table, (gpointer)(unsigned long)i); - g_snprintf(str, 16, "%" G_GINT64_MODIFIER "u", ct->conversations[i].tx_frames+ct->conversations[i].rx_frames); + g_snprintf(str, COL_STR_LEN, "%" G_GINT64_MODIFIER "u", ct->conversations[i].tx_frames+ct->conversations[i].rx_frames); gtk_clist_set_text(ct->table, j, 4, str); - g_snprintf(str, 16, "%" G_GINT64_MODIFIER "u", ct->conversations[i].tx_bytes+ct->conversations[i].rx_bytes); + g_snprintf(str, COL_STR_LEN, "%" G_GINT64_MODIFIER "u", ct->conversations[i].tx_bytes+ct->conversations[i].rx_bytes); gtk_clist_set_text(ct->table, j, 5, str); - g_snprintf(str, 16, "%" G_GINT64_MODIFIER "u", ct->conversations[i].tx_frames); + g_snprintf(str, COL_STR_LEN, "%" G_GINT64_MODIFIER "u", ct->conversations[i].tx_frames); gtk_clist_set_text(ct->table, j, 6, str); - g_snprintf(str, 16, "%" G_GINT64_MODIFIER "u", ct->conversations[i].tx_bytes); + g_snprintf(str, COL_STR_LEN, "%" G_GINT64_MODIFIER "u", ct->conversations[i].tx_bytes); gtk_clist_set_text(ct->table, j, 7, str); - g_snprintf(str, 16, "%" G_GINT64_MODIFIER "u", ct->conversations[i].rx_frames); + g_snprintf(str, COL_STR_LEN, "%" G_GINT64_MODIFIER "u", ct->conversations[i].rx_frames); gtk_clist_set_text(ct->table, j, 8, str); - g_snprintf(str, 16, "%" G_GINT64_MODIFIER "u", ct->conversations[i].rx_bytes); + g_snprintf(str, COL_STR_LEN, "%" G_GINT64_MODIFIER "u", ct->conversations[i].rx_bytes); gtk_clist_set_text(ct->table, j, 9, str); + duration_s = nstime_to_sec(&ct->conversations[i].stop_time) - nstime_to_sec(&ct->conversations[i].start_time); + g_snprintf(str, COL_STR_LEN, "%s", rel_time_to_secs_str(&ct->conversations[i].start_time)); + gtk_clist_set_text(ct->table, j, 10, str); + g_snprintf(str, COL_STR_LEN, "%.4f", duration_s); + gtk_clist_set_text(ct->table, j, 11, str); + if (duration_s > 0 && ct->conversations[i].tx_frames > 1) { + /* XXX - The gint64 casts below are needed for MSVC++ 6.0 */ + g_snprintf(str, COL_STR_LEN, "%.2f", (gint64) ct->conversations[i].tx_bytes * 8 / duration_s); + gtk_clist_set_text(ct->table, j, 12, str); + } else { + gtk_clist_set_text(ct->table, j, 12, NO_BPS_STR); + } + if (duration_s > 0 && ct->conversations[i].rx_frames > 1) { + /* XXX - The gint64 casts below are needed for MSVC++ 6.0 */ + g_snprintf(str, COL_STR_LEN, "%.2f", (gint64) ct->conversations[i].rx_bytes * 8 / duration_s); + gtk_clist_set_text(ct->table, j, 13, str); + } else { + gtk_clist_set_text(ct->table, j, 13, NO_BPS_STR); + } } draw_ct_table_addresses(ct); @@ -1153,14 +1197,16 @@ draw_ct_table_data_cb(void *arg) #if (GTK_MAJOR_VERSION >= 2) static void -copy_as_csv_cb(GtkWindow *win _U_, gpointer data) +copy_as_csv_cb(GtkWindow *copy_bt, gpointer data _U_) { guint32 i,j; gchar *table_entry; GtkClipboard *cb; GString *CSV_str = g_string_new(""); - conversations_table *talkers=(conversations_table *)data; + conversations_table *talkers=OBJECT_GET_DATA(copy_bt, CONV_PTR_KEY); + if (!talkers) + return; /* Add the column headers to the CSV data */ for(i=0;inum_columns;i++){ /* all columns */ @@ -1201,11 +1247,6 @@ init_ct_table_page(conversations_table *conversations, GtkWidget *vbox, gboolean GString *error_string; GtkWidget *label; char title[256]; -#if (GTK_MAJOR_VERSION >= 2) - GtkWidget *copy_bt; - GtkTooltips *tooltips = gtk_tooltips_new(); -#endif - conversations->page_lb=NULL; conversations->resolve_names=TRUE; @@ -1221,6 +1262,10 @@ init_ct_table_page(conversations_table *conversations, GtkWidget *vbox, gboolean conversations->default_titles[7]="Bytes A->B"; conversations->default_titles[8]="Packets A<-B"; conversations->default_titles[9]="Bytes A<-B"; + conversations->default_titles[10]="Rel Start"; + conversations->default_titles[11]="Duration"; + conversations->default_titles[12]="bps A->B"; + conversations->default_titles[13]="bps A<-B"; if (strcmp(table_name, "NCP")==0) { conversations->default_titles[1]="Connection A"; conversations->default_titles[3]="Connection B"; @@ -1264,16 +1309,9 @@ init_ct_table_page(conversations_table *conversations, GtkWidget *vbox, gboolean gtk_clist_set_sort_type(conversations->table, GTK_SORT_ASCENDING); - gtk_clist_set_column_auto_resize(conversations->table, 0, TRUE); - gtk_clist_set_column_auto_resize(conversations->table, 1, TRUE); - gtk_clist_set_column_auto_resize(conversations->table, 2, TRUE); - gtk_clist_set_column_auto_resize(conversations->table, 3, TRUE); - gtk_clist_set_column_auto_resize(conversations->table, 4, TRUE); - gtk_clist_set_column_auto_resize(conversations->table, 5, TRUE); - gtk_clist_set_column_auto_resize(conversations->table, 6, TRUE); - gtk_clist_set_column_auto_resize(conversations->table, 7, TRUE); - gtk_clist_set_column_auto_resize(conversations->table, 8, TRUE); - gtk_clist_set_column_auto_resize(conversations->table, 9, TRUE); + for (i = 0; i < NUM_COLS; i++) { + gtk_clist_set_column_auto_resize(conversations->table, i, TRUE); + } gtk_clist_set_shadow_type(conversations->table, GTK_SHADOW_IN); gtk_clist_column_titles_show(conversations->table); @@ -1293,16 +1331,6 @@ init_ct_table_page(conversations_table *conversations, GtkWidget *vbox, gboolean /* create popup menu for this table */ ct_create_popup_menu(conversations); -#if (GTK_MAJOR_VERSION >= 2) - /* XXX - maybe we want to have a "Copy as CSV" stock button here? */ - /*copy_bt = gtk_button_new_with_label ("Copy content to clipboard as CSV");*/ - copy_bt = BUTTON_NEW_FROM_STOCK(GTK_STOCK_COPY); - gtk_tooltips_set_tip(tooltips, copy_bt, - "Copy all statistical values of this page to the clipboard in CSV (Comma Separated Values) format.", NULL); - SIGNAL_CONNECT(copy_bt, "clicked", copy_as_csv_cb,(gpointer *) conversations); - gtk_box_pack_start(GTK_BOX(vbox), copy_bt, FALSE, FALSE, 0); -#endif - /* register the tap and rerun the taps on the packet list */ error_string=register_tap_listener(tap_name, conversations, filter, reset_ct_table_data_cb, packet_func, draw_ct_table_data_cb); if(error_string){ @@ -1324,7 +1352,10 @@ init_conversation_table(gboolean hide_ports, const char *table_name, const char GtkWidget *bbox; GtkWidget *close_bt, *help_bt; gboolean ret; - +#if (GTK_MAJOR_VERSION >= 2) + GtkWidget *copy_bt; + GtkTooltips *tooltips = gtk_tooltips_new(); +#endif conversations=g_malloc(sizeof(conversations_table)); @@ -1345,16 +1376,34 @@ init_conversation_table(gboolean hide_ports, const char *table_name, const char } /* Button row. */ + /* XXX - maybe we want to have a "Copy as CSV" stock button here? */ + /*copy_bt = gtk_button_new_with_label ("Copy content to clipboard as CSV");*/ +#if (GTK_MAJOR_VERSION >= 2) + if(topic_available(HELP_STATS_CONVERSATIONS_DIALOG)) { + bbox = dlg_button_row_new(GTK_STOCK_CLOSE, GTK_STOCK_COPY, GTK_STOCK_HELP, NULL); + } else { + bbox = dlg_button_row_new(GTK_STOCK_CLOSE, GTK_STOCK_COPY, NULL); + } +#else if(topic_available(HELP_STATS_CONVERSATIONS_DIALOG)) { bbox = dlg_button_row_new(GTK_STOCK_CLOSE, GTK_STOCK_HELP, NULL); } else { bbox = dlg_button_row_new(GTK_STOCK_CLOSE, NULL); } +#endif gtk_box_pack_end(GTK_BOX(vbox), bbox, FALSE, FALSE, 0); close_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_CLOSE); window_set_cancel_button(conversations->win, close_bt, window_cancel_button_cb); +#if (GTK_MAJOR_VERSION >= 2) + copy_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_COPY); + gtk_tooltips_set_tip(tooltips, copy_bt, + "Copy all statistical values of this page to the clipboard in CSV (Comma Separated Values) format.", NULL); + OBJECT_SET_DATA(copy_bt, CONV_PTR_KEY, conversations); + SIGNAL_CONNECT(copy_bt, "clicked", copy_as_csv_cb, NULL); +#endif + if(topic_available(HELP_STATS_CONVERSATIONS_DIALOG)) { help_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_HELP); SIGNAL_CONNECT(help_bt, "clicked", topic_cb, HELP_STATS_CONVERSATIONS_DIALOG); @@ -1379,6 +1428,21 @@ init_conversation_table(gboolean hide_ports, const char *table_name, const char +#if (GTK_MAJOR_VERSION >= 2) +static void +ct_nb_switch_page_cb(GtkNotebook *nb, GtkNotebookPage *pg _U_, guint page, gpointer data) +{ + GtkWidget *copy_bt = (GtkWidget *) data; + void ** pages = OBJECT_GET_DATA(nb, NB_PAGES_KEY); + + page++; + + if (pages && page > 0 && (int) page <= GPOINTER_TO_INT(pages[0]) && copy_bt) { + OBJECT_SET_DATA(copy_bt, CONV_PTR_KEY, pages[page]); + } +} +#endif + static void ct_win_destroy_notebook_cb(GtkWindow *win _U_, gpointer data) { @@ -1389,11 +1453,9 @@ ct_win_destroy_notebook_cb(GtkWindow *win _U_, gpointer data) for (page=1; page<=GPOINTER_TO_INT(pages[0]); page++) { ct_win_destroy_cb(NULL, pages[page]); } + g_free(pages); } - - - static conversations_table * init_ct_notebook_page_cb(gboolean hide_ports, const char *table_name, const char *tap_name, const char *filter, tap_packet_cb packet_func) { @@ -1464,9 +1526,9 @@ ct_resolve_toggle_dest(GtkWidget *widget, gpointer data) draw_ct_table_addresses(conversations); - /* Allow table to redraw */ + /* Allow table to redraw */ gtk_clist_thaw(conversations->table); - gtk_clist_freeze(conversations->table); + gtk_clist_freeze(conversations->table); } } @@ -1488,7 +1550,9 @@ init_conversation_notebook_cb(GtkWidget *w _U_, gpointer d _U_) GSList *current_table; register_ct_t *registered; GtkTooltips *tooltips = gtk_tooltips_new(); - +#if (GTK_MAJOR_VERSION >= 2) + GtkWidget *copy_bt; +#endif pages = g_malloc(sizeof(void *) * (g_slist_length(registered_ct_tables) + 1)); @@ -1502,6 +1566,7 @@ init_conversation_notebook_cb(GtkWidget *w _U_, gpointer d _U_) nb = gtk_notebook_new(); gtk_container_add(GTK_CONTAINER(vbox), nb); + OBJECT_SET_DATA(nb, NB_PAGES_KEY, pages); page = 0; @@ -1511,6 +1576,7 @@ init_conversation_notebook_cb(GtkWidget *w _U_, gpointer d _U_) page_lb = gtk_label_new(""); conversations = init_ct_notebook_page_cb(registered->hide_ports, registered->table_name, registered->tap_name, registered->filter, registered->packet_func); + OBJECT_SET_DATA(conversations->win, CONV_PTR_KEY, conversations); gtk_notebook_append_page(GTK_NOTEBOOK(nb), conversations->win, page_lb); conversations->win = win; conversations->page_lb = page_lb; @@ -1533,16 +1599,36 @@ init_conversation_notebook_cb(GtkWidget *w _U_, gpointer d _U_) SIGNAL_CONNECT(resolv_cb, "toggled", ct_resolve_toggle_dest, pages); /* Button row. */ + /* XXX - maybe we want to have a "Copy as CSV" stock button here? */ + /*copy_bt = gtk_button_new_with_label ("Copy content to clipboard as CSV");*/ +#if (GTK_MAJOR_VERSION >= 2) + if(topic_available(HELP_STATS_CONVERSATIONS_DIALOG)) { + bbox = dlg_button_row_new(GTK_STOCK_CLOSE, GTK_STOCK_COPY, GTK_STOCK_HELP, NULL); + } else { + bbox = dlg_button_row_new(GTK_STOCK_CLOSE, GTK_STOCK_COPY, NULL); + } +#else if(topic_available(HELP_STATS_CONVERSATIONS_DIALOG)) { bbox = dlg_button_row_new(GTK_STOCK_CLOSE, GTK_STOCK_HELP, NULL); } else { bbox = dlg_button_row_new(GTK_STOCK_CLOSE, NULL); } +#endif gtk_box_pack_end(GTK_BOX(vbox), bbox, FALSE, FALSE, 0); close_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_CLOSE); window_set_cancel_button(win, close_bt, window_cancel_button_cb); +#if (GTK_MAJOR_VERSION >= 2) + copy_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_COPY); + gtk_tooltips_set_tip(tooltips, copy_bt, + "Copy all statistical values of this page to the clipboard in CSV (Comma Separated Values) format.", NULL); + SIGNAL_CONNECT(copy_bt, "clicked", copy_as_csv_cb, NULL); + OBJECT_SET_DATA(copy_bt, CONV_PTR_KEY, pages[page]); + + SIGNAL_CONNECT(nb, "switch-page", ct_nb_switch_page_cb, copy_bt); +#endif + if(topic_available(HELP_STATS_CONVERSATIONS_DIALOG)) { help_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_HELP); SIGNAL_CONNECT(help_bt, "clicked", topic_cb, HELP_STATS_CONVERSATIONS_DIALOG); @@ -1564,7 +1650,7 @@ init_conversation_notebook_cb(GtkWidget *w _U_, gpointer d _U_) void -add_conversation_table_data(conversations_table *ct, const address *src, const address *dst, guint32 src_port, guint32 dst_port, int num_frames, int num_bytes, SAT_E sat, int port_type) +add_conversation_table_data(conversations_table *ct, const address *src, const address *dst, guint32 src_port, guint32 dst_port, int num_frames, int num_bytes, nstime_t *ts, SAT_E sat, int port_type) { const address *addr1, *addr2; guint32 port1, port2; @@ -1646,6 +1732,13 @@ add_conversation_table_data(conversations_table *ct, const address *src, const a conversation->tx_frames=0; conversation->rx_bytes=0; conversation->tx_bytes=0; + if (ts) { + memcpy(&conversation->start_time, ts, sizeof(conversation->start_time)); + memcpy(&conversation->stop_time, ts, sizeof(conversation->stop_time)); + } else { + nstime_set_unset(&conversation->start_time); + nstime_set_unset(&conversation->stop_time); + } } /* update the conversation struct */ @@ -1657,10 +1750,23 @@ add_conversation_table_data(conversations_table *ct, const address *src, const a conversation->rx_bytes+=num_bytes; } + if (ts) { + if (nstime_cmp(ts, &conversation->stop_time) > 0) { + memcpy(&conversation->stop_time, ts, sizeof(conversation->stop_time)); + } else if (nstime_cmp(ts, &conversation->start_time) < 0) { + memcpy(&conversation->start_time, ts, sizeof(conversation->start_time)); + } + } + /* if this was a new conversation we have to create a clist row for it */ if(new_conversation){ char *entries[NUM_COLS]; - char frames[16],bytes[16],txframes[16],txbytes[16],rxframes[16],rxbytes[16]; + char frames[COL_STR_LEN], bytes[COL_STR_LEN], + txframes[COL_STR_LEN], txbytes[COL_STR_LEN], + rxframes[COL_STR_LEN], rxbytes[COL_STR_LEN], + start_time[COL_STR_LEN], duration[COL_STR_LEN], + txbps[COL_STR_LEN], rxbps[COL_STR_LEN]; + double duration_s; /* these values will be filled by call to draw_ct_table_addresses() below */ entries[0] = ""; @@ -1668,24 +1774,56 @@ add_conversation_table_data(conversations_table *ct, const address *src, const a entries[2] = ""; entries[3] = ""; - g_snprintf(frames, 16, "%" G_GINT64_MODIFIER "u", conversation->tx_frames+conversation->rx_frames); + g_snprintf(frames, COL_STR_LEN, "%" G_GINT64_MODIFIER "u", conversation->tx_frames+conversation->rx_frames); entries[4]=frames; - g_snprintf(bytes, 16, "%" G_GINT64_MODIFIER "u", conversation->tx_bytes+conversation->rx_bytes); + g_snprintf(bytes, COL_STR_LEN, "%" G_GINT64_MODIFIER "u", conversation->tx_bytes+conversation->rx_bytes); entries[5]=bytes; - g_snprintf(txframes, 16, "%" G_GINT64_MODIFIER "u", conversation->tx_frames); + g_snprintf(txframes, COL_STR_LEN, "%" G_GINT64_MODIFIER "u", conversation->tx_frames); entries[6]=txframes; - g_snprintf(txbytes, 16, "%" G_GINT64_MODIFIER "u", conversation->tx_bytes); + g_snprintf(txbytes, COL_STR_LEN, "%" G_GINT64_MODIFIER "u", conversation->tx_bytes); entries[7]=txbytes; - g_snprintf(rxframes, 16, "%" G_GINT64_MODIFIER "u", conversation->rx_frames); + g_snprintf(rxframes, COL_STR_LEN, "%" G_GINT64_MODIFIER "u", conversation->rx_frames); entries[8]=rxframes; - g_snprintf(rxbytes, 16, "%" G_GINT64_MODIFIER "u", conversation->rx_bytes); + g_snprintf(rxbytes, COL_STR_LEN, "%" G_GINT64_MODIFIER "u", conversation->rx_bytes); entries[9]=rxbytes; + duration_s = nstime_to_sec(&conversation->start_time) - nstime_to_sec(&conversation->stop_time); + g_snprintf(start_time, COL_STR_LEN, "%s", rel_time_to_secs_str(&conversation->start_time)); + g_snprintf(duration, COL_STR_LEN, "%.4f", duration_s); + entries[10]=start_time; + entries[11]=duration; + if (duration_s > 0 && conversation->tx_frames > 1) { + g_snprintf(txbps, COL_STR_LEN, "%.2f", (gint64) conversation->tx_bytes * 8 / duration_s); + entries[12]=txbps; + } else { + entries[12] = NO_BPS_STR; + } + if (duration_s > 0 && conversation->rx_frames > 1) { + g_snprintf(rxbps, COL_STR_LEN, "%.2f", (gint64) conversation->rx_bytes * 8 / duration_s); + entries[13]=rxbps; + } else { + entries[13] = NO_BPS_STR; + } + gtk_clist_insert(ct->table, conversation_idx, entries); gtk_clist_set_row_data(ct->table, conversation_idx, (gpointer)(long) conversation_idx); draw_ct_table_address(ct, conversation_idx); } } + +/* + * Editor modelines + * + * Local Variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * ex: set shiftwidth=4 tabstop=8 expandtab + * :indentSize=4:tabSize=8:noTabs=true: + */ + diff --git a/gtk/conversations_table.h b/gtk/conversations_table.h index 5a65246e89..89888c3cd1 100644 --- a/gtk/conversations_table.h +++ b/gtk/conversations_table.h @@ -7,17 +7,17 @@ * Wireshark - Network traffic analyzer * By Gerald Combs * 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. @@ -32,17 +32,20 @@ /** Conversation information */ typedef struct _conversation_t { - address src_address; /**< source address */ - address dst_address; /**< destination address */ - SAT_E sat; /**< address type */ - guint32 port_type; /**< port_type (e.g. PT_TCP) */ - guint32 src_port; /**< source port */ - guint32 dst_port; /**< destination port */ + address src_address; /**< source address */ + address dst_address; /**< destination address */ + SAT_E sat; /**< address type */ + guint32 port_type; /**< port_type (e.g. PT_TCP) */ + guint32 src_port; /**< source port */ + guint32 dst_port; /**< destination port */ - guint64 rx_frames; /**< number of received packets */ - guint64 tx_frames; /**< number of transmitted packets */ - guint64 rx_bytes; /**< number of received bytes */ - guint64 tx_bytes; /**< number of transmitted bytes */ + guint64 rx_frames; /**< number of received packets */ + guint64 tx_frames; /**< number of transmitted packets */ + guint64 rx_bytes; /**< number of received bytes */ + guint64 tx_bytes; /**< number of transmitted bytes */ + + nstime_t start_time; /**< start time for the conversation */ + nstime_t stop_time; /**< stop time for the conversation */ } conv_t; /** Conversation widget */ @@ -52,8 +55,8 @@ typedef struct _conversations_table { GtkWidget *page_lb; /**< label */ GtkWidget *scrolled_window; /**< the scrolled window */ GtkCList *table; /**< the GTK table */ - guint32 num_columns; /**< number of columns in the above table */ - const char *default_titles[10]; /**< Column headers */ + guint32 num_columns; /**< number of columns in the above table */ + const char *default_titles[14]; /**< Column headers */ GtkWidget *menu; /**< context menu */ gboolean has_ports; /**< table has ports */ guint32 num_conversations; /**< number of conversations */ @@ -97,10 +100,12 @@ extern void init_conversation_notebook_cb(GtkWidget *widget, gpointer data); * @param dst_port destination port * @param num_frames number of packets * @param num_bytes number of bytes + * @param ts timestamp * @param sat address type * @param port_type the port type (e.g. PT_TCP) */ -extern void add_conversation_table_data(conversations_table *ct, const address *src, const address *dst, - guint32 src_port, guint32 dst_port, int num_frames, int num_bytes, SAT_E sat, int port_type); +extern void add_conversation_table_data(conversations_table *ct, const address *src, const address *dst, + guint32 src_port, guint32 dst_port, int num_frames, int num_bytes, nstime_t *ts, + SAT_E sat, int port_type); #endif /* __CONVERSATIONS_TABLE_H__ */ diff --git a/gtk/conversations_tcpip.c b/gtk/conversations_tcpip.c index 7d8afd8ac0..4c86501d7e 100644 --- a/gtk/conversations_tcpip.c +++ b/gtk/conversations_tcpip.c @@ -48,7 +48,7 @@ tcpip_conversation_packet(void *pct, packet_info *pinfo, epan_dissect_t *edt _U_ { const struct tcpheader *tcphdr=vip; - add_conversation_table_data((conversations_table *)pct, &tcphdr->ip_src, &tcphdr->ip_dst, tcphdr->th_sport, tcphdr->th_dport, 1, pinfo->fd->pkt_len, SAT_NONE, PT_TCP); + add_conversation_table_data((conversations_table *)pct, &tcphdr->ip_src, &tcphdr->ip_dst, tcphdr->th_sport, tcphdr->th_dport, 1, pinfo->fd->pkt_len, &pinfo->fd->rel_ts, SAT_NONE, PT_TCP); return 1; } diff --git a/gtk/conversations_tr.c b/gtk/conversations_tr.c index d3a0c80ced..440f3b095d 100644 --- a/gtk/conversations_tr.c +++ b/gtk/conversations_tr.c @@ -47,7 +47,7 @@ tr_conversation_packet(void *pct, packet_info *pinfo, epan_dissect_t *edt _U_, c { const tr_hdr *trhdr=vip; - add_conversation_table_data((conversations_table *)pct, &trhdr->src, &trhdr->dst, 0, 0, 1, pinfo->fd->pkt_len, SAT_TOKENRING, PT_NONE); + add_conversation_table_data((conversations_table *)pct, &trhdr->src, &trhdr->dst, 0, 0, 1, pinfo->fd->pkt_len, &pinfo->fd->rel_ts, SAT_TOKENRING, PT_NONE); return 1; } diff --git a/gtk/conversations_udpip.c b/gtk/conversations_udpip.c index e18dbcd938..5ef123b67c 100644 --- a/gtk/conversations_udpip.c +++ b/gtk/conversations_udpip.c @@ -47,7 +47,7 @@ udpip_conversation_packet(void *pct, packet_info *pinfo, epan_dissect_t *edt _U_ { const e_udphdr *udphdr=vip; - add_conversation_table_data((conversations_table *)pct, &udphdr->ip_src, &udphdr->ip_dst, udphdr->uh_sport, udphdr->uh_dport, 1, pinfo->fd->pkt_len, SAT_NONE, PT_UDP); + add_conversation_table_data((conversations_table *)pct, &udphdr->ip_src, &udphdr->ip_dst, udphdr->uh_sport, udphdr->uh_dport, 1, pinfo->fd->pkt_len, &pinfo->fd->rel_ts, SAT_NONE, PT_UDP); return 1; } diff --git a/gtk/conversations_usb.c b/gtk/conversations_usb.c index e29689b28b..cabeb5ed83 100644 --- a/gtk/conversations_usb.c +++ b/gtk/conversations_usb.c @@ -44,7 +44,7 @@ static int usb_conversation_packet(void *pct, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vip _U_) { - add_conversation_table_data((conversations_table *)pct, &pinfo->src, &pinfo->dst, 0, 0, 1, pinfo->fd->pkt_len, SAT_NONE, PT_NONE); + add_conversation_table_data((conversations_table *)pct, &pinfo->src, &pinfo->dst, 0, 0, 1, pinfo->fd->pkt_len, &pinfo->fd->rel_ts, SAT_NONE, PT_NONE); return 1; } diff --git a/gtk/conversations_wlan.c b/gtk/conversations_wlan.c index e666b9d321..b23d2111aa 100644 --- a/gtk/conversations_wlan.c +++ b/gtk/conversations_wlan.c @@ -47,7 +47,7 @@ wlan_conversation_packet(void *pct, packet_info *pinfo, epan_dissect_t *edt _U_, { const wlan_hdr *whdr=vip; - add_conversation_table_data((conversations_table *)pct, &whdr->src, &whdr->dst, 0, 0, 1, pinfo->fd->pkt_len, SAT_WLAN, PT_NONE); + add_conversation_table_data((conversations_table *)pct, &whdr->src, &whdr->dst, 0, 0, 1, pinfo->fd->pkt_len, &pinfo->fd->rel_ts, SAT_WLAN, PT_NONE); return 1; } diff --git a/gtk/dlg_utils.c b/gtk/dlg_utils.c index bb6d137fde..d2455c030e 100644 --- a/gtk/dlg_utils.c +++ b/gtk/dlg_utils.c @@ -106,25 +106,26 @@ dlg_button_row_new(const gchar *stock_id_first, ...) GtkWidget *help_hbox; GtkWidget *button; - const gchar *ok = NULL; const gchar *apply = NULL; - const gchar *save = NULL; - const gchar *dont_save = NULL; const gchar *cancel = NULL; - const gchar *close = NULL; - const gchar *clear = NULL; const gchar *cap_start = NULL; const gchar *cap_stop = NULL; - const gchar *stop = NULL; + const gchar *clear = NULL; + const gchar *close = NULL; + const gchar *copy = NULL; const gchar *create_stat = NULL; - const gchar *help = NULL; - const gchar *print = NULL; - const gchar *find = NULL; - const gchar *jump = NULL; - const gchar *yes = NULL; - const gchar *no = NULL; - const gchar *filter_stream= NULL; const gchar *delete = NULL; + const gchar *dont_save = NULL; + const gchar *filter_stream= NULL; + const gchar *find = NULL; + const gchar *help = NULL; + const gchar *jump = NULL; + const gchar *no = NULL; + const gchar *ok = NULL; + const gchar *print = NULL; + const gchar *save = NULL; + const gchar *stop = NULL; + const gchar *yes = NULL; va_start(stock_id_list, stock_id_first); @@ -171,6 +172,8 @@ dlg_button_row_new(const gchar *stock_id_first, ...) filter_stream = stock_id; } else if (strcmp(stock_id, GTK_STOCK_DELETE) == 0) { delete = stock_id; + } else if (strcmp(stock_id, GTK_STOCK_COPY) == 0) { + copy = stock_id; } else { /* we don't know that button! */ g_assert_not_reached(); @@ -336,6 +339,7 @@ dlg_button_row_new(const gchar *stock_id_first, ...) if (jump != NULL) dlg_button_new(hbox, button_hbox, jump); if (find != NULL) dlg_button_new(hbox, button_hbox, find); if (print != NULL) dlg_button_new(hbox, button_hbox, print); + if (copy != NULL) dlg_button_new(hbox, button_hbox, copy); if (create_stat != NULL) dlg_button_new(hbox, button_hbox, create_stat); if (apply != NULL) dlg_button_new(hbox, button_hbox, apply); if (yes != NULL) dlg_button_new(hbox, button_hbox, yes);