diff --git a/src/curses/ui_call_flow.c b/src/curses/ui_call_flow.c index 4b42264..db99882 100644 --- a/src/curses/ui_call_flow.c +++ b/src/curses/ui_call_flow.c @@ -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); diff --git a/src/packet/dissectors/packet_ip.c b/src/packet/dissectors/packet_ip.c index d901fe6..2064873 100644 --- a/src/packet/dissectors/packet_ip.c +++ b/src/packet/dissectors/packet_ip.c @@ -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; } \ No newline at end of file diff --git a/src/packet/dissectors/packet_rtcp.c b/src/packet/dissectors/packet_rtcp.c index 112b147..2629564 100644 --- a/src/packet/dissectors/packet_rtcp.c +++ b/src/packet/dissectors/packet_rtcp.c @@ -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; } diff --git a/src/packet/dissectors/packet_rtcp.h b/src/packet/dissectors/packet_rtcp.h index 7f5e2f9..0aaaca1 100644 --- a/src/packet/dissectors/packet_rtcp.h +++ b/src/packet/dissectors/packet_rtcp.h @@ -32,6 +32,9 @@ #include +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(); diff --git a/src/packet/dissectors/packet_rtp.c b/src/packet/dissectors/packet_rtp.c index 922e378..4075ca7 100644 --- a/src/packet/dissectors/packet_rtp.c +++ b/src/packet/dissectors/packet_rtp.c @@ -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; } diff --git a/src/packet/dissectors/packet_udp.c b/src/packet/dissectors/packet_udp.c index 9a9b83e..2bcac41 100644 --- a/src/packet/dissectors/packet_udp.c +++ b/src/packet/dissectors/packet_udp.c @@ -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; } \ No newline at end of file diff --git a/src/packet/packet.c b/src/packet/packet.c index 867acad..a33cb9e 100644 --- a/src/packet/packet.c +++ b/src/packet/packet.c @@ -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) { diff --git a/src/packet/rtp.c b/src/packet/rtp.c index 5bce0d1..f1bbad8 100644 --- a/src/packet/rtp.c +++ b/src/packet/rtp.c @@ -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; -} diff --git a/src/packet/rtp.h b/src/packet/rtp.h index 3374573..3232444 100644 --- a/src/packet/rtp.h +++ b/src/packet/rtp.h @@ -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 */ diff --git a/src/storage.c b/src/storage.c index c81f7ae..e8025c9 100644 --- a/src/storage.c +++ b/src/storage.c @@ -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; }