/* rtp_stream.c
* RTP streams summary addition for ethereal
*
- * $Id: rtp_stream.c,v 1.9 2004/01/31 02:25:46 ulfl Exp $
+ * $Id$
*
* Copyright 2003, Alcatel Business Systems
* By Lars Ruoff <lars.ruoff@gmx.net>
#include "globals.h"
-#include "tap.h"
+#include <epan/tap.h>
#include "register.h"
-#include "packet-rtp.h"
+#include <epan/dissectors/packet-rtp.h>
-#include <epan/filesystem.h>
+#include "alert_box.h"
#include "simple_dialog.h"
+#include "file_util.h"
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#include <string.h>
-
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
+#include <epan/addr_resolv.h>
/****************************************************************************/
/****************************************************************************/
/* GCompareFunc style comparison function for _rtp_stream_info */
-gint rtp_stream_info_cmp(gconstpointer aa, gconstpointer bb)
+static gint rtp_stream_info_cmp(gconstpointer aa, gconstpointer bb)
{
const struct _rtp_stream_info* a = aa;
const struct _rtp_stream_info* b = bb;
return 0;
if (a==NULL || b==NULL)
return 1;
- if ((a->src_addr == b->src_addr)
+ if (ADDRESSES_EQUAL(&(a->src_addr), &(b->src_addr))
&& (a->src_port == b->src_port)
- && (a->dest_addr == b->dest_addr)
+ && ADDRESSES_EQUAL(&(a->dest_addr), &(b->dest_addr))
&& (a->dest_port == b->dest_port)
&& (a->ssrc == b->ssrc))
return 0;
return;
}
+static void rtpstream_reset_cb(void *arg)
+{
+ rtpstream_reset(arg);
+}
+
/****************************************************************************/
/* redraw the output */
-void rtpstream_draw(rtpstream_tapinfo_t *tapinfo _U_)
+static void rtpstream_draw(void *arg _U_)
{
/* XXX: see rtpstream_on_update in rtp_streams_dlg.c for comments
gtk_signal_emit_by_name(top_level, "signal_rtpstream_update");
guint16 padding; /* 2 padding bytes */
fprintf(file, "#!rtpplay%s %s/%u\n", RTPFILE_VERSION,
- ip_to_str((guint8*) &strinfo->dest_addr),
+ get_addr_name(&(strinfo->dest_addr)),
strinfo->dest_port);
start_sec = g_htonl(strinfo->start_sec);
start_usec = g_htonl(strinfo->start_usec);
- source = strinfo->src_addr; /* already is in network order */
+ source = *(strinfo->src_addr.data); /* rtpdump only accepts guint32 as source, will be fake for IPv6 */
port = g_htons(strinfo->src_port);
padding = 0;
/****************************************************************************/
/* whenever a RTP packet is seen by the tap listener */
-int rtpstream_packet(rtpstream_tapinfo_t *tapinfo _U_, packet_info *pinfo, epan_dissect_t *edt _U_, struct _rtp_info *rtpinfo _U_)
+static int rtpstream_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt _U_, const void *arg2)
{
+ rtpstream_tapinfo_t *tapinfo = arg;
+ const struct _rtp_info *rtpinfo = arg2;
rtp_stream_info_t tmp_strinfo;
rtp_stream_info_t *strinfo = NULL;
GList* list;
-
rtp_sample_t sample;
+ struct _rtp_conversation_info *p_conv_data = NULL;
+
/* gather infos on the stream this packet is part of */
- g_memmove(&(tmp_strinfo.src_addr), pinfo->src.data, 4);
+ COPY_ADDRESS(&(tmp_strinfo.src_addr), &(pinfo->src));
tmp_strinfo.src_port = pinfo->srcport;
- g_memmove(&(tmp_strinfo.dest_addr), pinfo->dst.data, 4);
+ COPY_ADDRESS(&(tmp_strinfo.dest_addr), &(pinfo->dst));
tmp_strinfo.dest_port = pinfo->destport;
tmp_strinfo.ssrc = rtpinfo->info_sync_src;
tmp_strinfo.pt = rtpinfo->info_payload_type;
if (!strinfo) {
tmp_strinfo.npackets = 0;
tmp_strinfo.first_frame_num = pinfo->fd->num;
- tmp_strinfo.start_sec = pinfo->fd->abs_secs;
- tmp_strinfo.start_usec = pinfo->fd->abs_usecs;
+ tmp_strinfo.start_sec = pinfo->fd->abs_ts.secs;
+ tmp_strinfo.start_usec = pinfo->fd->abs_ts.nsecs/1000;
+ tmp_strinfo.start_rel_sec = pinfo->fd->rel_ts.secs;
+ tmp_strinfo.start_rel_usec = pinfo->fd->rel_ts.nsecs/1000;
tmp_strinfo.tag_vlan_error = 0;
tmp_strinfo.tag_diffserv_error = 0;
tmp_strinfo.vlan_id = 0;
+ tmp_strinfo.problem = FALSE;
+
+ /* reset RTP stats */
+ tmp_strinfo.rtp_stats.first_packet = TRUE;
+ tmp_strinfo.rtp_stats.max_delta = 0;
+ tmp_strinfo.rtp_stats.max_jitter = 0;
+ tmp_strinfo.rtp_stats.mean_jitter = 0;
+ tmp_strinfo.rtp_stats.delta = 0;
+ tmp_strinfo.rtp_stats.diff = 0;
+ tmp_strinfo.rtp_stats.jitter = 0;
+ tmp_strinfo.rtp_stats.bandwidth = 0;
+ tmp_strinfo.rtp_stats.total_bytes = 0;
+ tmp_strinfo.rtp_stats.bw_start_index = 0;
+ tmp_strinfo.rtp_stats.bw_index = 0;
+ tmp_strinfo.rtp_stats.timestamp = 0;
+ tmp_strinfo.rtp_stats.max_nr = 0;
+ tmp_strinfo.rtp_stats.total_nr = 0;
+ tmp_strinfo.rtp_stats.sequence = 0;
+ tmp_strinfo.rtp_stats.start_seq_nr = 0;
+ tmp_strinfo.rtp_stats.stop_seq_nr = 0;
+ tmp_strinfo.rtp_stats.cycles = 0;
+ tmp_strinfo.rtp_stats.under = FALSE;
+ tmp_strinfo.rtp_stats.start_time = 0;
+ tmp_strinfo.rtp_stats.time = 0;
+ tmp_strinfo.rtp_stats.reg_pt = PT_UNDEFINED;
+
+ /* Get the Setup frame number who set this RTP stream */
+ p_conv_data = p_get_proto_data(pinfo->fd, proto_get_id_by_filter_name("rtp"));
+ if (p_conv_data)
+ tmp_strinfo.setup_frame_number = p_conv_data->frame_number;
+ else
+ tmp_strinfo.setup_frame_number = 0xFFFFFFFF;
+
strinfo = g_malloc(sizeof(rtp_stream_info_t));
*strinfo = tmp_strinfo; /* memberwise copy of struct */
tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
}
+ /* get RTP stats for the packet */
+ rtp_packet_analyse(&(strinfo->rtp_stats), pinfo, rtpinfo);
+ if (strinfo->rtp_stats.flags & STAT_FLAG_WRONG_TIMESTAMP
+ || strinfo->rtp_stats.flags & STAT_FLAG_WRONG_SEQ)
+ strinfo->problem = TRUE;
+
+
/* increment the packets counter for this stream */
++(strinfo->npackets);
+ strinfo->stop_rel_sec = pinfo->fd->rel_ts.secs;
+ strinfo->stop_rel_usec = pinfo->fd->rel_ts.nsecs/1000;
/* increment the packets counter of all streams */
++(tapinfo->npackets);
}
else if (tapinfo->mode == TAP_SAVE) {
if (rtp_stream_info_cmp(&tmp_strinfo, tapinfo->filter_stream_fwd)==0) {
+ /* XXX - what if rtpinfo->info_all_data_present is
+ FALSE, so that we don't *have* all the data? */
sample.header.rec_time =
- (pinfo->fd->abs_usecs + 1000000 - tapinfo->filter_stream_fwd->start_usec)/1000
- + (pinfo->fd->abs_secs - tapinfo->filter_stream_fwd->start_sec - 1)*1000;
+ (pinfo->fd->abs_ts.nsecs/1000 + 1000000 - tapinfo->filter_stream_fwd->start_usec)/1000
+ + (pinfo->fd->abs_ts.secs - tapinfo->filter_stream_fwd->start_sec - 1)*1000;
sample.header.frame_length = rtpinfo->info_data_len;
sample.frame = rtpinfo->info_data;
rtp_write_sample(&sample, tapinfo->save_file);
}
}
else if (tapinfo->mode == TAP_MARK) {
+
if (rtp_stream_info_cmp(&tmp_strinfo, tapinfo->filter_stream_fwd)==0
|| rtp_stream_info_cmp(&tmp_strinfo, tapinfo->filter_stream_rev)==0)
{
- mark_frame(&cfile, pinfo->fd);
+ cf_mark_frame(&cfile, pinfo->fd);
}
}
register_tap_listener_rtp_stream();
the_tapinfo_struct.mode = TAP_ANALYSE;
- retap_packets(&cfile);
+ cf_retap_packets(&cfile, FALSE);
if (!was_registered)
remove_tap_listener_rtp_stream();
{
gboolean was_registered = the_tapinfo_struct.is_registered;
/* open file for saving */
- the_tapinfo_struct.save_file = fopen(filename, "wb");
+ the_tapinfo_struct.save_file = eth_fopen(filename, "wb");
if (the_tapinfo_struct.save_file==NULL) {
- simple_dialog(ESD_TYPE_ERROR, NULL,
- file_open_error_message(errno, TRUE), filename);
+ open_failure_alert_box(filename, errno, TRUE);
return FALSE;
}
rtp_write_header(stream, the_tapinfo_struct.save_file);
if (ferror(the_tapinfo_struct.save_file)) {
- simple_dialog(ESD_TYPE_ERROR, NULL,
- file_write_error_message(errno), filename);
+ write_failure_alert_box(filename, errno);
fclose(the_tapinfo_struct.save_file);
return FALSE;
}
the_tapinfo_struct.mode = TAP_SAVE;
the_tapinfo_struct.filter_stream_fwd = stream;
- retap_packets(&cfile);
+ cf_retap_packets(&cfile, FALSE);
the_tapinfo_struct.mode = TAP_ANALYSE;
if (!was_registered)
remove_tap_listener_rtp_stream();
if (ferror(the_tapinfo_struct.save_file)) {
- simple_dialog(ESD_TYPE_ERROR, NULL,
- file_write_error_message(errno), filename);
+ write_failure_alert_box(filename, errno);
fclose(the_tapinfo_struct.save_file);
return FALSE;
}
if (fclose(the_tapinfo_struct.save_file) == EOF) {
- simple_dialog(ESD_TYPE_ERROR, NULL,
- file_write_error_message(errno), filename);
+ write_failure_alert_box(filename, errno);
return FALSE;
}
return TRUE;
the_tapinfo_struct.mode = TAP_MARK;
the_tapinfo_struct.filter_stream_fwd = stream_fwd;
the_tapinfo_struct.filter_stream_rev = stream_rev;
- retap_packets(&cfile);
+ cf_retap_packets(&cfile, FALSE);
the_tapinfo_struct.mode = TAP_ANALYSE;
if (!was_registered)
/* TAP INTERFACE */
/****************************************************************************/
-/****************************************************************************/
-static void
-rtpstream_init_tap(char *dummy _U_)
-{
- /* XXX: never called? */
-}
-
-
/* XXX just copied from gtk/rpc_stat.c */
void protect_thread_critical_region(void);
void unprotect_thread_critical_region(void);
GString *error_string;
if (!the_tapinfo_struct.is_registered) {
- register_ethereal_tap("rtp", rtpstream_init_tap);
-
error_string = register_tap_listener("rtp", &the_tapinfo_struct,
- NULL,
- (void*)rtpstream_reset, (void*)rtpstream_packet, (void*)rtpstream_draw);
+ NULL, rtpstream_reset_cb, rtpstream_packet,
+ rtpstream_draw);
if (error_string != NULL) {
- simple_dialog(ESD_TYPE_WARN | ESD_TYPE_MODAL, NULL, error_string->str);
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+ error_string->str);
g_string_free(error_string, TRUE);
exit(1);
}