rtcp: move rtcp related functions to rtcp dissector

This commit is contained in:
Kaian 2018-04-20 23:40:40 +02:00
parent 81fac8f131
commit c734e6e407
10 changed files with 148 additions and 178 deletions

View File

@ -1076,15 +1076,6 @@ call_flow_draw_raw_rtcp(ui_t *ui, rtp_stream_t *stream)
mvwvline(ui->win, 1, ui->width - raw_width - 2, ACS_VLINE, ui->height - 2);
wattroff(ui->win, COLOR_PAIR(CP_BLUE_ON_DEF));
mvwprintw(raw_win, 0, 0, "============ RTCP Information ============");
mvwprintw(raw_win, 2, 0, "Sender's packet count: %d", stream->rtcpinfo.spc);
mvwprintw(raw_win, 3, 0, "Fraction Lost: %d / 256", stream->rtcpinfo.flost);
mvwprintw(raw_win, 4, 0, "Fraction discarded: %d / 256", stream->rtcpinfo.fdiscard);
mvwprintw(raw_win, 6, 0, "MOS - Listening Quality: %.1f", (float) stream->rtcpinfo.mosl / 10);
mvwprintw(raw_win, 7, 0, "MOS - Conversational Quality: %.1f", (float) stream->rtcpinfo.mosc / 10);
// Copy the raw_win contents into the panel
copywin(raw_win, ui->win, 0, 0, 1, ui->width - raw_width - 1, raw_height, ui->width - 2, 0);

View File

@ -228,7 +228,7 @@ packet_ip_new()
proto->init = packet_ip_init;
proto->dissect = packet_ip_parse;
proto->deinit = packet_ip_deinit;
proto->subdissectors = g_slist_append(proto->subdissectors, GUINT_TO_POINTER(PACKET_TCP));
proto->subdissectors = g_slist_append(proto->subdissectors, GUINT_TO_POINTER(PACKET_UDP));
proto->subdissectors = g_slist_append(proto->subdissectors, GUINT_TO_POINTER(PACKET_TCP));
return proto;
}

View File

@ -36,31 +36,122 @@
#include "packet/dissectors/packet_udp.h"
#include "packet_rtp.h"
/**
* @brief Check if the data is a RTCP packet
* RFC 5761 Section 4. Distinguishable RTP and RTCP Packets
* RFC 5764 Section 5.1.2. Reception (packet demultiplexing)
*/
static gboolean
packet_rtcp_valid(GByteArray *data)
{
g_return_val_if_fail(data != NULL, FALSE);
struct rtcp_hdr_generic *hdr = (struct rtcp_hdr_generic*) data;
if ((data->len >= RTCP_HDR_LENGTH) &&
(RTP_VERSION(data->data[0]) == RTP_VERSION_RFC1889) &&
(data->data[0] > 127 && data->data[0] < 192) &&
(hdr->type >= 192 && hdr->type <= 223)) {
return 0;
}
// Not a RTCP packet
return FALSE;
}
static GByteArray *
packet_rtcp_parse(PacketParser *parser G_GNUC_UNUSED, Packet *packet, GByteArray *data)
{
packet_t *oldpkt = g_malloc0(sizeof(packet_t));
struct rtcp_hdr_generic hdr;
struct rtcp_hdr_sr hdr_sr;
struct rtcp_hdr_xr hdr_xr;
struct rtcp_blk_xr blk_xr;
struct rtcp_blk_xr_voip blk_xr_voip;
PacketIpData *ipdata = g_ptr_array_index(packet->proto, PACKET_IP);
g_return_val_if_fail(ipdata != NULL, NULL);
oldpkt->src = ipdata->saddr;
oldpkt->dst = ipdata->daddr;
PacketUdpData *udpdata = g_ptr_array_index(packet->proto, PACKET_UDP);
g_return_val_if_fail(udpdata != NULL, NULL);
oldpkt->newpacket = packet;
oldpkt->src.port = udpdata->sport;
oldpkt->dst.port = udpdata->dport;
packet_set_payload(oldpkt, data->data, data->len);
oldpkt->frames = g_sequence_new(NULL);
for (GList *l = packet->frames; l != NULL; l = l->next) {
PacketFrame *frame = l->data;
packet_add_frame(oldpkt, frame->header, frame->data);
// Not RTCP Packet
if (!packet_rtcp_valid(data)) {
return data;
}
storage_check_rtp_packet(oldpkt);
// Allocate RTCP packet data
PacketRtcpData *rtcp = g_malloc0(sizeof(PacketRtcpData));
// Parse all packet payload headers
while (data->len > 0) {
// Check we have at least rtcp generic info
if (data->len < sizeof(struct rtcp_hdr_generic))
break;
// Copy into RTCP generic header
memcpy(&hdr, data->data, sizeof(hdr));
// Check RTP version
if (RTP_VERSION(hdr.version) != RTP_VERSION_RFC1889)
break;
// Header length
gint hlen = g_ntohs(hdr.len) * 4 + 4;
// No enough data for this RTCP header
if (hlen > data->len)
break;
// Check RTCP packet header type
switch (hdr.type) {
case RTCP_HDR_SR:
// Get Sender Report header
memcpy(&hdr_sr, data->data, sizeof(hdr_sr));
rtcp->spc = ntohl(hdr_sr.spc);
break;
case RTCP_HDR_RR:
case RTCP_HDR_SDES:
case RTCP_HDR_BYE:
case RTCP_HDR_APP:
case RTCP_RTPFB:
case RTCP_PSFB:
break;
case RTCP_XR:
// Get Sender Report Extended header
memcpy(&hdr_xr, data->data, sizeof(hdr_xr));
size_t bsize = sizeof(hdr_xr);
// Read all report blocks
while (bsize < ntohs(hdr_xr.len) * 4 + 4) {
// Read block header
memcpy(&blk_xr, data->data + bsize, sizeof(blk_xr));
// Check block type
switch (blk_xr.type) {
case RTCP_XR_VOIP_METRCS:
memcpy(&blk_xr_voip, data->data + sizeof(hdr_xr), sizeof(blk_xr_voip));
rtcp->fdiscard = blk_xr_voip.drate;
rtcp->flost = blk_xr_voip.lrate;
rtcp->mosl = blk_xr_voip.moslq;
rtcp->mosc = blk_xr_voip.moscq;
break;
default: break;
}
bsize += ntohs(blk_xr.len) * 4 + 4;
}
break;
case RTCP_AVB:
case RTCP_RSI:
case RTCP_TOKEN:
default:
// Not handled headers. Skip the rest of this packet
g_byte_array_set_size(data, 0);
break;
}
// Remove this header data
g_byte_array_remove_range(data, 0, hlen);
}
// Set packet RTP informaiton
g_ptr_array_insert(packet->proto, PACKET_RTCP, rtcp);
/** @TODO Backwards compatibility during refactoring */
storage_check_rtp_packet(packet_to_oldpkt(packet));
return NULL;
}

View File

@ -32,6 +32,9 @@
#include <glib.h>
typedef struct _PacketRtcpData PacketRtcpData;
// RTCP header types
//! http://www.iana.org/assignments/rtp-parameters/rtp-parameters.xhtml
enum rtcp_header_types
@ -204,6 +207,20 @@ struct rtcp_blk_xr_voip
guint16 jbadelay;
};
struct _PacketRtcpData
{
//! Sender packet count
guint32 spc;
//! Fraction lost x/256
guint8 flost;
//! guint8 discarded x/256
guint8 fdiscard;
//! MOS - listening Quality
guint8 mosl;
//! MOS - Conversational Quality
guint8 mosc;
};
PacketDissector *
packet_rtcp_new();

View File

