Commit 2cd6f5f4 authored by Simon Morlat's avatar Simon Morlat
Browse files

implement rtcp-mux, not tested yet.

parent 2c2f6f2e
......@@ -109,6 +109,7 @@ struct SalOp{
bool_t manual_refresher;
bool_t has_auth_pending;
bool_t supports_session_timers;
bool_t op_released;
};
......
......@@ -38,6 +38,7 @@ void sal_op_release(SalOp *op){
if (op->refresher) {
belle_sip_refresher_stop(op->refresher);
}
op->op_released = TRUE;
sal_op_unref(op);
}
......
......@@ -55,7 +55,9 @@ static void presence_process_dialog_terminated(void *ctx, const belle_sip_dialog
if (op->dialog) {
if (belle_sip_dialog_is_server(op->dialog)){
ms_message("Incoming subscribtion from [%s] terminated",sal_op_get_from(op));
op->base.root->callbacks.subscribe_presence_closed(op, sal_op_get_from(op));
if (!op->op_released){
op->base.root->callbacks.subscribe_presence_closed(op, sal_op_get_from(op));
}
}
set_or_update_dialog(op, NULL);
}
......@@ -98,7 +100,9 @@ static void presence_response_event(void *op_base, const belle_sip_response_even
if (code>=300) {
if (strcmp("SUBSCRIBE",belle_sip_request_get_method(request))==0){
ms_message("subscription to [%s] rejected",sal_op_get_to(op));
op->base.root->callbacks.notify_presence(op,SalSubscribeTerminated, NULL,NULL); /*NULL = offline*/
if (!op->op_released){
op->base.root->callbacks.notify_presence(op,SalSubscribeTerminated, NULL,NULL); /*NULL = offline*/
}
return;
}
}
......@@ -156,7 +160,9 @@ static void presence_process_timeout(void *user_ctx, const belle_sip_timeout_eve
if (strcmp("SUBSCRIBE",belle_sip_request_get_method(request))==0){
ms_message("subscription to [%s] timeout",sal_op_get_to(op));
op->base.root->callbacks.notify_presence(op,SalSubscribeTerminated, NULL,NULL); /*NULL = offline*/
if (!op->op_released){
op->base.root->callbacks.notify_presence(op,SalSubscribeTerminated, NULL,NULL); /*NULL = offline*/
}
}
}
......@@ -176,12 +182,13 @@ static SalPresenceModel * process_presence_notification(SalOp *op, belle_sip_req
return NULL;
if (body==NULL) return NULL;
op->base.root->callbacks.parse_presence_requested(op,
if (!op->op_released){
op->base.root->callbacks.parse_presence_requested(op,
belle_sip_header_content_type_get_type(content_type),
belle_sip_header_content_type_get_subtype(content_type),
body,
&result);
}
return result;
}
......@@ -210,7 +217,9 @@ static void handle_notify(SalOp *op, belle_sip_request_t *req, belle_sip_dialog_
/* Presence notification body parsed successfully. */
resp = sal_op_create_response_from_request(op, req, 200); /*create first because the op may be destroyed by notify_presence */
op->base.root->callbacks.notify_presence(op, sub_state, presence_model, NULL);
if (!op->op_released){
op->base.root->callbacks.notify_presence(op, sub_state, presence_model, NULL);
}
} else if (body){
/* Formatting error in presence notification body. */
ms_warning("Wrongly formatted presence document.");
......
......@@ -304,6 +304,10 @@ static void stream_description_to_sdp ( belle_sdp_session_description_t *session
}
if ( dir ) belle_sdp_media_description_add_attribute ( media_desc,belle_sdp_attribute_create ( dir,NULL ) );
if (stream->rtcp_mux){
belle_sdp_media_description_add_attribute(media_desc, belle_sdp_attribute_create ("rtcp-mux",NULL ) );
}
if (rtp_port != 0) {
different_rtp_and_rtcp_addr = (rtcp_addr[0] != '\0') && (strcmp(rtp_addr, rtcp_addr) != 0);
if ((rtcp_port != (rtp_port + 1)) || (different_rtp_and_rtcp_addr == TRUE)) {
......@@ -781,6 +785,8 @@ static SalStreamDescription * sdp_to_stream_description(SalMediaDescription *md,
stream->dir=md->dir; /*takes default value if not present*/
}
stream->rtcp_mux = belle_sdp_media_description_get_attribute(media_desc, "rtcp_mux") != NULL;
/* Get media payload types */
sdp_parse_payload_types(media_desc, stream);
......
......@@ -1058,6 +1058,7 @@ static void vfu_request(SalOp *op){
static void dtmf_received(SalOp *op, char dtmf){
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op);
if (!call) return;
linphone_core_notify_dtmf_received(lc, call, dtmf);
}
......
......@@ -659,6 +659,7 @@ void linphone_call_make_local_media_description(LinphoneCall *call) {
CodecConstraints codec_hints={0};
LinphoneCallParams *params = call->params;
LinphoneCore *lc = call->core;
bool_t rtcp_mux = lp_config_get_int(lc->config, "rtp", "rtcp_mux", 0);
/*multicast is only set in case of outgoing call*/
if (call->dir == LinphoneCallOutgoing && linphone_call_params_audio_multicast_enabled(params)) {
......@@ -709,6 +710,7 @@ void linphone_call_make_local_media_description(LinphoneCall *call) {
md->streams[call->main_audio_stream_index].proto=get_proto_from_call_params(params);
md->streams[call->main_audio_stream_index].dir=get_audio_dir_from_call_params(params);
md->streams[call->main_audio_stream_index].type=SalAudio;
md->streams[call->main_audio_stream_index].rtcp_mux = rtcp_mux;
if (params->down_ptime)
md->streams[call->main_audio_stream_index].ptime=params->down_ptime;
else
......@@ -739,6 +741,7 @@ void linphone_call_make_local_media_description(LinphoneCall *call) {
md->streams[call->main_video_stream_index].proto=md->streams[call->main_audio_stream_index].proto;
md->streams[call->main_video_stream_index].dir=get_video_dir_from_call_params(params);
md->streams[call->main_video_stream_index].type=SalVideo;
md->streams[call->main_video_stream_index].rtcp_mux = rtcp_mux;
strncpy(md->streams[call->main_video_stream_index].name,"Video",sizeof(md->streams[call->main_video_stream_index].name)-1);
if (params->has_video){
......@@ -771,6 +774,7 @@ void linphone_call_make_local_media_description(LinphoneCall *call) {
md->streams[call->main_text_stream_index].proto=md->streams[call->main_audio_stream_index].proto;
md->streams[call->main_text_stream_index].dir=SalStreamSendRecv;
md->streams[call->main_text_stream_index].type=SalText;
md->streams[call->main_text_stream_index].rtcp_mux = rtcp_mux;
strncpy(md->streams[call->main_text_stream_index].name,"Text",sizeof(md->streams[call->main_text_stream_index].name)-1);
if (params->realtimetext_enabled) {
strncpy(md->streams[call->main_text_stream_index].rtp_addr,linphone_call_get_public_ip_for_stream(call,call->main_text_stream_index),sizeof(md->streams[call->main_text_stream_index].rtp_addr));
......@@ -3002,6 +3006,7 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, LinphoneCallSta
ms_qos_analyzer_algorithm_from_string(linphone_core_get_adaptive_rate_algorithm(lc)));
audio_stream_enable_adaptive_jittcomp(call->audiostream, linphone_core_audio_adaptive_jittcomp_enabled(lc));
rtp_session_set_jitter_compensation(call->audiostream->ms.sessions.rtp_session,linphone_core_get_audio_jittcomp(lc));
rtp_session_enable_rtcp_mux(call->audiostream->ms.sessions.rtp_session, stream->rtcp_mux);
if (!call->params->in_conference && call->params->record_file){
audio_stream_mixed_record_open(call->audiostream,call->params->record_file);
call->current_params->record_file=ms_strdup(call->params->record_file);
......@@ -3149,6 +3154,7 @@ static void linphone_call_start_video_stream(LinphoneCall *call, LinphoneCallSta
ms_qos_analyzer_algorithm_from_string(linphone_core_get_adaptive_rate_algorithm(lc)));
video_stream_enable_adaptive_jittcomp(call->videostream, linphone_core_video_adaptive_jittcomp_enabled(lc));
rtp_session_set_jitter_compensation(call->videostream->ms.sessions.rtp_session, linphone_core_get_video_jittcomp(lc));
rtp_session_enable_rtcp_mux(call->videostream->ms.sessions.rtp_session, vstream->rtcp_mux);
if (lc->video_conf.preview_vsize.width!=0)
video_stream_set_preview_size(call->videostream,lc->video_conf.preview_vsize);
video_stream_set_fps(call->videostream,linphone_core_get_preferred_framerate(lc));
......@@ -3275,8 +3281,10 @@ static void linphone_call_start_text_stream(LinphoneCall *call) {
ms_media_stream_sessions_set_srtp_send_key_b64(&call->textstream->ms.sessions, tstream->crypto[0].algo, local_st_desc->crypto[crypto_idx].master_key);
}
}
configure_rtp_session_for_rtcp_fb(call, tstream);
configure_rtp_session_for_rtcp_xr(lc, call, SalText);
rtp_session_enable_rtcp_mux(call->textstream->ms.sessions.rtp_session, tstream->rtcp_mux);
if (is_multicast) rtp_session_set_multicast_ttl(call->textstream->ms.sessions.rtp_session,tstream->ttl);
......
......@@ -310,67 +310,66 @@ static void initiate_outgoing(const SalStreamDescription *local_offer,
result->type=local_offer->type;
if (local_offer->rtp_addr[0]!='\0' && ms_is_multicast(local_offer->rtp_addr)) {
/*6.2 Multicast Streams
...
If a multicast stream is accepted, the address and port information
in the answer MUST match that of the offer. Similarly, the
directionality information in the answer (sendonly, recvonly, or
sendrecv) MUST equal that of the offer. This is because all
participants in a multicast session need to have equivalent views of
the parameters of the session, an underlying assumption of the
multicast bias of RFC 2327.*/
if (strcmp(local_offer->rtp_addr,remote_answer->rtp_addr) !=0 ) {
ms_message("Remote answered IP [%s] does not match offered [%s] for local stream description [%p]"
,remote_answer->rtp_addr
,local_offer->rtp_addr
,local_offer);
result->rtp_port=0;
return;
}
if (local_offer->rtp_port!=remote_answer->rtp_port) {
ms_message("Remote answered rtp port [%i] does not match offered [%i] for local stream description [%p]"
,remote_answer->rtp_port
,local_offer->rtp_port
,local_offer);
result->rtp_port=0;
return;
}
if (local_offer->dir!=remote_answer->dir) {
ms_message("Remote answered dir [%s] does not match offered [%s] for local stream description [%p]"
,sal_stream_dir_to_string(remote_answer->dir)
,sal_stream_dir_to_string(local_offer->dir)
,local_offer);
result->rtp_port=0;
return;
}
if (local_offer->bandwidth!=remote_answer->bandwidth) {
ms_message("Remote answered bandwidth [%i] does not match offered [%i] for local stream description [%p]"
,remote_answer->bandwidth
,local_offer->bandwidth
,local_offer);
result->rtp_port=0;
return;
}
if (local_offer->ptime > 0 && local_offer->ptime!=remote_answer->ptime) {
ms_message("Remote answered ptime [%i] does not match offered [%i] for local stream description [%p]"
,remote_answer->ptime
,local_offer->ptime
,local_offer);
result->rtp_port=0;
return;
}
if (local_offer->ttl > 0 && local_offer->ttl!=remote_answer->ttl) {
ms_message("Remote answered ttl [%i] does not match offered [%i] for local stream description [%p]"
,remote_answer->ttl
,local_offer->ttl
,local_offer);
result->rtp_port=0;
return;
}
result->ttl=local_offer->ttl;
result->dir=local_offer->dir;
result->multicast_role = SalMulticastSender;
/*6.2 Multicast Streams
...
If a multicast stream is accepted, the address and port information
in the answer MUST match that of the offer. Similarly, the
directionality information in the answer (sendonly, recvonly, or
sendrecv) MUST equal that of the offer. This is because all
participants in a multicast session need to have equivalent views of
the parameters of the session, an underlying assumption of the
multicast bias of RFC 2327.*/
if (strcmp(local_offer->rtp_addr,remote_answer->rtp_addr) !=0 ) {
ms_message("Remote answered IP [%s] does not match offered [%s] for local stream description [%p]"
,remote_answer->rtp_addr
,local_offer->rtp_addr
,local_offer);
result->rtp_port=0;
return;
}
if (local_offer->rtp_port!=remote_answer->rtp_port) {
ms_message("Remote answered rtp port [%i] does not match offered [%i] for local stream description [%p]"
,remote_answer->rtp_port
,local_offer->rtp_port
,local_offer);
result->rtp_port=0;
return;
}
if (local_offer->dir!=remote_answer->dir) {
ms_message("Remote answered dir [%s] does not match offered [%s] for local stream description [%p]"
,sal_stream_dir_to_string(remote_answer->dir)
,sal_stream_dir_to_string(local_offer->dir)
,local_offer);
result->rtp_port=0;
return;
}
if (local_offer->bandwidth!=remote_answer->bandwidth) {
ms_message("Remote answered bandwidth [%i] does not match offered [%i] for local stream description [%p]"
,remote_answer->bandwidth
,local_offer->bandwidth
,local_offer);
result->rtp_port=0;
return;
}
if (local_offer->ptime > 0 && local_offer->ptime!=remote_answer->ptime) {
ms_message("Remote answered ptime [%i] does not match offered [%i] for local stream description [%p]"
,remote_answer->ptime
,local_offer->ptime
,local_offer);
result->rtp_port=0;
return;
}
if (local_offer->ttl > 0 && local_offer->ttl!=remote_answer->ttl) {
ms_message("Remote answered ttl [%i] does not match offered [%i] for local stream description [%p]"
,remote_answer->ttl
,local_offer->ttl
,local_offer);
result->rtp_port=0;
return;
}
result->ttl=local_offer->ttl;
result->dir=local_offer->dir;
result->multicast_role = SalMulticastSender;
} else {
result->dir=compute_dir_outgoing(local_offer->dir,remote_answer->dir);
}
......@@ -409,8 +408,7 @@ static void initiate_outgoing(const SalStreamDescription *local_offer,
result->dtls_fingerprint[0] = '\0';
result->dtls_role = SalDtlsRoleInvalid;
}
result->rtcp_mux = remote_answer->rtcp_mux && local_offer->rtcp_mux;
}
......@@ -478,8 +476,7 @@ static void initiate_incoming(const SalStreamDescription *local_cap,
result->dtls_fingerprint[0] = '\0';
result->dtls_role = SalDtlsRoleInvalid;
}
result->rtcp_mux = remote_offer->rtcp_mux && local_cap->rtcp_mux;
}
......
......@@ -1888,10 +1888,15 @@ void linphone_notify_recv(LinphoneCore *lc, SalOp *op, SalSubscribeStatus ss, Sa
return ;
}
if (ss==SalSubscribeTerminated){
sal_op_release(op);
if (lf){
sal_op_release(lf->outsub);
lf->outsub=NULL;
lf->subscribe_active=FALSE;
if (lf->outsub != op){
sal_op_release(op);
}
}else{
sal_op_release(op);
}
}
}
......
......@@ -245,7 +245,8 @@ typedef struct SalStreamDescription{
char ice_pwd[SAL_MEDIA_DESCRIPTION_MAX_ICE_PWD_LEN];
bool_t ice_mismatch;
bool_t ice_completed;
bool_t pad[2];
bool_t rtcp_mux;
bool_t pad[1];
char dtls_fingerprint[256];
SalDtlsRole dtls_role;
int ttl; /*for multicast -1 to disable*/
......
oRTP @ cb4f9f5c
Subproject commit 055c29e5b3be15ada48c7c6b195e6f6ee732c0c0
Subproject commit cb4f9f5ce7d984b81d6a71416abc77bda2f82bdb
......@@ -5483,6 +5483,64 @@ end:
linphone_core_manager_destroy(marie);
linphone_core_manager_destroy(pauline);
}
static void _call_with_rtcp_mux(bool_t caller_rtcp_mux, bool_t callee_rtcp_mux, bool_t with_ice){
LinphoneCoreManager * marie = linphone_core_manager_new( "marie_rc");
LinphoneCoreManager *pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
const LinphoneCallParams *params;
MSList *lcs = NULL;
lcs = ms_list_append(lcs, marie->lc);
lcs = ms_list_append(lcs, pauline->lc);
if (caller_rtcp_mux){
lp_config_set_int(linphone_core_get_config(marie->lc), "rtp", "rtcp_mux", 1);
}
if (callee_rtcp_mux){
lp_config_set_int(linphone_core_get_config(pauline->lc), "rtp", "rtcp_mux", 1);
}
if (with_ice){
linphone_core_set_firewall_policy(marie->lc, LinphonePolicyUseIce);
linphone_core_set_firewall_policy(pauline->lc, LinphonePolicyUseIce);
}
if (!BC_ASSERT_TRUE(call(marie,pauline))) goto end;
params = linphone_call_get_remote_params(linphone_core_get_current_call(pauline->lc));
BC_ASSERT_TRUE(caller_rtcp_mux == (linphone_call_params_get_custom_sdp_media_attribute(params, LinphoneStreamTypeAudio, "rtcp-mux") != NULL));
if (caller_rtcp_mux){
params = linphone_call_get_remote_params(linphone_core_get_current_call(marie->lc));
BC_ASSERT_TRUE(callee_rtcp_mux == (linphone_call_params_get_custom_sdp_media_attribute(params, LinphoneStreamTypeAudio, "rtcp-mux") != NULL));
}
if (with_ice){
check_ice(marie, pauline, LinphoneIceStateHostConnection);
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallStreamsRunning, 2));
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallStreamsRunning, 2));
}
liblinphone_tester_check_rtcp(marie,pauline);
check_media_direction(pauline, linphone_core_get_current_call(pauline->lc), lcs, LinphoneMediaDirectionSendRecv, LinphoneMediaDirectionInvalid);
end_call(marie,pauline);
end:
ms_list_free(lcs);
linphone_core_manager_destroy(pauline);
linphone_core_manager_destroy(marie);
}
static void call_with_rtcp_mux(void){
_call_with_rtcp_mux(TRUE, TRUE, FALSE);
}
static void call_with_rtcp_mux_not_accepted(void){
_call_with_rtcp_mux(TRUE, FALSE, FALSE);
}
static void call_with_ice_and_rtcp_mux(void){
_call_with_rtcp_mux(TRUE, TRUE, TRUE);
}
test_t call_tests[] = {
{ "Early declined call", early_declined_call },
{ "Call declined", call_declined },
......@@ -5641,7 +5699,10 @@ test_t call_tests[] = {
{ "Call with network switch in early state 1", call_with_network_switch_in_early_state_1 },
{ "Call with network switch in early state 2", call_with_network_switch_in_early_state_2 },
{ "Call with network switch and ICE", call_with_network_switch_and_ice },
{ "Call with network switch with socket refresh", call_with_network_switch_and_socket_refresh }
{ "Call with network switch with socket refresh", call_with_network_switch_and_socket_refresh },
{ "Call with rtcp-mux", call_with_rtcp_mux},
{ "Call with rtcp-mux not accepted", call_with_rtcp_mux_not_accepted},
{ "Call with ICE and rtcp-mux", call_with_ice_and_rtcp_mux}
};
test_suite_t call_test_suite = {"Single Call", NULL, NULL, liblinphone_tester_before_each, liblinphone_tester_after_each,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment