linphone_call_set_state(call,LinphoneCallConnected,"Connected");
if (call->referer) linphone_core_notify_refer_state(lc,call->referer,call);
}
- if (md && !sal_media_description_empty(md)){
+ if (md && !sal_media_description_empty(md) && !linphone_core_incompatible_security(lc,md)){
+ linphone_call_update_remote_session_id_and_ver(call);
if (sal_media_description_has_dir(md,SalStreamSendOnly) ||
sal_media_description_has_dir(md,SalStreamInactive)){
if (lc->vtable.display_status){
}else{
/*send a bye*/
ms_error("Incompatible SDP offer received in 200Ok, need to abort the call");
- linphone_core_abort_call(lc,call,_("Incompatible, check codecs..."));
+ linphone_core_abort_call(lc,call,_("Incompatible, check codecs or security settings..."));
}
}
linphone_core_update_ice_from_remote_media_description(call,rmd);
linphone_core_update_local_media_description_from_ice(call->localdesc,call->ice_session);
}
+ linphone_call_update_remote_session_id_and_ver(call);
sal_call_accept(call->op);
md=sal_call_get_final_media_description(call->op);
if (md && !sal_media_description_empty(md))
new_stream = sal_media_description_find_stream(new_md, SalProtoRtpSavp, SalAudio);
if (old_stream && new_stream) {
const SalStreamDescription *local_st_desc = sal_media_description_find_stream(call->localdesc, SalProtoRtpSavp, SalAudio);
- int crypto_idx = find_crypto_index_from_tag(local_st_desc->crypto, new_stream->crypto_local_tag);
- if (crypto_idx >= 0) {
- audio_stream_enable_srtp(call->audiostream, new_stream->crypto[0].algo, local_st_desc->crypto[crypto_idx].master_key, new_stream->crypto[0].master_key);
- call->audiostream_encrypted = TRUE;
- } else {
- ms_warning("Failed to find local crypto algo with tag: %d", new_stream->crypto_local_tag);
- call->audiostream_encrypted = FALSE;
- }
- for (i = 0; i < SAL_CRYPTO_ALGO_MAX; i++) {
- old_stream->crypto[i].tag = new_stream->crypto[i].tag;
- old_stream->crypto[i].algo = new_stream->crypto[i].algo;
- strncpy(old_stream->crypto[i].master_key, new_stream->crypto[i].master_key, sizeof(old_stream->crypto[i].master_key) - 1);
+ if (local_st_desc) {
+ int crypto_idx = find_crypto_index_from_tag(local_st_desc->crypto, new_stream->crypto_local_tag);
+ if (crypto_idx >= 0) {
+ audio_stream_enable_srtp(call->audiostream, new_stream->crypto[0].algo, local_st_desc->crypto[crypto_idx].master_key, new_stream->crypto[0].master_key);
+ call->audiostream_encrypted = TRUE;
+ } else {
+ ms_warning("Failed to find local crypto algo with tag: %d", new_stream->crypto_local_tag);
+ call->audiostream_encrypted = FALSE;
+ }
+ for (i = 0; i < SAL_CRYPTO_ALGO_MAX; i++) {
+ old_stream->crypto[i].tag = new_stream->crypto[i].tag;
+ old_stream->crypto[i].algo = new_stream->crypto[i].algo;
+ strncpy(old_stream->crypto[i].master_key, new_stream->crypto[i].master_key, sizeof(old_stream->crypto[i].master_key) - 1);
+ }
}
}
new_stream = sal_media_description_find_stream(new_md, SalProtoRtpSavp, SalVideo);
if (old_stream && new_stream) {
const SalStreamDescription *local_st_desc = sal_media_description_find_stream(call->localdesc, SalProtoRtpSavp, SalVideo);
- int crypto_idx = find_crypto_index_from_tag(local_st_desc->crypto, new_stream->crypto_local_tag);
- if (crypto_idx >= 0) {
- video_stream_enable_strp(call->videostream, new_stream->crypto[0].algo, local_st_desc->crypto[crypto_idx].master_key, new_stream->crypto[0].master_key);
- call->videostream_encrypted = TRUE;
- } else {
- ms_warning("Failed to find local crypto algo with tag: %d", new_stream->crypto_local_tag);
- call->videostream_encrypted = FALSE;
- }
- for (i = 0; i < SAL_CRYPTO_ALGO_MAX; i++) {
- old_stream->crypto[i].tag = new_stream->crypto[i].tag;
- old_stream->crypto[i].algo = new_stream->crypto[i].algo;
- strncpy(old_stream->crypto[i].master_key, new_stream->crypto[i].master_key, sizeof(old_stream->crypto[i].master_key) - 1);
+ if (local_st_desc) {
+ int crypto_idx = find_crypto_index_from_tag(local_st_desc->crypto, new_stream->crypto_local_tag);
+ if (crypto_idx >= 0) {
+ video_stream_enable_strp(call->videostream, new_stream->crypto[0].algo, local_st_desc->crypto[crypto_idx].master_key, new_stream->crypto[0].master_key);
+ call->videostream_encrypted = TRUE;
+ } else {
+ ms_warning("Failed to find local crypto algo with tag: %d", new_stream->crypto_local_tag);
+ call->videostream_encrypted = FALSE;
+ }
+ for (i = 0; i < SAL_CRYPTO_ALGO_MAX; i++) {
+ old_stream->crypto[i].tag = new_stream->crypto[i].tag;
+ old_stream->crypto[i].algo = new_stream->crypto[i].algo;
+ strncpy(old_stream->crypto[i].master_key, new_stream->crypto[i].master_key, sizeof(old_stream->crypto[i].master_key) - 1);
+ }
}
}
#endif
}
+ void linphone_call_update_remote_session_id_and_ver(LinphoneCall *call) {
+ SalMediaDescription *remote_desc = sal_call_get_remote_media_description(call->op);
+ if (remote_desc) {
+ call->remote_session_id = remote_desc->session_id;
+ call->remote_session_ver = remote_desc->session_ver;
+ }
+ }
+
void linphone_call_delete_ice_session(LinphoneCall *call){
if (call->ice_session != NULL) {
ice_session_destroy(call->ice_session);
static void linphone_core_free_hooks(LinphoneCore *lc);
#include "enum.h"
+
const char *linphone_core_get_nat_address_resolved(LinphoneCore *lc);
void linphone_core_get_local_ip(LinphoneCore *lc, const char *dest, char *result);
static void toggle_video_preview(LinphoneCore *lc, bool_t val);
sal_set_root_ca(lc->sal, lp_config_get_string(lc->config,"sip","root_ca", ROOT_CA_FILE));
#endif
linphone_core_verify_server_certificates(lc,lp_config_get_int(lc->config,"sip","verify_server_certs",TRUE));
+ linphone_core_verify_server_cn(lc,lp_config_get_int(lc->config,"sip","verify_server_cn",TRUE));
/*setting the dscp must be done before starting the transports, otherwise it is not taken into effect*/
sal_set_dscp(lc->sal,linphone_core_get_sip_dscp(lc));
/*start listening on ports*/
return FALSE;
}
+bool_t linphone_core_incompatible_security(LinphoneCore *lc, SalMediaDescription *md){
+ if (linphone_core_is_media_encryption_mandatory(lc) && linphone_core_get_media_encryption(lc)==LinphoneMediaEncryptionSRTP){
+ int i;
+ for(i=0;i<md->nstreams;i++){
+ SalStreamDescription *sd=&md->streams[i];
+ if (sd->proto!=SalProtoRtpSavp){
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+
void linphone_core_notify_incoming_call(LinphoneCore *lc, LinphoneCall *call){
char *barmesg;
char *tmp;
linphone_call_make_local_media_description(lc,call);
sal_call_set_local_media_description(call->op,call->localdesc);
md=sal_call_get_final_media_description(call->op);
- if (md && sal_media_description_empty(md)){
- sal_call_decline(call->op,SalReasonMedia,NULL);
- linphone_call_unref(call);
- return;
+ if (md){
+ if (sal_media_description_empty(md) || linphone_core_incompatible_security(lc,md)){
+ sal_call_decline(call->op,SalReasonMedia,NULL);
+ linphone_call_unref(call);
+ return;
+ }
}
from_parsed=linphone_address_new(sal_op_get_from(call->op));
}
linphone_core_update_local_media_description_from_ice(call->localdesc, call->ice_session);
}
+ linphone_call_update_remote_session_id_and_ver(call);
sal_call_set_local_media_description(call->op,call->localdesc);
sal_call_accept(call->op);
md=sal_call_get_final_media_description(call->op);
* @return 0 if sucessful, -1 otherwise (actually when this function call is performed outside ot #LinphoneCallUpdatedByRemote state).
**/
int linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params){
+ SalMediaDescription *remote_desc;
+ bool_t keep_sdp_version;
#ifdef VIDEO_ENABLED
bool_t old_has_video = call->params.has_video;
#endif
linphone_call_state_to_string(call->state));
return -1;
}
+ remote_desc = sal_call_get_remote_media_description(call->op);
+ keep_sdp_version = lp_config_get_int(lc->config, "sip", "keep_sdp_version", 0);
+ if (keep_sdp_version &&(remote_desc->session_id == call->remote_session_id) && (remote_desc->session_ver == call->remote_session_ver)) {
+ /* Remote has sent an INVITE with the same SDP as before, so send a 200 OK with the same SDP as before. */
+ ms_warning("SDP version has not changed, send same SDP as before.");
+ sal_call_accept(call->op);
+ linphone_call_set_state(call,LinphoneCallStreamsRunning,"Connected (streams running)");
+ return 0;
+ }
if (params==NULL){
call->params.has_video=lc->video_policy.automatically_accept || call->current_params.has_video;
}else
ms_warning("Video isn't supported in conference");
call->params.has_video = FALSE;
}
- call->params.has_video &= linphone_core_media_description_contains_video_stream(sal_call_get_remote_media_description(call->op));
+ call->params.has_video &= linphone_core_media_description_contains_video_stream(remote_desc);
call->camera_active=call->params.has_video;
linphone_call_make_local_media_description(lc,call);
if (call->ice_session != NULL) {
- linphone_core_update_ice_from_remote_media_description(call, sal_call_get_remote_media_description(call->op));
+ linphone_core_update_ice_from_remote_media_description(call, remote_desc);
#ifdef VIDEO_ENABLED
if ((call->ice_session != NULL) &&!ice_session_candidates_gathered(call->ice_session)) {
if ((call->params.has_video) && (call->params.has_video != old_has_video)) {
audio_stream_prepare_sound(call->audiostream,lc->sound_conf.play_sndcard,lc->sound_conf.capt_sndcard);
}
+ linphone_call_update_remote_session_id_and_ver(call);
sal_call_accept(call->op);
if (lc->vtable.display_status!=NULL)
lc->vtable.display_status(lc,_("Connected."));
sal_verify_server_certificates(lc->sal,yesno);
}
+/**
+ * Specify whether the tls server certificate common name must be verified when connecting to a SIP/TLS server.
+**/
+void linphone_core_verify_server_cn(LinphoneCore *lc, bool_t yesno){
+ sal_verify_server_cn(lc->sal,yesno);
+}
+
static void notify_end_of_ring(void *ud, MSFilter *f, unsigned int event, void *arg){
LinphoneCore *lc=(LinphoneCore*)ud;
lc->preview_finished=1;
IceSession *ice_session;
LinphoneChatMessage* pending_message;
int ping_time;
+ unsigned int remote_session_id;
+ unsigned int remote_session_ver;
bool_t refer_pending;
bool_t media_pending;
bool_t audio_muted;
void linphone_call_delete_ice_session(LinphoneCall *call);
void linphone_call_stop_media_streams_for_ice_gathering(LinphoneCall *call);
void linphone_call_update_crypto_parameters(LinphoneCall *call, SalMediaDescription *old_md, SalMediaDescription *new_md);
+ void linphone_call_update_remote_session_id_and_ver(LinphoneCall *call);
const char * linphone_core_get_identity(LinphoneCore *lc);
const char * linphone_core_get_route(LinphoneCore *lc);
int linphone_core_start_accept_call_update(LinphoneCore *lc, LinphoneCall *call);
void linphone_core_start_refered_call(LinphoneCore *lc, LinphoneCall *call);
void linphone_core_notify_incoming_call(LinphoneCore *lc, LinphoneCall *call);
+bool_t linphone_core_incompatible_security(LinphoneCore *lc, SalMediaDescription *md);
extern SalCallbacks linphone_sal_callbacks;
void linphone_proxy_config_set_error(LinphoneProxyConfig *cfg, LinphoneReason error);
bool_t linphone_core_rtcp_enabled(const LinphoneCore *lc);