fix issue where rtp stack was not paying attn to header extensions

This commit is contained in:
Anthony Minessale 2012-12-13 19:49:02 -06:00
parent ab886cad30
commit d301451782
3 changed files with 47 additions and 15 deletions

View File

@ -42,6 +42,7 @@
SWITCH_BEGIN_EXTERN_C SWITCH_BEGIN_EXTERN_C
#define SWITCH_RTP_MAX_BUF_LEN 16384 #define SWITCH_RTP_MAX_BUF_LEN 16384
#define SWITCH_RTCP_MAX_BUF_LEN 16384 #define SWITCH_RTCP_MAX_BUF_LEN 16384
#define SWITCH_RTP_MAX_BUF_LEN_WORDS 4094 /* (max / 4) - 2 */
#define SWITCH_RTP_MAX_CRYPTO_LEN 64 #define SWITCH_RTP_MAX_CRYPTO_LEN 64
#define SWITCH_RTP_KEY_LEN 30 #define SWITCH_RTP_KEY_LEN 30
#define SWITCH_RTP_CRYPTO_KEY_32 "AES_CM_128_HMAC_SHA1_32" #define SWITCH_RTP_CRYPTO_KEY_32 "AES_CM_128_HMAC_SHA1_32"

View File

@ -767,6 +767,11 @@ typedef struct {
unsigned ssrc:32; /* synchronization source */ unsigned ssrc:32; /* synchronization source */
} switch_rtp_hdr_t; } switch_rtp_hdr_t;
typedef struct {
unsigned length:16; /* length */
unsigned profile:16; /* defined by profile */
} switch_rtp_hdr_ext_t;
#else /* BIG_ENDIAN */ #else /* BIG_ENDIAN */
typedef struct { typedef struct {
@ -781,6 +786,11 @@ typedef struct {
unsigned ssrc:32; /* synchronization source */ unsigned ssrc:32; /* synchronization source */
} switch_rtp_hdr_t; } switch_rtp_hdr_t;
typedef struct {
unsigned profile:16; /* defined by profile */
unsigned length:16; /* length */
} switch_rtp_hdr_ext_t;
#endif #endif
#ifdef _MSC_VER #ifdef _MSC_VER

View File

@ -97,13 +97,18 @@ static switch_hash_t *alloc_hash = NULL;
typedef struct { typedef struct {
srtp_hdr_t header; srtp_hdr_t header;
char body[SWITCH_RTP_MAX_BUF_LEN]; char body[SWITCH_RTP_MAX_BUF_LEN];
switch_rtp_hdr_ext_t *ext;
char *ebody;
} rtp_msg_t; } rtp_msg_t;
#define RTP_BODY(_s) (char *) (_s->recv_msg.ebody ? _s->recv_msg.ebody : _s->recv_msg.body)
typedef struct { typedef struct {
switch_rtcp_hdr_t header; switch_rtcp_hdr_t header;
char body[SWITCH_RTCP_MAX_BUF_LEN]; char body[SWITCH_RTCP_MAX_BUF_LEN];
} rtcp_msg_t; } rtcp_msg_t;
typedef enum { typedef enum {
VAD_FIRE_TALK = (1 << 0), VAD_FIRE_TALK = (1 << 0),
VAD_FIRE_NOT_TALK = (1 << 1) VAD_FIRE_NOT_TALK = (1 << 1)
@ -345,7 +350,7 @@ static handle_rfc2833_result_t handle_rfc2833(switch_rtp_t *rtp_session, switch_
#ifdef DEBUG_2833 #ifdef DEBUG_2833
if (rtp_session->dtmf_data.in_digit_sanity && !(rtp_session->dtmf_data.in_digit_sanity % 100)) { if (rtp_session->dtmf_data.in_digit_sanity && !(rtp_session->dtmf_data.in_digit_sanity % 100)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "sanity %d\n", rtp_session->dtmf_data.in_digit_sanity); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "sanity %d %ld\n", rtp_session->dtmf_data.in_digit_sanity, bytes);
} }
#endif #endif
@ -364,7 +369,7 @@ static handle_rfc2833_result_t handle_rfc2833(switch_rtp_t *rtp_session, switch_
if (bytes > rtp_header_len && !switch_test_flag(rtp_session, SWITCH_RTP_FLAG_PROXY_MEDIA) && if (bytes > rtp_header_len && !switch_test_flag(rtp_session, SWITCH_RTP_FLAG_PROXY_MEDIA) &&
!switch_test_flag(rtp_session, SWITCH_RTP_FLAG_PASS_RFC2833) && rtp_session->recv_te && rtp_session->recv_msg.header.pt == rtp_session->recv_te) { !switch_test_flag(rtp_session, SWITCH_RTP_FLAG_PASS_RFC2833) && rtp_session->recv_te && rtp_session->recv_msg.header.pt == rtp_session->recv_te) {
switch_size_t len = bytes - rtp_header_len; switch_size_t len = bytes - rtp_header_len;
unsigned char *packet = (unsigned char *) rtp_session->recv_msg.body; unsigned char *packet = (unsigned char *) RTP_BODY(rtp_session);
int end; int end;
uint16_t duration; uint16_t duration;
char key; char key;
@ -372,6 +377,7 @@ static handle_rfc2833_result_t handle_rfc2833(switch_rtp_t *rtp_session, switch_
uint32_t ts; uint32_t ts;
if (!(packet[0] || packet[1] || packet[2] || packet[3]) && len >= 8) { if (!(packet[0] || packet[1] || packet[2] || packet[3]) && len >= 8) {
switch_core_session_t *session = switch_core_memory_pool_get_data(rtp_session->pool, "__session"); switch_core_session_t *session = switch_core_memory_pool_get_data(rtp_session->pool, "__session");
packet += 4; packet += 4;
len -= 4; len -= 4;
@ -398,7 +404,7 @@ static handle_rfc2833_result_t handle_rfc2833(switch_rtp_t *rtp_session, switch_
} }
} }
#ifdef DEBUG_2833 #ifdef DEBUG_2833
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "packet[%d]: %02x %02x %02x %02x\n", (int) len, (unsigned) packet[0], (unsigned) packet[1], (unsigned) packet[2], (unsigned) packet[3]); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "packet[%d]: %02x %02x %02x %02x\n", (int) len, (unsigned char) packet[0], (unsigned char) packet[1], (unsigned char) packet[2], (unsigned char) packet[3]);
#endif #endif
if (in_digit_seq > rtp_session->dtmf_data.in_digit_seq) { if (in_digit_seq > rtp_session->dtmf_data.in_digit_seq) {
@ -407,7 +413,7 @@ static handle_rfc2833_result_t handle_rfc2833(switch_rtp_t *rtp_session, switch_
#ifdef DEBUG_2833 #ifdef DEBUG_2833
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "read: %c %u %u %u %u %d %d %s\n", switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "read: %c %u %u %u %u %d %d %s\n",
key, in_digit_seq, rtp_session->dtmf_data.in_digit_seq, key, in_digit_seq, rtp_session->dtmf_data.in_digit_seq,
ts, duration, rtp_session->recv_msg.header.m, end, end && !rtp_session->dtmf_data.in_digit_ts ? "ignored" : ""); ts, duration, rtp_session->recv_msg.header.m, end, end && !rtp_session->dtmf_data.in_digit_ts ? "ignored" : "");
#endif #endif
@ -488,7 +494,7 @@ static handle_rfc2833_result_t handle_rfc2833(switch_rtp_t *rtp_session, switch_
} else if (!rtp_session->dtmf_data.in_digit_ts) { } else if (!rtp_session->dtmf_data.in_digit_ts) {
#ifdef DEBUG_2833 #ifdef DEBUG_2833
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "start %d\n", ts); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "start %d [%c]\n", ts, key);
#endif #endif
rtp_session->dtmf_data.in_digit_ts = ts; rtp_session->dtmf_data.in_digit_ts = ts;
rtp_session->dtmf_data.last_in_digit_ts = ts; rtp_session->dtmf_data.last_in_digit_ts = ts;
@ -2872,14 +2878,28 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
switch_assert(bytes); switch_assert(bytes);
more: more:
*bytes = sizeof(rtp_msg_t); *bytes = sizeof(rtp_msg_t);
status = switch_socket_recvfrom(rtp_session->from_addr, rtp_session->sock_input, 0, (void *) &rtp_session->recv_msg, bytes); status = switch_socket_recvfrom(rtp_session->from_addr, rtp_session->sock_input, 0, (void *) &rtp_session->recv_msg, bytes);
ts = ntohl(rtp_session->recv_msg.header.ts); ts = ntohl(rtp_session->recv_msg.header.ts);
rtp_session->recv_msg.ebody = NULL;
if (*bytes) { if (*bytes) {
uint16_t seq = ntohs((uint16_t) rtp_session->recv_msg.header.seq); uint16_t seq = ntohs((uint16_t) rtp_session->recv_msg.header.seq);
if (rtp_session->recv_msg.header.x) { /* header extensions */
rtp_session->recv_msg.ext = (switch_rtp_hdr_ext_t *) rtp_session->recv_msg.body;
rtp_session->recv_msg.ext->length = ntohs(rtp_session->recv_msg.ext->length);
rtp_session->recv_msg.ext->profile = ntohs(rtp_session->recv_msg.ext->profile);
if (rtp_session->recv_msg.ext->length < SWITCH_RTP_MAX_BUF_LEN_WORDS) {
rtp_session->recv_msg.ebody = rtp_session->recv_msg.body + (rtp_session->recv_msg.ext->length * 4) + 4;
}
}
#ifdef DEBUG_MISSED_SEQ
if (rtp_session->last_seq && rtp_session->last_seq+1 != seq) { if (rtp_session->last_seq && rtp_session->last_seq+1 != seq) {
#ifdef DEBUG_MISSED_SEQ
//2012-11-28 18:33:11.799070 [ERR] switch_rtp.c:2883 Missed -65536 RTP frames from sequence [65536] to [-1] (missed). Time since last read [20021] //2012-11-28 18:33:11.799070 [ERR] switch_rtp.c:2883 Missed -65536 RTP frames from sequence [65536] to [-1] (missed). Time since last read [20021]
switch_size_t flushed_packets_diff = rtp_session->stats.inbound.flush_packet_count - rtp_session->last_flush_packet_count; switch_size_t flushed_packets_diff = rtp_session->stats.inbound.flush_packet_count - rtp_session->last_flush_packet_count;
switch_size_t num_missed = (switch_size_t)seq - (rtp_session->last_seq+1); switch_size_t num_missed = (switch_size_t)seq - (rtp_session->last_seq+1);
@ -2913,8 +2933,9 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
flushed_packets_diff, rtp_session->last_read_time ? switch_micro_time_now()-rtp_session->last_read_time : 0); flushed_packets_diff, rtp_session->last_read_time ? switch_micro_time_now()-rtp_session->last_read_time : 0);
} }
} }
#endif
} }
#endif
rtp_session->last_seq = seq; rtp_session->last_seq = seq;
} }
@ -3026,7 +3047,7 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_BYTESWAP) && rtp_session->recv_msg.header.pt == rtp_session->rpayload) { if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_BYTESWAP) && rtp_session->recv_msg.header.pt == rtp_session->rpayload) {
switch_swap_linear((int16_t *)rtp_session->recv_msg.body, (int) *bytes - rtp_header_len); switch_swap_linear((int16_t *)RTP_BODY(rtp_session), (int) *bytes - rtp_header_len);
} }
if (rtp_session->jb && !rtp_session->pause_jb && rtp_session->recv_msg.header.version == 2 && *bytes) { if (rtp_session->jb && !rtp_session->pause_jb && rtp_session->recv_msg.header.version == 2 && *bytes) {
@ -3042,7 +3063,7 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
if (stfu_n_eat(rtp_session->jb, rtp_session->last_read_ts, if (stfu_n_eat(rtp_session->jb, rtp_session->last_read_ts,
ntohs((uint16_t) rtp_session->recv_msg.header.seq), ntohs((uint16_t) rtp_session->recv_msg.header.seq),
rtp_session->recv_msg.header.pt, rtp_session->recv_msg.header.pt,
rtp_session->recv_msg.body, *bytes - rtp_header_len, rtp_session->timer.samplecount) == STFU_ITS_TOO_LATE) { RTP_BODY(rtp_session), *bytes - rtp_header_len, rtp_session->timer.samplecount) == STFU_ITS_TOO_LATE) {
goto more; goto more;
} }
@ -3056,7 +3077,7 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
if (rtp_session->jb && !rtp_session->pause_jb) { if (rtp_session->jb && !rtp_session->pause_jb) {
if ((jb_frame = stfu_n_read_a_frame(rtp_session->jb))) { if ((jb_frame = stfu_n_read_a_frame(rtp_session->jb))) {
memcpy(rtp_session->recv_msg.body, jb_frame->data, jb_frame->dlen); memcpy(RTP_BODY(rtp_session), jb_frame->data, jb_frame->dlen);
if (jb_frame->plc) { if (jb_frame->plc) {
(*flags) |= SFF_PLC; (*flags) |= SFF_PLC;
@ -3679,7 +3700,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
} }
if (bytes && rtp_session->recv_msg.header.version != 2) { if (bytes && rtp_session->recv_msg.header.version != 2) {
uint8_t *data = (uint8_t *) rtp_session->recv_msg.body; uint8_t *data = (uint8_t *) RTP_BODY(rtp_session);
if (rtp_session->recv_msg.header.version == 0) { if (rtp_session->recv_msg.header.version == 0) {
if (rtp_session->ice.ice_user) { if (rtp_session->ice.ice_user) {
@ -3724,7 +3745,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
timer_check: timer_check:
if (do_cng) { if (do_cng) {
uint8_t *data = (uint8_t *) rtp_session->recv_msg.body; uint8_t *data = (uint8_t *) RTP_BODY(rtp_session);
do_2833(rtp_session, session); do_2833(rtp_session, session);
@ -3915,7 +3936,7 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_read(switch_rtp_t *rtp_session, void
*datalen = bytes; *datalen = bytes;
memcpy(data, rtp_session->recv_msg.body, bytes); memcpy(data, RTP_BODY(rtp_session), bytes);
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
@ -3979,7 +4000,7 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_zerocopy_read_frame(switch_rtp_t *rtp
bytes = rtp_common_read(rtp_session, &frame->payload, &frame->flags, io_flags); bytes = rtp_common_read(rtp_session, &frame->payload, &frame->flags, io_flags);
frame->data = rtp_session->recv_msg.body; frame->data = RTP_BODY(rtp_session);
frame->packet = &rtp_session->recv_msg; frame->packet = &rtp_session->recv_msg;
frame->packetlen = bytes; frame->packetlen = bytes;
frame->source = __FILE__; frame->source = __FILE__;
@ -4067,7 +4088,7 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_zerocopy_read(switch_rtp_t *rtp_sessi
} }
bytes = rtp_common_read(rtp_session, payload_type, flags, io_flags); bytes = rtp_common_read(rtp_session, payload_type, flags, io_flags);
*data = rtp_session->recv_msg.body; *data = RTP_BODY(rtp_session);
if (bytes < 0) { if (bytes < 0) {
*datalen = 0; *datalen = 0;