mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-01-31 02:09:22 +00:00
Merge remote-tracking branch 'origin/dev_dtls'
This commit is contained in:
commit
623554f2f0
25 changed files with 719 additions and 142 deletions
12
configure.ac
12
configure.ac
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -159,8 +159,12 @@ static void propagate_encryption_changed(LinphoneCall *call){
|
|||
call->current_params->media_encryption=LinphoneMediaEncryptionNone;
|
||||
linphone_core_notify_call_encryption_changed(call->core, call, FALSE, call->auth_token);
|
||||
} else {
|
||||
ms_message("All streams are encrypted");
|
||||
call->current_params->media_encryption=LinphoneMediaEncryptionZRTP;
|
||||
if (call->auth_token) {/* ZRTP only is using auth_token */
|
||||
call->current_params->media_encryption=LinphoneMediaEncryptionZRTP;
|
||||
} else { /* otherwise it must be DTLS as SDES doesn't go through this function */
|
||||
call->current_params->media_encryption=LinphoneMediaEncryptionDTLS;
|
||||
}
|
||||
ms_message("All streams are encrypted key exchanged using %s", call->current_params->media_encryption==LinphoneMediaEncryptionZRTP?"ZRTP":call->current_params->media_encryption==LinphoneMediaEncryptionDTLS?"DTLS":"Unknown mechanism");
|
||||
linphone_core_notify_call_encryption_changed(call->core, call, TRUE, call->auth_token);
|
||||
}
|
||||
}
|
||||
|
|
@ -172,8 +176,10 @@ static void linphone_call_audiostream_encryption_changed(void *data, bool_t encr
|
|||
call = (LinphoneCall *)data;
|
||||
|
||||
if (encrypted) {
|
||||
snprintf(status,sizeof(status)-1,_("Authentication token is %s"),call->auth_token);
|
||||
linphone_core_notify_display_status(call->core, status);
|
||||
if (call->params->media_encryption==LinphoneMediaEncryptionZRTP) { /* if encryption is DTLS, no status to be displayed */
|
||||
snprintf(status,sizeof(status)-1,_("Authentication token is %s"),call->auth_token);
|
||||
linphone_core_notify_display_status(call->core, status);
|
||||
}
|
||||
}
|
||||
|
||||
propagate_encryption_changed(call);
|
||||
|
|
@ -572,6 +578,14 @@ void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *
|
|||
l=make_codec_list(lc, &codec_hints, lc->codecs_conf.audio_codecs);
|
||||
md->streams[0].max_rate=get_max_codec_sample_rate(l);
|
||||
md->streams[0].payloads=l;
|
||||
if (call->audiostream && call->audiostream->ms.sessions.rtp_session) {
|
||||
char* me = linphone_address_as_string_uri_only(call->me);
|
||||
md->streams[0].rtp_ssrc=rtp_session_get_send_ssrc(call->audiostream->ms.sessions.rtp_session);
|
||||
strncpy(md->streams[0].rtcp_cname,me,sizeof(md->streams[0].rtcp_cname));
|
||||
ms_free(me);
|
||||
}
|
||||
else
|
||||
ms_warning("Cannot get audio local ssrc for call [%p]",call);
|
||||
nb_active_streams++;
|
||||
|
||||
if (call->params->has_video){
|
||||
|
|
@ -587,6 +601,14 @@ void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *
|
|||
codec_hints.previously_used=old_md ? old_md->streams[1].already_assigned_payloads : NULL;
|
||||
l=make_codec_list(lc, &codec_hints, lc->codecs_conf.video_codecs);
|
||||
md->streams[1].payloads=l;
|
||||
if (call->videostream && call->videostream->ms.sessions.rtp_session) {
|
||||
char* me = linphone_address_as_string_uri_only(call->me);
|
||||
md->streams[0].rtp_ssrc=rtp_session_get_send_ssrc(call->videostream->ms.sessions.rtp_session);
|
||||
strncpy(md->streams[0].rtcp_cname,me,sizeof(md->streams[0].rtcp_cname));
|
||||
ms_free(me);
|
||||
}
|
||||
else
|
||||
ms_warning("Cannot get video local ssrc for call [%p]",call);
|
||||
nb_active_streams++;
|
||||
}
|
||||
|
||||
|
|
@ -608,6 +630,14 @@ void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *
|
|||
}
|
||||
|
||||
setup_encryption_keys(call,md);
|
||||
/* if media encryption is set to DTLS check presence of fingerprint in the call which shall have been set at stream init but it may have failed when retrieving certificate resulting in no fingerprint present and then DTLS not usable */
|
||||
if ((call->params->media_encryption==LinphoneMediaEncryptionDTLS) && (call->dtls_certificate_fingerprint!= NULL)) {
|
||||
memcpy(md->dtls_fingerprint, call->dtls_certificate_fingerprint, strlen((const char *)(call->dtls_certificate_fingerprint))); /* get the self fingerprint from call(it's computed at stream init) */
|
||||
md->dtls_role = SalDtlsRoleUnset; /* if we are offering, SDP will have actpass setup attribute when role is unset, if we are responding the result mediadescription will be set to SalDtlsRoleIsClient */
|
||||
} else {
|
||||
md->dtls_fingerprint[0] = '\0';
|
||||
md->dtls_role = SalDtlsRoleInvalid;
|
||||
}
|
||||
setup_rtcp_fb(call, md);
|
||||
setup_rtcp_xr(call, md);
|
||||
|
||||
|
|
@ -709,6 +739,12 @@ static void linphone_call_init_common(LinphoneCall *call, LinphoneAddress *from,
|
|||
call->camera_enabled=TRUE;
|
||||
call->current_params = linphone_call_params_new();
|
||||
call->current_params->media_encryption=LinphoneMediaEncryptionNone;
|
||||
call->dtls_certificate_fingerprint = NULL;
|
||||
if (call->dir == LinphoneCallIncoming)
|
||||
call->me=to;
|
||||
else
|
||||
call->me=from;
|
||||
linphone_address_ref(call->me);
|
||||
|
||||
linphone_core_get_audio_port_range(call->core, &min_port, &max_port);
|
||||
port_config_set(call,0,min_port,max_port);
|
||||
|
|
@ -799,7 +835,7 @@ static void linphone_call_get_local_ip(LinphoneCall *call, const LinphoneAddress
|
|||
}
|
||||
if (res != NULL) freeaddrinfo(res);
|
||||
}
|
||||
if (_linphone_core_get_firewall_policy(call->core)==LinphonePolicyUseNatAddress
|
||||
if (linphone_core_get_firewall_policy(call->core)==LinphonePolicyUseNatAddress
|
||||
&& (ip=linphone_core_get_nat_address_resolved(call->core))!=NULL){
|
||||
strncpy(call->localip,ip,LINPHONE_IPADDR_SIZE);
|
||||
return;
|
||||
|
|
@ -836,11 +872,13 @@ LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddr
|
|||
linphone_call_init_common(call,from,to);
|
||||
call->params = linphone_call_params_copy(params);
|
||||
|
||||
if (_linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) {
|
||||
if (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) {
|
||||
call->ice_session = ice_session_new();
|
||||
/*for backward compatibility purposes, shall be enabled by default in futur*/
|
||||
ice_session_enable_message_integrity_check(call->ice_session,lp_config_get_int(lc->config,"net","ice_session_enable_message_integrity_check",0));
|
||||
ice_session_set_role(call->ice_session, IR_Controlling);
|
||||
}
|
||||
if (_linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseStun) {
|
||||
if (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseStun) {
|
||||
call->ping_time=linphone_core_run_stun_tests(call->core,call);
|
||||
}
|
||||
#ifdef BUILD_UPNP
|
||||
|
|
@ -872,7 +910,7 @@ static void linphone_call_incoming_select_ip_version(LinphoneCall *call){
|
|||
void linphone_call_set_compatible_incoming_call_parameters(LinphoneCall *call, const SalMediaDescription *md) {
|
||||
call->params->has_video &= linphone_core_media_description_contains_video_stream(md);
|
||||
|
||||
/* Handle AVPF and SRTP. */
|
||||
/* Handle AVPF, SRTP and DTLS. */
|
||||
call->params->avpf_enabled = sal_media_description_has_avpf(md);
|
||||
if (call->params->avpf_enabled == TRUE) {
|
||||
if (call->dest_proxy != NULL) {
|
||||
|
|
@ -881,6 +919,9 @@ void linphone_call_set_compatible_incoming_call_parameters(LinphoneCall *call, c
|
|||
call->params->avpf_rr_interval = linphone_core_get_avpf_rr_interval(call->core)*1000;
|
||||
}
|
||||
}
|
||||
if ((sal_media_description_has_dtls(md) == TRUE) && (media_stream_dtls_supported() == TRUE)) {
|
||||
call->params->media_encryption = LinphoneMediaEncryptionDTLS;
|
||||
}
|
||||
if ((sal_media_description_has_srtp(md) == TRUE) && (ms_srtp_supported() == TRUE)) {
|
||||
call->params->media_encryption = LinphoneMediaEncryptionSRTP;
|
||||
}
|
||||
|
|
@ -939,17 +980,20 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro
|
|||
// In this case WE chose the media parameters according to policy.
|
||||
linphone_call_set_compatible_incoming_call_parameters(call, md);
|
||||
}
|
||||
fpol=_linphone_core_get_firewall_policy(call->core);
|
||||
fpol=linphone_core_get_firewall_policy(call->core);
|
||||
/*create the ice session now if ICE is required*/
|
||||
if (fpol==LinphonePolicyUseIce){
|
||||
if (md){
|
||||
call->ice_session = ice_session_new();
|
||||
/*for backward compatibility purposes, shall be enabled by default in futur*/
|
||||
ice_session_enable_message_integrity_check(call->ice_session,lp_config_get_int(lc->config,"net","ice_session_enable_message_integrity_check",0));
|
||||
ice_session_set_role(call->ice_session, IR_Controlled);
|
||||
}else{
|
||||
fpol=LinphonePolicyNoFirewall;
|
||||
ms_warning("ICE not supported for incoming INVITE without SDP.");
|
||||
}
|
||||
}
|
||||
|
||||
/*reserve the sockets immediately*/
|
||||
linphone_call_init_media_streams(call);
|
||||
switch (fpol) {
|
||||
|
|
@ -1054,8 +1098,19 @@ static void linphone_call_set_terminated(LinphoneCall *call){
|
|||
void linphone_call_fix_call_parameters(LinphoneCall *call){
|
||||
call->params->has_video=call->current_params->has_video;
|
||||
|
||||
if (call->params->media_encryption != LinphoneMediaEncryptionZRTP) /*in case of ZRTP call parameter are handle after zrtp negociation*/
|
||||
call->params->media_encryption=call->current_params->media_encryption;
|
||||
switch(call->params->media_encryption) {
|
||||
case LinphoneMediaEncryptionZRTP:
|
||||
case LinphoneMediaEncryptionDTLS:
|
||||
case LinphoneMediaEncryptionNone:
|
||||
/* do nothing */
|
||||
break;
|
||||
case LinphoneMediaEncryptionSRTP:
|
||||
call->params->media_encryption=call->current_params->media_encryption;
|
||||
break;
|
||||
default:
|
||||
ms_fatal("Unknown media encryption type on call [%p]", call);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const char *linphone_call_state_to_string(LinphoneCallState cs){
|
||||
|
|
@ -1204,6 +1259,10 @@ static void linphone_call_destroy(LinphoneCall *obj){
|
|||
ms_free(obj->auth_token);
|
||||
obj->auth_token=NULL;
|
||||
}
|
||||
if (obj->dtls_certificate_fingerprint) {
|
||||
ms_free(obj->dtls_certificate_fingerprint);
|
||||
obj->dtls_certificate_fingerprint=NULL;
|
||||
}
|
||||
if (obj->dtmfs_timer) {
|
||||
linphone_call_cancel_dtmfs(obj);
|
||||
}
|
||||
|
|
@ -1219,6 +1278,11 @@ static void linphone_call_destroy(LinphoneCall *obj){
|
|||
linphone_call_params_unref(obj->remote_params);
|
||||
obj->remote_params=NULL;
|
||||
}
|
||||
if (obj->me) {
|
||||
linphone_address_unref(obj->me);
|
||||
obj->me = NULL;
|
||||
}
|
||||
|
||||
sal_error_info_reset(&obj->non_op_error);
|
||||
}
|
||||
|
||||
|
|
@ -1256,11 +1320,16 @@ const LinphoneCallParams * linphone_call_get_current_params(LinphoneCall *call){
|
|||
#endif
|
||||
|
||||
if (linphone_call_all_streams_encrypted(call)) {
|
||||
if (linphone_call_get_authentication_token(call)) {
|
||||
call->current_params->media_encryption=LinphoneMediaEncryptionZRTP;
|
||||
} else {
|
||||
call->current_params->media_encryption=LinphoneMediaEncryptionSRTP;
|
||||
}
|
||||
if (linphone_call_get_authentication_token(call)) {
|
||||
call->current_params->media_encryption=LinphoneMediaEncryptionZRTP;
|
||||
} else {
|
||||
/* TODO : check this or presence of dtls_fingerprint in the call? */
|
||||
if (call->params->media_encryption == LinphoneMediaEncryptionDTLS) {
|
||||
call->current_params->media_encryption=LinphoneMediaEncryptionDTLS;
|
||||
} else {
|
||||
call->current_params->media_encryption=LinphoneMediaEncryptionSRTP;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
call->current_params->media_encryption=LinphoneMediaEncryptionNone;
|
||||
}
|
||||
|
|
@ -1629,7 +1698,7 @@ static void port_config_set_random_choosed(LinphoneCall *call, int stream_index,
|
|||
|
||||
static void _linphone_call_prepare_ice_for_stream(LinphoneCall *call, int stream_index, bool_t create_checklist){
|
||||
MediaStream *ms=stream_index == 0 ? (MediaStream*)call->audiostream : (MediaStream*)call->videostream;
|
||||
if ((_linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) && (call->ice_session != NULL)){
|
||||
if ((linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) && (call->ice_session != NULL)){
|
||||
IceCheckList *cl;
|
||||
rtp_session_set_pktinfo(ms->sessions.rtp_session, TRUE);
|
||||
rtp_session_set_symmetric_rtp(ms->sessions.rtp_session, FALSE);
|
||||
|
|
@ -1650,7 +1719,7 @@ int linphone_call_prepare_ice(LinphoneCall *call, bool_t incoming_offer){
|
|||
SalMediaDescription *remote = NULL;
|
||||
bool_t has_video=FALSE;
|
||||
|
||||
if ((_linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) && (call->ice_session != NULL)){
|
||||
if ((linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) && (call->ice_session != NULL)){
|
||||
if (incoming_offer){
|
||||
remote=sal_call_get_remote_media_description(call->op);
|
||||
has_video=call->params->has_video && linphone_core_media_description_contains_video_stream(remote);
|
||||
|
|
@ -1686,13 +1755,38 @@ void linphone_call_init_audio_stream(LinphoneCall *call){
|
|||
AudioStream *audiostream;
|
||||
const char *location;
|
||||
int dscp;
|
||||
RtpTransport *meta_rtp=NULL;
|
||||
RtpTransport *meta_rtcp=NULL;
|
||||
char rtcp_tool[128]={0};
|
||||
char* cname;
|
||||
snprintf(rtcp_tool,sizeof(rtcp_tool)-1,"%s-%s",linphone_core_get_user_agent_name(),linphone_core_get_user_agent_version());
|
||||
|
||||
if (call->audiostream != NULL) return;
|
||||
if (call->sessions[0].rtp_session==NULL){
|
||||
call->audiostream=audiostream=audio_stream_new(call->media_ports[0].rtp_port,call->media_ports[0].rtcp_port,call->af==AF_INET6);
|
||||
cname = linphone_address_as_string_uri_only(call->me);
|
||||
audio_stream_set_rtcp_information(call->audiostream, cname, rtcp_tool);
|
||||
ms_free(cname);
|
||||
rtp_session_set_symmetric_rtp(audiostream->ms.sessions.rtp_session,linphone_core_symmetric_rtp_enabled(lc));
|
||||
if (call->params->media_encryption==LinphoneMediaEncryptionDTLS) {
|
||||
MSDtlsSrtpParams params;
|
||||
char *certificate, *key;
|
||||
memset(¶ms,0,sizeof(MSDtlsSrtpParams));
|
||||
/* TODO : search for a certificate with CNAME=sip uri(retrieved from variable me) or default : linphone-dtls-default-identity */
|
||||
/* This will parse the directory to find a matching fingerprint or generate it if not found */
|
||||
/* returned string must be freed */
|
||||
sal_certificates_chain_parse_directory(&certificate, &key, &call->dtls_certificate_fingerprint, lc->user_certificates_path, "linphone-dtls-default-identity", SAL_CERTIFICATE_RAW_FORMAT_PEM, TRUE, TRUE);
|
||||
|
||||
if (key!= NULL && certificate!=NULL) {
|
||||
params.pem_certificate = (char *)certificate;
|
||||
params.pem_pkey = (char *)key;
|
||||
params.role = MSDtlsSrtpRoleUnset; /* default is unset, then check if we have a result SalMediaDescription */
|
||||
audio_stream_enable_dtls(call->audiostream,¶ms);
|
||||
ms_free(certificate);
|
||||
ms_free(key);
|
||||
} else {
|
||||
ms_error("Unable to retrieve or generate DTLS certificate and key - DTLS disabled");
|
||||
/* TODO : check if encryption forced, if yes, stop call */
|
||||
}
|
||||
}
|
||||
}else{
|
||||
call->audiostream=audio_stream_new_with_sessions(&call->sessions[0]);
|
||||
}
|
||||
|
|
@ -1739,14 +1833,18 @@ void linphone_call_init_audio_stream(LinphoneCall *call){
|
|||
}
|
||||
|
||||
audio_stream_set_features(audiostream,linphone_core_get_audio_features(lc));
|
||||
rtp_session_get_transports(audiostream->ms.sessions.rtp_session,&meta_rtp,&meta_rtcp);
|
||||
if (lc->rtptf && (meta_rtp==NULL && meta_rtcp==NULL)){
|
||||
/*the transport just need to be created once, then they are kept into the RtpSession, which is the same for the entire call duration.*/
|
||||
RtpTransport *artp=lc->rtptf->audio_rtp_func(lc->rtptf->audio_rtp_func_data, call->media_ports[0].rtp_port);
|
||||
RtpTransport *artcp=lc->rtptf->audio_rtcp_func(lc->rtptf->audio_rtcp_func_data, call->media_ports[0].rtcp_port);
|
||||
meta_rtp_transport_new(&meta_rtp,TRUE,artp, 0);
|
||||
meta_rtp_transport_new(&meta_rtcp,FALSE,artcp, 0);
|
||||
rtp_session_set_transports(audiostream->ms.sessions.rtp_session,meta_rtp,meta_rtcp);
|
||||
|
||||
if (lc->rtptf){
|
||||
RtpTransport *meta_rtp;
|
||||
RtpTransport *meta_rtcp;
|
||||
|
||||
rtp_session_get_transports(audiostream->ms.sessions.rtp_session,&meta_rtp,&meta_rtcp);
|
||||
if (meta_rtp_transport_get_endpoint(meta_rtp) == NULL) {
|
||||
meta_rtp_transport_set_endpoint(meta_rtp,lc->rtptf->audio_rtp_func(lc->rtptf->audio_rtp_func_data, call->media_ports[0].rtp_port));
|
||||
}
|
||||
if (meta_rtp_transport_get_endpoint(meta_rtcp) == NULL) {
|
||||
meta_rtp_transport_set_endpoint(meta_rtcp,lc->rtptf->audio_rtcp_func(lc->rtptf->audio_rtcp_func_data, call->media_ports[0].rtcp_port));
|
||||
}
|
||||
}
|
||||
|
||||
call->audiostream_app_evq = ortp_ev_queue_new();
|
||||
|
|
@ -1758,8 +1856,9 @@ void linphone_call_init_audio_stream(LinphoneCall *call){
|
|||
void linphone_call_init_video_stream(LinphoneCall *call){
|
||||
#ifdef VIDEO_ENABLED
|
||||
LinphoneCore *lc=call->core;
|
||||
RtpTransport *meta_rtp=NULL;
|
||||
RtpTransport *meta_rtcp=NULL;
|
||||
char* cname;
|
||||
char rtcp_tool[128];
|
||||
snprintf(rtcp_tool,sizeof(rtcp_tool)-1,"%s-%s",linphone_core_get_user_agent_name(),linphone_core_get_user_agent_version());
|
||||
|
||||
if (call->videostream == NULL){
|
||||
int video_recv_buf_size=lp_config_get_int(lc->config,"video","recv_buf_size",0);
|
||||
|
|
@ -1768,10 +1867,36 @@ void linphone_call_init_video_stream(LinphoneCall *call){
|
|||
|
||||
if (call->sessions[1].rtp_session==NULL){
|
||||
call->videostream=video_stream_new(call->media_ports[1].rtp_port,call->media_ports[1].rtcp_port, call->af==AF_INET6);
|
||||
cname = linphone_address_as_string_uri_only(call->me);
|
||||
video_stream_set_rtcp_information(call->videostream, cname, rtcp_tool);
|
||||
ms_free(cname);
|
||||
rtp_session_set_symmetric_rtp(call->videostream->ms.sessions.rtp_session,linphone_core_symmetric_rtp_enabled(lc));
|
||||
|
||||
if (call->params->media_encryption==LinphoneMediaEncryptionDTLS) {
|
||||
MSDtlsSrtpParams params;
|
||||
char *certificate, *key;
|
||||
memset(¶ms,0,sizeof(MSDtlsSrtpParams));
|
||||
/* TODO : search for a certificate with CNAME=sip uri(retrieved from variable me) or default : linphone-dtls-default-identity */
|
||||
/* This will parse the directory to find a matching fingerprint or generate it if not found */
|
||||
/* returned string must be freed */
|
||||
sal_certificates_chain_parse_directory(&certificate, &key, &call->dtls_certificate_fingerprint, lc->user_certificates_path, "linphone-dtls-default-identity", SAL_CERTIFICATE_RAW_FORMAT_PEM, TRUE, TRUE);
|
||||
|
||||
if (key!= NULL && certificate!=NULL) {
|
||||
params.pem_certificate = (char *)certificate;
|
||||
params.pem_pkey = (char *)key;
|
||||
params.role = MSDtlsSrtpRoleUnset; /* default is unset, then check if we have a result SalMediaDescription */
|
||||
video_stream_enable_dtls(call->videostream,¶ms);
|
||||
ms_free(certificate);
|
||||
ms_free(key);
|
||||
} else {
|
||||
ms_error("Unable to retrieve or generate DTLS certificate and key - DTLS disabled");
|
||||
/* TODO : check if encryption forced, if yes, stop call */
|
||||
}
|
||||
}
|
||||
}else{
|
||||
call->videostream=video_stream_new_with_sessions(&call->sessions[1]);
|
||||
}
|
||||
|
||||
if (call->media_ports[1].rtp_port==-1){
|
||||
port_config_set_random_choosed(call,1,call->videostream->ms.sessions.rtp_session);
|
||||
}
|
||||
|
|
@ -1783,14 +1908,18 @@ void linphone_call_init_video_stream(LinphoneCall *call){
|
|||
if (display_filter != NULL)
|
||||
video_stream_set_display_filter_name(call->videostream,display_filter);
|
||||
video_stream_set_event_callback(call->videostream,video_stream_event_cb, call);
|
||||
rtp_session_get_transports(call->videostream->ms.sessions.rtp_session,&meta_rtp,&meta_rtcp);
|
||||
if (lc->rtptf && (meta_rtp==NULL && meta_rtcp==NULL)){
|
||||
RtpTransport *vrtp=lc->rtptf->video_rtp_func(lc->rtptf->video_rtp_func_data, call->media_ports[1].rtp_port);
|
||||
RtpTransport *vrtcp=lc->rtptf->video_rtcp_func(lc->rtptf->video_rtcp_func_data, call->media_ports[1].rtcp_port);
|
||||
|
||||
meta_rtp_transport_new(&meta_rtp,TRUE,vrtp, 0);
|
||||
meta_rtp_transport_new(&meta_rtcp,FALSE,vrtcp, 0);
|
||||
rtp_session_set_transports(call->videostream->ms.sessions.rtp_session,meta_rtp,meta_rtcp);
|
||||
|
||||
if (lc->rtptf){
|
||||
RtpTransport *meta_rtp;
|
||||
RtpTransport *meta_rtcp;
|
||||
|
||||
rtp_session_get_transports(call->videostream->ms.sessions.rtp_session,&meta_rtp,&meta_rtcp);
|
||||
if (meta_rtp_transport_get_endpoint(meta_rtp) == NULL) {
|
||||
meta_rtp_transport_set_endpoint(meta_rtp,lc->rtptf->video_rtp_func(lc->rtptf->video_rtp_func_data, call->media_ports[1].rtp_port));
|
||||
}
|
||||
if (meta_rtp_transport_get_endpoint(meta_rtcp) == NULL) {
|
||||
meta_rtp_transport_set_endpoint(meta_rtcp,lc->rtptf->video_rtcp_func(lc->rtptf->video_rtcp_func_data, call->media_ports[1].rtcp_port));
|
||||
}
|
||||
}
|
||||
call->videostream_app_evq = ortp_ev_queue_new();
|
||||
rtp_session_register_event_queue(call->videostream->ms.sessions.rtp_session,call->videostream_app_evq);
|
||||
|
|
@ -2084,7 +2213,7 @@ static void configure_rtp_session_for_rtcp_xr(LinphoneCore *lc, LinphoneCall *ca
|
|||
rtp_session_configure_rtcp_xr(session, ¤tconfig);
|
||||
}
|
||||
|
||||
static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cname, bool_t muted, bool_t send_ringbacktone, bool_t use_arc){
|
||||
static void linphone_call_start_audio_stream(LinphoneCall *call, bool_t muted, bool_t send_ringbacktone, bool_t use_arc){
|
||||
LinphoneCore *lc=call->core;
|
||||
LpConfig* conf;
|
||||
int used_pt=-1;
|
||||
|
|
@ -2102,7 +2231,9 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cna
|
|||
snprintf(rtcp_tool,sizeof(rtcp_tool)-1,"%s-%s",linphone_core_get_user_agent_name(),linphone_core_get_user_agent_version());
|
||||
|
||||
stream = sal_media_description_find_best_stream(call->resultdesc, SalAudio);
|
||||
ms_message("DTLS: call_start_audio_stream, stream is %s", stream==NULL?"NULL":"not NULL");
|
||||
if (stream && stream->dir!=SalStreamInactive && stream->rtp_port!=0){
|
||||
ms_message("DTLS: call_start_audio_stream : we have stream and all stuff to start it");
|
||||
playcard=lc->sound_conf.lsd_card ?
|
||||
lc->sound_conf.lsd_card : lc->sound_conf.play_sndcard;
|
||||
captcard=lc->sound_conf.capt_sndcard;
|
||||
|
|
@ -2111,6 +2242,7 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cna
|
|||
call->audio_profile=make_profile(call,call->resultdesc,stream,&used_pt);
|
||||
|
||||
if (used_pt!=-1){
|
||||
ms_message("DTLS: call_start_audio_stream : we made a profile and have used_pt != -1");
|
||||
call->current_params->audio_codec = rtp_profile_get_payload(call->audio_profile, used_pt);
|
||||
if (playcard==NULL) {
|
||||
ms_warning("No card defined for playback !");
|
||||
|
|
@ -2169,14 +2301,13 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cna
|
|||
crypto_idx = find_crypto_index_from_tag(local_st_desc->crypto, stream->crypto_local_tag);
|
||||
|
||||
if (crypto_idx >= 0) {
|
||||
media_stream_set_srtp_recv_key_b64(&call->audiostream->ms,stream->crypto[0].algo,stream->crypto[0].master_key);
|
||||
media_stream_set_srtp_send_key_b64(&call->audiostream->ms,stream->crypto[0].algo,local_st_desc->crypto[crypto_idx].master_key);
|
||||
media_stream_set_srtp_recv_key_b64(&(call->audiostream->ms.sessions),stream->crypto[0].algo,stream->crypto[0].master_key);
|
||||
media_stream_set_srtp_send_key_b64(&(call->audiostream->ms.sessions),stream->crypto[0].algo,local_st_desc->crypto[crypto_idx].master_key);
|
||||
} else {
|
||||
ms_warning("Failed to find local crypto algo with tag: %d", stream->crypto_local_tag);
|
||||
}
|
||||
}
|
||||
configure_rtp_session_for_rtcp_xr(lc, call, SalAudio);
|
||||
audio_stream_set_rtcp_information(call->audiostream, cname, rtcp_tool);
|
||||
audio_stream_start_full(
|
||||
call->audiostream,
|
||||
call->audio_profile,
|
||||
|
|
@ -2212,16 +2343,14 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cna
|
|||
}
|
||||
}
|
||||
|
||||
static void linphone_call_start_video_stream(LinphoneCall *call, const char *cname,bool_t all_inputs_muted){
|
||||
static void linphone_call_start_video_stream(LinphoneCall *call, bool_t all_inputs_muted){
|
||||
#ifdef VIDEO_ENABLED
|
||||
LinphoneCore *lc=call->core;
|
||||
int used_pt=-1;
|
||||
char rtcp_tool[128]={0};
|
||||
const SalStreamDescription *vstream;
|
||||
MSFilter* source = NULL;
|
||||
bool_t reused_preview = FALSE;
|
||||
|
||||
snprintf(rtcp_tool,sizeof(rtcp_tool)-1,"%s-%s",linphone_core_get_user_agent_name(),linphone_core_get_user_agent_version());
|
||||
|
||||
/* shutdown preview */
|
||||
if (lc->previewstream!=NULL) {
|
||||
|
|
@ -2291,8 +2420,8 @@ static void linphone_call_start_video_stream(LinphoneCall *call, const char *cna
|
|||
if (sal_stream_description_has_srtp(vstream) == TRUE) {
|
||||
int crypto_idx = find_crypto_index_from_tag(local_st_desc->crypto, vstream->crypto_local_tag);
|
||||
if (crypto_idx >= 0) {
|
||||
media_stream_set_srtp_recv_key_b64(&call->videostream->ms,vstream->crypto[0].algo,vstream->crypto[0].master_key);
|
||||
media_stream_set_srtp_send_key_b64(&call->videostream->ms,vstream->crypto[0].algo,local_st_desc->crypto[crypto_idx].master_key);
|
||||
media_stream_set_srtp_recv_key_b64(&(call->videostream->ms.sessions),vstream->crypto[0].algo,vstream->crypto[0].master_key);
|
||||
media_stream_set_srtp_send_key_b64(&(call->videostream->ms.sessions),vstream->crypto[0].algo,local_st_desc->crypto[crypto_idx].master_key);
|
||||
}
|
||||
}
|
||||
configure_rtp_session_for_rtcp_xr(lc, call, SalVideo);
|
||||
|
|
@ -2301,7 +2430,6 @@ static void linphone_call_start_video_stream(LinphoneCall *call, const char *cna
|
|||
video_stream_set_direction (call->videostream, dir);
|
||||
ms_message("%s lc rotation:%d\n", __FUNCTION__, lc->device_rotation);
|
||||
video_stream_set_device_rotation(call->videostream, lc->device_rotation);
|
||||
video_stream_set_rtcp_information(call->videostream, cname, rtcp_tool);
|
||||
video_stream_set_freeze_on_error(call->videostream, lp_config_get_int(lc->config, "video", "freeze_on_error", 0));
|
||||
if( lc->video_conf.reuse_preview_source && source ){
|
||||
ms_message("video_stream_start_with_source kept: %p", source);
|
||||
|
|
@ -2333,8 +2461,6 @@ static void linphone_call_start_video_stream(LinphoneCall *call, const char *cna
|
|||
|
||||
void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_muted, bool_t send_ringbacktone){
|
||||
LinphoneCore *lc=call->core;
|
||||
LinphoneAddress *me=linphone_core_get_primary_contact_parsed(lc);
|
||||
char *cname;
|
||||
bool_t use_arc=linphone_core_adaptive_rate_control_enabled(lc);
|
||||
#ifdef VIDEO_ENABLED
|
||||
const SalStreamDescription *vstream=sal_media_description_find_best_stream(call->resultdesc,SalVideo);
|
||||
|
|
@ -2347,8 +2473,6 @@ void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_mut
|
|||
ms_fatal("start_media_stream() called without prior init !");
|
||||
return;
|
||||
}
|
||||
cname=linphone_address_as_string_uri_only(me);
|
||||
|
||||
#if defined(VIDEO_ENABLED)
|
||||
if (vstream!=NULL && vstream->dir!=SalStreamInactive && vstream->payloads!=NULL){
|
||||
/*when video is used, do not make adaptive rate control on audio, it is stupid.*/
|
||||
|
|
@ -2359,12 +2483,14 @@ void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_mut
|
|||
call, linphone_core_get_upload_bandwidth(lc),linphone_core_get_download_bandwidth(lc));
|
||||
|
||||
if (call->audiostream!=NULL) {
|
||||
linphone_call_start_audio_stream(call,cname,all_inputs_muted||call->audio_muted,send_ringbacktone,use_arc);
|
||||
linphone_call_start_audio_stream(call,all_inputs_muted||call->audio_muted,send_ringbacktone,use_arc);
|
||||
} else {
|
||||
ms_warning("DTLS no audio stream!");
|
||||
}
|
||||
call->current_params->has_video=FALSE;
|
||||
if (call->videostream!=NULL) {
|
||||
if (call->audiostream) audio_stream_link_video(call->audiostream,call->videostream);
|
||||
linphone_call_start_video_stream(call,cname,all_inputs_muted);
|
||||
linphone_call_start_video_stream(call,all_inputs_muted);
|
||||
}
|
||||
|
||||
call->all_muted=all_inputs_muted;
|
||||
|
|
@ -2384,19 +2510,60 @@ void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_mut
|
|||
video_stream_enable_zrtp(call->videostream,call->audiostream,¶ms);
|
||||
}
|
||||
#endif
|
||||
}else{
|
||||
} else if (call->params->media_encryption==LinphoneMediaEncryptionDTLS) {
|
||||
/* DTLS engine was already initialised during stream init. Before starting it we must be sure that the role(client or server) is set.
|
||||
* Role may have already been set to server if we initiate the call and already received a packet from peer, in that case do nothing */
|
||||
SalDtlsRole salRole = call->resultdesc->streams[0].dtls_role; /* TODO: is streams[0] necessary the audiostream in the media description ? */
|
||||
if (salRole==SalDtlsRoleInvalid) { /* it's invalid in streams[0] but check also at session level */
|
||||
salRole = call->resultdesc->dtls_role;
|
||||
}
|
||||
|
||||
if (salRole!=SalDtlsRoleInvalid) { /* if DTLS is available at both end points */
|
||||
/* give the peer certificate fingerprint to dtls context */
|
||||
SalMediaDescription *remote_desc = sal_call_get_remote_media_description(call->op);
|
||||
ms_dtls_srtp_set_peer_fingerprint(call->audiostream->ms.sessions.dtls_context, remote_desc->streams[0].dtls_fingerprint);
|
||||
} else {
|
||||
ms_warning("unable to start DTLS engine on audiostream, Dtls role in resulting media description is invalid\n");
|
||||
}
|
||||
if (salRole == SalDtlsRoleIsClient) { /* local endpoint is client */
|
||||
ms_dtls_srtp_set_role(call->audiostream->ms.sessions.dtls_context, MSDtlsSrtpRoleIsClient); /* set the role to client */
|
||||
ms_dtls_srtp_start(call->audiostream->ms.sessions.dtls_context); /* then start the engine, it will send the DTLS client Hello */
|
||||
} else if (salRole == SalDtlsRoleIsServer) { /* local endpoint is server */
|
||||
ms_dtls_srtp_set_role(call->audiostream->ms.sessions.dtls_context, MSDtlsSrtpRoleIsServer); /* this may complete the server setup */
|
||||
/* no need to start engine, we are waiting for DTLS Client Hello */
|
||||
}
|
||||
#ifdef VIDEO_ENABLED
|
||||
salRole = call->resultdesc->streams[1].dtls_role; /* TODO: is streams[1] necessary the videostream in the media description ? */
|
||||
if (salRole==SalDtlsRoleInvalid) { /* it's invalid in streams[0] but check also at session level */
|
||||
salRole = call->resultdesc->dtls_role;
|
||||
}
|
||||
|
||||
if (salRole!=SalDtlsRoleInvalid) { /* if DTLS is available at both end points */
|
||||
/* give the peer certificate fingerprint to dtls context */
|
||||
SalMediaDescription *remote_desc = sal_call_get_remote_media_description(call->op);
|
||||
ms_dtls_srtp_set_peer_fingerprint(call->videostream->ms.sessions.dtls_context, remote_desc->streams[1].dtls_fingerprint);
|
||||
} else {
|
||||
ms_warning("unable to start DTLS engine on videostream, Dtls role in resulting media description is invalid\n");
|
||||
}
|
||||
if (salRole == SalDtlsRoleIsClient) { /* local endpoint is client */
|
||||
ms_dtls_srtp_set_role(call->videostream->ms.sessions.dtls_context, MSDtlsSrtpRoleIsClient); /* set the role to client */
|
||||
ms_dtls_srtp_start(call->videostream->ms.sessions.dtls_context); /* then start the engine, it will send the DTLS client Hello */
|
||||
} else if (salRole == SalDtlsRoleIsServer) { /* local endpoint is server */
|
||||
ms_dtls_srtp_set_role(call->videostream->ms.sessions.dtls_context, MSDtlsSrtpRoleIsServer); /* this may complete the server setup */
|
||||
/* no need to start engine, we are waiting for DTLS Client Hello */
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} else {
|
||||
call->current_params->media_encryption=linphone_call_all_streams_encrypted(call) ?
|
||||
LinphoneMediaEncryptionSRTP : LinphoneMediaEncryptionNone;
|
||||
LinphoneMediaEncryptionSRTP : LinphoneMediaEncryptionNone;
|
||||
}
|
||||
|
||||
if ((call->ice_session != NULL) && (ice_session_state(call->ice_session) != IS_Completed)) {
|
||||
ice_session_start_connectivity_checks(call->ice_session);
|
||||
}
|
||||
|
||||
goto end;
|
||||
end:
|
||||
ms_free(cname);
|
||||
linphone_address_destroy(me);
|
||||
}
|
||||
|
||||
void linphone_call_stop_media_streams_for_ice_gathering(LinphoneCall *call){
|
||||
|
|
@ -2412,9 +2579,9 @@ static bool_t update_stream_crypto_params(LinphoneCall *call, const SalStreamDes
|
|||
int crypto_idx = find_crypto_index_from_tag(local_st_desc->crypto, new_stream->crypto_local_tag);
|
||||
if (crypto_idx >= 0) {
|
||||
if (call->localdesc_changed & SAL_MEDIA_DESCRIPTION_CRYPTO_KEYS_CHANGED)
|
||||
media_stream_set_srtp_send_key_b64(ms,new_stream->crypto[0].algo,local_st_desc->crypto[crypto_idx].master_key);
|
||||
media_stream_set_srtp_send_key_b64(&(ms->sessions),new_stream->crypto[0].algo,local_st_desc->crypto[crypto_idx].master_key);
|
||||
if (strcmp(old_stream->crypto[0].master_key,new_stream->crypto[0].master_key)!=0){
|
||||
media_stream_set_srtp_recv_key_b64(ms,new_stream->crypto[0].algo,new_stream->crypto[0].master_key);
|
||||
media_stream_set_srtp_recv_key_b64(&(ms->sessions),new_stream->crypto[0].algo,new_stream->crypto[0].master_key);
|
||||
}
|
||||
return TRUE;
|
||||
} else {
|
||||
|
|
@ -2962,6 +3129,31 @@ static void linphone_core_disconnected(LinphoneCore *lc, LinphoneCall *call){
|
|||
linphone_core_play_named_tone(lc,LinphoneToneCallLost);
|
||||
}
|
||||
|
||||
static void change_ice_media_destinations(LinphoneCall *call) {
|
||||
const char *rtp_addr;
|
||||
const char *rtcp_addr;
|
||||
int rtp_port;
|
||||
int rtcp_port;
|
||||
bool_t result;
|
||||
|
||||
if (call->audiostream && ice_session_check_list(call->ice_session, 0)) {
|
||||
result = ice_check_list_selected_valid_remote_candidate(ice_session_check_list(call->ice_session, 0), &rtp_addr, &rtp_port, &rtcp_addr, &rtcp_port);
|
||||
if (result == TRUE) {
|
||||
ms_message("Change audio stream destination: RTP=%s:%d RTCP=%s:%d", rtp_addr, rtp_port, rtcp_addr, rtcp_port);
|
||||
rtp_session_set_remote_addr_full(call->audiostream->ms.sessions.rtp_session, rtp_addr, rtp_port, rtcp_addr, rtcp_port);
|
||||
}
|
||||
}
|
||||
#ifdef VIDEO_ENABLED
|
||||
if (call->videostream && ice_session_check_list(call->ice_session, 1)) {
|
||||
result = ice_check_list_selected_valid_remote_candidate(ice_session_check_list(call->ice_session, 1), &rtp_addr, &rtp_port, &rtcp_addr, &rtcp_port);
|
||||
if (result == TRUE) {
|
||||
ms_message("Change video stream destination: RTP=%s:%d RTCP=%s:%d", rtp_addr, rtp_port, rtcp_addr, rtcp_port);
|
||||
rtp_session_set_remote_addr_full(call->videostream->ms.sessions.rtp_session, rtp_addr, rtp_port, rtcp_addr, rtcp_port);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){
|
||||
OrtpEventType evt=ortp_event_get_type(ev);
|
||||
OrtpEventData *evd=ortp_event_get_data(ev);
|
||||
|
|
@ -2979,6 +3171,7 @@ static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){
|
|||
if (ice_session_role(call->ice_session) == IR_Controlling) {
|
||||
linphone_core_update_call(call->core, call, params);
|
||||
}
|
||||
change_ice_media_destinations(call);
|
||||
break;
|
||||
case IS_Failed:
|
||||
if (ice_session_has_completed_check_list(call->ice_session) == TRUE) {
|
||||
|
|
@ -3125,7 +3318,12 @@ void linphone_call_handle_stream_events(LinphoneCall *call, int stream_index){
|
|||
} else if (evt == ORTP_EVENT_ZRTP_SAS_READY) {
|
||||
if (ms->type==AudioStreamType)
|
||||
linphone_call_audiostream_auth_token_ready(call, evd->info.zrtp_sas.sas, evd->info.zrtp_sas.verified);
|
||||
} else if ((evt == ORTP_EVENT_ICE_SESSION_PROCESSING_FINISHED) || (evt == ORTP_EVENT_ICE_GATHERING_FINISHED)
|
||||
} else if (evt == ORTP_EVENT_DTLS_ENCRYPTION_CHANGED) {
|
||||
if (ms->type==AudioStreamType)
|
||||
linphone_call_audiostream_encryption_changed(call, evd->info.dtls_stream_encrypted);
|
||||
else if (ms->type==VideoStreamType)
|
||||
propagate_encryption_changed(call);
|
||||
}else if ((evt == ORTP_EVENT_ICE_SESSION_PROCESSING_FINISHED) || (evt == ORTP_EVENT_ICE_GATHERING_FINISHED)
|
||||
|| (evt == ORTP_EVENT_ICE_LOSING_PAIRS_COMPLETED) || (evt == ORTP_EVENT_ICE_RESTART_NEEDED)) {
|
||||
handle_ice_events(call, ev);
|
||||
} else if (evt==ORTP_EVENT_TELEPHONE_EVENT){
|
||||
|
|
@ -3259,7 +3457,7 @@ static LinphoneAddress *get_fixed_contact(LinphoneCore *lc, LinphoneCall *call ,
|
|||
const char *localip=call->localip;
|
||||
|
||||
/* first use user's supplied ip address if asked*/
|
||||
if (_linphone_core_get_firewall_policy(lc)==LinphonePolicyUseNatAddress){
|
||||
if (linphone_core_get_firewall_policy(lc)==LinphonePolicyUseNatAddress){
|
||||
ctt=linphone_core_get_primary_contact_parsed(lc);
|
||||
linphone_address_set_domain(ctt,linphone_core_get_nat_address_resolved(lc));
|
||||
ret=ctt;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
} else { /* get the fingerprint in session description */
|
||||
strcpy(result->streams[i].dtls_fingerprint, local_capabilities->dtls_fingerprint);
|
||||
}
|
||||
if (rs->dtls_role==SalDtlsRoleUnset) {
|
||||
result->streams[i].dtls_role = SalDtlsRoleIsClient;
|
||||
}
|
||||
} else {
|
||||
result->streams[i].dtls_fingerprint[0] = '\0';
|
||||
result->streams[i].dtls_role = SalDtlsRoleInvalid;
|
||||
}
|
||||
|
||||
// Handle media RTCP XR attribute
|
||||
memset(&result->streams[i].rtcp_xr, 0, sizeof(result->streams[i].rtcp_xr));
|
||||
if (rs->rtcp_xr.enabled == TRUE) {
|
||||
|
|
@ -477,6 +517,18 @@ int offer_answer_initiate_incoming(const SalMediaDescription *local_capabilities
|
|||
|
||||
strcpy(result->name,local_capabilities->name);
|
||||
|
||||
// Handle dtls session attribute: if both local and remote have a dtls fingerprint and a dtls setup, add the local fingerprint to the answer
|
||||
if ((local_capabilities->dtls_role!=SalDtlsRoleInvalid) && (remote_offer->dtls_role!=SalDtlsRoleInvalid)
|
||||
&&(strlen(local_capabilities->dtls_fingerprint)>0) && (strlen(remote_offer->dtls_fingerprint)>0)) {
|
||||
strcpy(result->dtls_fingerprint, local_capabilities->dtls_fingerprint);
|
||||
if (remote_offer->dtls_role==SalDtlsRoleUnset) {
|
||||
result->dtls_role = SalDtlsRoleIsClient;
|
||||
}
|
||||
} else {
|
||||
result->dtls_fingerprint[0] = '\0';
|
||||
result->dtls_role = SalDtlsRoleInvalid;
|
||||
}
|
||||
|
||||
// Handle session RTCP XR attribute
|
||||
memset(&result->rtcp_xr, 0, sizeof(result->rtcp_xr));
|
||||
if (remote_offer->rtcp_xr.enabled == TRUE) {
|
||||
|
|
|
|||
|
|
@ -213,6 +213,7 @@ struct _LinphoneCall{
|
|||
struct _RtpProfile *audio_profile;
|
||||
struct _RtpProfile *video_profile;
|
||||
struct _LinphoneCallLog *log;
|
||||
LinphoneAddress *me; /*Either from or to based on call dir*/
|
||||
SalOp *op;
|
||||
SalOp *ping_op;
|
||||
char localip[LINPHONE_IPADDR_SIZE]; /* our best guess for local ipaddress for this call */
|
||||
|
|
@ -253,6 +254,7 @@ struct _LinphoneCall{
|
|||
char *dtmf_sequence; /*DTMF sequence needed to be sent using #dtmfs_timer*/
|
||||
belle_sip_source_t *dtmfs_timer; /*DTMF timer needed to send a DTMF sequence*/
|
||||
|
||||
char *dtls_certificate_fingerprint; /**> This fingerprint is computed during stream init and is stored in call to be used when making local media description */
|
||||
bool_t refer_pending;
|
||||
bool_t expect_media_in_ack;
|
||||
bool_t audio_muted;
|
||||
|
|
@ -296,20 +298,6 @@ void linphone_core_update_proxy_register(LinphoneCore *lc);
|
|||
void linphone_core_refresh_subscribes(LinphoneCore *lc);
|
||||
int linphone_core_abort_call(LinphoneCore *lc, LinphoneCall *call, const char *error);
|
||||
const char *linphone_core_get_nat_address_resolved(LinphoneCore *lc);
|
||||
/**
|
||||
* @brief Equivalent to _linphone_core_get_firewall_policy_with_lie(lc, TRUE)
|
||||
* @param lc LinphoneCore instance
|
||||
* @return Fairewall policy
|
||||
*/
|
||||
LinphoneFirewallPolicy _linphone_core_get_firewall_policy(const LinphoneCore *lc);
|
||||
/**
|
||||
* @brief Get the firwall policy which has been set.
|
||||
* @param lc Instance of LinphoneCore
|
||||
* @param lie If true, the configured firewall policy will be returned only if no tunnel are enabled.
|
||||
* Otherwise, NoFirewallPolicy value will be returned.
|
||||
* @return The firewall policy
|
||||
*/
|
||||
LinphoneFirewallPolicy _linphone_core_get_firewall_policy_with_lie(const LinphoneCore *lc, bool_t lie);
|
||||
|
||||
int linphone_proxy_config_send_publish(LinphoneProxyConfig *cfg, LinphonePresenceModel *presence);
|
||||
void linphone_proxy_config_set_state(LinphoneProxyConfig *cfg, LinphoneRegistrationState rstate, const char *message);
|
||||
|
|
@ -757,6 +745,7 @@ struct _LinphoneCore
|
|||
MSList *hooks;
|
||||
LinphoneConference conf_ctx;
|
||||
char* zrtp_secrets_cache;
|
||||
char* user_certificates_path;
|
||||
LinphoneVideoPolicy video_policy;
|
||||
bool_t use_files;
|
||||
bool_t apply_nat_settings;
|
||||
|
|
|
|||
|
|
@ -121,7 +121,9 @@ SalStreamDescription * sal_media_description_find_secure_stream_of_type(SalMedia
|
|||
}
|
||||
|
||||
SalStreamDescription * sal_media_description_find_best_stream(SalMediaDescription *md, SalStreamType type) {
|
||||
SalStreamDescription *desc = sal_media_description_find_stream(md, SalProtoRtpSavpf, type);
|
||||
SalStreamDescription *desc = sal_media_description_find_stream(md, SalProtoUdpTlsRtpSavpf, type);
|
||||
if (desc == NULL) desc = sal_media_description_find_stream(md, SalProtoUdpTlsRtpSavp, type);
|
||||
if (desc == NULL) desc = sal_media_description_find_stream(md, SalProtoRtpSavpf, type);
|
||||
if (desc == NULL) desc = sal_media_description_find_stream(md, SalProtoRtpSavp, type);
|
||||
if (desc == NULL) desc = sal_media_description_find_stream(md, SalProtoRtpAvpf, type);
|
||||
if (desc == NULL) desc = sal_media_description_find_stream(md, SalProtoRtpAvp, type);
|
||||
|
|
@ -195,13 +197,17 @@ bool_t sal_stream_description_active(const SalStreamDescription *sd) {
|
|||
}
|
||||
|
||||
bool_t sal_stream_description_has_avpf(const SalStreamDescription *sd) {
|
||||
return ((sd->proto == SalProtoRtpAvpf) || (sd->proto == SalProtoRtpSavpf));
|
||||
return ((sd->proto == SalProtoRtpAvpf) || (sd->proto == SalProtoRtpSavpf) || (sd->proto == SalProtoUdpTlsRtpSavpf));
|
||||
}
|
||||
|
||||
bool_t sal_stream_description_has_srtp(const SalStreamDescription *sd) {
|
||||
return ((sd->proto == SalProtoRtpSavp) || (sd->proto == SalProtoRtpSavpf));
|
||||
}
|
||||
|
||||
bool_t sal_stream_description_has_dtls(const SalStreamDescription *sd) {
|
||||
return ((sd->proto == SalProtoUdpTlsRtpSavp) || (sd->proto == SalProtoUdpTlsRtpSavpf));
|
||||
}
|
||||
|
||||
bool_t sal_media_description_has_avpf(const SalMediaDescription *md) {
|
||||
int i;
|
||||
if (md->nb_streams == 0) return FALSE;
|
||||
|
|
@ -222,6 +228,16 @@ bool_t sal_media_description_has_srtp(const SalMediaDescription *md) {
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
bool_t sal_media_description_has_dtls(const SalMediaDescription *md) {
|
||||
int i;
|
||||
if (md->nb_streams == 0) return FALSE;
|
||||
for (i = 0; i < md->nb_streams; i++) {
|
||||
if (!sal_stream_description_active(&md->streams[i])) continue;
|
||||
if (sal_stream_description_has_dtls(&md->streams[i]) != TRUE) return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
static bool_t fmtp_equals(const char *p1, const char *p2){
|
||||
if (p1 && p2 && strcmp(p1,p2)==0) return TRUE;
|
||||
|
|
@ -608,8 +624,10 @@ const char* sal_media_proto_to_string(SalMediaProto type) {
|
|||
switch (type) {
|
||||
case SalProtoRtpAvp:return "RTP/AVP";
|
||||
case SalProtoRtpSavp:return "RTP/SAVP";
|
||||
case SalProtoUdpTlsRtpSavp:return "UDP/TLS/RTP/SAVP";
|
||||
case SalProtoRtpAvpf:return "RTP/AVPF";
|
||||
case SalProtoRtpSavpf:return "RTP/SAVPF";
|
||||
case SalProtoUdpTlsRtpSavpf:return "UDP/TLS/RTP/SAVPF";
|
||||
default: return "unknown";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -680,6 +680,12 @@ void linphone_gtk_in_call_view_show_encryption(LinphoneCall *call){
|
|||
gtk_widget_hide(status_icon);
|
||||
gtk_widget_hide(verify_button);
|
||||
break;
|
||||
case LinphoneMediaEncryptionDTLS:
|
||||
gtk_widget_show_all(encryption_box);
|
||||
gtk_label_set_markup(GTK_LABEL(label),_("Secured by DTLS"));
|
||||
gtk_widget_hide(status_icon);
|
||||
gtk_widget_hide(verify_button);
|
||||
break;
|
||||
case LinphoneMediaEncryptionZRTP:
|
||||
{
|
||||
gchar *text=g_strdup_printf(_("Secured by ZRTP - [auth token: %s]"),linphone_call_get_authentication_token(call));
|
||||
|
|
|
|||
|
|
@ -181,9 +181,11 @@ static GOptionEntry linphone_options[]={
|
|||
#ifndef WIN32
|
||||
#define CONFIG_FILE ".linphonerc"
|
||||
#define SECRETS_FILE ".linphone-zidcache"
|
||||
#define CERTIFICATES_PATH ".linphone-usr-crt"
|
||||
#else
|
||||
#define CONFIG_FILE "linphonerc"
|
||||
#define SECRETS_FILE "linphone-zidcache"
|
||||
#define CERTIFICATES_PATH "linphone-usr-crt"
|
||||
#endif
|
||||
|
||||
char *linphone_gtk_get_config_file(const char *filename){
|
||||
|
|
@ -288,6 +290,7 @@ static void linphone_gtk_init_liblinphone(const char *config_file,
|
|||
const char *factory_config_file, const char *db_file) {
|
||||
LinphoneCoreVTable vtable={0};
|
||||
gchar *secrets_file=linphone_gtk_get_config_file(SECRETS_FILE);
|
||||
gchar *user_certificates_dir=linphone_gtk_get_config_file(CERTIFICATES_PATH);
|
||||
|
||||
vtable.global_state_changed=linphone_gtk_global_state_changed;
|
||||
vtable.call_state_changed=linphone_gtk_call_state_changed;
|
||||
|
|
@ -325,6 +328,8 @@ static void linphone_gtk_init_liblinphone(const char *config_file,
|
|||
linphone_core_set_waiting_callback(the_core,linphone_gtk_wait,NULL);
|
||||
linphone_core_set_zrtp_secrets_file(the_core,secrets_file);
|
||||
g_free(secrets_file);
|
||||
linphone_core_set_user_certificates_path(the_core,user_certificates_dir);
|
||||
g_free(user_certificates_dir);
|
||||
linphone_core_enable_video_capture(the_core, TRUE);
|
||||
linphone_core_enable_video_display(the_core, TRUE);
|
||||
linphone_core_set_native_video_window_id(the_core,-1);/*don't create the window*/
|
||||
|
|
|
|||
|
|
@ -1199,11 +1199,13 @@ static void linphone_gtk_media_encryption_changed(GtkWidget *combo){
|
|||
if (strcasecmp(selected,"SRTP")==0){
|
||||
linphone_core_set_media_encryption(lc,LinphoneMediaEncryptionSRTP);
|
||||
linphone_gtk_set_media_encryption_mandatory_sensitive(toplevel,TRUE);
|
||||
}else if (strcasecmp(selected,"DTLS")==0){
|
||||
linphone_core_set_media_encryption(lc,LinphoneMediaEncryptionDTLS);
|
||||
linphone_gtk_set_media_encryption_mandatory_sensitive(toplevel,FALSE);
|
||||
}else if (strcasecmp(selected,"ZRTP")==0){
|
||||
linphone_core_set_media_encryption(lc,LinphoneMediaEncryptionZRTP);
|
||||
linphone_gtk_set_media_encryption_mandatory_sensitive(toplevel,FALSE);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
linphone_core_set_media_encryption(lc,LinphoneMediaEncryptionNone);
|
||||
linphone_gtk_set_media_encryption_mandatory_sensitive(toplevel,FALSE);
|
||||
}
|
||||
|
|
@ -1219,7 +1221,7 @@ static void linphone_gtk_show_media_encryption(GtkWidget *pb){
|
|||
LinphoneCore *lc=linphone_gtk_get_core();
|
||||
GtkWidget *combo=linphone_gtk_get_widget(pb,"media_encryption_combo");
|
||||
bool_t no_enc=TRUE;
|
||||
int srtp_id=-1,zrtp_id=-1;
|
||||
int srtp_id=-1,zrtp_id=-1,dtls_id=-1;
|
||||
GtkTreeModel *model;
|
||||
GtkListStore *store;
|
||||
GtkTreeIter iter;
|
||||
|
|
@ -1239,12 +1241,26 @@ static void linphone_gtk_show_media_encryption(GtkWidget *pb){
|
|||
srtp_id=1;
|
||||
no_enc=FALSE;
|
||||
}
|
||||
if (linphone_core_media_encryption_supported(lc,LinphoneMediaEncryptionDTLS)){
|
||||
gtk_list_store_append(store,&iter);
|
||||
gtk_list_store_set(store,&iter,0,_("DTLS"),-1);
|
||||
if (srtp_id!=-1) dtls_id=2;
|
||||
else dtls_id=1;
|
||||
no_enc=FALSE;
|
||||
}
|
||||
if (linphone_core_media_encryption_supported(lc,LinphoneMediaEncryptionZRTP)){
|
||||
gtk_list_store_append(store,&iter);
|
||||
gtk_list_store_set(store,&iter,0,_("ZRTP"),-1);
|
||||
no_enc=FALSE;
|
||||
if (srtp_id!=-1) zrtp_id=2;
|
||||
else zrtp_id=1;
|
||||
if (srtp_id!=-1) {
|
||||
if (dtls_id!=-1)
|
||||
zrtp_id=3;
|
||||
else zrtp_id=2;
|
||||
} else {
|
||||
if (dtls_id!=-1)
|
||||
zrtp_id=2;
|
||||
else zrtp_id=1;
|
||||
}
|
||||
}
|
||||
if (no_enc){
|
||||
/*hide this setting*/
|
||||
|
|
@ -1264,6 +1280,12 @@ static void linphone_gtk_show_media_encryption(GtkWidget *pb){
|
|||
linphone_gtk_set_media_encryption_mandatory_sensitive(pb,TRUE);
|
||||
}
|
||||
break;
|
||||
case LinphoneMediaEncryptionDTLS:
|
||||
if (dtls_id!=-1) {
|
||||
gtk_combo_box_set_active(GTK_COMBO_BOX(combo),dtls_id);
|
||||
linphone_gtk_set_media_encryption_mandatory_sensitive(pb,TRUE);
|
||||
}
|
||||
break;
|
||||
case LinphoneMediaEncryptionZRTP:
|
||||
if (zrtp_id!=-1) {
|
||||
gtk_combo_box_set_active(GTK_COMBO_BOX(combo),zrtp_id);
|
||||
|
|
|
|||
|
|
@ -133,6 +133,8 @@ typedef enum{
|
|||
SalProtoRtpSavp,
|
||||
SalProtoRtpAvpf,
|
||||
SalProtoRtpSavpf,
|
||||
SalProtoUdpTlsRtpSavp,
|
||||
SalProtoUdpTlsRtpSavpf,
|
||||
SalProtoOther
|
||||
}SalMediaProto;
|
||||
const char* sal_media_proto_to_string(SalMediaProto type);
|
||||
|
|
@ -163,7 +165,7 @@ typedef struct SalIceCandidate {
|
|||
int rport;
|
||||
} SalIceCandidate;
|
||||
|
||||
#define SAL_MEDIA_DESCRIPTION_MAX_ICE_CANDIDATES 10
|
||||
#define SAL_MEDIA_DESCRIPTION_MAX_ICE_CANDIDATES 20
|
||||
|
||||
typedef struct SalIceRemoteCandidate {
|
||||
char addr[SAL_MEDIA_DESCRIPTION_MAX_ICE_ADDR_LEN];
|
||||
|
|
@ -186,6 +188,13 @@ typedef struct SalSrtpCryptoAlgo {
|
|||
|
||||
#define SAL_CRYPTO_ALGO_MAX 4
|
||||
|
||||
typedef enum {
|
||||
SalDtlsRoleInvalid,
|
||||
SalDtlsRoleIsServer,
|
||||
SalDtlsRoleIsClient,
|
||||
SalDtlsRoleUnset
|
||||
} SalDtlsRole;
|
||||
|
||||
typedef struct SalStreamDescription{
|
||||
char name[16]; /*unique name of stream, in order to ease offer/answer model algorithm*/
|
||||
SalMediaProto proto;
|
||||
|
|
@ -194,6 +203,8 @@ typedef struct SalStreamDescription{
|
|||
char proto_other[32];
|
||||
char rtp_addr[64];
|
||||
char rtcp_addr[64];
|
||||
unsigned int rtp_ssrc;
|
||||
char rtcp_cname[255];
|
||||
int rtp_port;
|
||||
int rtcp_port;
|
||||
MSList *payloads; /*<list of PayloadType */
|
||||
|
|
@ -212,6 +223,8 @@ typedef struct SalStreamDescription{
|
|||
bool_t ice_mismatch;
|
||||
bool_t ice_completed;
|
||||
bool_t pad[2];
|
||||
char dtls_fingerprint[256];
|
||||
SalDtlsRole dtls_role;
|
||||
} SalStreamDescription;
|
||||
|
||||
const char *sal_stream_description_get_type_as_string(const SalStreamDescription *desc);
|
||||
|
|
@ -236,6 +249,8 @@ typedef struct SalMediaDescription{
|
|||
bool_t ice_lite;
|
||||
bool_t ice_completed;
|
||||
bool_t pad[2];
|
||||
char dtls_fingerprint[256];
|
||||
SalDtlsRole dtls_role;
|
||||
} SalMediaDescription;
|
||||
|
||||
typedef struct SalMessage{
|
||||
|
|
@ -270,8 +285,10 @@ void sal_media_description_set_dir(SalMediaDescription *md, SalStreamDir stream_
|
|||
bool_t sal_stream_description_active(const SalStreamDescription *sd);
|
||||
bool_t sal_stream_description_has_avpf(const SalStreamDescription *sd);
|
||||
bool_t sal_stream_description_has_srtp(const SalStreamDescription *sd);
|
||||
bool_t sal_stream_description_has_dtls(const SalStreamDescription *sd);
|
||||
bool_t sal_media_description_has_avpf(const SalMediaDescription *md);
|
||||
bool_t sal_media_description_has_srtp(const SalMediaDescription *md);
|
||||
bool_t sal_media_description_has_dtls(const SalMediaDescription *md);
|
||||
int sal_media_description_get_nb_active_streams(const SalMediaDescription *md);
|
||||
|
||||
|
||||
|
|
@ -515,6 +532,18 @@ void sal_certificates_chain_parse_file(SalAuthInfo* auth_info, const char* path,
|
|||
*/
|
||||
void sal_signing_key_parse_file(SalAuthInfo* auth_info, const char* path, const char *passwd);
|
||||
|
||||
/**
|
||||
* Parse a directory for files containing certificate with the given subject CNAME
|
||||
* @param[out] certificate_pem the address of a string to store the certificate in PEM format. To be freed by caller
|
||||
* @param[out] key_pem the address of a string to store the key in PEM format. To be freed by caller
|
||||
* @param[in] path directory to parse
|
||||
* @param[in] subject subject CNAME
|
||||
* @param[in] format either PEM or DER
|
||||
* @param[in] generate_certificate if true, if matching certificate and key can't be found, generate it and store it into the given dir, filename will be subject.pem
|
||||
* @param[in] generate_dtls_fingerprint if true and we have a certificate, generate the dtls fingerprint as described in rfc4572
|
||||
*/
|
||||
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);
|
||||
|
||||
void sal_certificates_chain_delete(SalCertificatesChain *chain);
|
||||
void sal_signing_key_delete(SalSigningKey *key);
|
||||
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 06c11ea38a8a3a90f0ce8e3d726b5b2fee60f270
|
||||
Subproject commit cf926c3127bec00dde2bcabef9c1591cd39a6c8f
|
||||
2
oRTP
2
oRTP
|
|
@ -1 +1 @@
|
|||
Subproject commit e5470e271d5be74f425db9221cd35a60ce4cf52e
|
||||
Subproject commit 4ef1702f7f8f21d65e6e9da68d4f8f2c2376f614
|
||||
|
|
@ -33,7 +33,6 @@
|
|||
#endif
|
||||
|
||||
static void srtp_call(void);
|
||||
static void call_base(LinphoneMediaEncryption mode, bool_t enable_video,bool_t enable_relay,LinphoneFirewallPolicy policy);
|
||||
static char *create_filepath(const char *dir, const char *filename, const char *ext);
|
||||
|
||||
// prototype definition for call_recording()
|
||||
|
|
@ -105,6 +104,7 @@ void linphone_call_encryption_changed(LinphoneCore *lc, LinphoneCall *call, bool
|
|||
else
|
||||
counters->number_of_LinphoneCallEncryptedOff++;
|
||||
}
|
||||
|
||||
void linphone_transfer_state_changed(LinphoneCore *lc, LinphoneCall *transfered, LinphoneCallState new_call_state) {
|
||||
char* to=linphone_address_as_string(linphone_call_get_call_log(transfered)->to);
|
||||
char* from=linphone_address_as_string(linphone_call_get_call_log(transfered)->from);
|
||||
|
|
@ -266,10 +266,10 @@ bool_t call_with_params2(LinphoneCoreManager* caller_mgr
|
|||
|
||||
if (linphone_core_get_media_encryption(caller_mgr->lc) != LinphoneMediaEncryptionNone
|
||||
&& linphone_core_get_media_encryption(callee_mgr->lc) != LinphoneMediaEncryptionNone) {
|
||||
/*wait for encryption to be on, in case of zrtp, it can take a few seconds*/
|
||||
if (linphone_core_get_media_encryption(caller_mgr->lc) == LinphoneMediaEncryptionZRTP)
|
||||
/*wait for encryption to be on, in case of zrtp or dtls, it can take a few seconds*/
|
||||
if ((linphone_core_get_media_encryption(caller_mgr->lc) == LinphoneMediaEncryptionZRTP) || (linphone_core_get_media_encryption(caller_mgr->lc) == LinphoneMediaEncryptionDTLS))
|
||||
wait_for(callee_mgr->lc,caller_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallEncryptedOn,initial_caller.number_of_LinphoneCallEncryptedOn+1);
|
||||
if (linphone_core_get_media_encryption(callee_mgr->lc) == LinphoneMediaEncryptionZRTP)
|
||||
if ((linphone_core_get_media_encryption(callee_mgr->lc) == LinphoneMediaEncryptionZRTP) || (linphone_core_get_media_encryption(callee_mgr->lc) == LinphoneMediaEncryptionDTLS))
|
||||
wait_for(callee_mgr->lc,caller_mgr->lc,&callee_mgr->stat.number_of_LinphoneCallEncryptedOn,initial_callee.number_of_LinphoneCallEncryptedOn+1);
|
||||
{
|
||||
const LinphoneCallParams* call_param = linphone_call_get_current_params(linphone_core_get_current_call(callee_mgr->lc));
|
||||
|
|
@ -2045,14 +2045,18 @@ static void simple_conference_with_ice(void) {
|
|||
}
|
||||
|
||||
static void srtp_call() {
|
||||
call_base(LinphoneMediaEncryptionSRTP,FALSE,FALSE,LinphonePolicyNoFirewall);
|
||||
call_base(LinphoneMediaEncryptionSRTP,FALSE,FALSE,LinphonePolicyNoFirewall,FALSE);
|
||||
}
|
||||
|
||||
static void zrtp_call() {
|
||||
call_base(LinphoneMediaEncryptionZRTP,FALSE,FALSE,LinphonePolicyNoFirewall);
|
||||
call_base(LinphoneMediaEncryptionZRTP,FALSE,FALSE,LinphonePolicyNoFirewall,FALSE);
|
||||
}
|
||||
static void zrtp_video_call() {
|
||||
call_base(LinphoneMediaEncryptionZRTP,TRUE,FALSE,LinphonePolicyNoFirewall);
|
||||
call_base(LinphoneMediaEncryptionZRTP,TRUE,FALSE,LinphonePolicyNoFirewall,FALSE);
|
||||
}
|
||||
|
||||
static void dtls_srtp_call() {
|
||||
call_base(LinphoneMediaEncryptionDTLS,FALSE,FALSE,LinphonePolicyNoFirewall,FALSE);
|
||||
}
|
||||
|
||||
static void call_with_declined_srtp(void) {
|
||||
|
|
@ -2209,17 +2213,38 @@ end:
|
|||
|
||||
}
|
||||
|
||||
|
||||
static void call_base(LinphoneMediaEncryption mode, bool_t enable_video,bool_t enable_relay,LinphoneFirewallPolicy policy) {
|
||||
void call_base(LinphoneMediaEncryption mode, bool_t enable_video,bool_t enable_relay,LinphoneFirewallPolicy policy,bool_t enable_tunnel) {
|
||||
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
|
||||
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
|
||||
if (enable_relay) {
|
||||
linphone_core_set_user_agent(marie->lc,"Natted Linphone",NULL);
|
||||
linphone_core_set_user_agent(pauline->lc,"Natted Linphone",NULL);
|
||||
}
|
||||
if (enable_tunnel) {
|
||||
int i;
|
||||
LinphoneTunnelConfig * tunnel_config = linphone_tunnel_config_new();
|
||||
linphone_tunnel_config_set_host(tunnel_config,"tunnel.linphone.org");
|
||||
linphone_tunnel_config_set_port(tunnel_config,443);
|
||||
linphone_tunnel_add_server(linphone_core_get_tunnel(marie->lc),tunnel_config);
|
||||
linphone_tunnel_enable_sip(linphone_core_get_tunnel(marie->lc),FALSE);
|
||||
linphone_tunnel_set_mode(linphone_core_get_tunnel(marie->lc),LinphoneTunnelModeEnable);
|
||||
for (i=0;i<10;i++) {
|
||||
if (linphone_tunnel_connected(linphone_core_get_tunnel(marie->lc))) {
|
||||
break;
|
||||
}
|
||||
linphone_core_iterate(marie->lc);
|
||||
ms_usleep(200000);
|
||||
}
|
||||
CU_ASSERT_TRUE(linphone_tunnel_connected(linphone_core_get_tunnel(marie->lc)));
|
||||
|
||||
}
|
||||
if (linphone_core_media_encryption_supported(marie->lc,mode)) {
|
||||
linphone_core_set_media_encryption(marie->lc,mode);
|
||||
linphone_core_set_media_encryption(pauline->lc,mode);
|
||||
if (mode==LinphoneMediaEncryptionDTLS) { /* for DTLS we must access certificates or at least have a directory to store them */
|
||||
marie->lc->user_certificates_path = ms_strdup_printf("%s/certificates/marie", liblinphone_tester_file_prefix);
|
||||
pauline->lc->user_certificates_path = ms_strdup_printf("%s/certificates/pauline", liblinphone_tester_file_prefix);
|
||||
}
|
||||
|
||||
linphone_core_set_firewall_policy(marie->lc,policy);
|
||||
linphone_core_set_stun_server(marie->lc,"stun.linphone.org");
|
||||
|
|
@ -2250,7 +2275,7 @@ static void call_base(LinphoneMediaEncryption mode, bool_t enable_video,bool_t e
|
|||
}
|
||||
|
||||
if (policy == LinphonePolicyUseIce)
|
||||
CU_ASSERT_TRUE(check_ice(pauline,marie,LinphoneIceStateHostConnection));
|
||||
CU_ASSERT_TRUE(check_ice(pauline,marie,enable_tunnel?LinphoneIceStateReflexiveConnection:LinphoneIceStateHostConnection));
|
||||
#ifdef VIDEO_ENABLED
|
||||
if (enable_video) {
|
||||
int i=0;
|
||||
|
|
@ -2263,7 +2288,7 @@ static void call_base(LinphoneMediaEncryption mode, bool_t enable_video,bool_t e
|
|||
|
||||
add_video(pauline,marie);
|
||||
if (policy == LinphonePolicyUseIce)
|
||||
CU_ASSERT_TRUE(check_ice(pauline,marie,LinphoneIceStateHostConnection));
|
||||
CU_ASSERT_TRUE(check_ice(pauline,marie,enable_tunnel?LinphoneIceStateReflexiveConnection:LinphoneIceStateHostConnection));
|
||||
|
||||
liblinphone_tester_check_rtcp(marie,pauline);
|
||||
/*wait for ice to found the direct path*/
|
||||
|
|
@ -2286,25 +2311,24 @@ static void call_base(LinphoneMediaEncryption mode, bool_t enable_video,bool_t e
|
|||
linphone_core_manager_destroy(marie);
|
||||
linphone_core_manager_destroy(pauline);
|
||||
}
|
||||
|
||||
#ifdef VIDEO_ENABLED
|
||||
static void srtp_video_ice_call(void) {
|
||||
call_base(LinphoneMediaEncryptionSRTP,TRUE,FALSE,LinphonePolicyUseIce);
|
||||
call_base(LinphoneMediaEncryptionSRTP,TRUE,FALSE,LinphonePolicyUseIce,FALSE);
|
||||
}
|
||||
static void zrtp_video_ice_call(void) {
|
||||
call_base(LinphoneMediaEncryptionZRTP,TRUE,FALSE,LinphonePolicyUseIce);
|
||||
call_base(LinphoneMediaEncryptionZRTP,TRUE,FALSE,LinphonePolicyUseIce,FALSE);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void srtp_ice_call(void) {
|
||||
call_base(LinphoneMediaEncryptionSRTP,FALSE,FALSE,LinphonePolicyUseIce);
|
||||
call_base(LinphoneMediaEncryptionSRTP,FALSE,FALSE,LinphonePolicyUseIce,FALSE);
|
||||
}
|
||||
|
||||
static void zrtp_ice_call(void) {
|
||||
call_base(LinphoneMediaEncryptionZRTP,FALSE,FALSE,LinphonePolicyUseIce);
|
||||
call_base(LinphoneMediaEncryptionZRTP,FALSE,FALSE,LinphonePolicyUseIce,FALSE);
|
||||
}
|
||||
static void zrtp_ice_call_with_relay(void) {
|
||||
call_base(LinphoneMediaEncryptionZRTP,FALSE,TRUE,LinphonePolicyUseIce);
|
||||
call_base(LinphoneMediaEncryptionZRTP,FALSE,TRUE,LinphonePolicyUseIce,FALSE);
|
||||
}
|
||||
|
||||
static void early_media_call(void) {
|
||||
|
|
@ -3471,6 +3495,7 @@ test_t call_tests[] = {
|
|||
{ "Call paused resumed from callee", call_paused_resumed_from_callee },
|
||||
{ "SRTP call", srtp_call },
|
||||
{ "ZRTP call",zrtp_call},
|
||||
{ "DTLS SRTP call",dtls_srtp_call},
|
||||
{ "ZRTP video call",zrtp_video_call},
|
||||
{ "SRTP call with declined srtp", call_with_declined_srtp },
|
||||
{ "Call with file player", call_with_file_player},
|
||||
|
|
|
|||
|
|
@ -312,5 +312,6 @@ void cunit_android_trace_handler(int level, const char *fmt, va_list args) ;
|
|||
#endif
|
||||
int liblinphone_tester_fprintf(FILE * stream, const char * format, ...);
|
||||
|
||||
void call_base(LinphoneMediaEncryption mode, bool_t enable_video,bool_t enable_relay,LinphoneFirewallPolicy policy,bool_t enable_tunnel);
|
||||
#endif /* LIBLINPHONE_TESTER_H_ */
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
#include "linphonecore.h"
|
||||
#include "private.h"
|
||||
#include "liblinphone_tester.h"
|
||||
#include "ortp/stun.h"
|
||||
#include "mediastreamer2/stun.h"
|
||||
#include "ortp/port.h"
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -59,6 +59,8 @@ static char* get_public_contact_ip(LinphoneCore* lc) {
|
|||
ms_free(contact);
|
||||
return ms_strdup(contact_host_ip);
|
||||
}
|
||||
|
||||
|
||||
static void call_with_transport_base(LinphoneTunnelMode tunnel_mode, bool_t with_sip, LinphoneMediaEncryption encryption) {
|
||||
if (linphone_core_tunnel_available()){
|
||||
LinphoneCoreManager *pauline = linphone_core_manager_new( "pauline_rc");
|
||||
|
|
@ -131,6 +133,7 @@ static void call_with_transport_base(LinphoneTunnelMode tunnel_mode, bool_t with
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
static void call_with_tunnel(void) {
|
||||
call_with_transport_base(LinphoneTunnelModeEnable, TRUE, LinphoneMediaEncryptionNone);
|
||||
}
|
||||
|
|
@ -151,12 +154,43 @@ static void call_with_tunnel_auto_without_sip_with_srtp(void) {
|
|||
call_with_transport_base(LinphoneTunnelModeAuto, FALSE, LinphoneMediaEncryptionSRTP);
|
||||
}
|
||||
|
||||
#ifdef VIDEO_ENABLED
|
||||
static void tunnel_srtp_video_ice_call(void) {
|
||||
call_base(LinphoneMediaEncryptionSRTP,TRUE,FALSE,LinphonePolicyUseIce,TRUE);
|
||||
}
|
||||
static void tunnel_zrtp_video_ice_call(void) {
|
||||
call_base(LinphoneMediaEncryptionZRTP,TRUE,FALSE,LinphonePolicyUseIce,TRUE);
|
||||
}
|
||||
static void tunnel_video_ice_call(void) {
|
||||
call_base(LinphoneMediaEncryptionNone,TRUE,FALSE,LinphonePolicyUseIce,TRUE);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void tunnel_srtp_ice_call(void) {
|
||||
call_base(LinphoneMediaEncryptionSRTP,FALSE,FALSE,LinphonePolicyUseIce,TRUE);
|
||||
}
|
||||
|
||||
static void tunnel_zrtp_ice_call(void) {
|
||||
call_base(LinphoneMediaEncryptionZRTP,FALSE,FALSE,LinphonePolicyUseIce,TRUE);
|
||||
}
|
||||
|
||||
static void tunnel_ice_call(void) {
|
||||
call_base(LinphoneMediaEncryptionNone,FALSE,FALSE,LinphonePolicyUseIce,TRUE);
|
||||
}
|
||||
test_t transport_tests[] = {
|
||||
{ "Tunnel only", call_with_tunnel },
|
||||
{ "Tunnel with SRTP", call_with_tunnel_srtp },
|
||||
{ "Tunnel without SIP", call_with_tunnel_without_sip },
|
||||
{ "Tunnel in automatic mode", call_with_tunnel_auto },
|
||||
{ "Tunnel in automatic mode with SRTP without SIP", call_with_tunnel_auto_without_sip_with_srtp },
|
||||
{ "Tunnel ice call", tunnel_ice_call },
|
||||
{ "Tunnel SRTP ice call", tunnel_srtp_ice_call },
|
||||
{ "Tunnel ZRTP ice call", tunnel_zrtp_ice_call },
|
||||
#ifdef VIDEO_ENABLED
|
||||
{ "Tunnel ice video call", tunnel_video_ice_call },
|
||||
{ "Tunnel SRTP ice video call", tunnel_srtp_video_ice_call },
|
||||
{ "Tunnel ZRTP ice video call", tunnel_zrtp_video_ice_call },
|
||||
#endif
|
||||
};
|
||||
|
||||
test_suite_t transport_test_suite = {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue