From bef9ab82d42baf09311b74159a87d5dfeb2fefc7 Mon Sep 17 00:00:00 2001 From: Luke Howard Date: Sat, 6 Jun 2020 00:45:24 +0000 Subject: [PATCH 1/4] support non-zero PTP domains --- src/mast.h | 1 + src/sdp.c | 9 ++++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/mast.h b/src/mast.h index 4a4bc4e..939fbed 100644 --- a/src/mast.h +++ b/src/mast.h @@ -137,6 +137,7 @@ typedef struct double packet_duration; // a=ptime char ptp_gmid[24]; // a=ts-refclk + unsigned int ptp_domain; // a=ts-refclk uint64_t clock_offset; // a=mediaclk } mast_sdp_t; diff --git a/src/sdp.c b/src/sdp.c index 23867f9..87e662c 100644 --- a/src/sdp.c +++ b/src/sdp.c @@ -77,6 +77,7 @@ static void sdp_media_parse(mast_sdp_t *sdp, char* line, int line_num) char *port = strsep(&line, " "); char *proto = strsep(&line, " "); char *fmt = strsep(&line, " "); + char *pEnd = NULL; if (media == NULL || strcmp(media, "audio") != 0) { mast_error("SDP media type is not audio: %s", media); @@ -92,7 +93,7 @@ static void sdp_media_parse(mast_sdp_t *sdp, char* line, int line_num) mast_error("SDP transport protocol is not RTP/AVP: %s", proto); } - if (fmt == NULL || strlen(fmt) > 2) { + if (fmt == NULL || strtoul(fmt, &pEnd, 10) > 127 || *pEnd) { mast_error("SDP media format is not valid: %s", fmt); } else { mast_sdp_set_payload_type(sdp, atoi(fmt)); @@ -133,8 +134,10 @@ static void sdp_attribute_parse(mast_sdp_t *sdp, char* line, int line_num) strncpy(sdp->ptp_gmid, ptp_gmid, sizeof(sdp->ptp_gmid)-1); } - if (ptp_domain && strcmp(ptp_domain, "0") != 0) { - mast_warn("PTP domain is not 0: %s", ptp_version); + if (ptp_domain) { + sdp->ptp_domain = atoi(ptp_domain); + if (sdp->ptp_domain) + mast_warn("PTP domain is not 0: %s", ptp_version); } } else { mast_warn("SDP Clock Source is not PTP"); From 4f2fb6c61665783d76f1db1e56c37551db7f154b Mon Sep 17 00:00:00 2001 From: Luke Howard Date: Sat, 6 Jun 2020 00:45:49 +0000 Subject: [PATCH 2/4] add RTP_VERSION constant --- src/mast.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mast.h b/src/mast.h index 939fbed..e38b665 100644 --- a/src/mast.h +++ b/src/mast.h @@ -159,6 +159,7 @@ void mast_sdp_set_encoding_name(mast_sdp_t *sdp, const char* encoding_name); #define RTP_MAX_PAYLOAD (1440) #define RTP_HEADER_LENGTH (12) +#define RTP_VERSION (2) typedef struct { From 7486a1733c60bc700c0beb939b8adb527a01e67e Mon Sep 17 00:00:00 2001 From: Luke Howard Date: Sat, 6 Jun 2020 00:46:09 +0000 Subject: [PATCH 3/4] add RTP sequence number checking API from RTP RFC --- src/mast.h | 22 +++++++++++- src/sequence.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 src/sequence.c diff --git a/src/mast.h b/src/mast.h index e38b665..743493c 100644 --- a/src/mast.h +++ b/src/mast.h @@ -188,7 +188,27 @@ int mast_rtp_recv( mast_socket_t* socket, mast_rtp_packet_t* packet ); // Return the duration of a packet in microseconds int mast_rtp_packet_duration(mast_rtp_packet_t* packet, mast_sdp_t* sdp); - +#define RTP_SEQ_MOD (1<<16) +#define RTP_MIN_SEQUENTIAL 2 + +typedef struct { + uint16_t max_seq; + uint32_t cycles; + uint32_t base_seq; + uint32_t bad_seq; + uint32_t probation; + uint32_t received; + uint32_t expected_prior; + uint32_t received_prior; + uint32_t transit; + uint32_t jitter; +} mast_rtp_sequence_state_t; + +void +mast_rtp_init_sequence(mast_rtp_sequence_state_t *s, uint16_t seq); + +int +mast_rtp_update_sequence(mast_rtp_sequence_state_t *s, uint16_t seq); // ------- Audio File Writing --------- diff --git a/src/sequence.c b/src/sequence.c new file mode 100644 index 0000000..801b575 --- /dev/null +++ b/src/sequence.c @@ -0,0 +1,97 @@ +/* + Copyright (C) The Internet Society (2003). All Rights Reserved. + + This document and translations of it may be copied and furnished to + others, and derivative works that comment on or otherwise explain it + or assist in its implementation may be prepared, copied, published + and distributed, in whole or in part, without restriction of any + kind, provided that the above copyright notice and this paragraph are + included on all such copies and derivative works. However, this + document itself may not be modified in any way, such as by removing + the copyright notice or references to the Internet Society or other + Internet organizations, except as needed for the purpose of + developing Internet standards in which case the procedures for + copyrights defined in the Internet Standards process must be + followed, or as required to translate it into languages other than + English. + + The limited permissions granted above are perpetual and will not be + revoked by the Internet Society or its successors or assigns. + + This document and the information contained herein is provided on an + "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING + TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION + HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF + MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. +*/ + +#include "mast.h" + +void +mast_rtp_init_sequence(mast_rtp_sequence_state_t *s, uint16_t seq) +{ + s->base_seq = seq; + s->max_seq = seq; + s->bad_seq = RTP_SEQ_MOD + 1; + s->cycles = 0; + s->received = 0; + s->received_prior = 0; + s->expected_prior = 0; +} + +int +mast_rtp_update_sequence(mast_rtp_sequence_state_t *s, uint16_t seq) +{ + uint16_t udelta = seq - s->max_seq; +#define MAX_DROPOUT 3000 +#define MAX_MISORDER 100 + + /* + * Source is not valid until RTP_MIN_SEQUENTIAL packets with + * sequential sequence numbers have been received. + */ + if (s->probation) { + /* packet is in sequence */ + if (seq == s->max_seq + 1) { + s->probation--; + s->max_seq = seq; + if (s->probation == 0) { + mast_rtp_init_sequence(s, seq); + s->received++; + return TRUE; + } + } else { + s->probation = RTP_MIN_SEQUENTIAL - 1; + s->max_seq = seq; + } + return FALSE; + } else if (udelta < MAX_DROPOUT) { + /* in order, with permissible gap */ + if (seq < s->max_seq) { + /* + * Sequence number wrapped - count another 64K cycle. + */ + s->cycles += RTP_SEQ_MOD; + } + s->max_seq = seq; + } else if (udelta <= RTP_SEQ_MOD - MAX_MISORDER) { + /* the sequence number made a very large jump */ + if (seq == s->bad_seq) { + /* + * Two sequential packets -- assume that the other side + * restarted without telling us so just re-sync + * (i.e., pretend this was the first packet). + */ + mast_rtp_init_sequence(s, seq); + } else { + s->bad_seq = (seq + 1) & (RTP_SEQ_MOD-1); + return FALSE; + } + } else { + /* duplicate or reordered packet */ + } + + s->received++; + return TRUE; +} From b1a4c3e01c9c4e9d4c8424193048b2a653d0beee Mon Sep 17 00:00:00 2001 From: Luke Howard Date: Sat, 6 Jun 2020 00:46:36 +0000 Subject: [PATCH 4/4] skip over extension headers and padding --- src/rtp.c | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/src/rtp.c b/src/rtp.c index 48ce8d3..7280425 100644 --- a/src/rtp.c +++ b/src/rtp.c @@ -17,7 +17,7 @@ int mast_rtp_parse( mast_rtp_packet_t* packet ) { - int header_len = RTP_HEADER_LENGTH; + size_t header_len = RTP_HEADER_LENGTH; // Byte 1 packet->version = bitMask(packet->buffer[0], 0x02, 6); @@ -39,12 +39,37 @@ int mast_rtp_parse( mast_rtp_packet_t* packet ) packet->ssrc = bytesToUInt32(&packet->buffer[8]); // Calculate the size of the payload - // FIXME: skip over header extension header_len += (packet->csrc_count * 4); + + if (packet->extension) { + uint16_t ext_header_len; + + if (packet->length < header_len + 4) + return -1; + + /* ignore extension header ID at buffer + header_len */ + ext_header_len = bytesToUInt16(&packet->buffer[header_len + 2]); + header_len += 4 + (ext_header_len * 4); + } + + if (packet->length < header_len) + return -1; + packet->payload_length = packet->length - header_len; packet->payload = packet->buffer + header_len; - // FIXME: Remove padding from payload_length + if (packet->padding) { + uint8_t padding_len; + + if (packet->payload_length < 1) + return -1; + + padding_len = packet->payload[packet->payload_length - 1]; + if (padding_len < 1 || padding_len > packet->payload_length) + return -1; + + packet->payload_length -= padding_len; + } // Success return 0;