/* rtp_stream.c
- * RTP streams summary addition for ethereal
+ * RTP streams summary addition for Wireshark
*
* $Id$
*
* Copyright 2003, Alcatel Business Systems
* By Lars Ruoff <lars.ruoff@gmx.net>
*
- * Ethereal - Network traffic analyzer
- * By Gerald Combs <gerald@ethereal.com>
+ * 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
# include "config.h"
#endif
-#include "rtp_stream.h"
-#include "rtp_stream_dlg.h"
-
-#include "globals.h"
-
-#include <epan/tap.h>
-#include "register.h"
-#include <epan/dissectors/packet-rtp.h>
-
-
-#include "alert_box.h"
-#include "simple_dialog.h"
+#include <stdio.h>
+#include <string.h>
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
# include <sys/types.h>
#endif
-#include <string.h>
-#include <epan/addr_resolv.h>
-
-
-/****************************************************************************/
-/* the one and only global rtpstream_tapinfo_t structure */
-static rtpstream_tapinfo_t the_tapinfo_struct =
- {0, NULL, 0, TAP_ANALYSE, NULL, NULL, NULL, 0, FALSE};
-
-
-/****************************************************************************/
-/* GCompareFunc style comparison function for _rtp_stream_info */
-gint rtp_stream_info_cmp(gconstpointer aa, gconstpointer bb)
-{
- const struct _rtp_stream_info* a = aa;
- const struct _rtp_stream_info* b = bb;
-
- if (a==b)
- return 0;
- if (a==NULL || b==NULL)
- return 1;
- if (ADDRESSES_EQUAL(&(a->src_addr), &(b->src_addr))
- && (a->src_port == b->src_port)
- && ADDRESSES_EQUAL(&(a->dest_addr), &(b->dest_addr))
- && (a->dest_port == b->dest_port)
- && (a->ssrc == b->ssrc))
- return 0;
- else
- return 1;
-}
+#include <epan/epan.h>
+#include <epan/packet.h>
+#include <epan/tap.h>
+#include <epan/dissectors/packet-rtp.h>
+#include <epan/addr_resolv.h>
-/****************************************************************************/
-/* when there is a [re]reading of packet's */
-void rtpstream_reset(rtpstream_tapinfo_t *tapinfo)
-{
- GList* list;
-
- if (tapinfo->mode == TAP_ANALYSE) {
- /* free the data items first */
- list = g_list_first(tapinfo->strinfo_list);
- while (list)
- {
- g_free(list->data);
- list = g_list_next(list);
- }
- g_list_free(tapinfo->strinfo_list);
- tapinfo->strinfo_list = NULL;
- tapinfo->nstreams = 0;
- tapinfo->npackets = 0;
- }
+#include "../globals.h"
+#include "../register.h"
+#include "../alert_box.h"
+#include "../simple_dialog.h"
+#include "../tap-rtp-common.h"
+#include <wsutil/file_util.h>
- ++(tapinfo->launch_count);
+#include "gtk/rtp_stream.h"
+#include "gtk/rtp_stream_dlg.h"
+#include "gtk/main.h"
- return;
-}
+/* The one and only global rtpstream_tapinfo_t structure for tshark and wireshark.
+ */
+static rtpstream_tapinfo_t the_tapinfo_struct =
+ {0, NULL, 0, TAP_ANALYSE, NULL, NULL, NULL, 0, FALSE};
-static void rtpstream_reset_cb(void *arg)
-{
- rtpstream_reset(arg);
-}
/****************************************************************************/
/* redraw the output */
-void rtpstream_draw(void *arg _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");
+ g_signal_emit_by_name(top_level, "signal_rtpstream_update");
*/
rtpstream_dlg_update(the_tapinfo_struct.strinfo_list);
return;
}
-/*
-* rtpdump file format
-*
-* The file starts with the tool to be used for playing this file,
-* the multicast/unicast receive address and the port.
-*
-* #!rtpplay1.0 224.2.0.1/3456\n
-*
-* This is followed by one binary header (RD_hdr_t) and one RD_packet_t
-* structure for each received packet. All fields are in network byte
-* order. We don't need the source IP address since we can do mapping
-* based on SSRC. This saves (a little) space, avoids non-IPv4
-* problems and privacy/security concerns. The header is followed by
-* the RTP/RTCP header and (optionally) the actual payload.
-*/
-
-#define RTPFILE_VERSION "1.0"
-
-/*
-* Write a header to the current output file.
-* The header consists of an identifying string, followed
-* by a binary structure.
-*/
-static void rtp_write_header(rtp_stream_info_t *strinfo, FILE *file)
-{
- guint32 start_sec; /* start of recording (GMT) (seconds) */
- guint32 start_usec; /* start of recording (GMT) (microseconds)*/
- guint32 source; /* network source (multicast address) */
- guint16 port; /* UDP port */
- guint16 padding; /* 2 padding bytes */
-
- fprintf(file, "#!rtpplay%s %s/%u\n", RTPFILE_VERSION,
- 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.data); /* rtpdump only accepts guint32 as source, will be fake for IPv6 */
- port = g_htons(strinfo->src_port);
- padding = 0;
-
- fwrite(&start_sec, 4, 1, file);
- fwrite(&start_usec, 4, 1, file);
- fwrite(&source, 4, 1, file);
- fwrite(&port, 2, 1, file);
- fwrite(&padding, 2, 1, file);
-}
-
-/* utility function for writing a sample to file in rtpdump -F dump format (.rtp)*/
-static void rtp_write_sample(rtp_sample_t* sample, FILE* file)
-{
- guint16 length; /* length of packet, including this header (may
- be smaller than plen if not whole packet recorded) */
- guint16 plen; /* actual header+payload length for RTP, 0 for RTCP */
- guint32 offset; /* milliseconds since the start of recording */
-
- length = g_htons(sample->header.frame_length + 8);
- plen = g_htons(sample->header.frame_length);
- offset = g_htonl(sample->header.rec_time);
-
- fwrite(&length, 2, 1, file);
- fwrite(&plen, 2, 1, file);
- fwrite(&offset, 4, 1, file);
- fwrite(sample->frame, sample->header.frame_length, 1, file);
-}
-
-
-/****************************************************************************/
-/* whenever a RTP packet is seen by the tap listener */
-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 */
- COPY_ADDRESS(&(tmp_strinfo.src_addr), &(pinfo->src));
- tmp_strinfo.src_port = pinfo->srcport;
- 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 (tapinfo->mode == TAP_ANALYSE) {
- /* check wether we already have a stream with these parameters in the list */
- list = g_list_first(tapinfo->strinfo_list);
- while (list)
- {
- if (rtp_stream_info_cmp(&tmp_strinfo, (rtp_stream_info_t*)(list->data))==0)
- {
- strinfo = (rtp_stream_info_t*)(list->data); /*found!*/
- break;
- }
- list = g_list_next(list);
- }
-
- /* not in the list? then create a new entry */
- 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_rel_sec = pinfo->fd->rel_secs;
- tmp_strinfo.start_rel_usec = pinfo->fd->rel_usecs;
- 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_secs;
- strinfo->stop_rel_usec = pinfo->fd->rel_usecs;
-
- /* increment the packets counter of all streams */
- ++(tapinfo->npackets);
-
- return 1; /* refresh output */
- }
- 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;
- 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)
- {
- cf_mark_frame(&cfile, pinfo->fd);
- }
- }
-
- return 0;
-}
-
/****************************************************************************/
/* scan for RTP streams */
void rtpstream_scan(void)
{
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 = ws_fopen(filename, "wb");
if (the_tapinfo_struct.save_file==NULL) {
open_failure_alert_box(filename, errno, TRUE);
return FALSE;
/* 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);
-
/****************************************************************************/
void
remove_tap_listener_rtp_stream(void)
GString *error_string;
if (!the_tapinfo_struct.is_registered) {
- register_tap_listener_cmd_arg("rtp", rtpstream_init_tap);
-
error_string = register_tap_listener("rtp", &the_tapinfo_struct,
- NULL, rtpstream_reset_cb, rtpstream_packet,
+ NULL, 0, rtpstream_reset_cb, rtpstream_packet,
rtpstream_draw);
if (error_string != NULL) {
simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
- error_string->str);
+ "%s", error_string->str);
g_string_free(error_string, TRUE);
exit(1);
}