chan_sip: Add rtcp-mux support

ASTERISK-26846 #close

Change-Id: I541a1602ff55ab73684e9f8002edb9e0e745d639
pull/7/head
Sean Bright 8 years ago
parent 732367e806
commit 15aa3c0a23

@ -27,9 +27,10 @@ From 14.3.0 to 14.4.0:
res_rtp_asterisk: res_rtp_asterisk:
- The RTP layer of Asterisk now has support for RFC 5761: "Multiplexing RTP - The RTP layer of Asterisk now has support for RFC 5761: "Multiplexing RTP
Data and Control Packets on a Single Port." So far, the only channel driver Data and Control Packets on a Single Port." For the PJSIP channel driver,
that supports this feature is chan_pjsip. You can set "rtcp_mux = yes" on chan_pjsip, you can set "rtcp_mux = yes" on a PJSIP endpoint in pjsip.conf
a PJSIP endpoint in pjsip.conf to enable the feature. to enable the feature. For chan_sip you can set "rtcp_mux = yes" either
globally or on a per-peer basis in sip.conf.
New in 14.0.0 New in 14.0.0

@ -1216,6 +1216,7 @@ static int process_sdp_o(const char *o, struct sip_pvt *p);
static int process_sdp_c(const char *c, struct ast_sockaddr *addr); static int process_sdp_c(const char *c, struct ast_sockaddr *addr);
static int process_sdp_a_sendonly(const char *a, int *sendonly); static int process_sdp_a_sendonly(const char *a, int *sendonly);
static int process_sdp_a_ice(const char *a, struct sip_pvt *p, struct ast_rtp_instance *instance); static int process_sdp_a_ice(const char *a, struct sip_pvt *p, struct ast_rtp_instance *instance);
static int process_sdp_a_rtcp_mux(const char *a, struct sip_pvt *p, int *requested);
static int process_sdp_a_dtls(const char *a, struct sip_pvt *p, struct ast_rtp_instance *instance); static int process_sdp_a_dtls(const char *a, struct sip_pvt *p, struct ast_rtp_instance *instance);
static int process_sdp_a_audio(const char *a, struct sip_pvt *p, struct ast_rtp_codecs *newaudiortp, int *last_rtpmap_codec); static int process_sdp_a_audio(const char *a, struct sip_pvt *p, struct ast_rtp_codecs *newaudiortp, int *last_rtpmap_codec);
static int process_sdp_a_video(const char *a, struct sip_pvt *p, struct ast_rtp_codecs *newvideortp, int *last_rtpmap_codec); static int process_sdp_a_video(const char *a, struct sip_pvt *p, struct ast_rtp_codecs *newvideortp, int *last_rtpmap_codec);
@ -6011,7 +6012,7 @@ static int dialog_initialize_rtp(struct sip_pvt *dialog)
ast_rtp_instance_set_hold_timeout(dialog->vrtp, dialog->rtpholdtimeout); ast_rtp_instance_set_hold_timeout(dialog->vrtp, dialog->rtpholdtimeout);
ast_rtp_instance_set_keepalive(dialog->vrtp, dialog->rtpkeepalive); ast_rtp_instance_set_keepalive(dialog->vrtp, dialog->rtpkeepalive);
ast_rtp_instance_set_prop(dialog->vrtp, AST_RTP_PROPERTY_RTCP, 1); ast_rtp_instance_set_prop(dialog->vrtp, AST_RTP_PROPERTY_RTCP, AST_RTP_INSTANCE_RTCP_STANDARD);
ast_rtp_instance_set_qos(dialog->vrtp, global_tos_video, global_cos_video, "SIP VIDEO"); ast_rtp_instance_set_qos(dialog->vrtp, global_tos_video, global_cos_video, "SIP VIDEO");
} }
@ -6031,14 +6032,14 @@ static int dialog_initialize_rtp(struct sip_pvt *dialog)
/* Do not timeout text as its not constant*/ /* Do not timeout text as its not constant*/
ast_rtp_instance_set_keepalive(dialog->trtp, dialog->rtpkeepalive); ast_rtp_instance_set_keepalive(dialog->trtp, dialog->rtpkeepalive);
ast_rtp_instance_set_prop(dialog->trtp, AST_RTP_PROPERTY_RTCP, 1); ast_rtp_instance_set_prop(dialog->trtp, AST_RTP_PROPERTY_RTCP, AST_RTP_INSTANCE_RTCP_STANDARD);
} }
ast_rtp_instance_set_timeout(dialog->rtp, dialog->rtptimeout); ast_rtp_instance_set_timeout(dialog->rtp, dialog->rtptimeout);
ast_rtp_instance_set_hold_timeout(dialog->rtp, dialog->rtpholdtimeout); ast_rtp_instance_set_hold_timeout(dialog->rtp, dialog->rtpholdtimeout);
ast_rtp_instance_set_keepalive(dialog->rtp, dialog->rtpkeepalive); ast_rtp_instance_set_keepalive(dialog->rtp, dialog->rtpkeepalive);
ast_rtp_instance_set_prop(dialog->rtp, AST_RTP_PROPERTY_RTCP, 1); ast_rtp_instance_set_prop(dialog->rtp, AST_RTP_PROPERTY_RTCP, AST_RTP_INSTANCE_RTCP_STANDARD);
ast_rtp_instance_set_prop(dialog->rtp, AST_RTP_PROPERTY_DTMF, ast_test_flag(&dialog->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833); ast_rtp_instance_set_prop(dialog->rtp, AST_RTP_PROPERTY_DTMF, ast_test_flag(&dialog->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833);
ast_rtp_instance_set_prop(dialog->rtp, AST_RTP_PROPERTY_DTMF_COMPENSATE, ast_test_flag(&dialog->flags[1], SIP_PAGE2_RFC2833_COMPENSATE)); ast_rtp_instance_set_prop(dialog->rtp, AST_RTP_PROPERTY_DTMF_COMPENSATE, ast_test_flag(&dialog->flags[1], SIP_PAGE2_RFC2833_COMPENSATE));
@ -7752,6 +7753,15 @@ static int interpret_t38_parameters(struct sip_pvt *p, const struct ast_control_
return res; return res;
} }
enum sip_media_fds {
SIP_AUDIO_RTP_FD,
SIP_AUDIO_RTCP_FD,
SIP_VIDEO_RTP_FD,
SIP_VIDEO_RTCP_FD,
SIP_TEXT_RTP_FD,
SIP_UDPTL_FD,
};
/*! /*!
* \internal * \internal
* \brief Create and initialize UDPTL for the specified dialog * \brief Create and initialize UDPTL for the specified dialog
@ -7780,7 +7790,7 @@ static int initialize_udptl(struct sip_pvt *p)
/* T38 can be supported by this dialog, create it and set the derived properties */ /* T38 can be supported by this dialog, create it and set the derived properties */
if ((p->udptl = ast_udptl_new_with_bindaddr(sched, io, 0, &bindaddr))) { if ((p->udptl = ast_udptl_new_with_bindaddr(sched, io, 0, &bindaddr))) {
if (p->owner) { if (p->owner) {
ast_channel_set_fd(p->owner, 5, ast_udptl_fd(p->udptl)); ast_channel_set_fd(p->owner, SIP_UDPTL_FD, ast_udptl_fd(p->udptl));
} }
ast_udptl_setqos(p->udptl, global_tos_audio, global_cos_audio); ast_udptl_setqos(p->udptl, global_tos_audio, global_cos_audio);
@ -8206,20 +8216,28 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit
* UDPTL is created as needed in the lifetime of a dialog, its file * UDPTL is created as needed in the lifetime of a dialog, its file
* descriptor is set in initialize_udptl */ * descriptor is set in initialize_udptl */
if (i->rtp) { if (i->rtp) {
ast_channel_set_fd(tmp, 0, ast_rtp_instance_fd(i->rtp, 0)); ast_channel_set_fd(tmp, SIP_AUDIO_RTP_FD, ast_rtp_instance_fd(i->rtp, 0));
ast_channel_set_fd(tmp, 1, ast_rtp_instance_fd(i->rtp, 1)); if (ast_test_flag(&i->flags[2], SIP_PAGE3_RTCP_MUX)) {
ast_channel_set_fd(tmp, SIP_AUDIO_RTCP_FD, -1);
} else {
ast_channel_set_fd(tmp, SIP_AUDIO_RTCP_FD, ast_rtp_instance_fd(i->rtp, 1));
}
ast_rtp_instance_set_write_format(i->rtp, fmt); ast_rtp_instance_set_write_format(i->rtp, fmt);
ast_rtp_instance_set_read_format(i->rtp, fmt); ast_rtp_instance_set_read_format(i->rtp, fmt);
} }
if (needvideo && i->vrtp) { if (needvideo && i->vrtp) {
ast_channel_set_fd(tmp, 2, ast_rtp_instance_fd(i->vrtp, 0)); ast_channel_set_fd(tmp, SIP_VIDEO_RTP_FD, ast_rtp_instance_fd(i->vrtp, 0));
ast_channel_set_fd(tmp, 3, ast_rtp_instance_fd(i->vrtp, 1)); if (ast_test_flag(&i->flags[2], SIP_PAGE3_RTCP_MUX)) {
ast_channel_set_fd(tmp, SIP_VIDEO_RTCP_FD, -1);
} else {
ast_channel_set_fd(tmp, SIP_VIDEO_RTCP_FD, ast_rtp_instance_fd(i->vrtp, 1));
}
} }
if (needtext && i->trtp) { if (needtext && i->trtp) {
ast_channel_set_fd(tmp, 4, ast_rtp_instance_fd(i->trtp, 0)); ast_channel_set_fd(tmp, SIP_TEXT_RTP_FD, ast_rtp_instance_fd(i->trtp, 0));
} }
if (i->udptl) { if (i->udptl) {
ast_channel_set_fd(tmp, 5, ast_udptl_fd(i->udptl)); ast_channel_set_fd(tmp, SIP_UDPTL_FD, ast_udptl_fd(i->udptl));
} }
if (state == AST_STATE_RING) { if (state == AST_STATE_RING) {
@ -10074,6 +10092,42 @@ static int has_media_stream(struct sip_pvt *p, enum media_type m)
return 0; return 0;
} }
static void configure_rtcp(struct sip_pvt *p, struct ast_rtp_instance *instance, int which, int remote_rtcp_mux)
{
int local_rtcp_mux = ast_test_flag(&p->flags[2], SIP_PAGE3_RTCP_MUX);
int fd = -1;
if (local_rtcp_mux && remote_rtcp_mux) {
ast_rtp_instance_set_prop(instance, AST_RTP_PROPERTY_RTCP, AST_RTP_INSTANCE_RTCP_MUX);
} else {
ast_rtp_instance_set_prop(instance, AST_RTP_PROPERTY_RTCP, AST_RTP_INSTANCE_RTCP_STANDARD);
fd = ast_rtp_instance_fd(instance, 1);
}
if (p->owner) {
ast_channel_set_fd(p->owner, which, fd);
}
}
static void set_ice_components(struct sip_pvt *p, struct ast_rtp_instance *instance, int remote_rtcp_mux)
{
struct ast_rtp_engine_ice *ice;
int local_rtcp_mux = ast_test_flag(&p->flags[2], SIP_PAGE3_RTCP_MUX);
ice = ast_rtp_instance_get_ice(instance);
if (!ice) {
return;
}
if (local_rtcp_mux && remote_rtcp_mux) {
/* We both support RTCP mux. Only one ICE component necessary */
ice->change_components(instance, 1);
} else {
/* They either don't support RTCP mux or we don't know if they do yet. */
ice->change_components(instance, 2);
}
}
/*! \brief Process SIP SDP offer, select formats and activate media channels /*! \brief Process SIP SDP offer, select formats and activate media channels
If offer is rejected, we will not change any properties of the call If offer is rejected, we will not change any properties of the call
Return 0 on success, a negative value on errors. Return 0 on success, a negative value on errors.
@ -10132,6 +10186,10 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
int secure_audio = FALSE; int secure_audio = FALSE;
int secure_video = FALSE; int secure_video = FALSE;
/* RTCP Multiplexing */
int remote_rtcp_mux_audio = FALSE;
int remote_rtcp_mux_video = FALSE;
/* Others */ /* Others */
int sendonly = -1; int sendonly = -1;
unsigned int numberofports; unsigned int numberofports;
@ -10662,6 +10720,8 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
} }
} else if (process_sdp_a_audio(value, p, &newaudiortp, &last_rtpmap_codec)) { } else if (process_sdp_a_audio(value, p, &newaudiortp, &last_rtpmap_codec)) {
processed = TRUE; processed = TRUE;
} else if (process_sdp_a_rtcp_mux(value, p, &remote_rtcp_mux_audio)) {
processed = TRUE;
} }
} }
/* Video specific scanning */ /* Video specific scanning */
@ -10683,6 +10743,8 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
} }
} else if (process_sdp_a_video(value, p, &newvideortp, &last_rtpmap_codec)) { } else if (process_sdp_a_video(value, p, &newvideortp, &last_rtpmap_codec)) {
processed = TRUE; processed = TRUE;
} else if (process_sdp_a_rtcp_mux(value, p, &remote_rtcp_mux_video)) {
processed = TRUE;
} }
} }
/* Text (T.140) specific scanning */ /* Text (T.140) specific scanning */
@ -10857,6 +10919,7 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
if (sa && portno > 0) { if (sa && portno > 0) {
/* Start ICE negotiation here, only when it is response, and setting that we are conrolling agent, /* Start ICE negotiation here, only when it is response, and setting that we are conrolling agent,
as we are offerer */ as we are offerer */
set_ice_components(p, p->rtp, remote_rtcp_mux_audio);
if (req->method == SIP_RESPONSE) { if (req->method == SIP_RESPONSE) {
start_ice(p->rtp, 1); start_ice(p->rtp, 1);
} }
@ -10870,11 +10933,7 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
ast_rtp_codecs_payloads_copy(&newaudiortp, ast_rtp_instance_get_codecs(p->rtp), p->rtp); ast_rtp_codecs_payloads_copy(&newaudiortp, ast_rtp_instance_get_codecs(p->rtp), p->rtp);
/* Ensure RTCP is enabled since it may be inactive /* Ensure RTCP is enabled since it may be inactive
if we're coming back from a T.38 session */ if we're coming back from a T.38 session */
ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_RTCP, 1); configure_rtcp(p, p->rtp, SIP_AUDIO_RTCP_FD, remote_rtcp_mux_audio);
/* Ensure audio RTCP reads are enabled */
if (p->owner) {
ast_channel_set_fd(p->owner, 1, ast_rtp_instance_fd(p->rtp, 1));
}
if (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO) { if (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO) {
ast_clear_flag(&p->flags[0], SIP_DTMF); ast_clear_flag(&p->flags[0], SIP_DTMF);
@ -10897,10 +10956,10 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
/* Prevent audio RTCP reads */ /* Prevent audio RTCP reads */
if (p->owner) { if (p->owner) {
ast_channel_set_fd(p->owner, 1, -1); ast_channel_set_fd(p->owner, SIP_AUDIO_RTCP_FD, -1);
} }
/* Silence RTCP while audio RTP is inactive */ /* Silence RTCP while audio RTP is inactive */
ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_RTCP, 0); ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_RTCP, AST_RTP_INSTANCE_RTCP_DISABLED);
} else { } else {
ast_rtp_instance_stop(p->rtp); ast_rtp_instance_stop(p->rtp);
if (debug) if (debug)
@ -10911,6 +10970,7 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
/* Setup video address and port */ /* Setup video address and port */
if (p->vrtp) { if (p->vrtp) {
if (vsa && vportno > 0) { if (vsa && vportno > 0) {
set_ice_components(p, p->vrtp, remote_rtcp_mux_video);
start_ice(p->vrtp, (req->method != SIP_RESPONSE) ? 0 : 1); start_ice(p->vrtp, (req->method != SIP_RESPONSE) ? 0 : 1);
ast_sockaddr_set_port(vsa, vportno); ast_sockaddr_set_port(vsa, vportno);
ast_rtp_instance_set_remote_address(p->vrtp, vsa); ast_rtp_instance_set_remote_address(p->vrtp, vsa);
@ -10919,6 +10979,7 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
ast_sockaddr_stringify(vsa)); ast_sockaddr_stringify(vsa));
} }
ast_rtp_codecs_payloads_copy(&newvideortp, ast_rtp_instance_get_codecs(p->vrtp), p->vrtp); ast_rtp_codecs_payloads_copy(&newvideortp, ast_rtp_instance_get_codecs(p->vrtp), p->vrtp);
configure_rtcp(p, p->vrtp, SIP_VIDEO_RTCP_FD, remote_rtcp_mux_video);
} else { } else {
ast_rtp_instance_stop(p->vrtp); ast_rtp_instance_stop(p->vrtp);
if (debug) if (debug)
@ -11265,6 +11326,18 @@ static int process_sdp_a_ice(const char *a, struct sip_pvt *p, struct ast_rtp_in
return found; return found;
} }
static int process_sdp_a_rtcp_mux(const char *a, struct sip_pvt *p, int *requested)
{
int found = FALSE;
if (!strncasecmp(a, "rtcp-mux", 8)) {
*requested = TRUE;
found = TRUE;
}
return found;
}
static int process_sdp_a_dtls(const char *a, struct sip_pvt *p, struct ast_rtp_instance *instance) static int process_sdp_a_dtls(const char *a, struct sip_pvt *p, struct ast_rtp_instance *instance)
{ {
struct ast_rtp_engine_dtls *dtls; struct ast_rtp_engine_dtls *dtls;
@ -13632,6 +13705,12 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
add_dtls_to_sdp(p->rtp, &a_audio); add_dtls_to_sdp(p->rtp, &a_audio);
} }
/* If we've got rtcp-mux enabled, just unconditionally offer it in all SDPs */
if (ast_test_flag(&p->flags[2], SIP_PAGE3_RTCP_MUX)) {
ast_str_append(&a_audio, 0, "a=rtcp-mux\r\n");
ast_str_append(&a_video, 0, "a=rtcp-mux\r\n");
}
} }
if (add_t38) { if (add_t38) {
@ -13999,18 +14078,18 @@ static int transmit_reinvite_with_sdp(struct sip_pvt *p, int t38version, int old
if (p->rtp) { if (p->rtp) {
if (t38version) { if (t38version) {
/* Silence RTCP while audio RTP is inactive */ /* Silence RTCP while audio RTP is inactive */
ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_RTCP, 0); ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_RTCP, AST_RTP_INSTANCE_RTCP_DISABLED);
if (p->owner) { if (p->owner) {
/* Prevent audio RTCP reads */ /* Prevent audio RTCP reads */
ast_channel_set_fd(p->owner, 1, -1); ast_channel_set_fd(p->owner, SIP_AUDIO_RTCP_FD, -1);
} }
} else if (ast_sockaddr_isnull(&p->redirip)) { } else if (ast_sockaddr_isnull(&p->redirip)) {
/* Enable RTCP since it will be inactive if we're coming back /* Enable RTCP since it will be inactive if we're coming back
* with this reinvite */ * with this reinvite */
ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_RTCP, 1); ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_RTCP, AST_RTP_INSTANCE_RTCP_STANDARD);
if (p->owner) { if (p->owner) {
/* Enable audio RTCP reads */ /* Enable audio RTCP reads */
ast_channel_set_fd(p->owner, 1, ast_rtp_instance_fd(p->rtp, 1)); ast_channel_set_fd(p->owner, SIP_AUDIO_RTCP_FD, ast_rtp_instance_fd(p->rtp, 1));
} }
} }
} }
@ -21021,6 +21100,7 @@ static char *_sip_show_peer(int type, int fd, struct mansession *s, const struct
ast_cli(fd, " Parkinglot : %s\n", peer->parkinglot); ast_cli(fd, " Parkinglot : %s\n", peer->parkinglot);
ast_cli(fd, " Use Reason : %s\n", AST_CLI_YESNO(ast_test_flag(&peer->flags[1], SIP_PAGE2_Q850_REASON))); ast_cli(fd, " Use Reason : %s\n", AST_CLI_YESNO(ast_test_flag(&peer->flags[1], SIP_PAGE2_Q850_REASON)));
ast_cli(fd, " Encryption : %s\n", AST_CLI_YESNO(ast_test_flag(&peer->flags[1], SIP_PAGE2_USE_SRTP))); ast_cli(fd, " Encryption : %s\n", AST_CLI_YESNO(ast_test_flag(&peer->flags[1], SIP_PAGE2_USE_SRTP)));
ast_cli(fd, " RTCP Mux : %s\n", AST_CLI_YESNO(ast_test_flag(&peer->flags[2], SIP_PAGE3_RTCP_MUX)));
ast_cli(fd, "\n"); ast_cli(fd, "\n");
peer = sip_unref_peer(peer, "sip_show_peer: sip_unref_peer: done with peer ptr"); peer = sip_unref_peer(peer, "sip_show_peer: sip_unref_peer: done with peer ptr");
} else if (peer && type == 1) { /* manager listing */ } else if (peer && type == 1) { /* manager listing */
@ -21091,6 +21171,7 @@ static char *_sip_show_peer(int type, int fd, struct mansession *s, const struct
astman_append(s, "SIP-Sess-Min: %d\r\n", peer->stimer.st_min_se); astman_append(s, "SIP-Sess-Min: %d\r\n", peer->stimer.st_min_se);
astman_append(s, "SIP-RTP-Engine: %s\r\n", peer->engine); astman_append(s, "SIP-RTP-Engine: %s\r\n", peer->engine);
astman_append(s, "SIP-Encryption: %s\r\n", ast_test_flag(&peer->flags[1], SIP_PAGE2_USE_SRTP) ? "Y" : "N"); astman_append(s, "SIP-Encryption: %s\r\n", ast_test_flag(&peer->flags[1], SIP_PAGE2_USE_SRTP) ? "Y" : "N");
astman_append(s, "SIP-RTCP-Mux: %s\r\n", ast_test_flag(&peer->flags[2], SIP_PAGE3_RTCP_MUX) ? "Y" : "N");
/* - is enumerated */ /* - is enumerated */
astman_append(s, "SIP-DTMFmode: %s\r\n", dtmfmode2str(ast_test_flag(&peer->flags[0], SIP_DTMF))); astman_append(s, "SIP-DTMFmode: %s\r\n", dtmfmode2str(ast_test_flag(&peer->flags[0], SIP_DTMF)));
@ -21719,6 +21800,7 @@ static char *sip_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_
ast_cli(a->fd, " MOH Interpret: %s\n", default_mohinterpret); ast_cli(a->fd, " MOH Interpret: %s\n", default_mohinterpret);
ast_cli(a->fd, " MOH Suggest: %s\n", default_mohsuggest); ast_cli(a->fd, " MOH Suggest: %s\n", default_mohsuggest);
ast_cli(a->fd, " Voice Mail Extension: %s\n", default_vmexten); ast_cli(a->fd, " Voice Mail Extension: %s\n", default_vmexten);
ast_cli(a->fd, " RTCP Multiplexing: %s\n", AST_CLI_YESNO(ast_test_flag(&global_flags[2], SIP_PAGE3_RTCP_MUX)));
if (realtimepeers || realtimeregs) { if (realtimepeers || realtimeregs) {
@ -30787,6 +30869,9 @@ static int handle_common_options(struct ast_flags *flags, struct ast_flags *mask
} else if (!strcasecmp(v->name, "buggymwi")) { } else if (!strcasecmp(v->name, "buggymwi")) {
ast_set_flag(&mask[1], SIP_PAGE2_BUGGY_MWI); ast_set_flag(&mask[1], SIP_PAGE2_BUGGY_MWI);
ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_BUGGY_MWI); ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_BUGGY_MWI);
} else if (!strcasecmp(v->name, "rtcp_mux")) {
ast_set_flag(&mask[2], SIP_PAGE3_RTCP_MUX);
ast_set2_flag(&flags[2], ast_true(v->value), SIP_PAGE3_RTCP_MUX);
} else } else
res = 0; res = 0;
@ -33418,9 +33503,9 @@ static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *i
if (p->rtp) { if (p->rtp) {
/* Prevent audio RTCP reads */ /* Prevent audio RTCP reads */
ast_channel_set_fd(chan, 1, -1); ast_channel_set_fd(chan, SIP_AUDIO_RTCP_FD, -1);
/* Silence RTCP while audio RTP is inactive */ /* Silence RTCP while audio RTP is inactive */
ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_RTCP, 0); ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_RTCP, AST_RTP_INSTANCE_RTCP_DISABLED);
} }
} else if (!ast_sockaddr_isnull(&p->redirip)) { } else if (!ast_sockaddr_isnull(&p->redirip)) {
memset(&p->redirip, 0, sizeof(p->redirip)); memset(&p->redirip, 0, sizeof(p->redirip));
@ -33432,9 +33517,9 @@ static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *i
if (p->vrtp) { if (p->vrtp) {
/* Prevent video RTCP reads */ /* Prevent video RTCP reads */
ast_channel_set_fd(chan, 3, -1); ast_channel_set_fd(chan, SIP_VIDEO_RTCP_FD, -1);
/* Silence RTCP while video RTP is inactive */ /* Silence RTCP while video RTP is inactive */
ast_rtp_instance_set_prop(p->vrtp, AST_RTP_PROPERTY_RTCP, 0); ast_rtp_instance_set_prop(p->vrtp, AST_RTP_PROPERTY_RTCP, AST_RTP_INSTANCE_RTCP_DISABLED);
} }
} else if (!ast_sockaddr_isnull(&p->vredirip)) { } else if (!ast_sockaddr_isnull(&p->vredirip)) {
memset(&p->vredirip, 0, sizeof(p->vredirip)); memset(&p->vredirip, 0, sizeof(p->vredirip));
@ -33443,9 +33528,9 @@ static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *i
if (p->vrtp) { if (p->vrtp) {
/* Enable RTCP since it will be inactive if we're coming back /* Enable RTCP since it will be inactive if we're coming back
* from a reinvite */ * from a reinvite */
ast_rtp_instance_set_prop(p->vrtp, AST_RTP_PROPERTY_RTCP, 1); ast_rtp_instance_set_prop(p->vrtp, AST_RTP_PROPERTY_RTCP, AST_RTP_INSTANCE_RTCP_STANDARD);
/* Enable video RTCP reads */ /* Enable video RTCP reads */
ast_channel_set_fd(chan, 3, ast_rtp_instance_fd(p->vrtp, 1)); ast_channel_set_fd(chan, SIP_VIDEO_RTCP_FD, ast_rtp_instance_fd(p->vrtp, 1));
} }
} }

