/* rtp_analysis.c
* RTP analysis addition for ethereal
*
- * $Id: rtp_analysis.c,v 1.16 2003/12/28 12:43:40 ulfl Exp $
+ * $Id: rtp_analysis.c,v 1.28 2004/01/27 18:05:32 obiot Exp $
*
* Copyright 2003, Alcatel Business Systems
* By Lars Ruoff <lars.ruoff@gmx.net>
#include "../graph/graph.h"
#endif
+#include "util.h"
#include "epan/epan_dissect.h"
#include "epan/filesystem.h"
#include "tap.h"
#include "progress_dlg.h"
#include "compat_macros.h"
+#include "image/clist_ascend.xpm"
+#include "image/clist_descend.xpm"
+
#include <math.h>
#include <fcntl.h>
#include <string.h>
/****************************************************************************/
+typedef struct column_arrows {
+ GtkWidget *table;
+ GtkWidget *ascend_pm;
+ GtkWidget *descend_pm;
+} column_arrows;
+
typedef struct _dialog_data_t {
GtkWidget *window;
GtkCList *clist_fwd;
GtkCList *clist_rev;
GtkWidget *label_stats_fwd;
GtkWidget *label_stats_rev;
+ column_arrows *col_arrows_fwd;
+ column_arrows *col_arrows_rev;
GtkWidget *notebook;
GtkCList *selected_clist;
GtkWidget *save_voice_as_w;
#endif
} dialog_data_t;
-#define OK_TEXT "Ok"
+#define OK_TEXT "[ Ok ]"
+#define PT_UNDEFINED -1
/* type of error when saving voice in a file didn't succeed */
typedef enum {
gboolean under;
gint cycles;
guint16 pt;
+ int reg_pt;
} tap_rtp_stat_t;
/* status flags for the flags parameter in tap_rtp_stat_t */
#define STAT_FLAG_WRONG_SEQ 0x04
#define STAT_FLAG_PT_CHANGE 0x08
#define STAT_FLAG_PT_CN 0x10
+#define STAT_FLAG_FOLLOW_PT_CN 0x20
+#define STAT_FLAG_REG_PT_CHANGE 0x40
typedef struct _tap_rtp_save_info_t {
FILE *fp;
} user_data_t;
+/* Column titles. */
+static gchar *titles[8] = {
+ "Packet",
+ "Sequence",
+ "Delay (s)",
+ "Jitter (s)",
+ "Marker",
+ "Status",
+ "Date",
+ "Length"
+};
+
+
typedef const guint8 * ip_addr_p;
/****************************************************************************/
/* when there is a [re]reading of packet's */
static void
-rtp_reset(user_data_t *user_data _U_)
+rtp_reset(void *user_data_arg)
{
+ user_data_t *user_data = user_data_arg;
+
user_data->forward.statinfo.first_packet = TRUE;
user_data->reversed.statinfo.first_packet = TRUE;
user_data->forward.statinfo.max_delay = 0;
user_data->reversed.statinfo.start_time = 0;
user_data->forward.statinfo.time = 0;
user_data->reversed.statinfo.time = 0;
+ user_data->forward.statinfo.reg_pt = PT_UNDEFINED;
+ user_data->reversed.statinfo.reg_pt = PT_UNDEFINED;
user_data->forward.saveinfo.count = 0;
user_data->reversed.saveinfo.count = 0;
/****************************************************************************/
/* whenever a RTP packet is seen by the tap listener */
-static int rtp_packet(user_data_t *user_data, packet_info *pinfo, epan_dissect_t *edt _U_, struct _rtp_info *rtpinfo)
+static int rtp_packet(void *user_data_arg, packet_info *pinfo, epan_dissect_t *edt _U_, void *rtpinfo_arg)
{
+ user_data_t *user_data = user_data_arg;
+ struct _rtp_info *rtpinfo = rtpinfo_arg;
#ifdef USE_CONVERSATION_GRAPH
value_pair_t vp;
#endif
if (rtpinfo->info_payload_type == PT_CN
|| rtpinfo->info_payload_type == PT_CN_OLD)
statinfo->flags |= STAT_FLAG_PT_CN;
+ if (statinfo->pt == PT_CN
+ || statinfo->pt == PT_CN_OLD)
+ statinfo->flags |= STAT_FLAG_FOLLOW_PT_CN;
if (rtpinfo->info_payload_type != statinfo->pt)
statinfo->flags |= STAT_FLAG_PT_CHANGE;
statinfo->pt = rtpinfo->info_payload_type;
-
+
/* store the current time and calculate the current jitter */
current_time = (double)pinfo->fd->rel_secs + (double) pinfo->fd->rel_usecs/1000000;
current_jitter = statinfo->jitter + ( fabs (current_time - (statinfo->time) -
statinfo->delta_timestamp = rtpinfo->info_timestamp - statinfo->timestamp;
statinfo->flags |= STAT_FLAG_MARKER;
}
- /* if neither then it is a normal packet */
- if (!(statinfo->first_packet) && !(rtpinfo->info_marker_set)) {
+ /* is it a regular packet? */
+ if (!(statinfo->flags & STAT_FLAG_FIRST)
+ && !(statinfo->flags & STAT_FLAG_MARKER)
+ && !(statinfo->flags & STAT_FLAG_PT_CN)
+ && !(statinfo->flags & STAT_FLAG_FOLLOW_PT_CN)) {
+ /* include it in maximum delay calculation */
if (statinfo->delay > statinfo->max_delay) {
statinfo->max_delay = statinfo->delay;
statinfo->max_nr = pinfo->fd->num;
}
}
+ /* regular payload change? (CN ignored) */
+ if (!(statinfo->flags & STAT_FLAG_FIRST)
+ && !(statinfo->flags & STAT_FLAG_PT_CN)) {
+ if ((statinfo->pt != statinfo->reg_pt)
+ && (statinfo->reg_pt != PT_UNDEFINED)) {
+ statinfo->flags |= STAT_FLAG_REG_PT_CHANGE;
+ }
+ }
+
+ /* set regular payload*/
+ if (!(statinfo->flags & STAT_FLAG_PT_CN)) {
+ statinfo->reg_pt = statinfo->pt;
+ }
+
/* When calculating expected rtp packets the seq number can wrap around
* so we have to count the number of cycles
}
+static const GdkColor COLOR_DEFAULT = {0, 0xffff, 0xffff, 0xffff};
+static const GdkColor COLOR_ERROR = {0, 0xffff, 0xbfff, 0xbfff};
+static const GdkColor COLOR_WARNING = {0, 0xffff, 0xdfff, 0xbfff};
+static const GdkColor COLOR_CN = {0, 0xbfff, 0xbfff, 0xffff};
+
/****************************************************************************/
/* adds statistics information from the packet to the clist */
static int rtp_packet_add_info(GtkCList *clist,
struct tm *tm_tmp;
time_t then;
gchar status[40];
- GdkColor color = {0, 0xffff, 0xffff, 0xffff};
+ GdkColor color = COLOR_DEFAULT;
then = pinfo->fd->abs_secs;
msecs = (guint16)(pinfo->fd->abs_usecs/1000);
if (statinfo->pt == PT_CN) {
snprintf(status,40,"Comfort noise (PT=13, RFC 3389)");
- color.pixel = 0;
- color.red = 0x7fff;
- color.green = 0x7fff;
- color.blue = 0xffff;
+ color = COLOR_CN;
}
else if (statinfo->pt == PT_CN_OLD) {
snprintf(status,40,"Comfort noise (PT=19, reserved)");
- color.pixel = 0;
- color.red = 0x7fff;
- color.green = 0x7fff;
- color.blue = 0xffff;
+ color = COLOR_CN;
}
else if (statinfo->flags & STAT_FLAG_WRONG_SEQ) {
snprintf(status,40,"Wrong sequence nr.");
- color.pixel = 0;
- color.red = 0xffff;
- color.green = 0x7fff;
- color.blue = 0x7fff;
+ color = COLOR_ERROR;
+ }
+ else if (statinfo->flags & STAT_FLAG_REG_PT_CHANGE) {
+ snprintf(status,40,"Payload changed to PT=%u", statinfo->pt);
+ color = COLOR_WARNING;
}
else if ((statinfo->flags & STAT_FLAG_PT_CHANGE)
&& !(statinfo->flags & STAT_FLAG_FIRST)
- && !(statinfo->flags & STAT_FLAG_PT_CN)) {
- snprintf(status,40,"Payload type changed to PT=%u", statinfo->pt);
- color.pixel = 0;
- color.red = 0xffff;
- color.green = 0x7fff;
- color.blue = 0x7fff;
+ && !(statinfo->flags & STAT_FLAG_PT_CN)
+ && (statinfo->flags & STAT_FLAG_FOLLOW_PT_CN)
+ && !(statinfo->flags & STAT_FLAG_MARKER)) {
+ snprintf(status,40,"Marker missing?");
+ color = COLOR_WARNING;
}
else {
+ if (statinfo->flags & STAT_FLAG_MARKER) {
+ color = COLOR_WARNING;
+ }
snprintf(status,40,OK_TEXT);
}
/* close the dialog window and remove the tap listener */
static void on_destroy(GtkWidget *win _U_, user_data_t *user_data _U_)
{
- protect_thread_critical_region();
- remove_tap_listener(user_data);
- unprotect_thread_critical_region();
-
+ /* close and remove temporary files */
if (user_data->forward.saveinfo.fp != NULL)
fclose(user_data->forward.saveinfo.fp);
if (user_data->reversed.saveinfo.fp != NULL)
fclose(user_data->reversed.saveinfo.fp);
+ /*XXX: test for error **/
remove(user_data->f_tempname);
remove(user_data->r_tempname);
- /* Is there a save voice window open? */
+ /* destroy save_voice_as window if open */
if (user_data->dlg.save_voice_as_w != NULL)
gtk_widget_destroy(user_data->dlg.save_voice_as_w);
#ifdef USE_CONVERSATION_GRAPH
- /* Is there a graph window open? */
+ /* destroy graph window if open */
if (user_data->dlg.graph_window != NULL)
gtk_widget_destroy(user_data->dlg.graph_window);
#endif
+ g_free(user_data->dlg.col_arrows_fwd);
+ g_free(user_data->dlg.col_arrows_rev);
g_free(user_data);
}
/* re-dissects all packets */
static void on_refresh_bt_clicked(GtkWidget *bt _U_, user_data_t *user_data _U_)
{
+ gchar filter_text[256];
+ dfilter_t *sfcode;
+ GString *error_string;
+
+ /* clear the dialog box clists */
gtk_clist_clear(GTK_CLIST(user_data->dlg.clist_fwd));
gtk_clist_clear(GTK_CLIST(user_data->dlg.clist_rev));
- redissect_packets(&cfile);
+
+ /* try to compile the filter. */
+ strcpy(filter_text,"rtp && ip");
+ if (!dfilter_compile(filter_text, &sfcode)) {
+ simple_dialog(ESD_TYPE_WARN | ESD_TYPE_MODAL, NULL, dfilter_error_msg);
+ return;
+ }
+
+ sprintf(filter_text,"rtp && (( ip.src==%s && udp.srcport==%u && ip.dst==%s && udp.dstport==%u ) || ( ip.src==%s && udp.srcport==%u && ip.dst==%s && udp.dstport==%u ))",
+ ip_to_str((ip_addr_p)&(user_data->ip_src_fwd)),
+ user_data->port_src_fwd,
+ ip_to_str((ip_addr_p)&(user_data->ip_dst_fwd)),
+ user_data->port_dst_fwd,
+ ip_to_str((ip_addr_p)&(user_data->ip_src_rev)),
+ user_data->port_src_rev,
+ ip_to_str((ip_addr_p)&(user_data->ip_dst_rev)),
+ user_data->port_dst_rev
+ );
+
+ /* register tap listener */
+ error_string = register_tap_listener("rtp", user_data, filter_text,
+ rtp_reset, rtp_packet, rtp_draw);
+ if (error_string != NULL) {
+ simple_dialog(ESD_TYPE_WARN | ESD_TYPE_MODAL, NULL, error_string->str);
+ g_string_free(error_string, TRUE);
+ return;
+ }
+
+ /* retap all packets */
+ retap_packets(&cfile);
+
+ /* remove tap listener again */
+ protect_thread_critical_region();
+ remove_tap_listener(user_data);
+ unprotect_thread_critical_region();
+
+ /* draw statistics info */
draw_stat(user_data);
+
+ gtk_clist_sort(user_data->dlg.clist_fwd);
+ gtk_clist_sort(user_data->dlg.clist_rev);
}
/****************************************************************************/
gint row;
if (user_data->dlg.selected_clist==NULL)
return;
-/*
- if (user_data->dlg.selected_row==-1)
- user_data->dlg.selected_row = 0;
-*/
+
clist = user_data->dlg.selected_clist;
row = user_data->dlg.selected_row + 1;
if (GTK_TOGGLE_BUTTON(forw)->active || GTK_TOGGLE_BUTTON(both)->active) {
fp = fopen(g_dest, "w");
+ if (fp == NULL) {
+ simple_dialog(ESD_TYPE_CRIT, NULL,
+ file_open_error_message(errno, TRUE), g_dest);
+ return;
+ }
if (GTK_TOGGLE_BUTTON(both)->active) {
fprintf(fp, "Forward\n");
+ if (ferror(fp)) {
+ simple_dialog(ESD_TYPE_CRIT, NULL,
+ file_write_error_message(errno), g_dest);
+ fclose(fp);
+ return;
+ }
}
- for(j = 0; j < GTK_CLIST(user_data->dlg.clist_fwd)->columns; j++) {
+ for(j = 0; j < 8; j++) {
if (j == 0) {
- fprintf(fp,"%s",GTK_CLIST(user_data->dlg.clist_fwd)->column[j].title);
+ fprintf(fp,"%s",titles[j]);
} else {
- fprintf(fp,",%s",GTK_CLIST(user_data->dlg.clist_fwd)->column[j].title);
+ fprintf(fp,",%s",titles[j]);
}
}
fprintf(fp,"\n");
+ if (ferror(fp)) {
+ simple_dialog(ESD_TYPE_CRIT, NULL,
+ file_write_error_message(errno), g_dest);
+ fclose(fp);
+ return;
+ }
for (i = 0; i < GTK_CLIST(user_data->dlg.clist_fwd)->rows; i++) {
for(j = 0; j < GTK_CLIST(user_data->dlg.clist_fwd)->columns; j++) {
gtk_clist_get_text(GTK_CLIST(user_data->dlg.clist_fwd),i,j,&columnText);
}
}
fprintf(fp,"\n");
+ if (ferror(fp)) {
+ simple_dialog(ESD_TYPE_CRIT, NULL,
+ file_write_error_message(errno), g_dest);
+ fclose(fp);
+ return;
+ }
}
- fclose(fp);
+ if (fclose(fp) == EOF) {
+ simple_dialog(ESD_TYPE_CRIT, NULL,
+ file_write_error_message(errno), g_dest);
+ return;
+ }
}
if (GTK_TOGGLE_BUTTON(rev)->active || GTK_TOGGLE_BUTTON(both)->active) {
if (GTK_TOGGLE_BUTTON(both)->active) {
fp = fopen(g_dest, "a");
+ if (fp == NULL) {
+ simple_dialog(ESD_TYPE_CRIT, NULL,
+ file_open_error_message(errno, TRUE),
+ g_dest);
+ return;
+ }
fprintf(fp, "\nReverse\n");
+ if (ferror(fp)) {
+ simple_dialog(ESD_TYPE_CRIT, NULL,
+ file_write_error_message(errno), g_dest);
+ fclose(fp);
+ return;
+ }
} else {
fp = fopen(g_dest, "w");
+ if (fp == NULL) {
+ simple_dialog(ESD_TYPE_CRIT, NULL,
+ file_open_error_message(errno, TRUE),
+ g_dest);
+ return;
+ }
}
- for(j = 0; j < GTK_CLIST(user_data->dlg.clist_rev)->columns; j++) {
+ for(j = 0; j < 8; j++) {
if (j == 0) {
- fprintf(fp,"%s",GTK_CLIST(user_data->dlg.clist_rev)->column[j].title);
+ fprintf(fp,"%s",titles[j]);
} else {
- fprintf(fp,",%s",GTK_CLIST(user_data->dlg.clist_rev)->column[j].title);
+ fprintf(fp,",%s",titles[j]);
}
}
fprintf(fp,"\n");
+ if (ferror(fp)) {
+ simple_dialog(ESD_TYPE_CRIT, NULL,
+ file_write_error_message(errno), g_dest);
+ fclose(fp);
+ return;
+ }
for (i = 0; i < GTK_CLIST(user_data->dlg.clist_rev)->rows; i++) {
for(j = 0; j < GTK_CLIST(user_data->dlg.clist_rev)->columns; j++) {
gtk_clist_get_text(GTK_CLIST(user_data->dlg.clist_rev),i,j,&columnText);
}
}
fprintf(fp,"\n");
+ if (ferror(fp)) {
+ simple_dialog(ESD_TYPE_CRIT, NULL,
+ file_write_error_message(errno), g_dest);
+ fclose(fp);
+ return;
+ }
+ }
+ if (fclose(fp) == EOF) {
+ simple_dialog(ESD_TYPE_CRIT, NULL,
+ file_write_error_message(errno), g_dest);
+ return;
}
- fclose(fp);
}
gtk_widget_destroy(GTK_WIDGET(user_data->dlg.save_csv_as_w));
return FALSE;
}
- progbar = create_progress_dlg("Saving voice in a file", dest, "Stop", &stop_flag);
+ progbar = create_progress_dlg("Saving voice in a file", dest, &stop_flag);
/* First we write the .au header. XXX Hope this is endian independant */
/* the magic word 0x2e736e64 == .snd */
gint32 f_lost = f_expected - user_data->forward.statinfo.total_nr;
gint32 r_lost = r_expected - user_data->reversed.statinfo.total_nr;
- g_snprintf(label_max, 199, "Max delay = %f sec at packet no. %u \n\n"
+ g_snprintf(label_max, 199, "Max delay = %f sec at packet no. %u \n"
"Total RTP packets = %u (expected %u) Lost RTP packets = %d"
" Sequence errors = %u",
- user_data->forward.statinfo.max_delay, user_data->forward.statinfo.max_nr, user_data->forward.statinfo.total_nr,
+ user_data->forward.statinfo.max_delay, user_data->forward.statinfo.max_nr,
+ user_data->forward.statinfo.total_nr,
f_expected, f_lost, user_data->forward.statinfo.sequence);
gtk_label_set_text(GTK_LABEL(user_data->dlg.label_stats_fwd), label_max);
- g_snprintf(label_max, 199, "Max delay = %f sec at packet no. %u \n\n"
+ g_snprintf(label_max, 199, "Max delay = %f sec at packet no. %u \n"
"Total RTP packets = %u (expected %u) Lost RTP packets = %d"
" Sequence errors = %u",
- user_data->reversed.statinfo.max_delay, user_data->reversed.statinfo.max_nr, user_data->reversed.statinfo.total_nr,
+ user_data->reversed.statinfo.max_delay, user_data->reversed.statinfo.max_nr,
+ user_data->reversed.statinfo.total_nr,
r_expected, r_lost, user_data->reversed.statinfo.sequence);
gtk_label_set_text(GTK_LABEL(user_data->dlg.label_stats_rev), label_max);
return ;
}
+
+#define NUM_COLS 8
+
/****************************************************************************/
/* append a line to clist */
static void add_to_clist(GtkCList *clist, guint32 number, guint16 seq_num,
gtk_clist_set_background(GTK_CLIST(clist), added_row, color);
}
+
+/****************************************************************************/
+/* callback for sorting columns of clist */
+static gint rtp_sort_column(GtkCList *clist, gconstpointer ptr1, gconstpointer ptr2)
+{
+ char *text1 = NULL;
+ char *text2 = NULL;
+ int i1, i2;
+ double f1, f2;
+
+ const GtkCListRow *row1 = (GtkCListRow *) ptr1;
+ const GtkCListRow *row2 = (GtkCListRow *) ptr2;
+
+ text1 = GTK_CELL_TEXT (row1->cell[clist->sort_column])->text;
+ text2 = GTK_CELL_TEXT (row2->cell[clist->sort_column])->text;
+
+ switch(clist->sort_column){
+ /* columns representing strings */
+ case 4:
+ case 5:
+ case 6:
+ return strcmp (text1, text2);
+ /* columns representing ints */
+ case 0:
+ case 1:
+ case 7:
+ i1=atoi(text1);
+ i2=atoi(text2);
+ return i1-i2;
+ /* columns representing floats */
+ case 2:
+ case 3:
+ f1=atof(text1);
+ f2=atof(text2);
+ if (fabs(f1-f2)<0.0000005)
+ return 0;
+ if (f1<f2)
+ return -1;
+ return 1;
+ }
+ g_assert_not_reached();
+ return 0;
+}
+
+
+/****************************************************************************/
+static void
+click_column_cb(GtkCList *clist, gint column, gpointer data)
+{
+ column_arrows *col_arrows = (column_arrows *) data;
+ int i;
+
+ gtk_clist_freeze(clist);
+
+ for (i = 0; i < NUM_COLS; i++) {
+ gtk_widget_hide(col_arrows[i].ascend_pm);
+ gtk_widget_hide(col_arrows[i].descend_pm);
+ }
+
+ if (column == clist->sort_column) {
+ if (clist->sort_type == GTK_SORT_ASCENDING) {
+ clist->sort_type = GTK_SORT_DESCENDING;
+ gtk_widget_show(col_arrows[column].descend_pm);
+ } else {
+ clist->sort_type = GTK_SORT_ASCENDING;
+ gtk_widget_show(col_arrows[column].ascend_pm);
+ }
+ } else {
+ clist->sort_type = GTK_SORT_ASCENDING;
+ gtk_widget_show(col_arrows[column].ascend_pm);
+ gtk_clist_set_sort_column(clist, column);
+ }
+ gtk_clist_thaw(clist);
+
+ gtk_clist_sort(clist);
+}
+
+
+/****************************************************************************/
+/* Add the packet list */
+static
+GtkWidget* create_clist(user_data_t* user_data)
+{
+ GtkWidget* clist_fwd;
+
+ /* clist for the information */
+ clist_fwd = gtk_clist_new(8);
+ gtk_widget_show(clist_fwd);
+ SIGNAL_CONNECT(clist_fwd, "select_row", on_clist_select_row, user_data);
+
+ gtk_clist_column_titles_show(GTK_CLIST(clist_fwd));
+ gtk_clist_set_compare_func(GTK_CLIST(clist_fwd), rtp_sort_column);
+ gtk_clist_set_sort_column(GTK_CLIST(clist_fwd), 0);
+ gtk_clist_set_sort_type(GTK_CLIST(clist_fwd), GTK_SORT_ASCENDING);
+
+ /* hide date and length column */
+ gtk_clist_set_column_visibility(GTK_CLIST(clist_fwd), 6, FALSE);
+ gtk_clist_set_column_visibility(GTK_CLIST(clist_fwd), 7, FALSE);
+
+ /* column widths and justification */
+ gtk_clist_set_column_width(GTK_CLIST(clist_fwd), 0, 60);
+ gtk_clist_set_column_width(GTK_CLIST(clist_fwd), 1, 75);
+ gtk_clist_set_column_width(GTK_CLIST(clist_fwd), 2, 75);
+ gtk_clist_set_column_width(GTK_CLIST(clist_fwd), 3, 75);
+ gtk_clist_set_column_width(GTK_CLIST(clist_fwd), 4, 50);
+ gtk_clist_set_column_justification(GTK_CLIST(clist_fwd), 0, GTK_JUSTIFY_RIGHT);
+ gtk_clist_set_column_justification(GTK_CLIST(clist_fwd), 1, GTK_JUSTIFY_RIGHT);
+ gtk_clist_set_column_justification(GTK_CLIST(clist_fwd), 2, GTK_JUSTIFY_CENTER);
+ gtk_clist_set_column_justification(GTK_CLIST(clist_fwd), 3, GTK_JUSTIFY_CENTER);
+ gtk_clist_set_column_justification(GTK_CLIST(clist_fwd), 4, GTK_JUSTIFY_CENTER);
+ gtk_clist_set_column_justification(GTK_CLIST(clist_fwd), 5, GTK_JUSTIFY_CENTER);
+
+ return clist_fwd;
+}
+
+
+/****************************************************************************/
+/* Add the sort by column feature for a packet clist */
+static
+column_arrows* add_sort_by_column(GtkWidget* window, GtkWidget* clist,
+ user_data_t* user_data _U_)
+{
+ column_arrows *col_arrows;
+ GdkBitmap *ascend_bm, *descend_bm;
+ GdkPixmap *ascend_pm, *descend_pm;
+ GtkStyle *win_style;
+ GtkWidget *column_lb;
+ int i;
+
+ col_arrows = (column_arrows *) g_malloc(sizeof(column_arrows) * NUM_COLS);
+ win_style = gtk_widget_get_style(window);
+ ascend_pm = gdk_pixmap_create_from_xpm_d(window->window,
+ &ascend_bm,
+ &win_style->bg[GTK_STATE_NORMAL],
+ (gchar **)clist_ascend_xpm);
+ descend_pm = gdk_pixmap_create_from_xpm_d(window->window,
+ &descend_bm,
+ &win_style->bg[GTK_STATE_NORMAL],
+ (gchar **)clist_descend_xpm);
+
+ for (i=0; i<NUM_COLS; i++) {
+ col_arrows[i].table = gtk_table_new(2, 2, FALSE);
+ gtk_table_set_col_spacings(GTK_TABLE(col_arrows[i].table), 5);
+ column_lb = gtk_label_new(titles[i]);
+ gtk_table_attach(GTK_TABLE(col_arrows[i].table), column_lb, 0, 1, 0, 2, GTK_SHRINK, GTK_SHRINK, 0, 0);
+ gtk_widget_show(column_lb);
+
+ col_arrows[i].ascend_pm = gtk_pixmap_new(ascend_pm, ascend_bm);
+ gtk_table_attach(GTK_TABLE(col_arrows[i].table), col_arrows[i].ascend_pm, 1, 2, 1, 2, GTK_SHRINK, GTK_SHRINK, 0, 0);
+ col_arrows[i].descend_pm = gtk_pixmap_new(descend_pm, descend_bm);
+ gtk_table_attach(GTK_TABLE(col_arrows[i].table), col_arrows[i].descend_pm, 1, 2, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0);
+ /* make packet-nr be the default sort order */
+ if (i == 0) {
+ gtk_widget_show(col_arrows[i].ascend_pm);
+ }
+ gtk_clist_set_column_widget(GTK_CLIST(clist), i, col_arrows[i].table);
+ gtk_widget_show(col_arrows[i].table);
+ }
+
+ SIGNAL_CONNECT(clist, "click-column", click_column_cb, col_arrows);
+
+ return col_arrows;
+}
+
/****************************************************************************/
/* Create the dialog box with all widgets */
void create_rtp_dialog(user_data_t* user_data)
GtkWidget *label_stats_rev;
GtkWidget *notebook;
- GtkWidget *main_vb, *page, *page_r, *label, *label1, *label2, *label3;
+ GtkWidget *main_vb, *page, *page_r;
+ GtkWidget *label;
GtkWidget *scrolled_window, *scrolled_window_r/*, *frame, *text, *label4, *page_help*/;
GtkWidget *box4, *voice_bt, *refresh_bt, *goto_bt, *close_bt, *csv_bt, *next_bt;
#ifdef USE_CONVERSATION_GRAPH
GtkWidget *graph_bt;
#endif
- gchar *titles[8] = {"Packet", "Sequence", "Delay (s)", "Jitter (s)", "Marker", "Status", "Date", "Length"};
gchar label_forward[150];
gchar label_reverse[150];
gchar str_ip_src[16];
gchar str_ip_dst[16];
+ column_arrows *col_arrows_fwd;
+ column_arrows *col_arrows_rev;
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
SIGNAL_CONNECT(window, "destroy", on_destroy, user_data);
/* Container for each row of widgets */
- main_vb = gtk_vbox_new(FALSE, 3);
- gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
+ main_vb = gtk_vbox_new(FALSE, 2);
+ gtk_container_border_width(GTK_CONTAINER(main_vb), 2);
gtk_container_add(GTK_CONTAINER(window), main_vb);
gtk_widget_show(main_vb);
-
/* Notebooks... */
strcpy(str_ip_src, ip_to_str((ip_addr_p)&user_data->ip_src_fwd));
strcpy(str_ip_dst, ip_to_str((ip_addr_p)&user_data->ip_dst_fwd));
g_snprintf(label_forward, 149,
- "Analysing connection from %s port %u to %s port %u SSRC = %u\n",
+ "Analysing stream from %s port %u to %s port %u SSRC = %u",
str_ip_src, user_data->port_src_fwd, str_ip_dst, user_data->port_dst_fwd, user_data->ssrc_fwd);
strcpy(str_ip_src, ip_to_str((ip_addr_p)&user_data->ip_src_rev));
strcpy(str_ip_dst, ip_to_str((ip_addr_p)&user_data->ip_dst_rev));
g_snprintf(label_reverse, 149,
- "Analysing connection from %s port %u to %s port %u SSRC = %u\n",
+ "Analysing stream from %s port %u to %s port %u SSRC = %u",
str_ip_src, user_data->port_src_rev, str_ip_dst, user_data->port_dst_rev, user_data->ssrc_rev);
/* Start a notebook for flipping between sets of changes */
user_data);
/* page for forward connection */
- page = gtk_vbox_new(FALSE, 5);
- gtk_container_set_border_width(GTK_CONTAINER(page), 20);
+ page = gtk_vbox_new(FALSE, 8);
+ gtk_container_set_border_width(GTK_CONTAINER(page), 8);
+
+ /* direction label */
+ label = gtk_label_new(label_forward);
+ gtk_box_pack_start(GTK_BOX(page), label, FALSE, FALSE, 0);
+
+ /* place for some statistics */
+ label_stats_fwd = gtk_label_new("\n");
+ gtk_box_pack_end(GTK_BOX(page), label_stats_fwd, FALSE, FALSE, 0);
/* scrolled window */
scrolled_window = gtk_scrolled_window_new(NULL, NULL);
- WIDGET_SET_SIZE(scrolled_window, 600, 200);
+ WIDGET_SET_SIZE(scrolled_window, 560, 200);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
- /* direction label */
- label1 = gtk_label_new(label_forward);
- gtk_box_pack_start(GTK_BOX(page), label1, FALSE, FALSE, 0);
-
- /* place for some statistics */
- label_stats_fwd = gtk_label_new("\n\n");
- gtk_box_pack_end(GTK_BOX(page), label_stats_fwd, FALSE, FALSE, 5);
-
- /* clist for the information */
- clist_fwd = gtk_clist_new_with_titles(8, titles);
+ /* packet clist */
+ clist_fwd = create_clist(user_data);
gtk_widget_show(clist_fwd);
gtk_container_add(GTK_CONTAINER(scrolled_window), clist_fwd);
gtk_box_pack_start(GTK_BOX(page), scrolled_window, TRUE, TRUE, 0);
- SIGNAL_CONNECT(clist_fwd, "select_row", on_clist_select_row, user_data);
- /* Hide date and length column */
- gtk_clist_set_column_visibility(GTK_CLIST(clist_fwd), 6, FALSE);
- gtk_clist_set_column_visibility(GTK_CLIST(clist_fwd), 7, FALSE);
+ gtk_widget_show(scrolled_window);
- /* label */
- label = gtk_label_new(" Forward Direction ");
+ /* tab */
+ label = gtk_label_new(" Forward Direction ");
gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label);
- /* column width and justification */
- gtk_clist_set_column_width(GTK_CLIST(clist_fwd), 0, 80);
- gtk_clist_set_column_width(GTK_CLIST(clist_fwd), 1, 80);
- gtk_clist_set_column_width(GTK_CLIST(clist_fwd), 2, 80);
- gtk_clist_set_column_width(GTK_CLIST(clist_fwd), 3, 80);
- gtk_clist_set_column_width(GTK_CLIST(clist_fwd), 4, 40);
- gtk_clist_set_column_justification(GTK_CLIST(clist_fwd), 0, GTK_JUSTIFY_CENTER);
- gtk_clist_set_column_justification(GTK_CLIST(clist_fwd), 1, GTK_JUSTIFY_CENTER);
- gtk_clist_set_column_justification(GTK_CLIST(clist_fwd), 2, GTK_JUSTIFY_CENTER);
- gtk_clist_set_column_justification(GTK_CLIST(clist_fwd), 3, GTK_JUSTIFY_CENTER);
- gtk_clist_set_column_justification(GTK_CLIST(clist_fwd), 4, GTK_JUSTIFY_CENTER);
- gtk_clist_set_column_justification(GTK_CLIST(clist_fwd), 5, GTK_JUSTIFY_CENTER);
-
/* same page for reversed connection */
- page_r = gtk_vbox_new(FALSE, 5);
- gtk_container_set_border_width(GTK_CONTAINER(page_r), 20);
+ page_r = gtk_vbox_new(FALSE, 8);
+ gtk_container_set_border_width(GTK_CONTAINER(page_r), 8);
+ label = gtk_label_new(label_reverse);
+ gtk_box_pack_start(GTK_BOX(page_r), label, FALSE, FALSE, 0);
+ label_stats_rev = gtk_label_new("\n");
+ gtk_box_pack_end(GTK_BOX(page_r), label_stats_rev, FALSE, FALSE, 0);
+
scrolled_window_r = gtk_scrolled_window_new(NULL, NULL);
- WIDGET_SET_SIZE(scrolled_window_r, 600, 200);
+ WIDGET_SET_SIZE(scrolled_window_r, 560, 200);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window_r),
GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
- label3 = gtk_label_new(label_reverse);
- gtk_box_pack_start(GTK_BOX(page_r), label3, FALSE, FALSE, 0);
- label_stats_rev = gtk_label_new("\n\n");
- gtk_box_pack_end(GTK_BOX(page_r), label_stats_rev, FALSE, FALSE, 5);
- clist_rev = gtk_clist_new_with_titles(8, titles);
- gtk_widget_show(clist_rev);
- gtk_clist_set_column_visibility(GTK_CLIST(clist_rev), 6, FALSE);
- gtk_clist_set_column_visibility(GTK_CLIST(clist_rev), 7, FALSE);
-
- SIGNAL_CONNECT(clist_rev, "select_row", on_clist_select_row, user_data);
+ clist_rev = create_clist(user_data);
+ gtk_widget_show(clist_rev);
gtk_container_add(GTK_CONTAINER(scrolled_window_r), clist_rev);
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);
-
- gtk_clist_set_column_width(GTK_CLIST(clist_rev), 0, 80);
- gtk_clist_set_column_width(GTK_CLIST(clist_rev), 1, 80);
- gtk_clist_set_column_width(GTK_CLIST(clist_rev), 2, 80);
- gtk_clist_set_column_width(GTK_CLIST(clist_rev), 3, 80);
- gtk_clist_set_column_width(GTK_CLIST(clist_rev), 4, 40);
- gtk_clist_set_column_justification(GTK_CLIST(clist_rev), 0, GTK_JUSTIFY_CENTER);
- gtk_clist_set_column_justification(GTK_CLIST(clist_rev), 1, GTK_JUSTIFY_CENTER);
- gtk_clist_set_column_justification(GTK_CLIST(clist_rev), 2, GTK_JUSTIFY_CENTER);
- gtk_clist_set_column_justification(GTK_CLIST(clist_rev), 3, GTK_JUSTIFY_CENTER);
- gtk_clist_set_column_justification(GTK_CLIST(clist_rev), 4, GTK_JUSTIFY_CENTER);
- gtk_clist_set_column_justification(GTK_CLIST(clist_rev), 5, GTK_JUSTIFY_CENTER);
+ gtk_widget_show(scrolled_window_r);
+
+ label = gtk_label_new(" Reversed Direction ");
+ gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page_r, label);
/* page for help&about or future
page_help = gtk_hbox_new(FALSE, 5);
- label4 = gtk_label_new(" Future ");
- gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page_help, label4);
+ label = gtk_label_new(" Future ");
+ gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page_help, label);
frame = gtk_frame_new("");
text = gtk_label_new("\n\nMaybe some more statistics: delay and jitter distribution,...");
gtk_label_set_justify(GTK_LABEL(text), GTK_JUSTIFY_LEFT);
gtk_widget_show(csv_bt);
SIGNAL_CONNECT(csv_bt, "clicked", save_csv_as_cb, user_data);
- refresh_bt = gtk_button_new_with_label("Refresh");
+ refresh_bt = BUTTON_NEW_FROM_STOCK(GTK_STOCK_REFRESH);
gtk_container_add(GTK_CONTAINER(box4), refresh_bt);
gtk_widget_show(refresh_bt);
SIGNAL_CONNECT(refresh_bt, "clicked", on_refresh_bt_clicked, user_data);
- goto_bt = gtk_button_new_with_label("Go to frame");
+ goto_bt = BUTTON_NEW_FROM_STOCK(GTK_STOCK_JUMP_TO);
gtk_container_add(GTK_CONTAINER(box4), goto_bt);
gtk_widget_show(goto_bt);
SIGNAL_CONNECT(goto_bt, "clicked", on_goto_bt_clicked, user_data);
SIGNAL_CONNECT(graph_bt, "clicked", on_graph_bt_clicked, user_data);
#endif
- next_bt = gtk_button_new_with_label("Next");
+ next_bt = gtk_button_new_with_label("Next non-Ok");
gtk_container_add(GTK_CONTAINER(box4), next_bt);
gtk_widget_show(next_bt);
SIGNAL_CONNECT(next_bt, "clicked", on_next_bt_clicked, user_data);
- close_bt = gtk_button_new_with_label("Close");
+ close_bt = BUTTON_NEW_FROM_STOCK(GTK_STOCK_CLOSE);
gtk_container_add(GTK_CONTAINER(box4), close_bt);
gtk_widget_show(close_bt);
SIGNAL_CONNECT(close_bt, "clicked", on_close_bt_clicked, user_data);
gtk_widget_show(window);
+ /* sort by column feature */
+ col_arrows_fwd = add_sort_by_column(window, clist_fwd, user_data);
+ col_arrows_rev = add_sort_by_column(window, clist_rev, user_data);
+
+ /* some widget references need to be saved for outside use */
user_data->dlg.window = window;
user_data->dlg.clist_fwd = GTK_CLIST(clist_fwd);
user_data->dlg.clist_rev = GTK_CLIST(clist_rev);
user_data->dlg.notebook = notebook;
user_data->dlg.selected_clist = GTK_CLIST(clist_fwd);
user_data->dlg.selected_row = 0;
+ user_data->dlg.col_arrows_fwd = col_arrows_fwd;
+ user_data->dlg.col_arrows_rev = col_arrows_rev;
}
/****************************************************************************/
static gboolean process_node(proto_node *ptree_node, header_field_info *hfinformation,
- const gchar* proto_field, guint32* p_result)
+ gchar* proto_field, guint32* p_result)
{
field_info *finfo;
proto_node *proto_sibling_node;
finfo = PITEM_FINFO(ptree_node);
if (hfinformation==(finfo->hfinfo)) {
- hfssrc = proto_registrar_get_byname((gchar*) proto_field);
+ hfssrc = proto_registrar_get_byname(proto_field);
if (hfssrc == NULL)
return FALSE;
for(ptree_node=ptree_node->first_child; ptree_node!=NULL;
/****************************************************************************/
static gboolean get_int_value_from_proto_tree(proto_tree *protocol_tree,
- const gchar* proto_name,
- const gchar* proto_field,
+ gchar* proto_name,
+ gchar* proto_field,
guint32* p_result)
{
proto_node *ptree_node;
header_field_info *hfinformation;
- hfinformation = proto_registrar_get_byname((gchar*) proto_name);
+ hfinformation = proto_registrar_get_byname(proto_name);
if (hfinformation == NULL)
return FALSE;
}
+/* XXX just copied from gtk/rpc_stat.c */
+void protect_thread_critical_region(void);
+void unprotect_thread_critical_region(void);
+
/****************************************************************************/
/* XXX only handles RTP over IPv4, should add IPv6 support */
void rtp_analysis(
)
{
user_data_t *user_data;
- gchar filter_text[256];
- dfilter_t *sfcode;
- GString *error_string;
+ int fd;
+ /* init */
user_data = g_malloc(sizeof(user_data_t));
user_data->ip_src_fwd = ip_src_fwd;
user_data->port_dst_rev = port_dst_rev;
user_data->ssrc_rev = ssrc_rev;
- create_rtp_dialog(user_data);
-
- /* Try to compile the filter. */
- strcpy(filter_text,"rtp && ip");
- if (!dfilter_compile(filter_text, &sfcode)) {
- simple_dialog(ESD_TYPE_WARN | ESD_TYPE_MODAL, NULL, dfilter_error_msg);
- return;
- }
-
- sprintf(filter_text,"rtp && ip && !icmp && (( ip.src==%s && udp.srcport==%u && ip.dst==%s && udp.dstport==%u ) || ( ip.src==%s && udp.srcport==%u && ip.dst==%s && udp.dstport==%u ))",
- ip_to_str((ip_addr_p)&ip_src_fwd),
- port_src_fwd,
- ip_to_str((ip_addr_p)&ip_dst_fwd),
- port_dst_fwd,
- ip_to_str((ip_addr_p)&ip_src_rev),
- port_src_rev,
- ip_to_str((ip_addr_p)&ip_dst_rev),
- port_dst_rev
- );
-
- error_string = register_tap_listener("rtp", user_data, filter_text,
- (void*)rtp_reset, (void*)rtp_packet, (void*)rtp_draw);
- if (error_string != NULL) {
- simple_dialog(ESD_TYPE_WARN | ESD_TYPE_MODAL, NULL, error_string->str);
- g_string_free(error_string, TRUE);
- g_free(user_data);
- return;
- /*exit(1);*/
- }
-
/* file names for storing sound data */
- strncpy(user_data->f_tempname, "f_tempnameXXXXXX", TMPNAMSIZE);
- strncpy(user_data->r_tempname, "r_tempnameXXXXXX", TMPNAMSIZE);
- mkstemp(user_data->f_tempname);
- mkstemp(user_data->r_tempname);
+ /*XXX: check for errors*/
+ fd = create_tempfile(user_data->f_tempname, sizeof(user_data->f_tempname),
+ "ether_rtp_f");
+ close(fd);
+ fd = create_tempfile(user_data->r_tempname, sizeof(user_data->r_tempname),
+ "ether_rtp_r");
+ close(fd);
user_data->forward.saveinfo.fp = NULL;
user_data->reversed.saveinfo.fp = NULL;
user_data->dlg.save_voice_as_w = NULL;
user_data->series_rev.value_pairs = NULL;
#endif
- redissect_packets(&cfile);
+ /* create the dialog box */
+ create_rtp_dialog(user_data);
- draw_stat(user_data);
+ /* proceed as if the Refresh button would have been pressed */
+ on_refresh_bt_clicked(NULL, user_data);
}
/****************************************************************************/
capture_file *cf;
epan_dissect_t *edt;
gint err;
+ gchar *err_info;
gboolean frame_matched;
frame_data *fdata;
GList *strinfo_list;
return; /* if we exit here it's an error */
/* dissect the current frame */
- if (!wtap_seek_read(cf->wth, fdata->file_off, &cf->pseudo_header, cf->pd, fdata->cap_len, &err)) {
+ if (!wtap_seek_read(cf->wth, fdata->file_off, &cf->pseudo_header,
+ cf->pd, fdata->cap_len, &err, &err_info)) {
simple_dialog(ESD_TYPE_WARN | ESD_TYPE_MODAL, NULL,
- file_read_error_message(err), cf->filename);
+ cf_read_error_message(err, err_info), cf->filename);
return;
}
edt = epan_dissect_new(TRUE, FALSE);
/* if it is not an rtp frame, show the rtpstream dialog */
frame_matched = dfilter_apply_edt(sfcode, edt);
if (frame_matched != 1) {
- rtpstream_dlg_show(rtpstream_get_info()->strinfo_list);
- return;
-/*
epan_dissect_free(edt);
simple_dialog(ESD_TYPE_WARN | ESD_TYPE_MODAL, NULL, "You didn't choose a RTP packet!");
return;
-*/
}
/* ok, it is a RTP frame, so let's get the ip and port values */
void
register_tap_menu_rtp_analysis(void)
{
- register_tap_menu_item("Statistics/RTP Streams/Analyse...",
+ register_tap_menu_item("_Statistics/RTP Streams/Analyse...",
rtp_analysis_cb, NULL, NULL, NULL);
}