Commit 41b76330 authored by jehan's avatar jehan

Merge branch 'master' of git.linphone.org:linphone

Conflicts:
	tester/liblinphone_tester.c
parents 19acd4a5 7ee0e189
......@@ -22,7 +22,7 @@
<folderInfo id="0.2079208171." name="/" resourcePath="">
<toolChain id="org.eclipse.cdt.build.core.prefbase.toolchain.2084203071" name="No ToolChain" resourceTypeBasedDiscovery="false" superClass="org.eclipse.cdt.build.core.prefbase.toolchain">
<targetPlatform binaryParser="org.eclipse.cdt.core.MachO64;org.eclipse.cdt.core.ELF" id="org.eclipse.cdt.build.core.prefbase.toolchain.2084203071.81924294" name=""/>
<builder arguments="-j4 CFLAGS=&quot;-g -Werror -Wall&quot; CXXFLAGS=&quot;-g&quot;" command="make" id="org.eclipse.cdt.build.core.settings.default.builder.731584538" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="org.eclipse.cdt.build.core.settings.default.builder"/>
<builder arguments="-j4 CFLAGS=&quot;-g -Wall&quot; CXXFLAGS=&quot;-g&quot;" command="make" id="org.eclipse.cdt.build.core.settings.default.builder.731584538" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="org.eclipse.cdt.build.core.settings.default.builder"/>
<tool id="org.eclipse.cdt.build.core.settings.holder.libs.1252970003" name="holder for library settings" superClass="org.eclipse.cdt.build.core.settings.holder.libs"/>
<tool id="org.eclipse.cdt.build.core.settings.holder.1371414073" name="GNU C++" superClass="org.eclipse.cdt.build.core.settings.holder">
<inputType id="org.eclipse.cdt.build.core.settings.holder.inType.306286573" languageId="org.eclipse.cdt.core.g++" languageName="GNU C++" sourceContentType="org.eclipse.cdt.core.cxxSource,org.eclipse.cdt.core.cxxHeader" superClass="org.eclipse.cdt.build.core.settings.holder.inType"/>
......
......@@ -53,3 +53,19 @@ coreapi/test_ecc
coreapi/test_lsd
gtk/version_date.h
specs.c
*.orig
*.rej
*.kdev4
*.lo
*.la
*.swp
.deps
.libs
coreapi/test_numbers
coreapi/help/notify
share/fresh-rootca.pem
share/certdata.txt
tester/liblinphone_tester
tools/lp-gen-wrappers
tools/lpc2xml_test
tools/xml2lpc_test
......@@ -10,6 +10,7 @@ This is Linphone, a free (GPL) video softphone based on the SIP protocol.
- you need at least:
- belle-sip>=1.0.0
- speex>=1.2.0 (including libspeexdsp part)
- libxml2
+ if you want the gtk/glade interface:
- libgtk >=2.16.0
......@@ -32,7 +33,7 @@ This is Linphone, a free (GPL) video softphone based on the SIP protocol.
Here is the command line to get these dependencies installed for Ubuntu && Debian
$ sudo apt-get install libtool intltool libgtk2.0-dev libosip2-dev libexosip2-dev libspeexdsp-dev libavcodec-dev libswscale-dev libx11-dev libvx-dev libgl1-mesa-dev libglew1.6-dev libv4l-dev
$ sudo apt-get install libtool intltool libgtk2.0-dev libosip2-dev libexosip2-dev libspeexdsp-dev libavcodec-dev libswscale-dev libx11-dev libxv-dev libgl1-mesa-dev libglew1.6-dev libv4l-dev libxml2-dev
+ for optional library
$ sudo apt-get install libreadline-dev libgsm1-dev libtheora-dev libsoup2.4-dev libsqlite3-dev libupnp4-dev
......
......@@ -7,9 +7,11 @@ You need:
- Macports: http://www.macports.org/
Download and install macports using its user friendly installer.
- In order to enable generation of bundle for multiple macos version it is recommended to edit /opt/local/etc/macports/macports.conf to add the
following line:
macosx_deployment_target 10.6
- In order to enable generation of bundle for multiple macos version and 32 bit processors, it is recommended to:
1) edit /opt/local/etc/macports/macports.conf to add the following line:
macosx_deployment_target 10.6
2) edit /opt/local/etc/macports/variants.conf to add the following line:
+universal
- Install build time dependencies
$ sudo port install automake autoconf libtool intltool
......@@ -34,7 +36,16 @@ You need:
The softwares below need to be compiled manually. To ensure compatibility with multiple mac os version it is recommended to do:
$ export MACOSX_DEPLOYMENT_TARGET=10.6
$ export CFLAGS="-arch i386 -arch x86_64 -mmacosx-version-min=10.5"
$ export OBJCFLAGS="-arch i386 -arch x86_64 -mmacosx-version-min=10.5"
$ export CXXFLAGS="-arch i386 -arch x86_64 -mmacosx-version-min=10.5"
$ export LDFLAGS="-arch i386 -arch x86_64 -mmacosx-version-min=10.5"
- Install polarssl (encryption library used by belle-sip)
$ git clone git://git.linphone.org/polarssl.git -b linphone
$ cd polarssl
$ ./autogen.sh && ./configure --prefix=/opt/local && make
$ sudo make install
- Install belle-sip (sip stack)
$ git clone git://git.linphone.org/belle-sip.git
......
......@@ -85,6 +85,10 @@ LOCAL_CFLAGS += -DHAVE_X264
endif
endif
ifeq ($(BUILD_CONTACT_HEADER),1)
LOCAL_CFLAGS += -DSAL_OP_CALL_FORCE_CONTACT_IN_RINGING
endif
ifeq ($(USE_JAVAH),1)
LOCAL_CFLAGS += -DUSE_JAVAH
endif
......
......@@ -112,11 +112,21 @@ void linphone_address_set_domain(LinphoneAddress *uri, const char *host){
* Sets the port number.
**/
void linphone_address_set_port(LinphoneAddress *uri, int port){
#ifdef USE_BELLESIP
sal_address_set_port(uri,port);
#else
sal_address_set_port_int(uri,port);
#endif
}
/**
* Set a transport.
**/
void linphone_address_set_transport(LinphoneAddress *uri, LinphoneTransportType tp){
sal_address_set_transport(uri,(SalTransport)tp);
}
/**
* Get the transport.
**/
LinphoneTransportType linphone_address_get_transport(const LinphoneAddress *uri){
return (LinphoneTransportType)sal_address_get_transport(uri);
}
/**
......@@ -142,6 +152,13 @@ char *linphone_address_as_string_uri_only(const LinphoneAddress *u){
return sal_address_as_string_uri_only(u);
}
/**
* Returns true if address refers to a secure location (sips)
**/
bool_t linphone_address_is_secure(const LinphoneAddress *uri){
return sal_address_is_secure(uri);
}
static bool_t strings_equals(const char *s1, const char *s2){
if (s1==NULL && s2==NULL) return TRUE;
if (s1!=NULL && s2!=NULL && strcmp(s1,s2)==0) return TRUE;
......
......@@ -43,6 +43,14 @@ const char *sal_address_get_scheme(const SalAddress *addr){
} else
return NULL;
}
bool_t sal_address_is_secure(const SalAddress *addr){
belle_sip_header_address_t* header_addr = BELLE_SIP_HEADER_ADDRESS(addr);
belle_sip_uri_t* uri = belle_sip_header_address_get_uri(header_addr);
if (uri) return belle_sip_uri_is_secure(uri);
return FALSE;
}
const char *sal_address_get_display_name(const SalAddress* addr){
belle_sip_header_address_t* header_addr = BELLE_SIP_HEADER_ADDRESS(addr);
return belle_sip_header_address_get_displayname(header_addr);
......@@ -52,17 +60,17 @@ const char *sal_address_get_display_name_unquoted(const SalAddress *addr){
return sal_address_get_display_name(addr);
}
#define SAL_ADDRESS_GET(addr,param) \
belle_sip_header_address_t* header_addr = BELLE_SIP_HEADER_ADDRESS(addr);\
{belle_sip_header_address_t* header_addr = BELLE_SIP_HEADER_ADDRESS(addr);\
belle_sip_uri_t* uri = belle_sip_header_address_get_uri(header_addr);\
if (uri) {\
return belle_sip_uri_get_##param(uri);\
} else\
return NULL;
return NULL;}
#define SAL_ADDRESS_SET(addr,param,value) \
#define SAL_ADDRESS_SET(addr,param,value) {\
belle_sip_header_address_t* header_addr = BELLE_SIP_HEADER_ADDRESS(addr);\
belle_sip_uri_t* uri = belle_sip_header_address_get_uri(header_addr);\
belle_sip_uri_set_##param(uri,value);
belle_sip_uri_set_##param(uri,value);}
const char *sal_address_get_username(const SalAddress *addr){
SAL_ADDRESS_GET(addr,user)
......@@ -121,13 +129,19 @@ void sal_address_clean(SalAddress *addr){
}
char *sal_address_as_string(const SalAddress *addr){
return belle_sip_object_to_string(BELLE_SIP_OBJECT(addr));
char tmp[1024]={0};
size_t off=0;
belle_sip_object_marshal((belle_sip_object_t*)addr,tmp,sizeof(tmp),&off);
return ms_strdup(tmp);
}
char *sal_address_as_string_uri_only(const SalAddress *addr){
belle_sip_header_address_t* header_addr = BELLE_SIP_HEADER_ADDRESS(addr);
belle_sip_uri_t* uri = belle_sip_header_address_get_uri(header_addr);
return belle_sip_object_to_string(BELLE_SIP_OBJECT(uri));
char tmp[1024]={0};
size_t off=0;
belle_sip_object_marshal((belle_sip_object_t*)uri,tmp,sizeof(tmp),&off);
return ms_strdup(tmp);
}
void sal_address_set_param(SalAddress *addr,const char* name,const char* value){
......@@ -137,7 +151,9 @@ void sal_address_set_param(SalAddress *addr,const char* name,const char* value){
}
void sal_address_set_transport(SalAddress* addr,SalTransport transport){
SAL_ADDRESS_SET(addr,transport_param,sal_transport_to_string(transport));
if (!sal_address_is_secure(addr)){
SAL_ADDRESS_SET(addr,transport_param,sal_transport_to_string(transport));
}
}
void sal_address_set_transport_name(SalAddress* addr,const char *transport){
......
......@@ -22,6 +22,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
typedef struct belle_sip_certificates_chain_t _SalCertificatesChain;
typedef struct belle_sip_signing_key_t _SalSigningKey;
/*
rfc3323
4.2 Expressing Privacy Preferences
......@@ -367,14 +371,16 @@ static void process_transaction_terminated(void *user_ctx, const belle_sip_trans
}
static void process_auth_requested(void *sal, belle_sip_auth_event_t *auth_event) {
SalAuthInfo* auth_info = sal_auth_info_create(auth_event);
static void process_auth_requested(void *sal, belle_sip_auth_event_t *event) {
SalAuthInfo* auth_info = sal_auth_info_create(event);
((Sal*)sal)->callbacks.auth_requested(sal,auth_info);
belle_sip_auth_event_set_passwd(auth_event,(const char*)auth_info->password);
belle_sip_auth_event_set_ha1(auth_event,(const char*)auth_info->ha1);
belle_sip_auth_event_set_userid(auth_event,(const char*)auth_info->userid);
belle_sip_auth_event_set_passwd(event,(const char*)auth_info->password);
belle_sip_auth_event_set_ha1(event,(const char*)auth_info->ha1);
belle_sip_auth_event_set_userid(event,(const char*)auth_info->userid);
belle_sip_auth_event_set_signing_key(event,(belle_sip_signing_key_t *)auth_info->key);
belle_sip_auth_event_set_client_certificates_chain(event,(belle_sip_certificates_chain_t* )auth_info->certificates);
sal_auth_info_delete(auth_info);
return;
}
Sal * sal_init(){
......@@ -477,11 +483,24 @@ void sal_uninit(Sal* sal){
belle_sip_object_unref(sal->prov);
belle_sip_object_unref(sal->stack);
belle_sip_object_unref(sal->listener);
if (sal->uuid) ms_free(sal->uuid);
if (sal->root_ca) ms_free(sal->root_ca);
ms_free(sal);
return ;
};
int sal_transport_available(Sal *sal, SalTransport t){
switch(t){
case SalTransportUDP:
case SalTransportTCP:
return TRUE;
case SalTransportTLS:
return belle_sip_stack_tls_available(sal->stack);
case SalTransportDTLS:
return FALSE;
}
return FALSE;
}
int sal_add_listen_port(Sal *ctx, SalAddress* addr){
int result;
belle_sip_listening_point_t* lp = belle_sip_stack_create_listening_point(ctx->stack
......@@ -699,9 +718,21 @@ SalAuthInfo* sal_auth_info_create(belle_sip_auth_event_t* event) {
auth_info->realm = ms_strdup(belle_sip_auth_event_get_realm(event));
auth_info->username = ms_strdup(belle_sip_auth_event_get_username(event));
auth_info->domain = ms_strdup(belle_sip_auth_event_get_domain(event));
auth_info->mode = (SalAuthMode)belle_sip_auth_event_get_mode(event);
return auth_info;
}
SalAuthMode sal_auth_info_get_mode(const SalAuthInfo* auth_info) { return auth_info->mode; }
SalSigningKey *sal_auth_info_get_signing_key(const SalAuthInfo* auth_info) { return auth_info->key; }
SalCertificatesChain *sal_auth_info_get_certificates_chain(const SalAuthInfo* auth_info) { return auth_info->certificates; }
void sal_auth_info_set_mode(SalAuthInfo* auth_info, SalAuthMode mode) { auth_info->mode = mode; }
void sal_certificates_chain_delete(SalCertificatesChain *chain) {
belle_sip_object_unref((belle_sip_object_t *)chain);
}
void sal_signing_key_delete(SalSigningKey *key) {
belle_sip_object_unref((belle_sip_object_t *)key);
}
const char* sal_op_type_to_string(const SalOpType type) {
switch(type) {
case SalOpRegister: return "SalOpRegister";
......@@ -839,14 +870,43 @@ void sal_enable_test_features(Sal*ctx, bool_t enabled){
ctx->enable_test_features=enabled;
}
unsigned long sal_resolve_a(Sal* sal, const char *name, int port, int family, SalResolverCallback cb, void *data){
return belle_sip_stack_resolve_a(sal->stack,name,port,family,(belle_sip_resolver_callback_t)cb,data);
SalResolverContext * sal_resolve_a(Sal* sal, const char *name, int port, int family, SalResolverCallback cb, void *data){
return (SalResolverContext*)belle_sip_stack_resolve_a(sal->stack,name,port,family,(belle_sip_resolver_callback_t)cb,data);
}
void sal_resolve_cancel(Sal *sal, unsigned long id){
belle_sip_stack_resolve_cancel(sal->stack,id);
/*
void sal_resolve_cancel(Sal *sal, SalResolverContext* ctx){
belle_sip_stack_resolve_cancel(sal->stack,ctx);
}
*/
void sal_enable_unconditional_answer(Sal *sal,int value) {
belle_sip_provider_enable_unconditional_answer(sal->prov,value);
}
/** Parse a file containing either a certificate chain order in PEM format or a single DER cert
* @param auth_info structure where to store the result of parsing
* @param path path to certificate chain file
* @param format either PEM or DER
*/
void sal_certificates_chain_parse_file(SalAuthInfo* auth_info, const char* path, SalCertificateRawFormat format) {
auth_info->certificates = (SalCertificatesChain*) belle_sip_certificates_chain_parse_file(path, (belle_sip_certificate_raw_format_t)format); //
if (auth_info->certificates) belle_sip_object_ref((belle_sip_object_t *) auth_info->certificates);
}
/**
* Parse a file containing either a private or public rsa key
* @param auth_info structure where to store the result of parsing
* @param passwd password (optionnal)
*/
void sal_signing_key_parse_file(SalAuthInfo* auth_info, const char* path, const char *passwd) {
auth_info->key = (SalSigningKey *) belle_sip_signing_key_parse_file(path, passwd);
if (auth_info->key) belle_sip_object_ref((belle_sip_object_t *) auth_info->key);
}
unsigned char * sal_get_random_bytes(unsigned char *ret, size_t size){
return belle_sip_random_bytes(ret,size);
}
......@@ -362,7 +362,6 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t
}
dialog_state=belle_sip_dialog_get_state(op->dialog);
switch(dialog_state) {
case BELLE_SIP_DIALOG_NULL: {
if (strcmp("INVITE",belle_sip_request_get_method(req))==0) {
if (!op->replaces && (op->replaces=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_replaces_t))) {
......@@ -461,7 +460,13 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t
}else{
SalBody salbody;
if (sal_op_get_body(op,(belle_sip_message_t*)req,&salbody)) {
op->base.root->callbacks.info_received(op,&salbody);
if (sal_body_has_type(&salbody,"application","dtmf-relay")){
char tmp[10];
if (sal_lines_get_value(salbody.data, "Signal",tmp, sizeof(tmp))){
op->base.root->callbacks.dtmf_received(op,tmp[0]);
}
}else
op->base.root->callbacks.info_received(op,&salbody);
} else {
op->base.root->callbacks.info_received(op,NULL);
}
......@@ -485,10 +490,9 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t
unsupported_method(server_transaction,req);
}
break;
default: {
default:
ms_error("unexpected dialog state [%s]",belle_sip_dialog_state_to_string(dialog_state));
}
/* no break */
break;
}
if (server_transaction) belle_sip_object_unref(server_transaction);
......@@ -603,10 +607,17 @@ int sal_call_notify_ringing(SalOp *op, bool_t early_media){
if (require) tags=belle_sip_header_get_unparsed_value(require);
/* if client requires 100rel, then add necessary stuff*/
if (tags && strstr(tags,"100rel")!=0) {
belle_sip_header_address_t* contact= (belle_sip_header_address_t*)sal_op_get_contact_address(op);
belle_sip_header_contact_t* contact_header;
belle_sip_message_add_header((belle_sip_message_t*)ringing_response,BELLE_SIP_HEADER(belle_sip_header_extension_create("Require","100rel")));
belle_sip_message_add_header((belle_sip_message_t*)ringing_response,BELLE_SIP_HEADER(belle_sip_header_extension_create("RSeq","1")));
}
#ifndef SAL_OP_CALL_FORCE_CONTACT_IN_RINGING
if (tags && strstr(tags,"100rel")!=0)
#endif
{
belle_sip_header_address_t* contact= (belle_sip_header_address_t*)sal_op_get_contact_address(op);
belle_sip_header_contact_t* contact_header;
if (contact && (contact_header=belle_sip_header_contact_create(contact))) {
belle_sip_message_add_header(BELLE_SIP_MESSAGE(ringing_response),BELLE_SIP_HEADER(contact_header));
}
......@@ -693,7 +704,7 @@ SalMediaDescription * sal_call_get_final_media_description(SalOp *h){
}
int sal_call_send_dtmf(SalOp *h, char dtmf){
if (h->dialog){
if (h->dialog && (belle_sip_dialog_get_state(h->dialog) == BELLE_SIP_DIALOG_CONFIRMED || belle_sip_dialog_get_state(h->dialog) == BELLE_SIP_DIALOG_EARLY)){
belle_sip_request_t *req=belle_sip_dialog_create_queued_request(h->dialog,"INFO");
if (req){
int bodylen;
......
......@@ -220,13 +220,13 @@ static int _sal_op_send_request_with_contact(SalOp* op, belle_sip_request_t* req
belle_sip_uri_t* outbound_proxy=NULL;
belle_sip_header_contact_t* contact;
int result =-1;
belle_sip_uri_t *next_hop_uri=NULL;
_sal_op_add_custom_headers(op, (belle_sip_message_t*)request);
if (!op->dialog || belle_sip_dialog_get_state(op->dialog) == BELLE_SIP_DIALOG_NULL) {
/*don't put route header if dialog is in confirmed state*/
const MSList *elem=sal_op_get_route_addresses(op);
belle_sip_uri_t *next_hop_uri;
const char *transport;
const char *method=belle_sip_request_get_method(request);
......@@ -234,24 +234,25 @@ static int _sal_op_send_request_with_contact(SalOp* op, belle_sip_request_t* req
outbound_proxy=belle_sip_header_address_get_uri((belle_sip_header_address_t*)elem->data);
next_hop_uri=outbound_proxy;
}else{
next_hop_uri=belle_sip_request_get_uri(request);
next_hop_uri=(belle_sip_uri_t*)belle_sip_object_clone((belle_sip_object_t*)belle_sip_request_get_uri(request));
}
transport=belle_sip_uri_get_transport_param(next_hop_uri);
if (transport==NULL){
/*compatibility mode: by default it should be udp as not explicitely set and if no udp listening point is available, then use
* the first available transport*/
if (belle_sip_provider_get_listening_point(prov,"UDP")==0){
if (belle_sip_provider_get_listening_point(prov,"TCP")!=NULL){
transport="tcp";
}else if (belle_sip_provider_get_listening_point(prov,"TLS")!=NULL){
transport="tls";
if (!belle_sip_uri_is_secure(next_hop_uri)){
if (belle_sip_provider_get_listening_point(prov,"UDP")==0){
if (belle_sip_provider_get_listening_point(prov,"TCP")!=NULL){
transport="tcp";
}else if (belle_sip_provider_get_listening_point(prov,"TLS")!=NULL ){
transport="tls";
}
}
if (transport){
belle_sip_message("Transport is not specified, using %s because UDP is not available.",transport);
belle_sip_uri_set_transport_param(next_hop_uri,transport);
}
}
if (transport){
belle_sip_message("Transport is not specified, using %s because UDP is not available.",transport);
belle_sip_uri_set_transport_param(next_hop_uri,transport);
}
/* not really usefull belle_sip_uri_fix(next_hop_uri);*/
}
if ((strcmp(method,"REGISTER")==0 || strcmp(method,"SUBSCRIBE")==0) && transport &&
(strcasecmp(transport,"TCP")==0 || strcasecmp(transport,"TLS")==0)){
......@@ -279,7 +280,7 @@ static int _sal_op_send_request_with_contact(SalOp* op, belle_sip_request_t* req
/*hmm just in case we already have authentication param in cache*/
belle_sip_provider_add_authorization(op->base.root->prov,request,NULL,NULL);
}
result = belle_sip_client_transaction_send_request_to(client_transaction,outbound_proxy/*might be null*/);
result = belle_sip_client_transaction_send_request_to(client_transaction,next_hop_uri/*might be null*/);
/*update call id if not set yet for this OP*/
if (result == 0 && !op->base.call_id) {
......
......@@ -25,29 +25,28 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "mediastreamer2/mediastream.h"
#include "lpconfig.h"
// stat
#ifndef WIN32
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#endif
static void register_failure(SalOp *op, SalError error, SalReason reason, const char *details);
static int media_parameters_changed(LinphoneCall *call, SalMediaDescription *oldmd, SalMediaDescription *newmd) {
if (call->params.in_conference != call->current_params.in_conference) return SAL_MEDIA_DESCRIPTION_CHANGED;
if (call->up_bw != linphone_core_get_upload_bandwidth(call->core)) return SAL_MEDIA_DESCRIPTION_CHANGED;
return sal_media_description_equals(oldmd, newmd);
if (call->localdesc_changed) ms_message("Local description has changed: %i", call->localdesc_changed);
return call->localdesc_changed | sal_media_description_equals(oldmd, newmd);
}
void linphone_core_update_streams_destinations(LinphoneCore *lc, LinphoneCall *call, SalMediaDescription *old_md, SalMediaDescription *new_md) {
SalStreamDescription *old_audiodesc = NULL;
SalStreamDescription *old_videodesc = NULL;
SalStreamDescription *new_audiodesc = NULL;
SalStreamDescription *new_videodesc = NULL;
char *rtp_addr, *rtcp_addr;
int i;
for (i = 0; i < old_md->n_active_streams; i++) {
if (old_md->streams[i].type == SalAudio) {
old_audiodesc = &old_md->streams[i];
} else if (old_md->streams[i].type == SalVideo) {
old_videodesc = &old_md->streams[i];
}
}
for (i = 0; i < new_md->n_active_streams; i++) {
if (new_md->streams[i].type == SalAudio) {
new_audiodesc = &new_md->streams[i];
......@@ -68,22 +67,9 @@ void linphone_core_update_streams_destinations(LinphoneCore *lc, LinphoneCall *c
ms_message("Change video stream destination: RTP=%s:%d RTCP=%s:%d", rtp_addr, new_videodesc->rtp_port, rtcp_addr, new_videodesc->rtcp_port);
rtp_session_set_remote_addr_full(call->videostream->ms.session, rtp_addr, new_videodesc->rtp_port, rtcp_addr, new_videodesc->rtcp_port);
}
#else
(void)new_videodesc;
#endif
/* Copy address and port values from new_md to old_md since we will keep old_md as resultdesc */
strcpy(old_md->addr, new_md->addr);
if (old_audiodesc && new_audiodesc) {
strcpy(old_audiodesc->rtp_addr, new_audiodesc->rtp_addr);
strcpy(old_audiodesc->rtcp_addr, new_audiodesc->rtcp_addr);
old_audiodesc->rtp_port = new_audiodesc->rtp_port;
old_audiodesc->rtcp_port = new_audiodesc->rtcp_port;
}
if (old_videodesc && new_videodesc) {
strcpy(old_videodesc->rtp_addr, new_videodesc->rtp_addr);
strcpy(old_videodesc->rtcp_addr, new_videodesc->rtcp_addr);
old_videodesc->rtp_port = new_videodesc->rtp_port;
old_videodesc->rtcp_port = new_videodesc->rtcp_port;
}
}
void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMediaDescription *new_md){
......@@ -105,9 +91,6 @@ void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMedia
ms_message("Media descriptions are different, need to restart the streams.");
} else {
if (md_changed == SAL_MEDIA_DESCRIPTION_UNCHANGED) {
/*as nothing has changed, keep the oldmd */
call->resultdesc=oldmd;
sal_media_description_unref(new_md);
if (call->all_muted){
ms_message("Early media finished, unmuting inputs...");
/*we were in early media, now we want to enable real media */
......@@ -120,7 +103,7 @@ void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMedia
#endif
}
ms_message("No need to restart streams, SDP is unchanged.");
return;
goto end;
}else {
if (md_changed & SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED) {
ms_message("Network parameters have changed, update them.");
......@@ -130,17 +113,13 @@ void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMedia
ms_message("Crypto parameters have changed, update them.");
linphone_call_update_crypto_parameters(call, oldmd, new_md);
}
call->resultdesc = oldmd;
sal_media_description_unref(new_md);
return;
goto end;
}
}
}
linphone_call_stop_media_streams (call);
linphone_call_init_media_streams (call);
}
if (oldmd)
sal_media_description_unref(oldmd);
if (new_md) {
bool_t all_muted=FALSE;
......@@ -162,6 +141,10 @@ void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMedia
if (call->state==LinphoneCallPausing && call->paused_by_app && ms_list_size(lc->calls)==1){
linphone_core_play_named_tone(lc,LinphoneToneCallOnHold);
}
end:
if (oldmd)
sal_media_description_unref(oldmd);
}
#if 0
static bool_t is_duplicate_call(LinphoneCore *lc, const LinphoneAddress *from, const LinphoneAddress *to){
......@@ -901,6 +884,46 @@ static void ping_reply(SalOp *op){
}
}
static const char *get_client_cert_path(LinphoneCore *lc) {
static char cldir[200] = {0};
#ifdef HAVE_GETENV
if (!cldir[0]) {
static char default_path[200] = {0};
snprintf(default_path, sizeof(default_path), "%s%s", getenv("HOME"), "/linphone_certs");
snprintf(cldir, sizeof(cldir), "%s", lp_config_get_string(lc->config,"sip","client_certificates_dir", default_path));
}
#endif
return cldir;
}
static bool_t fill_auth_info_with_client_certificate(LinphoneCore *lc, SalAuthInfo* sai) {
char chain_file[200];
char key_file[200];
const char *path = get_client_cert_path(lc);
snprintf(chain_file, sizeof(chain_file), "%s%s", path, "/chain.pem");
snprintf(key_file, sizeof(key_file), "%s%s", path, "/key.pem");
#ifndef WIN32
{
// optinal check for files
struct stat st;
if (stat(key_file,&st)) {
ms_warning("No client certificate key found in %s", key_file);
return FALSE;
}
if (stat(chain_file,&st)) {
ms_warning("No client certificate chain found in %s", chain_file);
return FALSE;
}
}
#endif
sal_certificates_chain_parse_file(sai, chain_file, SAL_CERTIFICATE_RAW_FORMAT_PEM );
sal_signing_key_parse_file(sai, key_file, "");
return sai->certificates && sai->key;
}
static bool_t fill_auth_info(LinphoneCore *lc, SalAuthInfo* sai) {
LinphoneAuthInfo *ai=(LinphoneAuthInfo*)linphone_core_find_auth_info(lc,sai->realm,sai->username,sai->domain);
if (ai) {
......@@ -916,18 +939,25 @@ static bool_t fill_auth_info(LinphoneCore *lc, SalAuthInfo* sai) {
}
static bool_t auth_requested(Sal* sal, SalAuthInfo* sai) {
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal);
if (fill_auth_info(lc,sai)) {
return TRUE;
} else {
if (lc->vtable.auth_info_requested) {
lc->vtable.auth_info_requested(lc,sai->realm,sai->username,sai->domain);
if (fill_auth_info(lc,sai)) {
return TRUE;
if (sai->mode == SalAuthModeHttpDigest) {
if (fill_auth_info(lc,sai)) {
return TRUE;
} else {
if (lc->vtable.auth_info_requested) {
lc->vtable.auth_info_requested(lc,sai->realm,sai->username,sai->domain);
if (fill_auth_info(lc,sai)) {
return TRUE;
}
}
return FALSE;
}
} else if (sai->mode == SalAuthModeTls) {
return fill_auth_info_with_client_certificate(lc,sai);
} else {
return FALSE;
}
}
static void notify_refer(SalOp *op, SalReferStatus status){
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
LinphoneCall *call=(LinphoneCall*) sal_op_get_user_pointer(op);
......
......@@ -95,6 +95,7 @@ void linphone_chat_room_destroy(LinphoneChatRoom *cr){
lc->chatrooms=ms_list_remove(lc->chatrooms,(void *) cr);
linphone_address_destroy(cr->peer_url);
ms_free(cr->peer);
ms_free(cr);
}
......
......@@ -43,24 +43,34 @@ static MSWebCam *get_nowebcam_device(){
}
#endif
static bool_t generate_b64_crypto_key(int key_length, char* key_out) {
static bool_t generate_b64_crypto_key(int key_length, char* key_out, size_t key_out_size) {
int b64_size;
uint8_t* tmp = (uint8_t*) malloc(key_length);
if (ortp_crypto_get_random(tmp, key_length)!=0) {
uint8_t* tmp = (uint8_t*) ms_malloc0(key_length);
if (sal_get_random_bytes(tmp, key_length)==NULL) {
ms_error("Failed to generate random key");
free(tmp);
ms_free(tmp);
return FALSE;
}
b64_size = b64_encode((const char*)tmp, key_length, NULL, 0);
if (b64_size == 0) {
ms_error("Failed to get b64 result size");
ms_free(tmp);
return FALSE;
}
if (b64_size>=key_out_size){
ms_error("Insufficient room for writing base64 SRTP key");
ms_free(tmp);
return FALSE;
}
b64_size=b64_encode((const char*)tmp, key_length, key_out, key_out_size);
if (b64_size == 0) {
ms_error("Failed to b64 encode key");
free(tmp);
ms_free(tmp);
return FALSE;
}
key_out[b64_size] = '\0';
b64_encode((const char*)tmp, key_length, key_out, 40);
free(tmp);
ms_free(tmp);
return TRUE;
}
......@@ -293,17 +303,18 @@ void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *
if (md->streams[i].proto == SalProtoRtpSavp) {
if (keep_srtp_keys && old_md && old_md->streams[i].proto==SalProtoRtpSavp){
int j;
ms_message("Keeping same crypto keys.");
for(j=0;j<SAL_CRYPTO_ALGO_MAX;++j){
memcpy(&md->streams[i].crypto[j],&old_md->streams[i].crypto[j],sizeof(SalSrtpCryptoAlgo));
}
}else{
md->streams[i].crypto[0].tag = 1;
md->streams[i].crypto[0].algo = AES_128_SHA1_80;
if (!generate_b64_crypto_key(30, md->streams[i].crypto[0].master_key))
if (!generate_b64_crypto_key(30, md->streams[i].crypto[0].master_key, SAL_SRTP_KEY_SIZE))
md->streams[i].crypto[0].algo = 0;
md->streams[i].crypto[1].tag = 2;
md->streams[i].crypto[1].algo = AES_128_SHA1_32;