RTP: Code clean up

Changes:
- rtpstream_packet renamed to rtpstream_packet_cb to follow *_cb pattern
- variables/types used in iax2_analysis_dialog were created as copy of *rtp* ones, but names were left as *rtp* -> *iax2*
- struct _rtp_stream_info replaced with rtp_stream_info_t
- there was tap-rtp-analysis.h, but no tap-rtp-analysis.c - related content was moved from tap-rtp-common.c
- *rtp_stream* functions renamed to *rtpstream*
- renamed rtp_stream_info_t to rtpstream_info_t to follow *rtpstream* pattern.
- renamed ui/rtp_stream.c rtpstream_draw -> rtpstream_draw_cb

Change-Id: Ib11ff5367cc464ea1b0c73432bc50b0eb9cd203e
Reviewed-on: https://code.wireshark.org/review/28299
Reviewed-by: Anders Broman <a.broman58@gmail.com>
This commit is contained in:
Jiri Novak 2018-06-14 23:19:01 +02:00 committed by Anders Broman
parent 434fbe20dd
commit 27a1906c58
21 changed files with 597 additions and 556 deletions

View File

@ -50,6 +50,7 @@
#include <ui/voip_calls.h>
#include <ui/rtp_stream.h>
#include <ui/tap-rtp-common.h>
#include <ui/tap-rtp-analysis.h>
#include <epan/to_str.h>
#include <epan/addr_resolv.h>
@ -1335,7 +1336,7 @@ sharkd_session_packet_tap_rtp_analyse_cb(void *tapdata, packet_info *pinfo, epan
tap_rtp_stat_t *statinfo = &(rtp_req->statinfo);
struct sharkd_analyse_rtp_items *item;
rtp_packet_analyse(statinfo, pinfo, rtpinfo);
rtppacket_analyse(statinfo, pinfo, rtpinfo);
item = (struct sharkd_analyse_rtp_items *) g_malloc(sizeof(struct sharkd_analyse_rtp_items));
@ -2095,7 +2096,7 @@ sharkd_session_process_tap_rtp_cb(void *arg)
printf(",\"streams\":[");
for (listx = g_list_first(rtp_tapinfo->strinfo_list); listx; listx = listx->next)
{
rtp_stream_info_t *streaminfo = (rtp_stream_info_t *) listx->data;
rtpstream_info_t *streaminfo = (rtpstream_info_t *) listx->data;
char *src_addr, *dst_addr;
char *payload;
@ -2432,7 +2433,7 @@ sharkd_session_process_tap(char *buf, const jsmntok_t *tokens, int count)
}
else if (!strcmp(tok_tap, "rtp-streams"))
{
tap_error = register_tap_listener("rtp", &rtp_tapinfo, tap_filter, 0, rtpstream_reset_cb, rtpstream_packet, sharkd_session_process_tap_rtp_cb);
tap_error = register_tap_listener("rtp", &rtp_tapinfo, tap_filter, 0, rtpstream_reset_cb, rtpstream_packet_cb, sharkd_session_process_tap_rtp_cb);
tap_data = &rtp_tapinfo;
tap_free = rtpstream_reset_cb;

View File

@ -42,6 +42,7 @@ set(NONGENERATED_UI_SRC
summary.c
tap_export_pdu.c
tap-iax2-analysis.c
tap-rtp-analysis.c
tap-rtp-common.c
tap-sctp-analysis.c
tap-rlc-graph.c

View File

@ -48,7 +48,7 @@ static void
rtp_streams_stat_draw(void *arg _U_)
{
GList *list;
rtp_stream_info_t *strinfo;
rtpstream_info_t *strinfo;
gchar *payload_type;
guint32 expected;
gint32 lost;
@ -70,7 +70,7 @@ rtp_streams_stat_draw(void *arg _U_)
list = g_list_first(list);
while (list)
{
strinfo = (rtp_stream_info_t*)(list->data);
strinfo = (rtpstream_info_t*)(list->data);
/* payload type */
if (strinfo->payload_type > 95) {
@ -132,7 +132,7 @@ rtp_streams_stat_init(const char *opt_arg _U_, void *userdata _U_)
err_p =
register_tap_listener("rtp", &the_tapinfo_struct, NULL, 0,
rtpstream_reset_cb,
rtpstream_packet,
rtpstream_packet_cb,
rtp_streams_stat_draw);
if (err_p != NULL)

View File

@ -358,7 +358,7 @@ Iax2AnalysisDialog::Iax2AnalysisDialog(QWidget &parent, CaptureFile &cf) :
tapinfo.tap_data = this;
tapinfo.mode = TAP_ANALYSE;
// register_tap_listener_rtp_stream(&tapinfo, NULL);
// register_tap_listener_rtpstream(&tapinfo, NULL);
/* Scan for RTP streams (redissect all packets) */
rtpstream_scan(&tapinfo, cap_file_.capFile(), NULL);
@ -411,7 +411,7 @@ Iax2AnalysisDialog::Iax2AnalysisDialog(QWidget &parent, CaptureFile &cf) :
Iax2AnalysisDialog::~Iax2AnalysisDialog()
{
delete ui;
// remove_tap_listener_rtp_stream(&tapinfo);
// remove_tap_listener_rtpstream(&tapinfo);
delete fwd_tempfile_;
delete rev_tempfile_;
}

View File

@ -230,7 +230,7 @@ enum {
num_graphs_
};
RtpAnalysisDialog::RtpAnalysisDialog(QWidget &parent, CaptureFile &cf, struct _rtp_stream_info *stream_fwd, struct _rtp_stream_info *stream_rev) :
RtpAnalysisDialog::RtpAnalysisDialog(QWidget &parent, CaptureFile &cf, rtpstream_info_t *stream_fwd, rtpstream_info_t *stream_rev) :
WiresharkDialog(parent, cf),
ui(new Ui::RtpAnalysisDialog),
port_src_fwd_(0),
@ -408,7 +408,7 @@ RtpAnalysisDialog::RtpAnalysisDialog(QWidget &parent, CaptureFile &cf, struct _r
RtpAnalysisDialog::~RtpAnalysisDialog()
{
delete ui;
// remove_tap_listener_rtp_stream(&tapinfo_);
// remove_tap_listener_rtpstream(&tapinfo_);
delete fwd_tempfile_;
delete rev_tempfile_;
}
@ -760,7 +760,7 @@ void RtpAnalysisDialog::addPacket(bool forward, packet_info *pinfo, const _rtp_i
// add_rtp_packet(rtpinfo, pinfo);
if (forward) {
rtp_packet_analyse(&fwd_statinfo_, pinfo, rtpinfo);
rtppacket_analyse(&fwd_statinfo_, pinfo, rtpinfo);
new RtpAnalysisTreeWidgetItem(ui->forwardTreeWidget, &fwd_statinfo_, pinfo, rtpinfo);
fwd_time_vals_.append(fwd_statinfo_.time / 1000);
@ -770,7 +770,7 @@ void RtpAnalysisDialog::addPacket(bool forward, packet_info *pinfo, const _rtp_i
savePayload(fwd_tempfile_, &fwd_statinfo_, pinfo, rtpinfo);
} else {
rtp_packet_analyse(&rev_statinfo_, pinfo, rtpinfo);
rtppacket_analyse(&rev_statinfo_, pinfo, rtpinfo);
new RtpAnalysisTreeWidgetItem(ui->reverseTreeWidget, &rev_statinfo_, pinfo, rtpinfo);
rev_time_vals_.append(rev_statinfo_.time / 1000);
@ -854,7 +854,7 @@ void RtpAnalysisDialog::savePayload(QTemporaryFile *tmpfile, tap_rtp_stat_t *sta
if (nchars != sizeof(save_data)) {
/* Write error or short write */
err_str_ = tr("Can't save in a file: File I/O problem.");
save_payload_error_ = TAP_RTP_FILE_IO_ERROR;
save_payload_error_ = TAP_RTP_FILE_WRITE_ERROR;
tmpfile->close();
return;
}
@ -863,7 +863,7 @@ void RtpAnalysisDialog::savePayload(QTemporaryFile *tmpfile, tap_rtp_stat_t *sta
if (nchars != save_data.payload_len) {
/* Write error or short write */
err_str_ = tr("Can't save in a file: File I/O problem.");
save_payload_error_ = TAP_RTP_FILE_IO_ERROR;
save_payload_error_ = TAP_RTP_FILE_WRITE_ERROR;
tmpfile->close();
return;
}
@ -1037,7 +1037,7 @@ void RtpAnalysisDialog::showPlayer()
if (num_streams_ < 1) return;
RtpPlayerDialog rtp_player_dialog(*this, cap_file_);
rtp_stream_info_t stream_info;
rtpstream_info_t stream_info;
// XXX We might want to create an "rtp_stream_id_t" struct with only
// addresses, ports & SSRC.
@ -1646,12 +1646,12 @@ void RtpAnalysisDialog::findStreams()
tapinfo_.tap_data = this;
tapinfo_.mode = TAP_ANALYSE;
// register_tap_listener_rtp_stream(&tapinfo_, NULL);
// register_tap_listener_rtpstream(&tapinfo_, NULL);
/* Scan for RTP streams (redissect all packets) */
rtpstream_scan(&tapinfo_, cap_file_.capFile(), NULL);
for (GList *strinfo_list = g_list_first(tapinfo_.strinfo_list); strinfo_list; strinfo_list = g_list_next(strinfo_list)) {
rtp_stream_info_t * strinfo = (rtp_stream_info_t*)(strinfo_list->data);
rtpstream_info_t * strinfo = (rtpstream_info_t*)(strinfo_list->data);
if (addresses_equal(&(strinfo->src_addr), &(src_fwd_))
&& (strinfo->src_port == port_src_fwd_)
&& (addresses_equal(&(strinfo->dest_addr), &(dst_fwd_)))

View File

@ -17,6 +17,7 @@
#include "epan/address.h"
#include "ui/rtp_stream.h"
#include "ui/tap-rtp-common.h"
#include "ui/tap-rtp-analysis.h"
#include <QAbstractButton>
@ -32,19 +33,12 @@ class RtpAnalysisDialog;
class QCPGraph;
class QTemporaryFile;
typedef enum {
TAP_RTP_NO_ERROR,
TAP_RTP_WRONG_LENGTH,
TAP_RTP_PADDING_ERROR,
TAP_RTP_FILE_IO_ERROR
} rtp_error_type_t;
class RtpAnalysisDialog : public WiresharkDialog
{
Q_OBJECT
public:
explicit RtpAnalysisDialog(QWidget &parent, CaptureFile &cf, struct _rtp_stream_info *stream_fwd = 0, struct _rtp_stream_info *stream_rev = 0);
explicit RtpAnalysisDialog(QWidget &parent, CaptureFile &cf, rtpstream_info_t *stream_fwd = 0, rtpstream_info_t *stream_rev = 0);
~RtpAnalysisDialog();
signals:
@ -132,7 +126,7 @@ private:
rtpstream_tapinfo_t tapinfo_;
QString err_str_;
rtp_error_type_t save_payload_error_;
tap_rtp_error_type_t save_payload_error_;
QMenu stream_ctx_menu_;
QMenu graph_ctx_menu_;

View File

@ -38,7 +38,7 @@
static spx_int16_t default_audio_sample_rate_ = 8000;
static const spx_int16_t visual_sample_rate_ = 1000;
RtpAudioStream::RtpAudioStream(QObject *parent, _rtp_stream_info *rtp_stream) :
RtpAudioStream::RtpAudioStream(QObject *parent, rtpstream_info_t *rtp_stream) :
QObject(parent),
decoders_hash_(rtp_decoder_hash_table_new()),
global_start_rel_time_(0.0),
@ -84,7 +84,7 @@ RtpAudioStream::~RtpAudioStream()
speex_resampler_destroy (visual_resampler_);
}
bool RtpAudioStream::isMatch(const _rtp_stream_info *rtp_stream) const
bool RtpAudioStream::isMatch(const rtpstream_info_t *rtp_stream) const
{
if (rtp_stream
&& addresses_equal(&rtp_stream->src_addr, &src_addr_)
@ -111,7 +111,7 @@ bool RtpAudioStream::isMatch(const _packet_info *pinfo, const _rtp_info *rtp_inf
// XXX We add multiple RTP streams here because that's what the GTK+ UI does.
// Should we make these distinct, with their own waveforms? It seems like
// that would simplify a lot of things.
void RtpAudioStream::addRtpStream(const _rtp_stream_info *rtp_stream)
void RtpAudioStream::addRtpStream(const rtpstream_info_t *rtp_stream)
{
if (!rtp_stream) return;
@ -296,7 +296,7 @@ void RtpAudioStream::decode()
silence_timestamps_.append(stop_rel_time_);
decoded_bytes_prev = 0;
/* defined start_timestmp to avoid overflow in timestamp. TODO: handle the timestamp correctly */
/* defined start_timestamp to avoid overflow in timestamp. TODO: handle the timestamp correctly */
/* XXX: if timestamps (RTP) are missing/ignored try use packet arrive time only (see also "rtp_time") */
start_timestamp = rtp_packet->info->info_timestamp;
start_rtp_time = 0;

View File

@ -17,6 +17,7 @@
#include <glib.h>
#include <epan/address.h>
#include <ui/rtp_stream.h>
#include <QAudio>
#include <QColor>
@ -30,7 +31,6 @@ class QAudioOutput;
class QTemporaryFile;
struct _rtp_info;
struct _rtp_stream_info;
struct _rtp_sample;
class RtpAudioStream : public QObject
@ -39,11 +39,11 @@ class RtpAudioStream : public QObject
public:
enum TimingMode { JitterBuffer, RtpTimestamp, Uninterrupted };
explicit RtpAudioStream(QObject *parent, struct _rtp_stream_info *rtp_stream);
explicit RtpAudioStream(QObject *parent, rtpstream_info_t *rtp_stream);
~RtpAudioStream();
bool isMatch(const struct _rtp_stream_info *rtp_stream) const;
bool isMatch(const rtpstream_info_t *rtp_stream) const;
bool isMatch(const struct _packet_info *pinfo, const struct _rtp_info *rtp_info) const;
void addRtpStream(const struct _rtp_stream_info *rtp_stream);
void addRtpStream(const rtpstream_info_t *rtp_stream);
void addRtpPacket(const struct _packet_info *pinfo, const struct _rtp_info *rtp_info);
void reset(double start_rel_time);
void decode();
@ -150,7 +150,7 @@ private:
QVector<struct _rtp_packet *>rtp_packets_;
QTemporaryFile *tempfile_;
struct _GHashTable *decoders_hash_;
QList<const struct _rtp_stream_info *>rtp_streams_;
QList<const rtpstream_info_t *>rtp_streams_;
double global_start_rel_time_;
double start_abs_offset_;
double start_rel_time_;

View File

@ -353,7 +353,7 @@ void RtpPlayerDialog::rescanPackets(bool rescale_axes)
updateWidgets();
}
void RtpPlayerDialog::addRtpStream(struct _rtp_stream_info *rtp_stream)
void RtpPlayerDialog::addRtpStream(rtpstream_info_t *rtp_stream)
{
if (!rtp_stream) return;
@ -771,7 +771,7 @@ void RtpPlayerDialog::on_buttonBox_helpRequested()
#if 0
// This also serves as a title in RtpAudioFrame.
static const QString stream_key_tmpl_ = "%1:%2 " UTF8_RIGHTWARDS_ARROW " %3:%4 0x%5";
const QString RtpPlayerDialog::streamKey(const struct _rtp_stream_info *rtp_stream)
const QString RtpPlayerDialog::streamKey(const rtpstream_info_t *rtp_stream)
{
const QString stream_key = QString(stream_key_tmpl_)
.arg(address_to_display_qstring(&rtp_stream->src_addr))

View File

@ -24,8 +24,6 @@ namespace Ui {
class RtpPlayerDialog;
}
struct _rtp_stream_info;
class QCPItemStraightLine;
class QDialogButtonBox;
class QMenu;
@ -62,7 +60,7 @@ public:
*
* @param rtp_stream struct with rtp_stream info
*/
void addRtpStream(struct _rtp_stream_info *rtp_stream);
void addRtpStream(rtpstream_info_t *rtp_stream);
public slots:
@ -115,7 +113,7 @@ private:
QCPItemStraightLine *cur_play_pos_;
QString playback_error_;
// const QString streamKey(const struct _rtp_stream_info *rtp_stream);
// const QString streamKey(const rtp_stream_info_t *rtp_stream);
// const QString streamKey(const packet_info *pinfo, const struct _rtp_info *rtpinfo);
// Tap callbacks

View File

@ -73,14 +73,14 @@ enum { rtp_stream_type_ = 1000 };
class RtpStreamTreeWidgetItem : public QTreeWidgetItem
{
public:
RtpStreamTreeWidgetItem(QTreeWidget *tree, rtp_stream_info_t *stream_info) :
RtpStreamTreeWidgetItem(QTreeWidget *tree, rtpstream_info_t *stream_info) :
QTreeWidgetItem(tree, rtp_stream_type_),
stream_info_(stream_info)
{
drawData();
}
rtp_stream_info_t *streamInfo() const { return stream_info_; }
rtpstream_info_t *streamInfo() const { return stream_info_; }
void drawData() {
if (!stream_info_) {
@ -199,7 +199,7 @@ public:
}
private:
rtp_stream_info_t *stream_info_;
rtpstream_info_t *stream_info_;
guint32 lost_;
};
@ -258,7 +258,7 @@ RtpStreamDialog::RtpStreamDialog(QWidget &parent, CaptureFile &cf) :
tapinfo_.tap_data = this;
tapinfo_.mode = TAP_ANALYSE;
register_tap_listener_rtp_stream(&tapinfo_, NULL);
register_tap_listener_rtpstream(&tapinfo_, NULL);
/* Scan for RTP streams (redissect all packets) */
rtpstream_scan(&tapinfo_, cf.capFile(), NULL);
@ -268,7 +268,7 @@ RtpStreamDialog::RtpStreamDialog(QWidget &parent, CaptureFile &cf) :
RtpStreamDialog::~RtpStreamDialog()
{
delete ui;
remove_tap_listener_rtp_stream(&tapinfo_);
remove_tap_listener_rtpstream(&tapinfo_);
}
bool RtpStreamDialog::eventFilter(QObject *, QEvent *event)
@ -336,7 +336,7 @@ void RtpStreamDialog::updateStreams()
// Add any missing items
while (cur_stream && cur_stream->data) {
rtp_stream_info_t *stream_info = (rtp_stream_info_t*) cur_stream->data;
rtpstream_info_t *stream_info = (rtpstream_info_t*) cur_stream->data;
new RtpStreamTreeWidgetItem(ui->streamTreeWidget, stream_info);
cur_stream = g_list_next(cur_stream);
}
@ -432,7 +432,7 @@ QList<QVariant> RtpStreamDialog::streamRowData(int row) const
void RtpStreamDialog::captureFileClosing()
{
remove_tap_listener_rtp_stream(&tapinfo_);
remove_tap_listener_rtpstream(&tapinfo_);
WiresharkDialog::captureFileClosing();
}
@ -443,7 +443,7 @@ void RtpStreamDialog::showStreamMenu(QPoint pos)
void RtpStreamDialog::on_actionAnalyze_triggered()
{
rtp_stream_info_t *stream_a, *stream_b = NULL;
rtpstream_info_t *stream_a, *stream_b = NULL;
QTreeWidgetItem *ti = ui->streamTreeWidget->selectedItems()[0];
RtpStreamTreeWidgetItem *rsti = static_cast<RtpStreamTreeWidgetItem*>(ti);
@ -502,7 +502,7 @@ void RtpStreamDialog::on_actionExportAsRtpDump_triggered()
// XXX If the user selected multiple frames is this the one we actually want?
QTreeWidgetItem *ti = ui->streamTreeWidget->selectedItems()[0];
RtpStreamTreeWidgetItem *rsti = static_cast<RtpStreamTreeWidgetItem*>(ti);
rtp_stream_info_t *stream_info = rsti->streamInfo();
rtpstream_info_t *stream_info = rsti->streamInfo();
if (stream_info) {
QString file_name;
QDir path(wsApp->lastOpenDir());
@ -530,10 +530,10 @@ void RtpStreamDialog::on_actionFindReverse_triggered()
if (ui->streamTreeWidget->selectedItems().count() < 1) return;
// Gather up our selected streams...
QList<rtp_stream_info_t *> selected_streams;
QList<rtpstream_info_t *> selected_streams;
foreach(QTreeWidgetItem *ti, ui->streamTreeWidget->selectedItems()) {
RtpStreamTreeWidgetItem *rsti = static_cast<RtpStreamTreeWidgetItem*>(ti);
rtp_stream_info_t *stream_info = rsti->streamInfo();
rtpstream_info_t *stream_info = rsti->streamInfo();
if (stream_info) {
selected_streams << stream_info;
}
@ -543,10 +543,10 @@ void RtpStreamDialog::on_actionFindReverse_triggered()
QTreeWidgetItemIterator iter(ui->streamTreeWidget, QTreeWidgetItemIterator::Unselected);
while (*iter) {
RtpStreamTreeWidgetItem *rsti = static_cast<RtpStreamTreeWidgetItem*>(*iter);
rtp_stream_info_t *stream_info = rsti->streamInfo();
rtpstream_info_t *stream_info = rsti->streamInfo();
if (stream_info) {
foreach (rtp_stream_info_t *fwd_stream, selected_streams) {
if (rtp_stream_info_is_reverse(fwd_stream, stream_info)) {
foreach (rtpstream_info_t *fwd_stream, selected_streams) {
if (rtpstream_info_is_reverse(fwd_stream, stream_info)) {
(*iter)->setSelected(true);
}
}
@ -561,7 +561,7 @@ void RtpStreamDialog::on_actionGoToSetup_triggered()
// XXX If the user selected multiple frames is this the one we actually want?
QTreeWidgetItem *ti = ui->streamTreeWidget->selectedItems()[0];
RtpStreamTreeWidgetItem *rsti = static_cast<RtpStreamTreeWidgetItem*>(ti);
rtp_stream_info_t *stream_info = rsti->streamInfo();
rtpstream_info_t *stream_info = rsti->streamInfo();
if (stream_info) {
emit goToPacket(stream_info->setup_frame_number);
}
@ -570,7 +570,7 @@ void RtpStreamDialog::on_actionGoToSetup_triggered()
void RtpStreamDialog::on_actionMarkPackets_triggered()
{
if (ui->streamTreeWidget->selectedItems().count() < 1) return;
rtp_stream_info_t *stream_a, *stream_b = NULL;
rtpstream_info_t *stream_a, *stream_b = NULL;
QTreeWidgetItem *ti = ui->streamTreeWidget->selectedItems()[0];
RtpStreamTreeWidgetItem *rsti = static_cast<RtpStreamTreeWidgetItem*>(ti);
@ -597,7 +597,7 @@ void RtpStreamDialog::on_actionPrepareFilter_triggered()
QStringList stream_filters;
foreach(QTreeWidgetItem *ti, ui->streamTreeWidget->selectedItems()) {
RtpStreamTreeWidgetItem *rsti = static_cast<RtpStreamTreeWidgetItem*>(ti);
rtp_stream_info_t *stream_info = rsti->streamInfo();
rtpstream_info_t *stream_info = rsti->streamInfo();
if (stream_info) {
QString ip_proto = stream_info->src_addr.type == AT_IPv6 ? "ipv6" : "ip";
stream_filters << QString("(%1.src==%2 && udp.srcport==%3 && %1.dst==%4 && udp.dstport==%5 && rtp.ssrc==0x%6)")
@ -611,7 +611,7 @@ void RtpStreamDialog::on_actionPrepareFilter_triggered()
}
if (stream_filters.length() > 0) {
QString filter = stream_filters.join(" || ");
remove_tap_listener_rtp_stream(&tapinfo_);
remove_tap_listener_rtpstream(&tapinfo_);
emit updateFilter(filter);
}
}

View File

@ -179,7 +179,7 @@ void VoipCallsDialog::tapDraw(void *tapinfo_ptr)
for (; graph_item; graph_item = g_list_next(graph_item)) {
for (GList *rsi_entry = g_list_first(tapinfo->rtp_stream_list); rsi_entry; rsi_entry = g_list_next(rsi_entry)) {
seq_analysis_item_t * sai = (seq_analysis_item_t *)graph_item->data;
rtp_stream_info_t *rsi = (rtp_stream_info_t *)rsi_entry->data;
rtpstream_info_t *rsi = (rtpstream_info_t *)rsi_entry->data;
if (rsi->start_fd->num == sai->frame_number) {
rsi->call_num = sai->conv_num;
@ -392,7 +392,7 @@ void VoipCallsDialog::showPlayer()
if (!vci) continue;
for (GList *rsi_entry = g_list_first(tapinfo_.rtp_stream_list); rsi_entry; rsi_entry = g_list_next(rsi_entry)) {
rtp_stream_info_t *rsi = (rtp_stream_info_t *)rsi_entry->data;
rtpstream_info_t *rsi = (rtpstream_info_t *)rsi_entry->data;
if (!rsi) continue;
//VOIP_CALLS_DEBUG("checking call %u, start frame %u == stream call %u, start frame %u, setup frame %u",

View File

@ -72,6 +72,7 @@ decode_rtp_packet(rtp_packet_t *rp, SAMPLE **out_buff, GHashTable *decoders_hash
g_hash_table_insert(decoders_hash, GUINT_TO_POINTER(payload_type), decoder);
}
if (decoder->handle) { /* Decode with registered codec */
/* if output == NULL and outputSizeBytes == NULL => ask for expected size of the buffer */
tmp_buff_len = codec_decode(decoder->handle, decoder->context, rp->payload_data, rp->info->info_payload_len, NULL, NULL);
tmp_buff = (SAMPLE *)g_malloc(tmp_buff_len);
decoded_bytes = codec_decode(decoder->handle, decoder->context, rp->payload_data, rp->info->info_payload_len, tmp_buff, &tmp_buff_len);

View File

@ -33,7 +33,7 @@
/****************************************************************************/
/* redraw the output */
static void rtpstream_draw(void *ti_ptr)
static void rtpstream_draw_cb(void *ti_ptr)
{
rtpstream_tapinfo_t *tapinfo = (rtpstream_tapinfo_t *)ti_ptr;
/* XXX: see rtpstream_on_update in rtp_streams_dlg.c for comments
@ -59,20 +59,20 @@ void rtpstream_scan(rtpstream_tapinfo_t *tapinfo, capture_file *cap_file, const
was_registered = tapinfo->is_registered;
if (!tapinfo->is_registered)
register_tap_listener_rtp_stream(tapinfo, fstring);
register_tap_listener_rtpstream(tapinfo, fstring);
/* RTP_STREAM_DEBUG("scanning %s, filter: %s", cap_file->filename, fstring); */
tapinfo->mode = TAP_ANALYSE;
cf_retap_packets(cap_file);
if (!was_registered)
remove_tap_listener_rtp_stream(tapinfo);
remove_tap_listener_rtpstream(tapinfo);
}
/****************************************************************************/
/* save rtp dump of stream_fwd */
gboolean rtpstream_save(rtpstream_tapinfo_t *tapinfo, capture_file *cap_file, rtp_stream_info_t* stream, const gchar *filename)
gboolean rtpstream_save(rtpstream_tapinfo_t *tapinfo, capture_file *cap_file, rtpstream_info_t* stream, const gchar *filename)
{
gboolean was_registered;
@ -97,7 +97,7 @@ gboolean rtpstream_save(rtpstream_tapinfo_t *tapinfo, capture_file *cap_file, rt
}
if (!tapinfo->is_registered)
register_tap_listener_rtp_stream(tapinfo, NULL);
register_tap_listener_rtpstream(tapinfo, NULL);
tapinfo->mode = TAP_SAVE;
tapinfo->filter_stream_fwd = stream;
@ -105,7 +105,7 @@ gboolean rtpstream_save(rtpstream_tapinfo_t *tapinfo, capture_file *cap_file, rt
tapinfo->mode = TAP_ANALYSE;
if (!was_registered)
remove_tap_listener_rtp_stream(tapinfo);
remove_tap_listener_rtpstream(tapinfo);
if (ferror(tapinfo->save_file)) {
write_failure_alert_box(filename, errno);
@ -122,7 +122,7 @@ gboolean rtpstream_save(rtpstream_tapinfo_t *tapinfo, capture_file *cap_file, rt
/****************************************************************************/
/* compare the endpoints of two RTP streams */
gboolean rtp_stream_info_is_reverse(const rtp_stream_info_t *stream_a, rtp_stream_info_t *stream_b)
gboolean rtpstream_info_is_reverse(const rtpstream_info_t *stream_a, rtpstream_info_t *stream_b)
{
if (stream_a == NULL || stream_b == NULL)
return FALSE;
@ -138,7 +138,7 @@ gboolean rtp_stream_info_is_reverse(const rtp_stream_info_t *stream_a, rtp_strea
/****************************************************************************/
/* mark packets in stream_fwd or stream_rev */
void rtpstream_mark(rtpstream_tapinfo_t *tapinfo, capture_file *cap_file, rtp_stream_info_t* stream_fwd, rtp_stream_info_t* stream_rev)
void rtpstream_mark(rtpstream_tapinfo_t *tapinfo, capture_file *cap_file, rtpstream_info_t* stream_fwd, rtpstream_info_t* stream_rev)
{
gboolean was_registered;
@ -149,7 +149,7 @@ void rtpstream_mark(rtpstream_tapinfo_t *tapinfo, capture_file *cap_file, rtp_st
was_registered = tapinfo->is_registered;
if (!tapinfo->is_registered)
register_tap_listener_rtp_stream(tapinfo, NULL);
register_tap_listener_rtpstream(tapinfo, NULL);
tapinfo->mode = TAP_MARK;
tapinfo->filter_stream_fwd = stream_fwd;
@ -158,7 +158,7 @@ void rtpstream_mark(rtpstream_tapinfo_t *tapinfo, capture_file *cap_file, rtp_st
tapinfo->mode = TAP_ANALYSE;
if (!was_registered)
remove_tap_listener_rtp_stream(tapinfo);
remove_tap_listener_rtpstream(tapinfo);
}
@ -168,7 +168,7 @@ void rtpstream_mark(rtpstream_tapinfo_t *tapinfo, capture_file *cap_file, rtp_st
/****************************************************************************/
void
remove_tap_listener_rtp_stream(rtpstream_tapinfo_t *tapinfo)
remove_tap_listener_rtpstream(rtpstream_tapinfo_t *tapinfo)
{
if (tapinfo && tapinfo->is_registered) {
remove_tap_listener(tapinfo);
@ -179,7 +179,7 @@ remove_tap_listener_rtp_stream(rtpstream_tapinfo_t *tapinfo)
/****************************************************************************/
void
register_tap_listener_rtp_stream(rtpstream_tapinfo_t *tapinfo, const char *fstring)
register_tap_listener_rtpstream(rtpstream_tapinfo_t *tapinfo, const char *fstring)
{
GString *error_string;
@ -189,8 +189,8 @@ register_tap_listener_rtp_stream(rtpstream_tapinfo_t *tapinfo, const char *fstri
if (!tapinfo->is_registered) {
error_string = register_tap_listener("rtp", tapinfo,
fstring, 0, rtpstream_reset_cb, rtpstream_packet,
rtpstream_draw);
fstring, 0, rtpstream_reset_cb, rtpstream_packet_cb,
rtpstream_draw_cb);
if (error_string != NULL) {
simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,

View File

@ -33,7 +33,7 @@ extern "C" {
#include <epan/tap.h>
/** Defines an rtp stream */
typedef struct _rtp_stream_info {
typedef struct _rtpstream_info {
address src_addr;
guint32 src_port;
address dest_addr;
@ -62,7 +62,7 @@ typedef struct _rtp_stream_info {
tap_rtp_stat_t rtp_stats; /**< here goes the RTP statistics info */
gboolean problem; /**< if the streams had wrong sequence numbers or wrong timestamps */
gchar *ed137_info;
} rtp_stream_info_t;
} rtpstream_info_t;
/** tapping modes */
typedef enum
@ -90,8 +90,8 @@ struct _rtpstream_tapinfo {
int npackets; /**< total number of rtp packets of all streams */
/* used while tapping. user shouldn't modify these */
tap_mode_t mode;
rtp_stream_info_t *filter_stream_fwd; /**< used as filter in some tap modes */
rtp_stream_info_t *filter_stream_rev; /**< used as filter in some tap modes */
rtpstream_info_t *filter_stream_fwd; /**< used as filter in some tap modes */
rtpstream_info_t *filter_stream_rev; /**< used as filter in some tap modes */
FILE *save_file;
gboolean is_registered; /**< if the tap listener is currently registered or not */
};
@ -116,13 +116,13 @@ struct _rtpstream_tapinfo {
* So whenever rtp_stream.c is added to the list of WIRESHARK_TAP_SRCs, the tap will be registered on startup.
* If not, it will be registered on demand by the rtp_streams and rtp_analysis functions that need it.
*/
void register_tap_listener_rtp_stream(rtpstream_tapinfo_t *tapinfo, const char *fstring);
void register_tap_listener_rtpstream(rtpstream_tapinfo_t *tapinfo, const char *fstring);
/**
* Removes the rtp_streams tap listener (if not already done)
* From that point on, the RTP streams list won't be updated any more.
*/
void remove_tap_listener_rtp_stream(rtpstream_tapinfo_t *tapinfo);
void remove_tap_listener_rtpstream(rtpstream_tapinfo_t *tapinfo);
/**
* Cleans up memory of rtp streams tap.
@ -139,21 +139,21 @@ void rtpstream_scan(rtpstream_tapinfo_t *tapinfo, capture_file *cap_file, const
* Saves an RTP stream as raw data stream with timestamp information for later RTP playback.
* (redissects all packets)
*/
gboolean rtpstream_save(rtpstream_tapinfo_t *tapinfo, capture_file *cap_file, rtp_stream_info_t* stream, const gchar *filename);
gboolean rtpstream_save(rtpstream_tapinfo_t *tapinfo, capture_file *cap_file, rtpstream_info_t* stream, const gchar *filename);
/**
* Compares the endpoints of two RTP streams.
*
* @return TRUE if the
*/
gboolean rtp_stream_info_is_reverse(const rtp_stream_info_t *stream_a, rtp_stream_info_t *stream_b);
gboolean rtpstream_info_is_reverse(const rtpstream_info_t *stream_a, rtpstream_info_t *stream_b);
/**
* Marks all packets belonging to either of stream_fwd or stream_rev.
* (both can be NULL)
* (redissects all packets)
*/
void rtpstream_mark(rtpstream_tapinfo_t *tapinfo, capture_file *cap_file, rtp_stream_info_t* stream_fwd, rtp_stream_info_t* stream_rev);
void rtpstream_mark(rtpstream_tapinfo_t *tapinfo, capture_file *cap_file, rtpstream_info_t* stream_fwd, rtpstream_info_t* stream_rev);
#define MAX_SILENCE_FRAMES 14400000

View File

@ -41,10 +41,10 @@ typedef struct _iax2_bw_history_item {
#define BUFF_BW 300
typedef struct _tap_iax2_stat_t {
gboolean first_packet; /* do not use in code that is called after rtp_packet_analyse */
gboolean first_packet; /* do not use in code that is called after iax2_packet_analyse */
/* use (flags & STAT_FLAG_FIRST) instead */
/* all of the following fields will be initialized after
rtp_packet_analyse has been called */
iax2_packet_analyse has been called */
guint32 flags; /* see STAT_FLAG-defines below */
guint16 seq_num;
guint32 timestamp;

479
ui/tap-rtp-analysis.c Normal file
View File

@ -0,0 +1,479 @@
/* tap-rtp-analysis.c
* RTP stream handler functions used by tshark and wireshark
*
* Copyright 2008, Ericsson AB
* By Balint Reczey <balint.reczey@ericsson.com>
*
* most functions are copied from ui/gtk/rtp_stream.c and ui/gtk/rtp_analysis.c
* Copyright 2003, Alcatel Business Systems
* By Lars Ruoff <lars.ruoff@gmx.net>
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "config.h"
#include <glib.h>
#include <math.h>
#include "globals.h"
#include <string.h>
#include <epan/rtp_pt.h>
#include <epan/addr_resolv.h>
#include <epan/proto_data.h>
#include <epan/dissectors/packet-rtp.h>
#include <wsutil/pint.h>
#include "rtp_stream.h"
#include "tap-rtp-common.h"
#include "tap-rtp-analysis.h"
typedef struct _key_value {
guint32 key;
guint32 value;
} key_value;
/* RTP sampling clock rates for fixed payload types as defined in
http://www.iana.org/assignments/rtp-parameters */
static const key_value clock_map[] = {
{PT_PCMU, 8000},
{PT_1016, 8000},
{PT_G721, 8000},
{PT_GSM, 8000},
{PT_G723, 8000},
{PT_DVI4_8000, 8000},
{PT_DVI4_16000, 16000},
{PT_LPC, 8000},
{PT_PCMA, 8000},
{PT_G722, 8000},
{PT_L16_STEREO, 44100},
{PT_L16_MONO, 44100},
{PT_QCELP, 8000},
{PT_CN, 8000},
{PT_MPA, 90000},
{PT_G728, 8000},
{PT_G728, 8000},
{PT_DVI4_11025, 11025},
{PT_DVI4_22050, 22050},
{PT_G729, 8000},
{PT_CN_OLD, 8000},
{PT_CELB, 90000},
{PT_JPEG, 90000},
{PT_NV, 90000},
{PT_H261, 90000},
{PT_MPV, 90000},
{PT_MP2T, 90000},
{PT_H263, 90000},
};
#define NUM_CLOCK_VALUES (sizeof clock_map / sizeof clock_map[0])
static guint32
get_clock_rate(guint32 key)
{
size_t i;
for (i = 0; i < NUM_CLOCK_VALUES; i++) {
if (clock_map[i].key == key)
return clock_map[i].value;
}
return 0;
}
typedef struct _mimetype_and_clock {
const gchar *pt_mime_name_str;
guint32 value;
} mimetype_and_clock;
/* RTP sampling clock rates for
"In addition to the RTP payload formats (encodings) listed in the RTP
Payload Types table, there are additional payload formats that do not
have static RTP payload types assigned but instead use dynamic payload
type number assignment. Each payload format is named by a registered
MIME subtype"
http://www.iana.org/assignments/rtp-parameters.
NOTE: Please keep the mimetypes in case insensitive alphabetical order.
*/
static const mimetype_and_clock mimetype_and_clock_map[] = {
{"AMR", 8000}, /* [RFC4867][RFC3267] */
{"AMR-WB", 16000}, /* [RFC4867][RFC3267] */
{"BMPEG", 90000}, /* [RFC2343],[RFC3555] */
{"BT656", 90000}, /* [RFC2431],[RFC3555] */
{"DV", 90000}, /* [RFC3189] */
{"EVRC", 8000}, /* [RFC3558] */
{"EVRC0", 8000}, /* [RFC4788] */
{"EVRC1", 8000}, /* [RFC4788] */
{"EVRCB", 8000}, /* [RFC4788] */
{"EVRCB0", 8000}, /* [RFC4788] */
{"EVRCB1", 8000}, /* [RFC4788] */
{"EVRCWB", 16000}, /* [RFC5188] */
{"EVRCWB0", 16000}, /* [RFC5188] */
{"EVRCWB1", 16000}, /* [RFC5188] */
{"EVS", 16000}, /* [3GPP TS 26.445] */
{"G7221", 16000}, /* [RFC3047] */
{"G726-16", 8000}, /* [RFC3551][RFC4856] */
{"G726-24", 8000}, /* [RFC3551][RFC4856] */
{"G726-32", 8000}, /* [RFC3551][RFC4856] */
{"G726-40", 8000}, /* [RFC3551][RFC4856] */
{"G729D", 8000}, /* [RFC3551][RFC4856] */
{"G729E", 8000}, /* [RFC3551][RFC4856] */
{"GSM-EFR", 8000}, /* [RFC3551] */
{"H263-1998", 90000}, /* [RFC2429],[RFC3555] */
{"H263-2000", 90000}, /* [RFC2429],[RFC3555] */
{"H264", 90000}, /* [RFC3984] */
{"MP1S", 90000}, /* [RFC2250],[RFC3555] */
{"MP2P", 90000}, /* [RFC2250],[RFC3555] */
{"MP4V-ES", 90000}, /* [RFC3016] */
{"mpa-robust", 90000}, /* [RFC3119] */
{"pointer", 90000}, /* [RFC2862] */
{"raw", 90000}, /* [RFC4175] */
{"red", 1000}, /* [RFC4102] */
{"SMV", 8000}, /* [RFC3558] */
{"SMV0", 8000}, /* [RFC3558] */
{"t140", 1000}, /* [RFC4103] */
{"telephone-event", 8000}, /* [RFC4733] */
};
#define NUM_DYN_CLOCK_VALUES (sizeof mimetype_and_clock_map / sizeof mimetype_and_clock_map[0])
static guint32
get_dyn_pt_clock_rate(const gchar *payload_type_str)
{
int i;
/* Search for matching mimetype in reverse order to avoid false matches
* when pt_mime_name_str is the prefix of payload_type_str */
for (i = NUM_DYN_CLOCK_VALUES - 1; i > -1 ; i--) {
if (g_ascii_strncasecmp(mimetype_and_clock_map[i].pt_mime_name_str,payload_type_str,(strlen(mimetype_and_clock_map[i].pt_mime_name_str))) == 0)
return mimetype_and_clock_map[i].value;
}
return 0;
}
/****************************************************************************/
void
rtppacket_analyse(tap_rtp_stat_t *statinfo,
packet_info *pinfo,
const struct _rtp_info *rtpinfo)
{
double current_time;
double current_jitter;
double current_diff = 0;
double nominaltime;
double arrivaltime; /* Time relative to start_time */
double expected_time;
double absskew;
guint32 clock_rate;
/* Store the current time */
current_time = nstime_to_msec(&pinfo->rel_ts);
/* Is this the first packet we got in this direction? */
if (statinfo->first_packet) {
/* Save the MAC address of the first RTP frame */
if( pinfo->dl_src.type == AT_ETHER){
copy_address(&(statinfo->first_packet_mac_addr), &(pinfo->dl_src));
}
statinfo->start_seq_nr = rtpinfo->info_seq_num;
statinfo->stop_seq_nr = rtpinfo->info_seq_num;
statinfo->seq_num = rtpinfo->info_seq_num;
statinfo->start_time = current_time;
statinfo->timestamp = rtpinfo->info_timestamp;
statinfo->first_timestamp = rtpinfo->info_timestamp;
statinfo->time = current_time;
statinfo->lastnominaltime = 0;
statinfo->pt = rtpinfo->info_payload_type;
statinfo->reg_pt = rtpinfo->info_payload_type;
if (pinfo->net_src.type == AT_IPv6) {
statinfo->bw_history[statinfo->bw_index].bytes = rtpinfo->info_data_len + 48;
} else {
statinfo->bw_history[statinfo->bw_index].bytes = rtpinfo->info_data_len + 28;
}
statinfo->bw_history[statinfo->bw_index].time = current_time;
statinfo->bw_index++;
if (pinfo->net_src.type == AT_IPv6) {
statinfo->total_bytes += rtpinfo->info_data_len + 48;
} else {
statinfo->total_bytes += rtpinfo->info_data_len + 28;
}
statinfo->bandwidth = (double)(statinfo->total_bytes*8)/1000;
/* Not needed ? initialised to zero? */
statinfo->delta = 0;
statinfo->jitter = 0;
statinfo->diff = 0;
statinfo->total_nr++;
statinfo->flags |= STAT_FLAG_FIRST;
if (rtpinfo->info_marker_set) {
statinfo->flags |= STAT_FLAG_MARKER;
}
statinfo->first_packet_num = pinfo->num;
statinfo->first_packet = FALSE;
return;
}
/* Reset flags */
statinfo->flags = 0;
#if 0
/*According to bug https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=11478
* this code causes problems. A better solution is needed if there is need for the functionality */
/* Try to detect duplicated packets due to mirroring/span ports by comparing src MAC addresses.
* Check for duplicates (src mac differs from first_packet_mac_addr) */
*/
if( pinfo->dl_src.type == AT_ETHER){
if(!addresses_equal(&(statinfo->first_packet_mac_addr), &(pinfo->dl_src))){
statinfo->flags |= STAT_FLAG_DUP_PKT;
statinfo->delta = current_time-(statinfo->time);
return;
}
}
#endif
/* When calculating expected rtp packets the seq number can wrap around
* so we have to count the number of cycles
* Variable cycles counts the wraps around in forwarding connection and
* under is flag that indicates where we are
*
* XXX How to determine number of cycles with all possible lost, late
* and duplicated packets without any doubt? It seems to me, that
* because of all possible combination of late, duplicated or lost
* packets, this can only be more or less good approximation
*
* There are some combinations (rare but theoretically possible),
* where below code won't work correctly - statistic may be wrong then.
*/
/* So if the current sequence number is less than the start one
* we assume, that there is another cycle running
*/
if ((rtpinfo->info_seq_num < statinfo->start_seq_nr) && (statinfo->under == FALSE)){
statinfo->cycles++;
statinfo->under = TRUE;
}
/* what if the start seq nr was 0? Then the above condition will never
* be true, so we add another condition. XXX The problem would arise
* if one of the packets with seq nr 0 or 65535 would be lost or late
*/
else if ((rtpinfo->info_seq_num == 0) && (statinfo->stop_seq_nr == 65535) &&
(statinfo->under == FALSE)) {
statinfo->cycles++;
statinfo->under = TRUE;
}
/* the whole round is over, so reset the flag */
else if ((rtpinfo->info_seq_num > statinfo->start_seq_nr) && (statinfo->under != FALSE)) {
statinfo->under = FALSE;
}
/* Since it is difficult to count lost, duplicate or late packets separately,
* we would like to know at least how many times the sequence number was not ok
*/
/* If the current seq number equals the last one or if we are here for
* the first time, then it is ok, we just store the current one as the last one
*/
if ( (statinfo->seq_num+1 == rtpinfo->info_seq_num) || (statinfo->flags & STAT_FLAG_FIRST) )
statinfo->seq_num = rtpinfo->info_seq_num;
/* If the first one is 65535 we wrap */
else if ( (statinfo->seq_num == 65535) && (rtpinfo->info_seq_num == 0) )
statinfo->seq_num = rtpinfo->info_seq_num;
/* Lost packets. If the prev seq is enormously larger than the cur seq
* we assume that instead of being massively late we lost the packet(s)
* that would have indicated the sequence number wrapping. An imprecise
* heuristic at best, but it seems to work well enough.
* https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=5958 */
else if (statinfo->seq_num+1 < rtpinfo->info_seq_num || statinfo->seq_num - rtpinfo->info_seq_num > 0xFF00) {
statinfo->seq_num = rtpinfo->info_seq_num;
statinfo->sequence++;
statinfo->flags |= STAT_FLAG_WRONG_SEQ;
}
/* Late or duplicated */
else if (statinfo->seq_num+1 > rtpinfo->info_seq_num) {
statinfo->sequence++;
statinfo->flags |= STAT_FLAG_WRONG_SEQ;
}
/* Check payload type */
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;
/*
* Return for unknown payload types
* Ignore jitter calculation for clockrate = 0
*/
if (statinfo->pt < 96 ){
clock_rate = get_clock_rate(statinfo->pt);
} else { /* Dynamic PT */
if ( rtpinfo->info_payload_type_str != NULL ) {
/* Is it a "telephone-event" ?
* Timestamp is not increased for telepone-event packets impacting
* calculation of Jitter Skew and clock drift.
* see 2.2.1 of RFC 4733
*/
if (g_ascii_strncasecmp("telephone-event",rtpinfo->info_payload_type_str,(strlen("telephone-event")))==0) {
clock_rate = 0;
statinfo->flags |= STAT_FLAG_PT_T_EVENT;
} else {
if(rtpinfo->info_payload_rate !=0) {
clock_rate = rtpinfo->info_payload_rate;
} else {
clock_rate = get_dyn_pt_clock_rate(rtpinfo->info_payload_type_str);
}
}
} else {
clock_rate = 0;
}
}
/* Handle wraparound ? */
arrivaltime = current_time - statinfo->start_time;
nominaltime = (double)(guint32_wraparound_diff(rtpinfo->info_timestamp, statinfo->first_timestamp));
/* Can only analyze defined sampling rates */
if (clock_rate != 0) {
statinfo->clock_rate = clock_rate;
/* Convert from sampling clock to ms */
nominaltime = nominaltime /(clock_rate/1000);
/* Calculate the current jitter(in ms) */
if (!statinfo->first_packet) {
expected_time = statinfo->time + (nominaltime - statinfo->lastnominaltime);
current_diff = fabs(current_time - expected_time);
current_jitter = (15 * statinfo->jitter + current_diff) / 16;
statinfo->delta = current_time-(statinfo->time);
statinfo->jitter = current_jitter;
statinfo->diff = current_diff;
}
statinfo->lastnominaltime = nominaltime;
/* Calculate skew, i.e. absolute jitter that also catches clock drift
* Skew is positive if TS (nominal) is too fast
*/
statinfo->skew = nominaltime - arrivaltime;
absskew = fabs(statinfo->skew);
if(absskew > fabs(statinfo->max_skew)) {
statinfo->max_skew = statinfo->skew;
}
/* Gather data for calculation of average, minimum and maximum framerate based on timestamp */
#if 0
if (numPackets > 0 && (!hardPayloadType || !alternatePayloadType)) {
/* Skip first packet and possibly alternate payload type packets */
double dt;
dt = nominaltime - statinfo->lastnominaltime;
sumdt += 1.0 * dt;
numdt += (dt != 0 ? 1 : 0);
mindt = (dt < mindt ? dt : mindt);
maxdt = (dt > maxdt ? dt : maxdt);
}
#endif
/* Gather data for calculation of skew least square */
statinfo->sumt += 1.0 * current_time;
statinfo->sumTS += 1.0 * nominaltime;
statinfo->sumt2 += 1.0 * current_time * current_time;
statinfo->sumtTS += 1.0 * current_time * nominaltime;
}
/* Calculate the BW in Kbps adding the IP+UDP header to the RTP -> 20bytes(IP) + 8bytes(UDP) */
if (pinfo->net_src.type == AT_IPv6) {
statinfo->bw_history[statinfo->bw_index].bytes = rtpinfo->info_data_len + 48;
} else {
statinfo->bw_history[statinfo->bw_index].bytes = rtpinfo->info_data_len + 28;
}
statinfo->bw_history[statinfo->bw_index].time = current_time;
/* Check if there are more than 1sec in the history buffer to calculate BW in bps. If so, remove those for the calculation */
while ((statinfo->bw_history[statinfo->bw_start_index].time+1000/* ms */)<current_time){
statinfo->total_bytes -= statinfo->bw_history[statinfo->bw_start_index].bytes;
statinfo->bw_start_index++;
if (statinfo->bw_start_index == BUFF_BW) statinfo->bw_start_index=0;
};
/* IP hdr + UDP + RTP */
if (pinfo->net_src.type == AT_IPv6){
statinfo->total_bytes += rtpinfo->info_data_len + 48;
}else{
statinfo->total_bytes += rtpinfo->info_data_len + 28;
}
statinfo->bandwidth = (double)(statinfo->total_bytes*8)/1000;
statinfo->bw_index++;
if (statinfo->bw_index == BUFF_BW) statinfo->bw_index = 0;
/* Used by GTK code only */
statinfo->delta_timestamp = guint32_wraparound_diff(rtpinfo->info_timestamp, statinfo->timestamp);
/* Is it a packet with the mark bit set? */
if (rtpinfo->info_marker_set) {
statinfo->flags |= STAT_FLAG_MARKER;
}
/* Difference can be negative. We don't expect difference bigger than 31 bits. Difference don't care about wrap around. */
gint32 tsdelta=rtpinfo->info_timestamp - statinfo->timestamp;
if (tsdelta < 0) {
statinfo->flags |= STAT_FLAG_WRONG_TIMESTAMP;
}
/* 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_WRONG_TIMESTAMP)
&& !(statinfo->flags & STAT_FLAG_FOLLOW_PT_CN)) {
/* Include it in maximum delta calculation */
if (statinfo->delta > statinfo->max_delta) {
statinfo->max_delta = statinfo->delta;
statinfo->max_nr = pinfo->num;
}
if (clock_rate != 0) {
/* Maximum and mean jitter calculation */
if (statinfo->jitter > statinfo->max_jitter) {
statinfo->max_jitter = statinfo->jitter;
}
statinfo->mean_jitter = (statinfo->mean_jitter*statinfo->total_nr + current_diff) / (statinfo->total_nr+1);
}
}
/* 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;
}
statinfo->time = current_time;
statinfo->timestamp = rtpinfo->info_timestamp;
statinfo->stop_seq_nr = rtpinfo->info_seq_num;
statinfo->total_nr++;
statinfo->last_payload_len = rtpinfo->info_payload_len - rtpinfo->info_padding_count;
return;
}
/*
* Editor modelines - https://www.wireshark.org/tools/modelines.html
*
* 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

@ -53,10 +53,10 @@ typedef struct _bw_history_item {
#define BUFF_BW 300
typedef struct _tap_rtp_stat_t {
gboolean first_packet; /**< do not use in code that is called after rtp_packet_analyse */
gboolean first_packet; /**< do not use in code that is called after rtppacket_analyse */
/* use (flags & STAT_FLAG_FIRST) instead */
/* all of the following fields will be initialized after
* rtp_packet_analyse has been called
* rtppacket_analyse has been called
*/
address first_packet_mac_addr; /**< MAC address of first packet, used to determine duplicates due to mirroring */
guint32 flags; /* see STAT_FLAG-defines below */
@ -122,7 +122,7 @@ typedef struct _tap_rtp_save_data_t {
struct _rtp_info;
/* function for analysing an RTP packet. Called from rtp_analysis and rtp_streams */
extern void rtp_packet_analyse(tap_rtp_stat_t *statinfo,
extern void rtppacket_analyse(tap_rtp_stat_t *statinfo,
packet_info *pinfo,
const struct _rtp_info *rtpinfo);

View File

@ -44,11 +44,11 @@ typedef struct st_rtpdump_info {
} rtpdump_info_t;
/****************************************************************************/
/* GCompareFunc style comparison function for _rtp_stream_info */
static gint rtp_stream_info_cmp(gconstpointer aa, gconstpointer bb)
/* GCompareFunc style comparison function for rtp_stream_info_t */
static gint rtpstream_info_cmp(gconstpointer aa, gconstpointer bb)
{
const struct _rtp_stream_info* a = (const struct _rtp_stream_info*)aa;
const struct _rtp_stream_info* b = (const struct _rtp_stream_info*)bb;
const rtpstream_info_t* a = (const rtpstream_info_t*)aa;
const rtpstream_info_t* b = (const rtpstream_info_t*)bb;
if (a==b)
return 0;
@ -122,7 +122,7 @@ void rtpstream_reset_cb(void *arg)
* The header consists of an identifying string, followed
* by a binary structure.
*/
void rtp_write_header(rtp_stream_info_t *strinfo, FILE *file)
void rtp_write_header(rtpstream_info_t *strinfo, FILE *file)
{
guint32 start_sec; /* start of recording (GMT) (seconds) */
guint32 start_usec; /* start of recording (GMT) (microseconds)*/
@ -185,12 +185,12 @@ static void rtp_write_sample(rtpdump_info_t* rtpdump_info, FILE* file)
/****************************************************************************/
/* whenever a RTP packet is seen by the tap listener */
int rtpstream_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt _U_, const void *arg2)
int rtpstream_packet_cb(void *arg, packet_info *pinfo, epan_dissect_t *edt _U_, const void *arg2)
{
rtpstream_tapinfo_t *tapinfo = (rtpstream_tapinfo_t *)arg;
const struct _rtp_info *rtpinfo = (const struct _rtp_info *)arg2;
rtp_stream_info_t new_stream_info;
rtp_stream_info_t *stream_info = NULL;
rtpstream_info_t new_stream_info;
rtpstream_info_t *stream_info = NULL;
GList* list;
rtpdump_info_t rtpdump_info;
@ -198,7 +198,7 @@ int rtpstream_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt _U_, con
/* gather infos on the stream this packet is part of.
* Addresses and strings are read-only and must be duplicated if copied. */
memset(&new_stream_info, 0, sizeof(rtp_stream_info_t));
memset(&new_stream_info, 0, sizeof(rtpstream_info_t));
copy_address_shallow(&(new_stream_info.src_addr), &(pinfo->src));
new_stream_info.src_port = pinfo->srcport;
copy_address_shallow(&(new_stream_info.dest_addr), &(pinfo->dst));
@ -212,9 +212,9 @@ int rtpstream_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt _U_, con
list = g_list_first(tapinfo->strinfo_list);
while (list)
{
if (rtp_stream_info_cmp(&new_stream_info, (rtp_stream_info_t*)(list->data))==0)
if (rtpstream_info_cmp(&new_stream_info, (rtpstream_info_t*)(list->data))==0)
{
stream_info = (rtp_stream_info_t*)(list->data); /*found!*/
stream_info = (rtpstream_info_t*)(list->data); /*found!*/
break;
}
list = g_list_next(list);
@ -236,7 +236,7 @@ int rtpstream_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt _U_, con
else
new_stream_info.setup_frame_number = 0xFFFFFFFF;
stream_info = g_new(rtp_stream_info_t,1);
stream_info = g_new(rtpstream_info_t,1);
/* Deep clone of contents. */
copy_address(&(new_stream_info.src_addr), &(new_stream_info.src_addr));
copy_address(&(new_stream_info.dest_addr), &(new_stream_info.dest_addr));
@ -246,7 +246,7 @@ int rtpstream_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt _U_, con
}
/* get RTP stats for the packet */
rtp_packet_analyse(&(stream_info->rtp_stats), pinfo, rtpinfo);
rtppacket_analyse(&(stream_info->rtp_stats), pinfo, rtpinfo);
if (stream_info->rtp_stats.flags & STAT_FLAG_WRONG_TIMESTAMP
|| stream_info->rtp_stats.flags & STAT_FLAG_WRONG_SEQ)
stream_info->problem = TRUE;
@ -262,7 +262,7 @@ int rtpstream_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt _U_, con
return 1; /* refresh output */
}
else if (tapinfo->mode == TAP_SAVE) {
if (rtp_stream_info_cmp(&new_stream_info, tapinfo->filter_stream_fwd)==0) {
if (rtpstream_info_cmp(&new_stream_info, tapinfo->filter_stream_fwd)==0) {
/* XXX - what if rtpinfo->info_all_data_present is
FALSE, so that we don't *have* all the data? */
rtpdump_info.rec_time = nstime_to_msec(&pinfo->abs_ts) -
@ -273,8 +273,8 @@ int rtpstream_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt _U_, con
}
}
else if (tapinfo->mode == TAP_MARK && tapinfo->tap_mark_packet) {
if (rtp_stream_info_cmp(&new_stream_info, tapinfo->filter_stream_fwd)==0
|| rtp_stream_info_cmp(&new_stream_info, tapinfo->filter_stream_rev)==0)
if (rtpstream_info_cmp(&new_stream_info, tapinfo->filter_stream_fwd)==0
|| rtpstream_info_cmp(&new_stream_info, tapinfo->filter_stream_rev)==0)
{
tapinfo->tap_mark_packet(tapinfo, pinfo->fd);
}
@ -282,440 +282,6 @@ int rtpstream_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt _U_, con
return 0;
}
typedef struct _key_value {
guint32 key;
guint32 value;
} key_value;
/* RTP sampling clock rates for fixed payload types as defined in
http://www.iana.org/assignments/rtp-parameters */
static const key_value clock_map[] = {
{PT_PCMU, 8000},
{PT_1016, 8000},
{PT_G721, 8000},
{PT_GSM, 8000},
{PT_G723, 8000},
{PT_DVI4_8000, 8000},
{PT_DVI4_16000, 16000},
{PT_LPC, 8000},
{PT_PCMA, 8000},
{PT_G722, 8000},
{PT_L16_STEREO, 44100},
{PT_L16_MONO, 44100},
{PT_QCELP, 8000},
{PT_CN, 8000},
{PT_MPA, 90000},
{PT_G728, 8000},
{PT_G728, 8000},
{PT_DVI4_11025, 11025},
{PT_DVI4_22050, 22050},
{PT_G729, 8000},
{PT_CN_OLD, 8000},
{PT_CELB, 90000},
{PT_JPEG, 90000},
{PT_NV, 90000},
{PT_H261, 90000},
{PT_MPV, 90000},
{PT_MP2T, 90000},
{PT_H263, 90000},
};
#define NUM_CLOCK_VALUES (sizeof clock_map / sizeof clock_map[0])
static guint32
get_clock_rate(guint32 key)
{
size_t i;
for (i = 0; i < NUM_CLOCK_VALUES; i++) {
if (clock_map[i].key == key)
return clock_map[i].value;
}
return 0;
}
typedef struct _mimetype_and_clock {
const gchar *pt_mime_name_str;
guint32 value;
} mimetype_and_clock;
/* RTP sampling clock rates for
"In addition to the RTP payload formats (encodings) listed in the RTP
Payload Types table, there are additional payload formats that do not
have static RTP payload types assigned but instead use dynamic payload
type number assignment. Each payload format is named by a registered
MIME subtype"
http://www.iana.org/assignments/rtp-parameters.
NOTE: Please keep the mimetypes in case insensitive alphabetical order.
*/
static const mimetype_and_clock mimetype_and_clock_map[] = {
{"AMR", 8000}, /* [RFC4867][RFC3267] */
{"AMR-WB", 16000}, /* [RFC4867][RFC3267] */
{"BMPEG", 90000}, /* [RFC2343],[RFC3555] */
{"BT656", 90000}, /* [RFC2431],[RFC3555] */
{"DV", 90000}, /* [RFC3189] */
{"EVRC", 8000}, /* [RFC3558] */
{"EVRC0", 8000}, /* [RFC4788] */
{"EVRC1", 8000}, /* [RFC4788] */
{"EVRCB", 8000}, /* [RFC4788] */
{"EVRCB0", 8000}, /* [RFC4788] */
{"EVRCB1", 8000}, /* [RFC4788] */
{"EVRCWB", 16000}, /* [RFC5188] */
{"EVRCWB0", 16000}, /* [RFC5188] */
{"EVRCWB1", 16000}, /* [RFC5188] */
{"EVS", 16000}, /* [3GPP TS 26.445] */
{"G7221", 16000}, /* [RFC3047] */
{"G726-16", 8000}, /* [RFC3551][RFC4856] */
{"G726-24", 8000}, /* [RFC3551][RFC4856] */
{"G726-32", 8000}, /* [RFC3551][RFC4856] */
{"G726-40", 8000}, /* [RFC3551][RFC4856] */
{"G729D", 8000}, /* [RFC3551][RFC4856] */
{"G729E", 8000}, /* [RFC3551][RFC4856] */
{"GSM-EFR", 8000}, /* [RFC3551] */
{"H263-1998", 90000}, /* [RFC2429],[RFC3555] */
{"H263-2000", 90000}, /* [RFC2429],[RFC3555] */
{"H264", 90000}, /* [RFC3984] */
{"MP1S", 90000}, /* [RFC2250],[RFC3555] */
{"MP2P", 90000}, /* [RFC2250],[RFC3555] */
{"MP4V-ES", 90000}, /* [RFC3016] */
{"mpa-robust", 90000}, /* [RFC3119] */
{"pointer", 90000}, /* [RFC2862] */
{"raw", 90000}, /* [RFC4175] */
{"red", 1000}, /* [RFC4102] */
{"SMV", 8000}, /* [RFC3558] */
{"SMV0", 8000}, /* [RFC3558] */
{"t140", 1000}, /* [RFC4103] */
{"telephone-event", 8000}, /* [RFC4733] */
};
#define NUM_DYN_CLOCK_VALUES (sizeof mimetype_and_clock_map / sizeof mimetype_and_clock_map[0])
static guint32
get_dyn_pt_clock_rate(const gchar *payload_type_str)
{
int i;
/* Search for matching mimetype in reverse order to avoid false matches
* when pt_mime_name_str is the prefix of payload_type_str */
for (i = NUM_DYN_CLOCK_VALUES - 1; i > -1 ; i--) {
if (g_ascii_strncasecmp(mimetype_and_clock_map[i].pt_mime_name_str,payload_type_str,(strlen(mimetype_and_clock_map[i].pt_mime_name_str))) == 0)
return mimetype_and_clock_map[i].value;
}
return 0;
}
/****************************************************************************/
void
rtp_packet_analyse(tap_rtp_stat_t *statinfo,
packet_info *pinfo,
const struct _rtp_info *rtpinfo)
{
double current_time;
double current_jitter;
double current_diff = 0;
double nominaltime;
double arrivaltime; /* Time relative to start_time */
double expected_time;
double absskew;
guint32 clock_rate;
/* Store the current time */
current_time = nstime_to_msec(&pinfo->rel_ts);
/* Is this the first packet we got in this direction? */
if (statinfo->first_packet) {
/* Save the MAC address of the first RTP frame */
if( pinfo->dl_src.type == AT_ETHER){
copy_address(&(statinfo->first_packet_mac_addr), &(pinfo->dl_src));
}
statinfo->start_seq_nr = rtpinfo->info_seq_num;
statinfo->stop_seq_nr = rtpinfo->info_seq_num;
statinfo->seq_num = rtpinfo->info_seq_num;
statinfo->start_time = current_time;
statinfo->timestamp = rtpinfo->info_timestamp;
statinfo->first_timestamp = rtpinfo->info_timestamp;
statinfo->time = current_time;
statinfo->lastnominaltime = 0;
statinfo->pt = rtpinfo->info_payload_type;
statinfo->reg_pt = rtpinfo->info_payload_type;
if (pinfo->net_src.type == AT_IPv6) {
statinfo->bw_history[statinfo->bw_index].bytes = rtpinfo->info_data_len + 48;
} else {
statinfo->bw_history[statinfo->bw_index].bytes = rtpinfo->info_data_len + 28;
}
statinfo->bw_history[statinfo->bw_index].time = current_time;
statinfo->bw_index++;
if (pinfo->net_src.type == AT_IPv6) {
statinfo->total_bytes += rtpinfo->info_data_len + 48;
} else {
statinfo->total_bytes += rtpinfo->info_data_len + 28;
}
statinfo->bandwidth = (double)(statinfo->total_bytes*8)/1000;
/* Not needed ? initialised to zero? */
statinfo->delta = 0;
statinfo->jitter = 0;
statinfo->diff = 0;
statinfo->total_nr++;
statinfo->flags |= STAT_FLAG_FIRST;
if (rtpinfo->info_marker_set) {
statinfo->flags |= STAT_FLAG_MARKER;
}
statinfo->first_packet_num = pinfo->num;
statinfo->first_packet = FALSE;
return;
}
/* Reset flags */
statinfo->flags = 0;
#if 0
/*According to bug https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=11478
* this code causes problems. A better solution is needed if there is need for the functionality */
/* Try to detect duplicated packets due to mirroring/span ports by comparing src MAC addresses.
* Chek for duplicates (src mac differs from first_packet_mac_addr) */
*/
if( pinfo->dl_src.type == AT_ETHER){
if(!addresses_equal(&(statinfo->first_packet_mac_addr), &(pinfo->dl_src))){
statinfo->flags |= STAT_FLAG_DUP_PKT;
statinfo->delta = current_time-(statinfo->time);
return;
}
}
#endif
/* When calculating expected rtp packets the seq number can wrap around
* so we have to count the number of cycles
* Variable cycles counts the wraps around in forwarding connection and
* under is flag that indicates where we are
*
* XXX How to determine number of cycles with all possible lost, late
* and duplicated packets without any doubt? It seems to me, that
* because of all possible combination of late, duplicated or lost
* packets, this can only be more or less good approximation
*
* There are some combinations (rare but theoretically possible),
* where below code won't work correctly - statistic may be wrong then.
*/
/* So if the current sequence number is less than the start one
* we assume, that there is another cycle running
*/
if ((rtpinfo->info_seq_num < statinfo->start_seq_nr) && (statinfo->under == FALSE)){
statinfo->cycles++;
statinfo->under = TRUE;
}
/* what if the start seq nr was 0? Then the above condition will never
* be true, so we add another condition. XXX The problem would arise
* if one of the packets with seq nr 0 or 65535 would be lost or late
*/
else if ((rtpinfo->info_seq_num == 0) && (statinfo->stop_seq_nr == 65535) &&
(statinfo->under == FALSE)) {
statinfo->cycles++;
statinfo->under = TRUE;
}
/* the whole round is over, so reset the flag */
else if ((rtpinfo->info_seq_num > statinfo->start_seq_nr) && (statinfo->under != FALSE)) {
statinfo->under = FALSE;
}
/* Since it is difficult to count lost, duplicate or late packets separately,
* we would like to know at least how many times the sequence number was not ok
*/
/* If the current seq number equals the last one or if we are here for
* the first time, then it is ok, we just store the current one as the last one
*/
if ( (statinfo->seq_num+1 == rtpinfo->info_seq_num) || (statinfo->flags & STAT_FLAG_FIRST) )
statinfo->seq_num = rtpinfo->info_seq_num;
/* If the first one is 65535 we wrap */
else if ( (statinfo->seq_num == 65535) && (rtpinfo->info_seq_num == 0) )
statinfo->seq_num = rtpinfo->info_seq_num;
/* Lost packets. If the prev seq is enormously larger than the cur seq
* we assume that instead of being massively late we lost the packet(s)
* that would have indicated the sequence number wrapping. An imprecise
* heuristic at best, but it seems to work well enough.
* https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=5958 */
else if (statinfo->seq_num+1 < rtpinfo->info_seq_num || statinfo->seq_num - rtpinfo->info_seq_num > 0xFF00) {
statinfo->seq_num = rtpinfo->info_seq_num;
statinfo->sequence++;
statinfo->flags |= STAT_FLAG_WRONG_SEQ;
}
/* Late or duplicated */
else if (statinfo->seq_num+1 > rtpinfo->info_seq_num) {
statinfo->sequence++;
statinfo->flags |= STAT_FLAG_WRONG_SEQ;
}
/* Check payload type */
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;
/*
* Return for unknown payload types
* Ignore jitter calculation for clockrate = 0
*/
if (statinfo->pt < 96 ){
clock_rate = get_clock_rate(statinfo->pt);
} else { /* Dynamic PT */
if ( rtpinfo->info_payload_type_str != NULL ) {
/* Is it a "telephone-event" ?
* Timestamp is not increased for telepone-event packets impacting
* calculation of Jitter Skew and clock drift.
* see 2.2.1 of RFC 4733
*/
if (g_ascii_strncasecmp("telephone-event",rtpinfo->info_payload_type_str,(strlen("telephone-event")))==0) {
clock_rate = 0;
statinfo->flags |= STAT_FLAG_PT_T_EVENT;
} else {
if(rtpinfo->info_payload_rate !=0) {
clock_rate = rtpinfo->info_payload_rate;
} else {
clock_rate = get_dyn_pt_clock_rate(rtpinfo->info_payload_type_str);
}
}
} else {
clock_rate = 0;
}
}
/* Handle wraparound ? */
arrivaltime = current_time - statinfo->start_time;
nominaltime = (double)(guint32_wraparound_diff(rtpinfo->info_timestamp, statinfo->first_timestamp));
/* Can only analyze defined sampling rates */
if (clock_rate != 0) {
statinfo->clock_rate = clock_rate;
/* Convert from sampling clock to ms */
nominaltime = nominaltime /(clock_rate/1000);
/* Calculate the current jitter(in ms) */
if (!statinfo->first_packet) {
expected_time = statinfo->time + (nominaltime - statinfo->lastnominaltime);
current_diff = fabs(current_time - expected_time);
current_jitter = (15 * statinfo->jitter + current_diff) / 16;
statinfo->delta = current_time-(statinfo->time);
statinfo->jitter = current_jitter;
statinfo->diff = current_diff;
}
statinfo->lastnominaltime = nominaltime;
/* Calculate skew, i.e. absolute jitter that also catches clock drift
* Skew is positive if TS (nominal) is too fast
*/
statinfo->skew = nominaltime - arrivaltime;
absskew = fabs(statinfo->skew);
if(absskew > fabs(statinfo->max_skew)) {
statinfo->max_skew = statinfo->skew;
}
/* Gather data for calculation of average, minimum and maximum framerate based on timestamp */
#if 0
if (numPackets > 0 && (!hardPayloadType || !alternatePayloadType)) {
/* Skip first packet and possibly alternate payload type packets */
double dt;
dt = nominaltime - statinfo->lastnominaltime;
sumdt += 1.0 * dt;
numdt += (dt != 0 ? 1 : 0);
mindt = (dt < mindt ? dt : mindt);
maxdt = (dt > maxdt ? dt : maxdt);
}
#endif
/* Gather data for calculation of skew least square */
statinfo->sumt += 1.0 * current_time;
statinfo->sumTS += 1.0 * nominaltime;
statinfo->sumt2 += 1.0 * current_time * current_time;
statinfo->sumtTS += 1.0 * current_time * nominaltime;
}
/* Calculate the BW in Kbps adding the IP+UDP header to the RTP -> 20bytes(IP) + 8bytes(UDP) */
if (pinfo->net_src.type == AT_IPv6) {
statinfo->bw_history[statinfo->bw_index].bytes = rtpinfo->info_data_len + 48;
} else {
statinfo->bw_history[statinfo->bw_index].bytes = rtpinfo->info_data_len + 28;
}
statinfo->bw_history[statinfo->bw_index].time = current_time;
/* Check if there are more than 1sec in the history buffer to calculate BW in bps. If so, remove those for the calculation */
while ((statinfo->bw_history[statinfo->bw_start_index].time+1000/* ms */)<current_time){
statinfo->total_bytes -= statinfo->bw_history[statinfo->bw_start_index].bytes;
statinfo->bw_start_index++;
if (statinfo->bw_start_index == BUFF_BW) statinfo->bw_start_index=0;
};
/* IP hdr + UDP + RTP */
if (pinfo->net_src.type == AT_IPv6){
statinfo->total_bytes += rtpinfo->info_data_len + 48;
}else{
statinfo->total_bytes += rtpinfo->info_data_len + 28;
}
statinfo->bandwidth = (double)(statinfo->total_bytes*8)/1000;
statinfo->bw_index++;
if (statinfo->bw_index == BUFF_BW) statinfo->bw_index = 0;
/* Used by GTK code only */
statinfo->delta_timestamp = guint32_wraparound_diff(rtpinfo->info_timestamp, statinfo->timestamp);
/* Is it a packet with the mark bit set? */
if (rtpinfo->info_marker_set) {
statinfo->flags |= STAT_FLAG_MARKER;
}
/* Difference can be negative. We don't expect difference bigger than 31 bits. Difference don't care about wrap around. */
gint32 tsdelta=rtpinfo->info_timestamp - statinfo->timestamp;
if (tsdelta < 0) {
statinfo->flags |= STAT_FLAG_WRONG_TIMESTAMP;
}
/* 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_WRONG_TIMESTAMP)
&& !(statinfo->flags & STAT_FLAG_FOLLOW_PT_CN)) {
/* Include it in maximum delta calculation */
if (statinfo->delta > statinfo->max_delta) {
statinfo->max_delta = statinfo->delta;
statinfo->max_nr = pinfo->num;
}
if (clock_rate != 0) {
/* Maximum and mean jitter calculation */
if (statinfo->jitter > statinfo->max_jitter) {
statinfo->max_jitter = statinfo->jitter;
}
statinfo->mean_jitter = (statinfo->mean_jitter*statinfo->total_nr + current_diff) / (statinfo->total_nr+1);
}
}
/* 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;
}
statinfo->time = current_time;
statinfo->timestamp = rtpinfo->info_timestamp;
statinfo->stop_seq_nr = rtpinfo->info_seq_num;
statinfo->total_nr++;
statinfo->last_payload_len = rtpinfo->info_payload_len - rtpinfo->info_padding_count;
return;
}
/*
* Editor modelines - https://www.wireshark.org/tools/modelines.html
*

View File

@ -22,29 +22,30 @@
extern "C" {
#endif /* __cplusplus */
#include "ui/rtp_stream.h"
/* type of error when saving voice in a file didn't succeed */
typedef enum {
TAP_RTP_NO_ERROR,
TAP_RTP_WRONG_CODEC,
TAP_RTP_WRONG_LENGTH,
TAP_RTP_PADDING_ERROR,
TAP_RTP_SHORT_FRAME,
TAP_RTP_FILE_OPEN_ERROR,
TAP_RTP_FILE_WRITE_ERROR,
TAP_RTP_NO_DATA
} error_type_t;
TAP_RTP_NO_DATA,
} tap_rtp_error_type_t;
typedef struct _tap_rtp_save_info_t {
FILE *fp;
guint32 count;
error_type_t error_type;
tap_rtp_error_type_t error_type;
gboolean saved;
} tap_rtp_save_info_t;
struct _rtp_stream_info;
void rtpstream_reset_cb(void*);
void rtp_write_header(struct _rtp_stream_info*, FILE*);
int rtpstream_packet(void*, packet_info*, epan_dissect_t *, const void *);
void rtp_write_header(rtpstream_info_t*, FILE*);
int rtpstream_packet_cb(void*, packet_info*, epan_dissect_t *, const void *);
#ifdef __cplusplus
}

View File

@ -259,7 +259,7 @@ void
voip_calls_reset_all_taps(voip_calls_tapinfo_t *tapinfo)
{
voip_calls_info_t *callsinfo;
rtp_stream_info_t *strinfo;
rtpstream_info_t *strinfo;
GList *list = NULL;
/* VOIP_CALLS_DEBUG("reset packets: %d streams: %d", tapinfo->npackets, tapinfo->nrtp_streams); */
@ -291,7 +291,7 @@ voip_calls_reset_all_taps(voip_calls_tapinfo_t *tapinfo)
list = g_list_first(tapinfo->rtp_stream_list);
while(list)
{
strinfo = (rtp_stream_info_t *)list->data;
strinfo = (rtpstream_info_t *)list->data;
wmem_free(NULL, strinfo->payload_type_name);
wmem_free(NULL, strinfo->ed137_info);
list = g_list_next(list);
@ -580,8 +580,8 @@ static gboolean
rtp_packet(void *tap_offset_ptr, packet_info *pinfo, epan_dissect_t *edt, void const *rtp_info_ptr)
{
voip_calls_tapinfo_t *tapinfo = tap_id_to_base(tap_offset_ptr, tap_id_offset_rtp_);
rtp_stream_info_t *tmp_listinfo;
rtp_stream_info_t *strinfo = NULL;
rtpstream_info_t *tmp_listinfo;
rtpstream_info_t *strinfo = NULL;
GList *list;
struct _rtp_conversation_info *p_conv_data = NULL;
@ -600,7 +600,7 @@ rtp_packet(void *tap_offset_ptr, packet_info *pinfo, epan_dissect_t *edt, void c
list = g_list_first(tapinfo->rtp_stream_list);
while (list)
{
tmp_listinfo=(rtp_stream_info_t *)list->data;
tmp_listinfo=(rtpstream_info_t *)list->data;
if ( (tmp_listinfo->setup_frame_number == rtp_info->info_setup_frame_num)
&& (tmp_listinfo->ssrc == rtp_info->info_sync_src) && (tmp_listinfo->end_stream == FALSE)) {
/* if the payload type has changed, we mark the stream as finished to create a new one
@ -616,7 +616,7 @@ rtp_packet(void *tap_offset_ptr, packet_info *pinfo, epan_dissect_t *edt, void c
/* if ed137_info has changed, create new stream */
tmp_listinfo->end_stream = TRUE;
} else {
strinfo = (rtp_stream_info_t*)(list->data);
strinfo = (rtpstream_info_t*)(list->data);
break;
}
}
@ -630,7 +630,7 @@ rtp_packet(void *tap_offset_ptr, packet_info *pinfo, epan_dissect_t *edt, void c
/* not in the list? then create a new entry */
if (strinfo==NULL) {
strinfo = (rtp_stream_info_t *)g_malloc0(sizeof(rtp_stream_info_t));
strinfo = (rtpstream_info_t *)g_malloc0(sizeof(rtpstream_info_t));
copy_address(&(strinfo->src_addr), &(pinfo->src));
strinfo->src_port = pinfo->srcport;
copy_address(&(strinfo->dest_addr), &(pinfo->dst));
@ -688,7 +688,7 @@ rtp_draw(void *tap_offset_ptr)
{
voip_calls_tapinfo_t *tapinfo = tap_id_to_base(tap_offset_ptr, tap_id_offset_rtp_);
GList *rtp_streams_list;
rtp_stream_info_t *rtp_listinfo;
rtpstream_info_t *rtp_listinfo;
/* GList *voip_calls_graph_list; */
seq_analysis_item_t *gai = NULL;
seq_analysis_item_t *new_gai;
@ -700,7 +700,7 @@ rtp_draw(void *tap_offset_ptr)
rtp_streams_list = g_list_first(tapinfo->rtp_stream_list);
while (rtp_streams_list)
{
rtp_listinfo = (rtp_stream_info_t *)rtp_streams_list->data;
rtp_listinfo = (rtpstream_info_t *)rtp_streams_list->data;
/* using the setup frame number of the RTP stream, we get the call number that it belongs to*/
/* voip_calls_graph_list = g_list_first(tapinfo->graph_analysis->list); */
@ -761,7 +761,7 @@ rtp_packet_draw(void *tap_offset_ptr)
{
voip_calls_tapinfo_t *tapinfo = tap_id_to_base(tap_offset_ptr, tap_id_offset_rtp_);
GList *rtp_streams_list;
rtp_stream_info_t *rtp_listinfo;
rtpstream_info_t *rtp_listinfo;
GList *voip_calls_graph_list;
guint item;
seq_analysis_item_t *gai;