forked from Mirrors/sngrep
rtcp: move rtcp related functions to rtcp dissector
This commit is contained in:
parent
81fac8f131
commit
c734e6e407
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue