diff options
Diffstat (limited to 'res')
-rw-r--r-- | res/res_rtp_asterisk.c | 108 |
1 files changed, 48 insertions, 60 deletions
diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c index fadace763..9e9a92c82 100644 --- a/res/res_rtp_asterisk.c +++ b/res/res_rtp_asterisk.c @@ -169,6 +169,12 @@ static int worker_terminate; #define COMPONENT_RTP 1 #define COMPONENT_RTCP 2 +/*! \brief RTP learning mode tracking information */ +struct rtp_learning_info { + int max_seq; /*!< The highest sequence number received */ + int packets; /*!< The number of remaining packets before the source is accepted */ +}; + /*! \brief RTP session description */ struct ast_rtp { int s; @@ -233,14 +239,13 @@ struct ast_rtp { enum strict_rtp_state strict_rtp_state; /*!< Current state that strict RTP protection is in */ struct ast_sockaddr strict_rtp_address; /*!< Remote address information for strict RTP purposes */ - struct ast_sockaddr alt_rtp_address; /*!<Alternate remote address information */ /* * Learning mode values based on pjmedia's probation mode. Many of these values are redundant to the above, * but these are in place to keep learning mode sequence values sealed from their normal counterparts. */ - uint16_t learning_max_seq; /*!< Highest sequence number heard */ - int learning_probation; /*!< Sequential packets untill source is valid */ + struct rtp_learning_info rtp_source_learn; /* Learning mode track for the expected RTP source */ + struct rtp_learning_info alt_source_learn; /* Learning mode tracking for a new RTP source after one has been chosen */ struct rtp_red *red; @@ -371,7 +376,6 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc static void ast_rtp_prop_set(struct ast_rtp_instance *instance, enum ast_rtp_property property, int value); static int ast_rtp_fd(struct ast_rtp_instance *instance, int rtcp); static void ast_rtp_remote_address_set(struct ast_rtp_instance *instance, struct ast_sockaddr *addr); -static void ast_rtp_alt_remote_address_set(struct ast_rtp_instance *instance, struct ast_sockaddr *addr); static int rtp_red_init(struct ast_rtp_instance *instance, int buffer_time, int *payloads, int generations); static int rtp_red_buffer(struct ast_rtp_instance *instance, struct ast_frame *frame); static int ast_rtp_local_bridge(struct ast_rtp_instance *instance0, struct ast_rtp_instance *instance1); @@ -1004,7 +1008,6 @@ static struct ast_rtp_engine asterisk_rtp_engine = { .prop_set = ast_rtp_prop_set, .fd = ast_rtp_fd, .remote_address_set = ast_rtp_remote_address_set, - .alt_remote_address_set = ast_rtp_alt_remote_address_set, .red_init = rtp_red_init, .red_buffer = rtp_red_buffer, .local_bridge = ast_rtp_local_bridge, @@ -1021,7 +1024,7 @@ static struct ast_rtp_engine asterisk_rtp_engine = { #endif }; -static void rtp_learning_seq_init(struct ast_rtp *rtp, uint16_t seq); +static void rtp_learning_seq_init(struct rtp_learning_info *info, uint16_t seq); static void ast_rtp_on_ice_complete(pj_ice_sess *ice, pj_status_t status) { @@ -1032,7 +1035,7 @@ static void ast_rtp_on_ice_complete(pj_ice_sess *ice, pj_status_t status) } rtp->strict_rtp_state = STRICT_RTP_LEARN; - rtp_learning_seq_init(rtp, (uint16_t)rtp->seqno); + rtp_learning_seq_init(&rtp->rtp_source_learn, (uint16_t)rtp->seqno); } static void ast_rtp_on_ice_rx_data(pj_ice_sess *ice, unsigned comp_id, unsigned transport_id, void *pkt, pj_size_t size, const pj_sockaddr_t *src_addr, unsigned src_addr_len) @@ -1592,13 +1595,13 @@ static int create_new_socket(const char *type, int af) * \brief Initializes sequence values and probation for learning mode. * \note This is an adaptation of pjmedia's pjmedia_rtp_seq_init function. * - * \param rtp pointer to rtp struct used with the received rtp packet. - * \param seq sequence number read from the rtp header + * \param info The learning information to track + * \param seq sequence number read from the rtp header to initialize the information with */ -static void rtp_learning_seq_init(struct ast_rtp *rtp, uint16_t seq) +static void rtp_learning_seq_init(struct rtp_learning_info *info, uint16_t seq) { - rtp->learning_max_seq = seq - 1; - rtp->learning_probation = learning_min_sequential; + info->max_seq = seq - 1; + info->packets = learning_min_sequential; } /*! @@ -1606,29 +1609,23 @@ static void rtp_learning_seq_init(struct ast_rtp *rtp, uint16_t seq) * \brief Updates sequence information for learning mode and determines if probation/learning mode should remain in effect. * \note This function was adapted from pjmedia's pjmedia_rtp_seq_update function. * - * \param rtp pointer to rtp struct used with the received rtp packet. + * \param info Structure tracking the learning progress of some address * \param seq sequence number read from the rtp header - * \return boolean value indicating if probation mode is active at the end of the function + * \retval 0 if probation mode should exit for this address + * \retval non-zero if probation mode should continue */ -static int rtp_learning_rtp_seq_update(struct ast_rtp *rtp, uint16_t seq) +static int rtp_learning_rtp_seq_update(struct rtp_learning_info *info, uint16_t seq) { - int probation = 1; - - ast_debug(1, "%p -- probation = %d, seq = %d\n", rtp, rtp->learning_probation, seq); - - if (seq == rtp->learning_max_seq + 1) { + if (seq == info->max_seq + 1) { /* packet is in sequence */ - rtp->learning_probation--; - rtp->learning_max_seq = seq; - if (rtp->learning_probation == 0) { - probation = 0; - } + info->packets--; } else { - rtp->learning_probation = learning_min_sequential - 1; - rtp->learning_max_seq = seq; + /* Sequence discontinuity; reset */ + info->packets = learning_min_sequential - 1; } + info->max_seq = seq; - return probation; + return (info->packets == 0); } static void rtp_add_candidates_to_ice(struct ast_rtp_instance *instance, struct ast_rtp *rtp, struct ast_sockaddr *addr, int port, int component, @@ -1719,7 +1716,8 @@ static int ast_rtp_new(struct ast_rtp_instance *instance, rtp->seqno = ast_random() & 0xffff; rtp->strict_rtp_state = (strictrtp ? STRICT_RTP_LEARN : STRICT_RTP_OPEN); if (strictrtp) { - rtp_learning_seq_init(rtp, (uint16_t)rtp->seqno); + rtp_learning_seq_init(&rtp->rtp_source_learn, (uint16_t)rtp->seqno); + rtp_learning_seq_init(&rtp->alt_source_learn, (uint16_t)rtp->seqno); } /* Create a new socket for us to listen on and use */ @@ -3552,34 +3550,36 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc /* If strict RTP protection is enabled see if we need to learn the remote address or if we need to drop the packet */ if (rtp->strict_rtp_state == STRICT_RTP_LEARN) { - ast_debug(1, "%p -- start learning mode pass with addr = %s\n", rtp, ast_sockaddr_stringify(&addr)); + ast_debug(1, "%p -- Probation learning mode pass with source address %s\n", rtp, ast_sockaddr_stringify(&addr)); /* For now, we always copy the address. */ ast_sockaddr_copy(&rtp->strict_rtp_address, &addr); /* Send the rtp and the seqno from header to rtp_learning_rtp_seq_update to see whether we can exit or not*/ - if (rtp_learning_rtp_seq_update(rtp, ntohl(rtpheader[0]))) { - ast_debug(1, "%p -- Condition for learning hasn't exited, so reject the frame.\n", rtp); + if (rtp_learning_rtp_seq_update(&rtp->rtp_source_learn, seqno)) { + ast_debug(1, "%p -- Probation at seq %d with %d to go; discarding frame\n", + rtp, rtp->rtp_source_learn.max_seq, rtp->rtp_source_learn.packets); return &ast_null_frame; } - ast_debug(1, "%p -- Probation Ended. Set strict_rtp_state to STRICT_RTP_CLOSED with address %s\n", rtp, ast_sockaddr_stringify(&addr)); + ast_verb(4, "%p -- Probation passed - setting RTP source address to %s\n", rtp, ast_sockaddr_stringify(&addr)); rtp->strict_rtp_state = STRICT_RTP_CLOSED; - } else if (rtp->strict_rtp_state == STRICT_RTP_CLOSED) { - if (ast_sockaddr_cmp(&rtp->strict_rtp_address, &addr)) { - /* Hmm, not the strict addres. Perhaps we're getting audio from the alternate? */ - if (!ast_sockaddr_cmp(&rtp->alt_rtp_address, &addr)) { - /* ooh, we did! You're now the new expected address, son! */ - ast_sockaddr_copy(&rtp->strict_rtp_address, - &addr); - } else { - const char *real_addr = ast_strdupa(ast_sockaddr_stringify(&addr)); - const char *expected_addr = ast_strdupa(ast_sockaddr_stringify(&rtp->strict_rtp_address)); - - ast_debug(1, "Received RTP packet from %s, dropping due to strict RTP protection. Expected it to be from %s\n", - real_addr, expected_addr); - + } + if (rtp->strict_rtp_state == STRICT_RTP_CLOSED) { + if (!ast_sockaddr_cmp(&rtp->strict_rtp_address, &addr)) { + /* Always reset the alternate learning source */ + rtp_learning_seq_init(&rtp->alt_source_learn, seqno); + } else { + /* Start trying to learn from the new address. If we pass a probationary period with + * it, that means we've stopped getting RTP from the original source and we should + * switch to it. + */ + if (rtp_learning_rtp_seq_update(&rtp->alt_source_learn, seqno)) { + ast_debug(1, "%p -- Received RTP packet from %s, dropping due to strict RTP protection. Will switch to it in %d packets\n", + rtp, ast_sockaddr_stringify(&addr), rtp->alt_source_learn.packets); return &ast_null_frame; } + ast_verb(4, "%p -- Switching RTP source address to %s\n", rtp, ast_sockaddr_stringify(&addr)); + ast_sockaddr_copy(&rtp->strict_rtp_address, &addr); } } @@ -3958,24 +3958,12 @@ static void ast_rtp_remote_address_set(struct ast_rtp_instance *instance, struct if (strictrtp && rtp->strict_rtp_state != STRICT_RTP_OPEN) { rtp->strict_rtp_state = STRICT_RTP_LEARN; - rtp_learning_seq_init(rtp, rtp->seqno); + rtp_learning_seq_init(&rtp->rtp_source_learn, rtp->seqno); } return; } -static void ast_rtp_alt_remote_address_set(struct ast_rtp_instance *instance, struct ast_sockaddr *addr) -{ - struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); - - /* No need to futz with rtp->rtcp here because ast_rtcp_read is already able to adjust if receiving - * RTCP from an "unexpected" source - */ - ast_sockaddr_copy(&rtp->alt_rtp_address, addr); - - return; -} - /*! \brief Write t140 redundacy frame * \param data primary data to be buffered */ |