Commit 623554f2 authored by johan's avatar johan
Browse files

Merge remote-tracking branch 'origin/dev_dtls'

parents b0f5e339 f63ec9b8
......@@ -628,6 +628,16 @@ AC_ARG_ENABLE(zrtp,
[zrtp=false]
)
AC_ARG_ENABLE(dtls,
[AS_HELP_STRING([--enable-dtls], [Turn on dtls support - requires polarssl > 1.4])],
[case "${enableval}" in
yes) dtls=true ;;
no) dtls=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-dtls) ;;
esac],
[dtls=false]
)
dnl build console if required
AM_CONDITIONAL(BUILD_CONSOLE, test x$console_ui = xtrue)
......@@ -638,6 +648,7 @@ dnl compilation of gtk user interface
AM_CONDITIONAL(BUILD_GTK_UI, [test x$gtk_ui = xtrue ] )
AM_CONDITIONAL(BUILD_WIN32, test x$mingw_found = xyes )
AM_CONDITIONAL(BUILD_ZRTP, test x$zrtp = xtrue)
AM_CONDITIONAL(BUILD_DTLS, test x$dtls = xtrue)
dnl check getenv
AH_TEMPLATE([HAVE_GETENV])
......@@ -985,6 +996,7 @@ printf "* %-30s %s\n" "Console interface" $console_ui
printf "* %-30s %s\n" "Tools" $build_tools
printf "* %-30s %s\n" "Message storage" $enable_msg_storage
printf "* %-30s %s\n" "zRTP encryption" $zrtp
printf "* %-30s %s\n" "DTLS encryption" $dtls
printf "* %-30s %s\n" "uPnP support" $build_upnp
printf "* %-30s %s\n" "LDAP support" $enable_ldap
printf "* %-30s %s\n" "ZLIB support" $found_zlib
......
......@@ -161,6 +161,7 @@ static int trace_level = 0;
static char *logfile_name = NULL;
static char configfile_name[PATH_MAX];
static char zrtpsecrets[PATH_MAX];
static char usr_certificates_path[PATH_MAX];
static const char *factory_configfile_name=NULL;
static char *sip_addr_to_call = NULL; /* for autocall */
static int window_id = 0; /* 0=standalone window, or window id for embedding video */
......@@ -680,6 +681,8 @@ linphonec_init(int argc, char **argv)
getenv("HOME"));
snprintf(zrtpsecrets, PATH_MAX, "%s/.linphone-zidcache",
getenv("HOME"));
snprintf(usr_certificates_path, PATH_MAX, "%s/.linphone-usr-crt",
getenv("HOME"));
#elif defined(_WIN32_WCE)
strncpy(configfile_name,PACKAGE_DIR "\\linphonerc",PATH_MAX);
mylogfile=fopen(PACKAGE_DIR "\\" "linphonec.log","w");
......@@ -689,6 +692,8 @@ linphonec_init(int argc, char **argv)
getenv("APPDATA"));
snprintf(zrtpsecrets, PATH_MAX, "%s/Linphone/linphone-zidcache",
getenv("APPDATA"));
snprintf(usr_certificates_path, PATH_MAX, "%s/Linphone/linphone-usr-crt",
getenv("APPDATA"));
#endif
/* Handle configuration filename changes */
switch (handle_configfile_migration())
......@@ -745,6 +750,7 @@ linphonec_init(int argc, char **argv)
linphone_core_set_user_agent(linphonec,"Linphonec", LINPHONE_VERSION);
linphone_core_set_zrtp_secrets_file(linphonec,zrtpsecrets);
linphone_core_set_user_certificates_path(linphonec,usr_certificates_path);
linphone_core_enable_video_capture(linphonec, vcap_enabled);
linphone_core_enable_video_display(linphonec, display_enabled);
if (display_enabled && window_id != 0)
......
......@@ -16,9 +16,6 @@
#include "ortp/rtpsession.h"
#include "linphonecore.h"
#include "linphonecore_utils.h"
#ifndef USE_BELLESIP
#include "eXosip2/eXosip_transport_hook.h"
#endif
#include "private.h"
#ifdef ANDROID
......@@ -97,7 +94,7 @@ RtpTransport *TunnelManager::createRtpTransport(int port){
void TunnelManager::startClient() {
ms_message("TunnelManager: Starting tunnel client");
mTunnelClient = new TunnelClient();
mTunnelClient = new TunnelClient(TRUE);
mTunnelClient->setCallback((TunnelClientController::StateCallback)tunnelCallback,this);
list<ServerAddr>::iterator it;
for(it=mServerAddrs.begin();it!=mServerAddrs.end();++it){
......@@ -122,18 +119,16 @@ int TunnelManager::customSendto(struct _RtpTransport *t, mblk_t *msg , int flags
}
int TunnelManager::customRecvfrom(struct _RtpTransport *t, mblk_t *msg, int flags, struct sockaddr *from, socklen_t *fromlen){
memset(&msg->recv_addr,0,sizeof(msg->recv_addr));
int err=((TunnelSocket*)t->data)->recvfrom(msg->b_wptr,msg->b_datap->db_lim-msg->b_datap->db_base,from,*fromlen);
//to make ice happy
inet_aton(((TunnelManager*)((TunnelSocket*)t->data)->getUserPointer())->mLocalAddr,&msg->recv_addr.addr.ipi_addr);
if (err>0) return err;
return 0;
}
TunnelManager::TunnelManager(LinphoneCore* lc) :
mCore(lc),
#ifndef USE_BELLESIP
mSipSocket(NULL),
mExosipTransport(NULL),
#endif
mMode(LinphoneTunnelModeDisable),
mState(disabled),
mTunnelizeSipPackets(true),
......@@ -153,6 +148,7 @@ TunnelManager::TunnelManager(LinphoneCore* lc) :
mVTable = linphone_core_v_table_new();
mVTable->network_reachable = networkReachableCb;
linphone_core_add_listener(mCore, mVTable);
linphone_core_get_local_ip_for(AF_INET, NULL, mLocalAddr);
}
TunnelManager::~TunnelManager(){
......@@ -371,6 +367,7 @@ void TunnelManager::networkReachableCb(LinphoneCore *lc, bool_t reachable) {
tunnel->startAutoDetection();
tunnel->mState = autodetecting;
}
linphone_core_get_local_ip_for(AF_INET, NULL,tunnel->mLocalAddr);
}
bool TunnelManager::startAutoDetection() {
......
......@@ -200,6 +200,7 @@ namespace belledonnecomm {
LinphoneRtpTransportFactories mTransportFactories;
Mutex mMutex;
std::queue<Event> mEvq;
char mLocalAddr[64];
};
/**
......
......@@ -1073,6 +1073,45 @@ void sal_signing_key_parse_file(SalAuthInfo* auth_info, const char* path, const
if (auth_info->key) belle_sip_object_ref((belle_sip_object_t *) auth_info->key);
}
/**
* Parse a directory to get a certificate with the given subject common name
*
*/
void sal_certificates_chain_parse_directory(char **certificate_pem, char **key_pem, char **fingerprint, const char* path, const char *subject, SalCertificateRawFormat format, bool_t generate_certificate, bool_t generate_dtls_fingerprint) {
belle_sip_certificates_chain_t *certificate = NULL;
belle_sip_signing_key_t *key = NULL;
*certificate_pem = NULL;
*key_pem = NULL;
if (belle_sip_get_certificate_and_pkey_in_dir(path, subject, &certificate, &key, (belle_sip_certificate_raw_format_t)format) == 0) {
*certificate_pem = belle_sip_certificates_chain_get_pem(certificate);
*key_pem = belle_sip_signing_key_get_pem(key);
ms_message("Retrieve certificate with CN=%s successful\n", subject);
} else {
if (generate_certificate == TRUE) {
if ( belle_sip_generate_self_signed_certificate(path, subject, &certificate, &key) == 0) {
*certificate_pem = belle_sip_certificates_chain_get_pem(certificate);
*key_pem = belle_sip_signing_key_get_pem(key);
ms_message("Generate self-signed certificate with CN=%s successful\n", subject);
}
}
}
/* generate the fingerprint as described in RFC4572 if needed */
if ((generate_dtls_fingerprint == TRUE) && (fingerprint != NULL)) {
if (*fingerprint != NULL) {
ms_free(*fingerprint);
}
*fingerprint = belle_sip_certificates_chain_get_fingerprint(certificate);
}
/* free key and certificate */
if ( certificate != NULL ) {
belle_sip_object_unref(certificate);
}
if ( key != NULL ) {
belle_sip_object_unref(key);
}
}
unsigned char * sal_get_random_bytes(unsigned char *ret, size_t size){
return belle_sip_random_bytes(ret,size);
}
......
......@@ -233,6 +233,29 @@ static void stream_description_to_sdp ( belle_sdp_session_description_t *session
}else break;
}
}
/* insert DTLS session attribute if needed */
if ((stream->proto == SalProtoUdpTlsRtpSavpf) || (stream->proto == SalProtoUdpTlsRtpSavp)) {
char* ssrc_attribute = ms_strdup_printf("%u cname:%s",htonl(stream->rtp_ssrc),stream->rtcp_cname);
if ((stream->dtls_role != SalDtlsRoleInvalid) && (strlen(stream->dtls_fingerprint)>0)) {
switch(stream->dtls_role) {
case SalDtlsRoleIsClient:
belle_sdp_media_description_add_attribute(media_desc, belle_sdp_attribute_create("setup","active"));
break;
case SalDtlsRoleIsServer:
belle_sdp_media_description_add_attribute(media_desc, belle_sdp_attribute_create("setup","passive"));
break;
case SalDtlsRoleUnset:
default:
belle_sdp_media_description_add_attribute(media_desc, belle_sdp_attribute_create("setup","actpass"));
break;
}
belle_sdp_media_description_add_attribute(media_desc, belle_sdp_attribute_create("fingerprint",stream->dtls_fingerprint));
}
belle_sdp_media_description_add_attribute(media_desc, belle_sdp_attribute_create("ssrc",ssrc_attribute)); /* truc de Jehan a virer? */
ms_free(ssrc_attribute);
}
switch ( stream->dir ) {
case SalStreamSendRecv:
/*dir="sendrecv";*/
......@@ -301,6 +324,13 @@ static void stream_description_to_sdp ( belle_sdp_session_description_t *session
belle_sip_object_unref((belle_sip_object_t*)media_attribute);
}
}
/*
* rfc5576
* 4.1. The "ssrc" Media Attribute
* <ssrc-id> is the synchronization source (SSRC) ID of the
* source being described, interpreted as a 32-bit unsigned integer in
* network byte order and represented in decimal.*/
belle_sdp_session_description_add_media_description(session_desc, media_desc);
}
......@@ -351,6 +381,23 @@ belle_sdp_session_description_t * media_description_to_sdp ( const SalMediaDescr
if (desc->ice_pwd[0] != '\0') belle_sdp_session_description_add_attribute(session_desc, belle_sdp_attribute_create("ice-pwd",desc->ice_pwd));
if (desc->ice_ufrag[0] != '\0') belle_sdp_session_description_add_attribute(session_desc, belle_sdp_attribute_create("ice-ufrag",desc->ice_ufrag));
/* insert DTLS session attribute if needed */
if ((desc->dtls_role != SalDtlsRoleInvalid) && (strlen(desc->dtls_fingerprint)>0)) {
switch(desc->dtls_role) {
case SalDtlsRoleIsClient:
belle_sdp_session_description_add_attribute(session_desc, belle_sdp_attribute_create("setup","active"));
break;
case SalDtlsRoleIsServer:
belle_sdp_session_description_add_attribute(session_desc, belle_sdp_attribute_create("setup","passive"));
break;
case SalDtlsRoleUnset:
default:
belle_sdp_session_description_add_attribute(session_desc, belle_sdp_attribute_create("setup","actpass"));
break;
}
belle_sdp_session_description_add_attribute(session_desc, belle_sdp_attribute_create("fingerprint",desc->dtls_fingerprint));
}
if (desc->rtcp_xr.enabled == TRUE) {
belle_sdp_session_description_add_attribute(session_desc, create_rtcp_xr_attribute(&desc->rtcp_xr));
}
......@@ -450,12 +497,15 @@ static void sdp_parse_media_ice_parameters(belle_sdp_media_description_t *media_
att_name = belle_sdp_attribute_get_name(attribute);
value = belle_sdp_attribute_get_value(attribute);
if ((keywordcmp("candidate", att_name) == 0) && (value != NULL)) {
if ( (nb_ice_candidates < sizeof (stream->ice_candidates)/sizeof(SalIceCandidate))
&& (keywordcmp("candidate", att_name) == 0)
&& (value != NULL)) {
SalIceCandidate *candidate = &stream->ice_candidates[nb_ice_candidates];
int nb = sscanf(value, "%s %u UDP %u %s %d typ %s raddr %s rport %d",
candidate->foundation, &candidate->componentID, &candidate->priority, candidate->addr, &candidate->port,
char proto[4];
int nb = sscanf(value, "%s %u %3s %u %s %d typ %s raddr %s rport %d",
candidate->foundation, &candidate->componentID, proto, &candidate->priority, candidate->addr, &candidate->port,
candidate->type, candidate->raddr, &candidate->rport);
if ((nb == 6) || (nb == 8)) nb_ice_candidates++;
if (strcasecmp("udp",proto)==0 && ((nb == 7) || (nb == 9))) nb_ice_candidates++;
else memset(candidate, 0, sizeof(*candidate));
} else if ((keywordcmp("remote-candidates", att_name) == 0) && (value != NULL)) {
SalIceRemoteCandidate candidate;
......@@ -646,6 +696,10 @@ static SalStreamDescription * sdp_to_stream_description(SalMediaDescription *md,
stream->proto = SalProtoRtpAvpf;
} else if (strcasecmp(proto, "RTP/SAVPF") == 0) {
stream->proto = SalProtoRtpSavpf;
} else if (strcasecmp(proto, "UDP/TLS/RTP/SAVP") == 0) {
stream->proto = SalProtoUdpTlsRtpSavp;
} else if (strcasecmp(proto, "UDP/TLS/RTP/SAVPF") == 0) {
stream->proto = SalProtoUdpTlsRtpSavpf;
} else {
strncpy(stream->proto_other,proto,sizeof(stream->proto_other)-1);
}
......@@ -701,6 +755,36 @@ static SalStreamDescription * sdp_to_stream_description(SalMediaDescription *md,
}
}
/* Read DTLS specific attributes : check is some are found in the stream description otherwise copy the session description one(which are at least set to Invalid) */
stream->dtls_role = SalDtlsRoleInvalid;
stream->dtls_fingerprint[0] = '\0';
if (((stream->proto == SalProtoUdpTlsRtpSavpf) || (stream->proto == SalProtoUdpTlsRtpSavp))) {
attribute=belle_sdp_media_description_get_attribute(media_desc,"setup");
if (attribute && (value=belle_sdp_attribute_get_value(attribute))!=NULL){
if (strncmp(value, "actpass", 7) == 0) {
stream->dtls_role = SalDtlsRoleUnset;
} else if (strncmp(value, "active", 6) == 0) {
stream->dtls_role = SalDtlsRoleIsClient;
} else if (strncmp(value, "passive", 7) == 0) {
stream->dtls_role = SalDtlsRoleIsServer;
}
if (stream->dtls_role != SalDtlsRoleInvalid || md->dtls_role != SalDtlsRoleInvalid) {
attribute=belle_sdp_media_description_get_attribute(media_desc,"fingerprint");
if (attribute && (value=belle_sdp_attribute_get_value(attribute))!=NULL){
strncpy(stream->dtls_fingerprint, value, sizeof(stream->dtls_fingerprint)-1);
} else {
/* no valid stream attributes, get them from session */
if (stream->dtls_role == SalDtlsRoleInvalid) stream->dtls_role = md->dtls_role;
strncpy(stream->dtls_fingerprint, md->dtls_fingerprint, strlen(md->dtls_fingerprint)+1);
}
}
} else { /* no setup attribute found in the stream, get the one from the session */
stream->dtls_role = md->dtls_role;
strncpy(stream->dtls_fingerprint, md->dtls_fingerprint, strlen(md->dtls_fingerprint)+1);
}
}
/* Read crypto lines if any */
if ((stream->proto == SalProtoRtpSavpf) || (stream->proto == SalProtoRtpSavp)) {
sdp_parse_media_crypto_parameters(media_desc, stream);
......@@ -756,6 +840,27 @@ int sdp_to_media_description ( belle_sdp_session_description_t *session_desc, S
desc->dir=SalStreamInactive;
}
/* Read dtls specific session attributes if any (setup and fingerprint - rfc5763) */
/* Presence of a valid dtls offer(setup and fingerprint attribute) is set in media Description by a dtls_fingerprint string longer than 0
* and a dtls_role != SalDtlsRoleInvalid */
desc->dtls_role = SalDtlsRoleInvalid;
desc->dtls_fingerprint[0] = '\0';
value=belle_sdp_session_description_get_attribute_value(session_desc,"setup");
if (value){
if (strncmp(value, "actpass", 7) == 0) {
desc->dtls_role = SalDtlsRoleUnset;
} else if (strncmp(value, "active", 6) == 0) {
desc->dtls_role = SalDtlsRoleIsClient;
} else if (strncmp(value, "passive", 7) == 0) {
desc->dtls_role = SalDtlsRoleIsServer;
}
}
value=belle_sdp_session_description_get_attribute_value(session_desc,"fingerprint");
if (value){
strncpy(desc->dtls_fingerprint, value, sizeof(desc->dtls_fingerprint)-1);
}
/* Get ICE remote ufrag and remote pwd, and ice_lite flag */
value=belle_sdp_session_description_get_attribute_value(session_desc,"ice-ufrag");
if (value) strncpy(desc->ice_ufrag, value, sizeof(desc->ice_ufrag) - 1);
......
......@@ -27,6 +27,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
SalMediaProto get_proto_from_call_params(const LinphoneCallParams *params) {
if ((params->media_encryption == LinphoneMediaEncryptionSRTP) && params->avpf_enabled) return SalProtoRtpSavpf;
if (params->media_encryption == LinphoneMediaEncryptionSRTP) return SalProtoRtpSavp;
if ((params->media_encryption == LinphoneMediaEncryptionDTLS) && params->avpf_enabled) return SalProtoUdpTlsRtpSavpf;
if (params->media_encryption == LinphoneMediaEncryptionDTLS) return SalProtoUdpTlsRtpSavp;
if (params->avpf_enabled) return SalProtoRtpAvpf;
return SalProtoRtpAvp;
}
......
......@@ -338,7 +338,7 @@ static void call_received(SalOp *h){
linphone_core_add_call(lc,call);
linphone_call_ref(call); /*prevent the call from being destroyed while we are notifying, if the user declines within the state callback */
if ((_linphone_core_get_firewall_policy(lc) == LinphonePolicyUseIce) && (call->ice_session != NULL)) {
if ((linphone_core_get_firewall_policy(lc) == LinphonePolicyUseIce) && (call->ice_session != NULL)) {
/* Defer ringing until the end of the ICE candidates gathering process. */
ms_message("Defer ringing to gather ICE candidates");
return;
......
This diff is collapsed.
......@@ -28,6 +28,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <sys/stat.h>
#include <ortp/telephonyevents.h>
#include <mediastreamer2/zrtp.h>
#include <mediastreamer2/dtls_srtp.h>
#include "mediastreamer2/mediastream.h"
#include "mediastreamer2/mseventqueue.h"
#include "mediastreamer2/msvolume.h"
......@@ -1453,6 +1454,12 @@ static void misc_config_read(LinphoneCore *lc) {
lp_config_set_string(config,"misc","uuid",tmp);
}else if (strcmp(uuid,"0")!=0) /*to allow to disable sip.instance*/
sal_set_uuid(lc->sal, uuid);
/* DTLS: if media_encryption DTLS SRTP is available, get or create the certificate directory */
/*if (ms_dtls_srtp_available()){
*//*JOHAN: USELESS? REMOVE IT*/
//const char *user_certificate_config_path = lp_config_get_string(config,"misc","uuid",);
// }*/
}
static void linphone_core_start(LinphoneCore * lc) {
......@@ -3094,12 +3101,12 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const
call->log->start_date_time=ms_time(NULL);
linphone_call_init_media_streams(call);
if (_linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) {
if (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) {
/* Defer the start of the call after the ICE gathering process. */
if (linphone_call_prepare_ice(call,FALSE)==1)
defer=TRUE;
}
else if (_linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseUpnp) {
else if (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseUpnp) {
#ifdef BUILD_UPNP
if (linphone_core_update_upnp(lc,call)<0) {
/* uPnP port mappings failed, proceed with the call anyway. */
......@@ -4932,23 +4939,8 @@ void linphone_core_set_firewall_policy(LinphoneCore *lc, LinphoneFirewallPolicy
if (linphone_core_ready(lc))
lp_config_set_string(lc->config,"net","firewall_policy",policy);
}
LinphoneFirewallPolicy linphone_core_get_firewall_policy(const LinphoneCore *lc) {
return _linphone_core_get_firewall_policy_with_lie(lc, FALSE);
}
LinphoneFirewallPolicy _linphone_core_get_firewall_policy(const LinphoneCore *lc) {
return _linphone_core_get_firewall_policy_with_lie(lc, TRUE);
}
LinphoneFirewallPolicy _linphone_core_get_firewall_policy_with_lie(const LinphoneCore *lc, bool_t lie){
LinphoneFirewallPolicy linphone_core_get_firewall_policy(const LinphoneCore *lc){
const char *policy;
if(lie) {
LinphoneTunnel *tunnel = linphone_core_get_tunnel(lc);
if(tunnel != NULL && linphone_tunnel_get_mode(tunnel)) {
return LinphonePolicyNoFirewall;
}
}
policy = lp_config_get_string(lc->config, "net", "firewall_policy", NULL);
if ((policy == NULL) || (strcmp(policy, "0") == 0))
return LinphonePolicyNoFirewall;
......@@ -6271,6 +6263,9 @@ static void linphone_core_uninit(LinphoneCore *lc)
if(lc->zrtp_secrets_cache != NULL) {
ms_free(lc->zrtp_secrets_cache);
}
if(lc->user_certificates_path != NULL) {
ms_free(lc->user_certificates_path);
}
if(lc->play_file!=NULL){
ms_free(lc->play_file);
}
......@@ -6709,6 +6704,17 @@ const char *linphone_core_get_zrtp_secrets_file(LinphoneCore *lc){
return lc->zrtp_secrets_cache;
}
void linphone_core_set_user_certificates_path(LinphoneCore *lc, const char* path){
if (lc->user_certificates_path != NULL) {
ms_free(lc->user_certificates_path);
}
lc->user_certificates_path = path ? ms_strdup(path) : NULL;
}
const char *linphone_core_get_user_certificates_path(LinphoneCore *lc){
return lc->user_certificates_path;
}
LinphoneCall* linphone_core_find_call_from_uri(const LinphoneCore *lc, const char *uri) {
MSList *calls;
LinphoneCall *c;
......@@ -6769,6 +6775,8 @@ const char *linphone_media_encryption_to_string(LinphoneMediaEncryption menc){
switch(menc){
case LinphoneMediaEncryptionSRTP:
return "LinphoneMediaEncryptionSRTP";
case LinphoneMediaEncryptionDTLS:
return "LinphoneMediaEncryptionDTLS";
case LinphoneMediaEncryptionZRTP:
return "LinphoneMediaEncryptionZRTP";
case LinphoneMediaEncryptionNone:
......@@ -6785,6 +6793,8 @@ bool_t linphone_core_media_encryption_supported(const LinphoneCore *lc, Linphone
switch(menc){
case LinphoneMediaEncryptionSRTP:
return ms_srtp_supported();
case LinphoneMediaEncryptionDTLS:
return ms_dtls_srtp_available();
case LinphoneMediaEncryptionZRTP:
return ms_zrtp_available();
case LinphoneMediaEncryptionNone:
......@@ -6808,7 +6818,14 @@ int linphone_core_set_media_encryption(LinphoneCore *lc, LinphoneMediaEncryption
type="none";
ret=-1;
}else type="zrtp";
}else if (menc == LinphoneMediaEncryptionDTLS){
if (!ms_dtls_srtp_available()){
ms_warning("DTLS not supported by library.");
type="none";
ret=-1;
}else type="dtls";
}
lp_config_set_string(lc->config,"sip","media_encryption",type);
return ret;
}
......@@ -6820,6 +6837,8 @@ LinphoneMediaEncryption linphone_core_get_media_encryption(LinphoneCore *lc) {
return LinphoneMediaEncryptionNone;
else if (strcmp(menc, "srtp")==0)
return LinphoneMediaEncryptionSRTP;
else if (strcmp(menc, "dtls")==0)
return LinphoneMediaEncryptionDTLS;
else if (strcmp(menc, "zrtp")==0)
return LinphoneMediaEncryptionZRTP;
else
......
......@@ -287,7 +287,8 @@ typedef enum _LinphoneAVPFMode LinphoneAVPFMode;
enum _LinphoneMediaEncryption {
LinphoneMediaEncryptionNone, /**< No media encryption is used */
LinphoneMediaEncryptionSRTP, /**< Use SRTP media encryption */
LinphoneMediaEncryptionZRTP /**< Use ZRTP media encryption */
LinphoneMediaEncryptionZRTP, /**< Use ZRTP media encryption */
LinphoneMediaEncryptionDTLS /**< Use DTLS media encryption */
};
/**
......@@ -3048,6 +3049,22 @@ LINPHONE_PUBLIC void linphone_core_set_zrtp_secrets_file(LinphoneCore *lc, const
*/
LINPHONE_PUBLIC const char *linphone_core_get_zrtp_secrets_file(LinphoneCore *lc);
/**
* Set the path to the directory storing the user's x509 certificates (used by dtls)
* @param[in] lc #LinphoneCore object
* @param[in] path The path to the directory to use to store the user's certificates.
* @ingroup initializing
*/
LINPHONE_PUBLIC void linphone_core_set_user_certificates_path(LinphoneCore *lc, const char* path);
/**
* Get the path to the directory storing the user's certificates.
* @param[in] lc #LinphoneCore object.
* @returns The path to the directory storing the user's certificates.
* @ingroup initializing
*/
LINPHONE_PUBLIC const char *linphone_core_get_user_certificates_path(LinphoneCore *lc);
/**
* Search from the list of current calls if a remote address match uri
* @ingroup call_control
......
......@@ -41,7 +41,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#endif /*_WIN32_WCE*/
#undef snprintf
#include <ortp/stun.h>
#include <mediastreamer2/stun.h>
#ifdef HAVE_GETIFADDRS
#include <net/if.h>
......@@ -891,8 +891,8 @@ void linphone_call_update_ice_from_remote_media_description(LinphoneCall *call,
if (cl && (stream->ice_pwd[0] != '\0') && (stream->ice_ufrag[0] != '\0')) {
if (ice_check_list_remote_credentials_changed(cl, stream->ice_ufrag, stream->ice_pwd)) {
if (ice_restarted == FALSE
&& ice_check_list_remote_ufrag(cl)
&& ice_check_list_remote_pwd(cl)) {
&& ice_check_list_get_remote_ufrag(cl)
&& ice_check_list_get_remote_pwd(cl)) {
/* restart onlu if remote ufrag/paswd was already set*/
ice_session_restart(call->ice_session);
ice_restarted = TRUE;
......
......@@ -316,6 +316,9 @@ static void initiate_outgoing(const SalStreamDescription *local_offer,
if (!match_crypto_algo(local_offer->crypto, remote_answer->crypto, &result->crypto[0], &result->crypto_local_tag, FALSE))
result->rtp_port = 0;
}
result->rtp_ssrc=local_offer->rtp_ssrc;
strncpy(result->rtcp_cname,local_offer->rtcp_cname,sizeof(result->rtcp_cname));
}
......@@ -350,6 +353,9 @@ static void initiate_incoming(const SalStreamDescription *local_cap,
memcpy(result->ice_candidates, local_cap->ice_candidates, sizeof(result->ice_candidates));
memcpy(result->ice_remote_candidates, local_cap->ice_remote_candidates, sizeof(result->ice_remote_candidates));
strcpy(result->name,local_cap->name);
result->rtp_ssrc=local_cap->rtp_ssrc;
strncpy(result->rtcp_cname,local_cap->rtcp_cname,sizeof(result->rtcp_cname));
}
/**
......@@ -384,6 +390,21 @@ int offer_answer_initiate_outgoing(const SalMediaDescription *local_offer,
result->rtcp_xr.enabled = FALSE;
}
// Handle dtls session attribute: if both local and remote have a dtls fingerprint and a dtls setup, get the remote fingerprint into the result
if ((local_offer->dtls_role!=SalDtlsRoleInvalid) && (remote_answer->dtls_role!=SalDtlsRoleInvalid)
&&(strlen(local_offer->dtls_fingerprint)>0) && (strlen(remote_answer->dtls_fingerprint)>0)) {
strcpy(result->dtls_fingerprint, remote_answer->dtls_fingerprint);
if (remote_answer->dtls_role==SalDtlsRoleIsClient) {
result->dtls_role = SalDtlsRoleIsServer;
} else {
result->dtls_role = SalDtlsRoleIsClient;
}
} else {
result->dtls_fingerprint[0] = '\0';
result->dtls_role = SalDtlsRoleInvalid;
}
return 0;
}
......@@ -403,7 +424,9 @@ static bool_t local_stream_not_already_used(const SalMediaDescription *result, c
static bool_t proto_compatible(SalMediaProto local, SalMediaProto remote) {
if (local == remote) return TRUE;
if ((remote == SalProtoRtpAvp) && ((local == SalProtoRtpSavp) || (local == SalProtoRtpSavpf))) return TRUE;
if ((remote == SalProtoRtpAvp) && ((local == SalProtoUdpTlsRtpSavp) || (local == SalProtoUdpTlsRtpSavpf))) return TRUE;
if ((remote == SalProtoRtpAvpf) && (local == SalProtoRtpSavpf)) return TRUE;
if ((remote == SalProtoRtpAvpf) && (local == SalProtoUdpTlsRtpSavpf)) return TRUE;
return FALSE;
}
......@@ -437,6 +460,23 @@ int offer_answer_initiate_incoming(const SalMediaDescription *local_capabilities
if (ls){
initiate_incoming(ls,rs,&result->streams[i],one_matching_codec);
// Handle dtls stream attribute: if both local and remote have a dtls fingerprint and a dtls setup, add the local fingerprint to the answer
// Note: local description usually stores dtls config at session level which means it apply to all streams, check this too
if (((ls->dtls_role!=SalDtlsRoleInvalid) || (local_capabilities->dtls_role!=SalDtlsRoleInvalid)) && (rs->dtls_role!=SalDtlsRoleInvalid)
&& ((strlen(ls->dtls_fingerprint)>0) || (strlen(local_capabilities->dtls_fingerprint)>0)) && (strlen(rs->dtls_fingerprint)>0)) {
if (strlen(ls->dtls_fingerprint)>0) { /* get the fingerprint in stream description */
strcpy(result->streams[i].dtls_fingerprint, ls->dtls_fingerprint);