@ -384,11 +384,12 @@
#define SIP_PAGE3_IGNORE_PREFCAPS (1 << 7) /*!< DP: Ignore prefcaps when setting up an outgoing call leg */ #define SIP_PAGE3_IGNORE_PREFCAPS (1 << 7) /*!< DP: Ignore prefcaps when setting up an outgoing call leg */
#define SIP_PAGE3_DISCARD_REMOTE_HOLD_RETRIEVAL (1 << 8) /*!< DGP: Stop telling the peer to start music on hold */ #define SIP_PAGE3_DISCARD_REMOTE_HOLD_RETRIEVAL (1 << 8) /*!< DGP: Stop telling the peer to start music on hold */
#define SIP_PAGE3_FORCE_AVP (1 << 9) /*!< DGP: Force 'RTP/AVP' for all streams, even DTLS */ #define SIP_PAGE3_FORCE_AVP (1 << 9) /*!< DGP: Force 'RTP/AVP' for all streams, even DTLS */
#define SIP_PAGE3_RTCP_MUX (1 << 10) /*!< DGP: Attempt to negotiate RFC 5761 RTCP multiplexing */
#define SIP_PAGE3_FLAGS_TO_COPY \ #define SIP_PAGE3_FLAGS_TO_COPY \
(SIP_PAGE3_SNOM_AOC | SIP_PAGE3_SRTP_TAG_32 | SIP_PAGE3_NAT_AUTO_RPORT | SIP_PAGE3_NAT_AUTO_COMEDIA | \ (SIP_PAGE3_SNOM_AOC | SIP_PAGE3_SRTP_TAG_32 | SIP_PAGE3_NAT_AUTO_RPORT | SIP_PAGE3_NAT_AUTO_COMEDIA | \
SIP_PAGE3_DIRECT_MEDIA_OUTGOING | SIP_PAGE3_USE_AVPF | SIP_PAGE3_ICE_SUPPORT | SIP_PAGE3_IGNORE_PREFCAPS | \ SIP_PAGE3_DIRECT_MEDIA_OUTGOING | SIP_PAGE3_USE_AVPF | SIP_PAGE3_ICE_SUPPORT | SIP_PAGE3_IGNORE_PREFCAPS | \
SIP_PAGE3_DISCARD_REMOTE_HOLD_RETRIEVAL | SIP_PAGE3_FORCE_AVP) SIP_PAGE3_DISCARD_REMOTE_HOLD_RETRIEVAL | SIP_PAGE3_FORCE_AVP | SIP_PAGE3_RTCP_MUX)
#define CHECK_AUTH_BUF_INITLEN 256 #define CHECK_AUTH_BUF_INITLEN 256

@ -1090,6 +1090,8 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls
; option may be specified at the global or peer scope. ; option may be specified at the global or peer scope.
;force_avp=yes ; Force 'RTP/AVP', 'RTP/AVPF', 'RTP/SAVP', and 'RTP/SAVPF' to be used for ;force_avp=yes ; Force 'RTP/AVP', 'RTP/AVPF', 'RTP/SAVP', and 'RTP/SAVPF' to be used for
; media streams when appropriate, even if a DTLS stream is present. ; media streams when appropriate, even if a DTLS stream is present.
;rtcp_mux=yes ; Enable support for RFC 5761 RTCP multiplexing which is required for
; WebRTC support
; ---------------------------------------- REALTIME SUPPORT ------------------------ ; ---------------------------------------- REALTIME SUPPORT ------------------------
; For additional information on ARA, the Asterisk Realtime Architecture, ; For additional information on ARA, the Asterisk Realtime Architecture,
; please read https://wiki.asterisk.org/wiki/display/AST/Realtime+Database+Configuration ; please read https://wiki.asterisk.org/wiki/display/AST/Realtime+Database+Configuration

Loading…
Cancel
Save