@ -85,7 +85,7 @@ packet_rtp_standard_codec(guint8 code)
* RFC 5764 Section 5.1.2. Reception (packet demultiplexing)
*/
static gboolean
data_is_rtp(GByteArray *data)
packet_rtp_valid(GByteArray *data)
{
g_return_val_if_fail(data != NULL, FALSE);
@ -106,7 +106,7 @@ static GByteArray *
packet_rtp_parse(PacketParser *parser G_GNUC_UNUSED, Packet *packet, GByteArray *data)
{
// Not RTP
if (data_is_rtp(data) != 1) {
if (!packet_rtp_valid(data)) {
return data;
}
@ -125,28 +125,7 @@ packet_rtp_parse(PacketParser *parser G_GNUC_UNUSED, Packet *packet, GByteArray
g_ptr_array_insert(packet->proto, PACKET_RTP, rtp);
/** @TODO Backwards compatibility during refactoring */
packet_t *oldpkt = g_malloc0(sizeof(packet_t));
PacketIpData *ipdata = g_ptr_array_index(packet->proto, PACKET_IP);
g_return_val_if_fail(ipdata != NULL, NULL);
oldpkt->newpacket = packet;
oldpkt->src = ipdata->saddr;
oldpkt->dst = ipdata->daddr;
PacketUdpData *udpdata = g_ptr_array_index(packet->proto, PACKET_UDP);
g_return_val_if_fail(udpdata != NULL, NULL);
oldpkt->src.port = udpdata->sport;
oldpkt->dst.port = udpdata->dport;
packet_set_payload(oldpkt, data->data, data->len);
oldpkt->frames = g_sequence_new(NULL);
for (GList *l = packet->frames; l != NULL; l = l->next) {
PacketFrame *frame = l->data;
packet_add_frame(oldpkt, frame->header, frame->data);
}
storage_check_rtp_packet(oldpkt);
storage_check_rtp_packet(packet_to_oldpkt(packet));
return NULL;
}

View File

@ -92,7 +92,7 @@ packet_udp_new()
proto->dissect = packet_udp_parse;
proto->subdissectors = g_slist_append(proto->subdissectors, GUINT_TO_POINTER(PACKET_SIP));
proto->subdissectors = g_slist_append(proto->subdissectors, GUINT_TO_POINTER(PACKET_RTP));
// proto->subdissectors = g_slist_append(proto->subdissectors, GUINT_TO_POINTER(PACKET_RTCP));
proto->subdissectors = g_slist_append(proto->subdissectors, GUINT_TO_POINTER(PACKET_RTCP));
return proto;
}

View File

@ -95,7 +95,9 @@ packet_to_oldpkt(Packet *packet)
}
PacketSipData *sipdata = g_ptr_array_index(packet->proto, PACKET_SIP);
packet_set_payload(oldpkt, sipdata->payload, strlen(sipdata->payload));
if (sipdata) {
packet_set_payload(oldpkt, sipdata->payload, strlen(sipdata->payload));
}
oldpkt->frames = g_sequence_new(NULL);
for (GList *l = packet->frames; l != NULL; l = l->next) {

View File

@ -64,7 +64,7 @@ stream_complete(rtp_stream_t *stream, Address src)
void
stream_set_format(rtp_stream_t *stream, uint32_t format)
{
stream->rtpinfo.fmtcode = format;
stream->fmtcode = format;
}
void
@ -101,14 +101,14 @@ stream_get_format(rtp_stream_t *stream)
return NULL;
// Try to get standard format form code
PacketRtpEncoding *encoding = packet_rtp_standard_codec(stream->rtpinfo.fmtcode);
PacketRtpEncoding *encoding = packet_rtp_standard_codec(stream->fmtcode);
if (encoding != NULL)
return encoding->format;
// Try to get format form SDP payload
for (guint i = 0; i < g_list_length(stream->media->formats); i++) {
PacketSdpFormat *format = g_list_nth_data(stream->media->formats, i);
if (format->id == stream->rtpinfo.fmtcode) {
if (format->id == stream->fmtcode) {
return format->alias;
}
}
@ -150,7 +150,7 @@ rtp_find_stream_format(Address src, Address dst, uint32_t format)
if (addressport_equals(stream->src, src) &&
addressport_equals(stream->dst, dst)) {
// Exact searched stream format
if (stream->rtpinfo.fmtcode == format) {
if (stream->fmtcode == format) {
return stream;
} else {
// Matching addresses but different format
@ -276,19 +276,3 @@ stream_is_active(rtp_stream_t *stream)
{
return ((int) time(NULL) - stream->lasttm <= STREAM_INACTIVE_SECS);
}
int
data_is_rtcp(u_char *data, uint32_t len)
{
struct rtcp_hdr_generic *hdr = (struct rtcp_hdr_generic*) data;
if ((len >= RTCP_HDR_LENGTH) &&
(RTP_VERSION(*data) == RTP_VERSION_RFC1889) &&
(data[0] > 127 && data[0] < 192) &&
(hdr->type >= 192 && hdr->type <= 223)) {
return 0;
}
// Not a RTCP packet
return 1;
}

View File

@ -59,26 +59,8 @@ struct rtp_stream {
struct timeval time;
//! Unix timestamp of last received packet
int lasttm;
// Stream information (depending on type)
union {
struct {
//! Format of first received packet of stre
guint8 fmtcode;
} rtpinfo;
struct {
//! Sender packet count
uint32_t spc;
//! Fraction lost x/256
uint8_t flost;
//! uint8_t discarded x/256
uint8_t fdiscard;
//! MOS - listening Quality
uint8_t mosl;
//! MOS - Conversational Quality
uint8_t mosc;
} rtcpinfo;
};
//! Format of first received packet of stre
guint8 fmtcode;
};
rtp_stream_t *
@ -140,12 +122,4 @@ stream_is_complete(rtp_stream_t *stream);
int
stream_is_active(rtp_stream_t *stream);
/**
* @brief Check if the data is a RTCP packet
* RFC 5761 Section 4. Distinguishable RTP and RTCP Packets
* RFC 5764 Section 5.1.2. Reception (packet demultiplexing)
*/
int
data_is_rtcp(u_char *data, uint32_t len);
#endif /* __SNGREP_RTP_H */

View File

@ -261,7 +261,7 @@ storage_check_rtp_packet(packet_t *packet)
return NULL;
// We have found a stream, but with different format
if (stream_is_complete(stream) && stream->rtpinfo.fmtcode != format) {
if (stream_is_complete(stream) && stream->fmtcode != format) {
// Create a new stream for this new format
stream = stream_create(packet->newpacket, stream->media);
stream_complete(stream, src);
@ -317,80 +317,12 @@ storage_check_rtp_packet(packet_t *packet)
stream_add_packet(stream, packet);
}
if (data_is_rtcp(payload, size) == 0) {
// Find the matching stream
if ((stream = rtp_find_stream(src, dst))) {
// Parse all packet payload headers
while ((int32_t) size > 0) {
// Check we have at least rtcp generic info
if (size < sizeof(struct rtcp_hdr_generic))
break;
memcpy(&hdr, payload, sizeof(hdr));
// Check RTP version
if (RTP_VERSION(hdr.version) != RTP_VERSION_RFC1889)
break;
// Header length
if ((len = ntohs(hdr.len) * 4 + 4) > size)
break;
// Check RTCP packet header typ
switch (hdr.type) {
case RTCP_HDR_SR:
// Get Sender Report header
memcpy(&hdr_sr, payload, sizeof(hdr_sr));
stream->rtcpinfo.spc = ntohl(hdr_sr.spc);
break;
case RTCP_HDR_RR:
case RTCP_HDR_SDES:
case RTCP_HDR_BYE:
case RTCP_HDR_APP:
case RTCP_RTPFB:
case RTCP_PSFB:
break;
case RTCP_XR:
// Get Sender Report Extended header
memcpy(&hdr_xr, payload, sizeof(hdr_xr));
bsize = sizeof(hdr_xr);
// Read all report blocks
while (bsize < ntohs(hdr_xr.len) * 4 + 4) {
// Read block header
memcpy(&blk_xr, payload + bsize, sizeof(blk_xr));
// Check block type
switch (blk_xr.type) {
case RTCP_XR_VOIP_METRCS:
memcpy(&blk_xr_voip, payload + sizeof(hdr_xr), sizeof(blk_xr_voip));
stream->rtcpinfo.fdiscard = blk_xr_voip.drate;
stream->rtcpinfo.flost = blk_xr_voip.lrate;
stream->rtcpinfo.mosl = blk_xr_voip.moslq;
stream->rtcpinfo.mosc = blk_xr_voip.moscq;
break;
default: break;
}
bsize += ntohs(blk_xr.len) * 4 + 4;
}
break;
case RTCP_AVB:
case RTCP_RSI:
case RTCP_TOKEN:
default:
// Not handled headers. Skip the rest of this packet
size = 0;
break;
}
payload += len;
size -= len;
}
// Add packet to stream
stream_complete(stream, src);
stream_add_packet(stream, packet);
}
// Check if packet has RTP data
PacketRtcpData *rtcp = g_ptr_array_index(packet->newpacket->proto, PACKET_RTP);
if (rtcp != NULL) {
// Add packet to stream
stream_complete(stream, src);
stream_add_packet(stream, packet);
} else {
return NULL;
}