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
This commit is contained in:
Gerald Combs 2007-11-20 18:35:41 +00:00
parent 06f0070947
commit dfb104544f
20 changed files with 317 additions and 128 deletions

View File

@ -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

View File

@ -2,7 +2,7 @@
* Routines for manipulating nstime_t structures
*
* Copyright (c) 2005 MX Telecom Ltd. <richardv@mxtelecom.com>
*
*
* $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:
*/

View File

@ -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);

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -1,7 +1,7 @@
/* conversations_jxta.c
* conversations_jxta copyright (c) 2005 Mike Duigou <bondolo@jxta.org>
* 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);

View File

@ -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;

View File

@ -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);
}

View File

@ -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);

View File

@ -42,6 +42,7 @@
#include <epan/address.h>
#include <epan/addr_resolv.h>
#include <epan/tap.h>
#include <epan/nstime.h>
#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;i<ct->num_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;i<talkers->num_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:
*/

View File

@ -7,17 +7,17 @@
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
@ -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__ */

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);