From cce5ee5b7a95378a2218954a1d58b04b120827a0 Mon Sep 17 00:00:00 2001 From: "Joshua C. Colp" Date: Wed, 17 Mar 2021 12:28:45 -0300 Subject: [PATCH] res_rtp_asterisk: Force resync on SSRC change. When an SSRC change occurs the timestamps are likely to change as well. As a result we need to reset the timestamp mapping done in the calc_rxstamp function so that they map properly from timestamp to real time. This previously occurred but due to packet retransmission support the explicit setting of the marker bit was not effective. ASTERISK-29352 Change-Id: I2d4c8f93ea24abc1030196706de2d70facf05a5a --- res/res_rtp_asterisk.c | 98 ++++++++++++++++++++++-------------------- 1 file changed, 51 insertions(+), 47 deletions(-) diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c index 21eff54511..b0a3f2a400 100644 --- a/res/res_rtp_asterisk.c +++ b/res/res_rtp_asterisk.c @@ -7203,12 +7203,13 @@ static void rtp_instance_parse_extmap_extensions(struct ast_rtp_instance *instan } static struct ast_frame *ast_rtp_interpret(struct ast_rtp_instance *instance, struct ast_srtp *srtp, - const struct ast_sockaddr *remote_address, unsigned char *read_area, int length, int prev_seqno) + const struct ast_sockaddr *remote_address, unsigned char *read_area, int length, int prev_seqno, + unsigned int bundled) { unsigned int *rtpheader = (unsigned int*)(read_area); struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); struct ast_rtp_instance *instance1; - int res = length, hdrlen = 12, seqno, payloadtype, padding, mark, ext, cc; + int res = length, hdrlen = 12, ssrc, seqno, payloadtype, padding, mark, ext, cc; unsigned int timestamp; RAII_VAR(struct ast_rtp_payload_type *, payload, NULL, ao2_cleanup); struct frame_list frames; @@ -7225,6 +7226,7 @@ static struct ast_frame *ast_rtp_interpret(struct ast_rtp_instance *instance, st } /* Pull out the various other fields we will need */ + ssrc = ntohl(rtpheader[2]); seqno = ntohl(rtpheader[0]); payloadtype = (seqno & 0x7f0000) >> 16; padding = seqno & (1 << 29); @@ -7274,6 +7276,42 @@ static struct ast_frame *ast_rtp_interpret(struct ast_rtp_instance *instance, st return AST_LIST_FIRST(&frames) ? AST_LIST_FIRST(&frames) : &ast_null_frame; } + /* Only non-bundled instances can change/learn the remote's SSRC implicitly. */ + if (!bundled) { + /* Force a marker bit and change SSRC if the SSRC changes */ + if (rtp->themssrc_valid && rtp->themssrc != ssrc) { + struct ast_frame *f, srcupdate = { + AST_FRAME_CONTROL, + .subclass.integer = AST_CONTROL_SRCCHANGE, + }; + + if (!mark) { + if (ast_debug_rtp_packet_is_allowed) { + ast_debug(0, "(%p) RTP forcing Marker bit, because SSRC has changed\n", instance); + } + mark = 1; + } + + f = ast_frisolate(&srcupdate); + AST_LIST_INSERT_TAIL(&frames, f, frame_list); + + rtp->seedrxseqno = 0; + rtp->rxcount = 0; + rtp->rxoctetcount = 0; + rtp->cycles = 0; + prev_seqno = 0; + rtp->last_seqno = 0; + rtp->last_end_timestamp = 0; + if (rtp->rtcp) { + rtp->rtcp->expected_prior = 0; + rtp->rtcp->received_prior = 0; + } + } + + rtp->themssrc = ssrc; /* Record their SSRC to put in future RR */ + rtp->themssrc_valid = 1; + } + rtp->rxcount++; rtp->rxoctetcount += (res - hdrlen); if (rtp->rxcount == 1) { @@ -7498,13 +7536,14 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc struct ast_srtp *srtp; RAII_VAR(struct ast_rtp_instance *, child, NULL, rtp_instance_unlock); struct ast_sockaddr addr; - int res, hdrlen = 12, version, payloadtype, mark; + int res, hdrlen = 12, version, payloadtype; unsigned char *read_area = rtp->rawdata + AST_FRIENDLY_OFFSET; size_t read_area_size = sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET; unsigned int *rtpheader = (unsigned int*)(read_area), seqno, ssrc, timestamp, prev_seqno; struct ast_sockaddr remote_address = { {0,} }; struct frame_list frames; struct ast_frame *frame; + unsigned int bundled; /* If this is actually RTCP let's hop on over and handle it */ if (rtcp) { @@ -7781,7 +7820,6 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc /* Pull out the various other fields we will need */ payloadtype = (seqno & 0x7f0000) >> 16; - mark = seqno & (1 << 23); seqno &= 0xffff; timestamp = ntohl(rtpheader[1]); @@ -7793,48 +7831,14 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc AST_LIST_HEAD_INIT_NOLOCK(&frames); - /* Only non-bundled instances can change/learn the remote's SSRC implicitly. */ - if (!child && !AST_VECTOR_SIZE(&rtp->ssrc_mapping)) { - /* Force a marker bit and change SSRC if the SSRC changes */ - if (rtp->themssrc_valid && rtp->themssrc != ssrc) { - struct ast_frame *f, srcupdate = { - AST_FRAME_CONTROL, - .subclass.integer = AST_CONTROL_SRCCHANGE, - }; - - if (!mark) { - if (ast_debug_rtp_packet_is_allowed) { - ast_debug(0, "(%p) RTP forcing Marker bit, because SSRC has changed\n", instance); - } - mark = 1; - } - - f = ast_frisolate(&srcupdate); - AST_LIST_INSERT_TAIL(&frames, f, frame_list); - - rtp->seedrxseqno = 0; - rtp->rxcount = 0; - rtp->rxoctetcount = 0; - rtp->cycles = 0; - rtp->lastrxseqno = 0; - rtp->last_seqno = 0; - rtp->last_end_timestamp = 0; - if (rtp->rtcp) { - rtp->rtcp->expected_prior = 0; - rtp->rtcp->received_prior = 0; - } - } - - rtp->themssrc = ssrc; /* Record their SSRC to put in future RR */ - rtp->themssrc_valid = 1; - } + bundled = (child || AST_VECTOR_SIZE(&rtp->ssrc_mapping)) ? 1 : 0; prev_seqno = rtp->lastrxseqno; rtp->lastrxseqno = seqno; if (!rtp->recv_buffer) { /* If there is no receive buffer then we can pass back the frame directly */ - frame = ast_rtp_interpret(instance, srtp, &addr, read_area, res, prev_seqno); + frame = ast_rtp_interpret(instance, srtp, &addr, read_area, res, prev_seqno, bundled); AST_LIST_INSERT_TAIL(&frames, frame, frame_list); return AST_LIST_FIRST(&frames); } else if (rtp->expectedrxseqno == -1 || seqno == rtp->expectedrxseqno) { @@ -7849,7 +7853,7 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc * return it directly without duplicating it. */ if (!ast_data_buffer_count(rtp->recv_buffer)) { - frame = ast_rtp_interpret(instance, srtp, &addr, read_area, res, prev_seqno); + frame = ast_rtp_interpret(instance, srtp, &addr, read_area, res, prev_seqno, bundled); AST_LIST_INSERT_TAIL(&frames, frame, frame_list); return AST_LIST_FIRST(&frames); } @@ -7864,7 +7868,7 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc * chance it will be overwritten. */ if (!ast_data_buffer_get(rtp->recv_buffer, rtp->expectedrxseqno)) { - frame = ast_rtp_interpret(instance, srtp, &addr, read_area, res, prev_seqno); + frame = ast_rtp_interpret(instance, srtp, &addr, read_area, res, prev_seqno, bundled); AST_LIST_INSERT_TAIL(&frames, frame, frame_list); return AST_LIST_FIRST(&frames); } @@ -7874,7 +7878,7 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc * to the head of the frames list and avoid having to duplicate it but this would result in out * of order packet processing by libsrtp which we are trying to avoid. */ - frame = ast_frdup(ast_rtp_interpret(instance, srtp, &addr, read_area, res, prev_seqno)); + frame = ast_frdup(ast_rtp_interpret(instance, srtp, &addr, read_area, res, prev_seqno, bundled)); if (frame) { AST_LIST_INSERT_TAIL(&frames, frame, frame_list); prev_seqno = seqno; @@ -7889,7 +7893,7 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc break; } - frame = ast_frdup(ast_rtp_interpret(instance, srtp, &addr, payload->buf, payload->size, prev_seqno)); + frame = ast_frdup(ast_rtp_interpret(instance, srtp, &addr, payload->buf, payload->size, prev_seqno, bundled)); ast_free(payload); if (!frame) { @@ -7935,7 +7939,7 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc /* If the packet we received is the one we are expecting at this point then add it in */ if (rtp->expectedrxseqno == seqno) { - frame = ast_frdup(ast_rtp_interpret(instance, srtp, &addr, read_area, res, prev_seqno)); + frame = ast_frdup(ast_rtp_interpret(instance, srtp, &addr, read_area, res, prev_seqno, bundled)); if (frame) { AST_LIST_INSERT_TAIL(&frames, frame, frame_list); prev_seqno = seqno; @@ -7960,7 +7964,7 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc payload = (struct ast_rtp_rtcp_nack_payload *)ast_data_buffer_remove(rtp->recv_buffer, rtp->expectedrxseqno); if (payload) { - frame = ast_frdup(ast_rtp_interpret(instance, srtp, &addr, payload->buf, payload->size, prev_seqno)); + frame = ast_frdup(ast_rtp_interpret(instance, srtp, &addr, payload->buf, payload->size, prev_seqno, bundled)); if (frame) { AST_LIST_INSERT_TAIL(&frames, frame, frame_list); prev_seqno = rtp->expectedrxseqno; @@ -7982,7 +7986,7 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc * to be the last packet processed right now and it is also guaranteed that it will always return * non-NULL. */ - frame = ast_rtp_interpret(instance, srtp, &addr, read_area, res, prev_seqno); + frame = ast_rtp_interpret(instance, srtp, &addr, read_area, res, prev_seqno, bundled); AST_LIST_INSERT_TAIL(&frames, frame, frame_list); rtp->expectedrxseqno = seqno + 1; if (rtp->expectedrxseqno == SEQNO_CYCLE_OVER) {