summaryrefslogtreecommitdiff
path: root/res
diff options
context:
space:
mode:
Diffstat (limited to 'res')
-rw-r--r--res/res_rtp_asterisk.c108
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
*/