From Brian K. Teravskis: add an option to save the data in CSV form.

svn path=/trunk/; revision=8405
This commit is contained in:
Guy Harris 2003-09-06 08:30:26 +00:00
parent 029c86ab1c
commit d66f162b71
3 changed files with 247 additions and 11 deletions

View File

@ -1822,6 +1822,10 @@ Josef Korelus <jkor [AT] quick.cz> {
GPRS BSSGP support
}
Brian K. Teravskis <Brian_Teravskis [AT] Cargill.com> {
Support for saving RTP analysis data in CSV form
}
And assorted fixes and enhancements by the people listed above and by:
Pavel Roskin <proski [AT] gnu.org>

View File

@ -2072,6 +2072,7 @@ B<http://www.ethereal.com>.
Vincent Jardin <vincent.jardin [AT] 6wind.com>
Jean-Michel Fayard <jean-michel.fayard [AT] moufrei.de>
Josef Korelus <jkor [AT] quick.cz>
Brian K. Teravskis <Brian_Teravskis [AT] Cargill.com>
Pavel Roskin <proski [AT] gnu.org>
Georgi Guninski <guninski [AT] guninski.com>
Jason Copenhaver <jcopenha [AT] typedef.org>

View File

@ -1,7 +1,7 @@
/*
* tap_rtp.c
*
* $Id: tap_rtp.c,v 1.14 2003/09/03 23:32:40 guy Exp $
* $Id: tap_rtp.c,v 1.15 2003/09/06 08:30:26 guy Exp $
*
* RTP analysing addition for ethereal
*
@ -123,6 +123,7 @@
static GtkWidget *rtp_w = NULL;
static GtkWidget *save_voice_as_w = NULL;
static GtkWidget *save_csv_as_w = NULL;
static GtkWidget *main_vb;
static GtkWidget *clist;
static GtkWidget *clist_r;
@ -285,10 +286,10 @@ static void draw_stat(void *prs)
/* append a line to clist */
/* XXX is there a nicer way to make these assignements? */
static void add_to_clist(gboolean forward, guint32 number, guint16 seq_num,
double delay, double jitter, gboolean status, gboolean marker)
double delay, double jitter, gboolean status, gboolean marker, gchar *timeStr, guint32 pkt_len)
{
gchar *data[6];
gchar field[6][30];
gchar *data[8];
gchar field[8][30];
data[0]=&field[0][0];
data[1]=&field[1][0];
@ -296,6 +297,8 @@ static void add_to_clist(gboolean forward, guint32 number, guint16 seq_num,
data[3]=&field[3][0];
data[4]=&field[4][0];
data[5]=&field[5][0];
data[6]=&field[6][0];
data[7]=&field[7][0];
g_snprintf(field[0], 20, "%u", number);
g_snprintf(field[1], 20, "%u", seq_num);
@ -303,6 +306,8 @@ static void add_to_clist(gboolean forward, guint32 number, guint16 seq_num,
g_snprintf(field[3], 20, "%f", jitter);
g_snprintf(field[4], 20, "%s", marker? "SET" : "");
g_snprintf(field[5], 29, "%s", status? "OK" : "NOK - Wrong sequence nr.");
g_snprintf(field[6], 32, "%s", timeStr);
g_snprintf(field[7], 20, "%u", pkt_len);
gtk_clist_append(GTK_CLIST(forward? clist : clist_r), data);
@ -405,7 +410,24 @@ int do_calculation(gboolean direc, packet_type pkt_type, void *ptrs, void *vpri,
double current_jitter;
guint8 *data;
gint16 tmp;
guint16 msecs;
gchar timeStr[32];
struct tm *tm_tmp;
time_t then;
then = pinfo->fd->abs_secs;
msecs = (guint16)(pinfo->fd->abs_usecs/1000);
tm_tmp = localtime(&then);
snprintf(timeStr,32,"%02d/%02d/%04d %02d:%02d:%02d.%03d",
tm_tmp->tm_mon + 1,
tm_tmp->tm_mday,
tm_tmp->tm_year + 1900,
tm_tmp->tm_hour,
tm_tmp->tm_min,
tm_tmp->tm_sec,
msecs);
/* store the current time and calculate the current jitter */
current_time = (double)pinfo->fd->rel_secs + (double) pinfo->fd->rel_usecs/1000000;
current_jitter = ptr->jitter + ( fabs (current_time - (ptr->time) -
@ -419,7 +441,8 @@ int do_calculation(gboolean direc, packet_type pkt_type, void *ptrs, void *vpri,
ptr->start_seq_nr = pri->info_seq_num;
ptr->start_time = current_time;
add_to_clist(direc, pinfo->fd->num, pri->info_seq_num, 0,
pri->info_marker_set? TRUE: FALSE, TRUE, FALSE);
pri->info_marker_set? TRUE: FALSE, TRUE, FALSE,
timeStr, pinfo->fd->pkt_len);
if (ptr->fp == NULL) {
ptr->saved = FALSE;
ptr->error_type = TAP_RTP_FILE_OPEN_ERROR;
@ -431,7 +454,7 @@ int do_calculation(gboolean direc, packet_type pkt_type, void *ptrs, void *vpri,
else if (pkt_type == MARK_SET) {
ptr->delta_timestamp = pri->info_timestamp - ptr->timestamp;
add_to_clist(direc, pinfo->fd->num, pri->info_seq_num, current_time - (ptr->time),
current_jitter, ptr->seq_num+1 == pri->info_seq_num? TRUE: FALSE, TRUE);
current_jitter, ptr->seq_num+1 == pri->info_seq_num? TRUE: FALSE, TRUE, timeStr, pinfo->fd->pkt_len);
}
/* if neither then it is a "normal" packet pkt_type == NORMAL_PACKET */
else {
@ -440,7 +463,7 @@ int do_calculation(gboolean direc, packet_type pkt_type, void *ptrs, void *vpri,
ptr->max_nr = pinfo->fd->num;
}
add_to_clist(direc, pinfo->fd->num, pri->info_seq_num, current_time -(ptr->time),
current_jitter , ptr->seq_num+1 == pri->info_seq_num?TRUE:FALSE, FALSE);
current_jitter , ptr->seq_num+1 == pri->info_seq_num?TRUE:FALSE, FALSE, timeStr, pinfo->fd->pkt_len);
}
/* When calculating expected rtp packets the seq number can wrap around
@ -677,6 +700,199 @@ static void refresh_cb(GtkWidget *w _U_, void *pri)
draw_stat(rs);
}
/* when we want to save the information */
static void save_csv_as_ok_cb(GtkWidget *ok_bt, gpointer fs)
{
gchar *g_dest;
GtkWidget *rev, *forw, *both;
info_stat *rs;
FILE *fp;
char *columnText;
int i,j;
g_dest = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION (fs)));
/* Perhaps the user specified a directory instead of a file.
Check whether they did. */
if (test_for_directory(g_dest) == EISDIR) {
/* It's a directory - set the file selection box to display it. */
set_last_open_dir(g_dest);
g_free(g_dest);
gtk_file_selection_set_filename(GTK_FILE_SELECTION(fs), last_open_dir);
return;
}
rev = (GtkWidget *)OBJECT_GET_DATA(ok_bt, "reversed_rb");
forw = (GtkWidget *)OBJECT_GET_DATA(ok_bt, "forward_rb");
both = (GtkWidget *)OBJECT_GET_DATA(ok_bt, "both_rb");
rs = (info_stat *)OBJECT_GET_DATA(ok_bt, "info_stat");
if (GTK_TOGGLE_BUTTON(forw)->active || GTK_TOGGLE_BUTTON(both)->active) {
fp = fopen(g_dest, "w");
if (GTK_TOGGLE_BUTTON(both)->active) {
fprintf(fp, "Forward\n");
}
for(j = 0; j < GTK_CLIST(clist)->columns; j++) {
if (j == 0) {
fprintf(fp,"%s",GTK_CLIST(clist)->column[j].title);
} else {
fprintf(fp,",%s",GTK_CLIST(clist)->column[j].title);
}
}
fprintf(fp,"\n");
for (i = 0; i < GTK_CLIST(clist)->rows; i++) {
for(j = 0; j < GTK_CLIST(clist)->columns; j++) {
gtk_clist_get_text(GTK_CLIST(clist),i,j,&columnText);
if (j == 0) {
fprintf(fp,"%s",columnText);
} else {
fprintf(fp,",%s",columnText);
}
}
fprintf(fp,"\n");
}
fclose(fp);
}
if (GTK_TOGGLE_BUTTON(rev)->active || GTK_TOGGLE_BUTTON(both)->active) {
if (GTK_TOGGLE_BUTTON(both)->active) {
fp = fopen(g_dest, "a");
fprintf(fp, "\nReverse\n");
} else {
fp = fopen(g_dest, "w");
}
for(j = 0; j < GTK_CLIST(clist_r)->columns; j++) {
if (j == 0) {
fprintf(fp,"%s",GTK_CLIST(clist_r)->column[j].title);
} else {
fprintf(fp,",%s",GTK_CLIST(clist_r)->column[j].title);
}
}
fprintf(fp,"\n");
for (i = 0; i < GTK_CLIST(clist_r)->rows; i++) {
for(j = 0; j < GTK_CLIST(clist_r)->columns; j++) {
gtk_clist_get_text(GTK_CLIST(clist_r),i,j,&columnText);
if (j == 0) {
fprintf(fp,"%s",columnText);
} else {
fprintf(fp,",%s",columnText);
}
}
fprintf(fp,"\n");
}
fclose(fp);
}
/* XXX I get GTK warning (sometimes?)!!! */
gtk_widget_destroy(GTK_WIDGET(save_csv_as_w));
}
static void save_csv_as_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
{
save_csv_as_w = NULL;
}
/* when the user wants to save the csv information in a file */
static void save_csv_as_cb(GtkWidget *w _U_, gpointer data)
{
info_stat *rs=(info_stat *)data;
GtkWidget *vertb;
GtkWidget *table1;
GtkWidget *label_format;
GtkWidget *channels_label;
GSList *channels_group = NULL;
GtkWidget *forward_rb;
GtkWidget *reversed_rb;
GtkWidget *both_rb;
GtkWidget *ok_bt;
if (save_csv_as_w != NULL) {
/* There's already a Save CSV info dialog box; reactivate it. */
reactivate_window(save_csv_as_w);
return;
}
save_csv_as_w = gtk_file_selection_new("Ethereal: Save Data As CSV");
gtk_signal_connect(GTK_OBJECT(save_csv_as_w), "destroy",
GTK_SIGNAL_FUNC(save_csv_as_destroy_cb), NULL);
/* Container for each row of widgets */
vertb = gtk_vbox_new(FALSE, 0);
gtk_container_border_width(GTK_CONTAINER(vertb), 5);
gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(save_csv_as_w)->action_area),
vertb, FALSE, FALSE, 0);
gtk_widget_show (vertb);
table1 = gtk_table_new (2, 4, FALSE);
gtk_widget_show (table1);
gtk_box_pack_start (GTK_BOX (vertb), table1, FALSE, FALSE, 0);
gtk_container_set_border_width (GTK_CONTAINER (table1), 10);
gtk_table_set_row_spacings (GTK_TABLE (table1), 20);
label_format = gtk_label_new ("Format: Comma Separated Values");
gtk_widget_show (label_format);
gtk_table_attach (GTK_TABLE (table1), label_format, 0, 3, 0, 1,
(GtkAttachOptions) (GTK_FILL),
(GtkAttachOptions) (0), 0, 0);
channels_label = gtk_label_new ("Channels:");
gtk_widget_show (channels_label);
gtk_table_attach (GTK_TABLE (table1), channels_label, 0, 1, 1, 2,
(GtkAttachOptions) (GTK_FILL),
(GtkAttachOptions) (0), 0, 0);
gtk_misc_set_alignment (GTK_MISC (channels_label), 0, 0.5);
forward_rb = gtk_radio_button_new_with_label (channels_group, "forward ");
channels_group = gtk_radio_button_group (GTK_RADIO_BUTTON (forward_rb));
gtk_widget_show (forward_rb);
gtk_table_attach (GTK_TABLE (table1), forward_rb, 1, 2, 1, 2,
(GtkAttachOptions) (GTK_FILL),
(GtkAttachOptions) (0), 0, 0);
reversed_rb = gtk_radio_button_new_with_label (channels_group, "reversed");
channels_group = gtk_radio_button_group (GTK_RADIO_BUTTON (reversed_rb));
gtk_widget_show (reversed_rb);
gtk_table_attach (GTK_TABLE (table1), reversed_rb, 2, 3, 1, 2,
(GtkAttachOptions) (GTK_FILL),
(GtkAttachOptions) (0), 0, 0);
both_rb = gtk_radio_button_new_with_label (channels_group, "both");
channels_group = gtk_radio_button_group (GTK_RADIO_BUTTON (both_rb));
gtk_widget_show (both_rb);
gtk_table_attach (GTK_TABLE (table1), both_rb, 3, 4, 1, 2,
(GtkAttachOptions) (GTK_FILL),
(GtkAttachOptions) (0), 0, 0);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(both_rb), TRUE);
ok_bt = GTK_FILE_SELECTION(save_csv_as_w)->ok_button;
OBJECT_SET_DATA(ok_bt, "forward_rb", forward_rb);
OBJECT_SET_DATA(ok_bt, "reversed_rb", reversed_rb);
OBJECT_SET_DATA(ok_bt, "both_rb", both_rb);
OBJECT_SET_DATA(ok_bt, "info_stat", rs);
/* Connect the cancel_button to destroy the widget */
SIGNAL_CONNECT_OBJECT(GTK_FILE_SELECTION(save_csv_as_w)->cancel_button,
"clicked", (GtkSignalFunc)gtk_widget_destroy,
save_csv_as_w);
/* Catch the "key_press_event" signal in the window, so that we can catch
the ESC key being pressed and act as if the "Cancel" button had
been selected. */
dlg_set_cancel(save_csv_as_w, GTK_FILE_SELECTION(save_csv_as_w)->cancel_button);
gtk_signal_connect(GTK_OBJECT(ok_bt), "clicked",
GTK_SIGNAL_FUNC(save_csv_as_ok_cb), save_csv_as_w);
gtk_widget_show(save_csv_as_w);
}
static void save_voice_as_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
{
/* Note that we no longer have a Save voice info dialog box. */
@ -952,9 +1168,9 @@ static void add_rtp_notebook(void *pri)
GtkWidget *notebook, *page, *page_r, *label, *label1, *label2, *label3;
GtkWidget *scrolled_window, *scrolled_window_r/*, *frame, *text, *label4, *page_help*/;
GtkWidget *box4, *voice_bt, *refresh_bt, *close_bn;
GtkWidget *box4, *voice_bt, *refresh_bt, *close_bn, *csv_bt;
gchar *titles[6] = {"Packet nr.", "Sequence", "Delay (s)", "Jitter (s)", "Marker", "Status"};
gchar *titles[8] = {"Packet nr.", "Sequence", "Delay (s)", "Jitter (s)", "Marker", "Status", "Date", "Length"};
gchar label_forward[150];
gchar label_reverse[150];
@ -995,7 +1211,7 @@ static void add_rtp_notebook(void *pri)
gtk_box_pack_end(GTK_BOX(page), max, FALSE, FALSE, 5);
/* clist for the information */
clist = gtk_clist_new_with_titles(6, titles);
clist = gtk_clist_new_with_titles(8, titles);
gtk_widget_show(clist);
gtk_container_add(GTK_CONTAINER(scrolled_window), clist);
gtk_box_pack_start(GTK_BOX(page), scrolled_window, TRUE, TRUE, 0);
@ -1004,6 +1220,10 @@ static void add_rtp_notebook(void *pri)
label = gtk_label_new(" Forward Direction ");
gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label);
/* Hide date and length column */
gtk_clist_set_column_visibility(GTK_CLIST(clist), 6, FALSE);
gtk_clist_set_column_visibility(GTK_CLIST(clist), 7, FALSE);
/* column width and justification */
gtk_clist_set_column_width(GTK_CLIST(clist), 0, 80);
gtk_clist_set_column_width(GTK_CLIST(clist), 1, 80);
@ -1028,13 +1248,18 @@ static void add_rtp_notebook(void *pri)
gtk_box_pack_start(GTK_BOX(page_r), label3, FALSE, FALSE, 0);
max_r = gtk_label_new("\n\n");
gtk_box_pack_end(GTK_BOX(page_r), max_r, FALSE, FALSE, 5);
clist_r = gtk_clist_new_with_titles(6, titles);
clist_r = gtk_clist_new_with_titles(8, titles);
gtk_widget_show(clist_r);
gtk_container_add(GTK_CONTAINER(scrolled_window_r), clist_r);
gtk_box_pack_start(GTK_BOX(page_r), scrolled_window_r, TRUE, TRUE, 0);
label2 = gtk_label_new(" Reversed Direction ");
gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page_r, label2);
/* Hide date and length column */
gtk_clist_set_column_visibility(GTK_CLIST(clist_r), 6, FALSE);
gtk_clist_set_column_visibility(GTK_CLIST(clist_r), 7, FALSE);
/* column width and justification */
gtk_clist_set_column_width(GTK_CLIST(clist_r), 0, 80);
gtk_clist_set_column_width(GTK_CLIST(clist_r), 1, 80);
gtk_clist_set_column_width(GTK_CLIST(clist_r), 2, 80);
@ -1080,6 +1305,12 @@ static void add_rtp_notebook(void *pri)
gtk_signal_connect(GTK_OBJECT(refresh_bt), "clicked",
GTK_SIGNAL_FUNC(refresh_cb), rs);
csv_bt = gtk_button_new_with_label("Save As CSV...");
gtk_container_add(GTK_CONTAINER(box4), csv_bt);
gtk_widget_show(csv_bt);
gtk_signal_connect(GTK_OBJECT(csv_bt), "clicked",
GTK_SIGNAL_FUNC(save_csv_as_cb), rs);
close_bn = gtk_button_new_with_label("Close");
gtk_container_add(GTK_CONTAINER(box4), close_bn);
gtk_widget_show(close_bn);