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

Conflicts:
	tester/liblinphone_tester.c
This commit is contained in:
Jehan Monnier 2013-12-02 17:07:55 +01:00
commit 41b76330c8
41 changed files with 988 additions and 373 deletions

View file

@ -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"/>

16
.gitignore vendored
View file

@ -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

3
README
View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -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){

View file

@ -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);
}

View file

@ -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;

View file

@ -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) {

View file

@ -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);

View file

@ -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);
}

View file

@ -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;
if (!generate_b64_crypto_key(30, md->streams[i].crypto[1].master_key))
if (!generate_b64_crypto_key(30, md->streams[i].crypto[1].master_key, SAL_SRTP_KEY_SIZE))
md->streams[i].crypto[1].algo = 0;
md->streams[i].crypto[2].algo = 0;
}
@ -322,7 +333,10 @@ void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *
#endif //BUILD_UPNP
linphone_address_destroy(addr);
call->localdesc=md;
if (old_md) sal_media_description_unref(old_md);
if (old_md){
call->localdesc_changed=sal_media_description_equals(md,old_md);
sal_media_description_unref(old_md);
}
}
static int find_port_offset(LinphoneCore *lc, SalStreamType type){
@ -762,6 +776,7 @@ void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const
static void linphone_call_destroy(LinphoneCall *obj)
{
ms_message("Call [%p] freed.",obj);
linphone_call_stop_media_streams(obj);
#ifdef BUILD_UPNP
linphone_call_delete_upnp_session(obj);
#endif //BUILD_UPNP
@ -1537,6 +1552,9 @@ static RtpProfile *make_profile(LinphoneCall *call, const SalMediaDescription *m
for(elem=desc->payloads;elem!=NULL;elem=elem->next){
PayloadType *pt=(PayloadType*)elem->data;
int number;
/* make a copy of the payload type, so that we left the ones from the SalStreamDescription unchanged.
If the SalStreamDescription is freed, this will have no impact on the running streams*/
pt=payload_type_clone(pt);
if ((pt->flags & PAYLOAD_TYPE_FLAG_CAN_SEND) && first) {
if (desc->type==SalAudio){
@ -1925,7 +1943,6 @@ void linphone_call_stop_media_streams_for_ice_gathering(LinphoneCall *call){
void linphone_call_update_crypto_parameters(LinphoneCall *call, SalMediaDescription *old_md, SalMediaDescription *new_md) {
SalStreamDescription *old_stream;
SalStreamDescription *new_stream;
int i;
old_stream = sal_media_description_find_stream(old_md, SalProtoRtpSavp, SalAudio);
new_stream = sal_media_description_find_stream(new_md, SalProtoRtpSavp, SalAudio);
@ -1940,11 +1957,6 @@ void linphone_call_update_crypto_parameters(LinphoneCall *call, SalMediaDescript
ms_warning("Failed to find local crypto algo with tag: %d", new_stream->crypto_local_tag);
call->audiostream_encrypted = FALSE;
}
for (i = 0; i < SAL_CRYPTO_ALGO_MAX; i++) {
old_stream->crypto[i].tag = new_stream->crypto[i].tag;
old_stream->crypto[i].algo = new_stream->crypto[i].algo;
strncpy(old_stream->crypto[i].master_key, new_stream->crypto[i].master_key, sizeof(old_stream->crypto[i].master_key) - 1);
}
}
}
@ -1962,11 +1974,6 @@ void linphone_call_update_crypto_parameters(LinphoneCall *call, SalMediaDescript
ms_warning("Failed to find local crypto algo with tag: %d", new_stream->crypto_local_tag);
call->videostream_encrypted = FALSE;
}
for (i = 0; i < SAL_CRYPTO_ALGO_MAX; i++) {
old_stream->crypto[i].tag = new_stream->crypto[i].tag;
old_stream->crypto[i].algo = new_stream->crypto[i].algo;
strncpy(old_stream->crypto[i].master_key, new_stream->crypto[i].master_key, sizeof(old_stream->crypto[i].master_key) - 1);
}
}
}
#endif
@ -2031,6 +2038,7 @@ void linphone_call_stop_audio_stream(LinphoneCall *call) {
}
audio_stream_stop(call->audiostream);
call->audiostream=NULL;
call->current_params.audio_codec = NULL;
}
}
@ -2044,6 +2052,7 @@ void linphone_call_stop_video_stream(LinphoneCall *call) {
linphone_call_log_fill_stats(call->log,(MediaStream*)call->videostream);
video_stream_stop(call->videostream);
call->videostream=NULL;
call->current_params.video_codec = NULL;
}
#endif
}
@ -2056,12 +2065,10 @@ void linphone_call_stop_media_streams(LinphoneCall *call){
ms_event_queue_skip(call->core->msevq);
}
if (call->audio_profile){
rtp_profile_clear_all(call->audio_profile);
rtp_profile_destroy(call->audio_profile);
call->audio_profile=NULL;
}
if (call->video_profile){
rtp_profile_clear_all(call->video_profile);
rtp_profile_destroy(call->video_profile);
call->video_profile=NULL;
}
@ -2550,7 +2557,7 @@ bool_t linphone_call_is_in_conference(const LinphoneCall *call) {
* @param cx a floating point number pointing the horizontal center of the zoom to be applied. This value should be between 0.0 and 1.0.
* @param cy a floating point number pointing the vertical center of the zoom to be applied. This value should be between 0.0 and 1.0.
*
* cx and cy are updated in return in case their coordinates were to excentrated for the requested zoom factor. The zoom ensures that all the screen is fullfilled with the video.
* cx and cy are updated in return in case their coordinates were too excentrated for the requested zoom factor. The zoom ensures that all the screen is fullfilled with the video.
**/
void linphone_call_zoom_video(LinphoneCall* call, float zoom_factor, float* cx, float* cy) {
VideoStream* vstream = call->videostream;

View file

@ -942,6 +942,7 @@ static void build_video_devices_table(LinphoneCore *lc){
static void video_config_read(LinphoneCore *lc){
#ifdef VIDEO_ENABLED
int capture, display, self_view;
int automatic_video=1;
#endif
const char *str;
#ifdef VIDEO_ENABLED
@ -958,11 +959,14 @@ static void video_config_read(LinphoneCore *lc){
lp_config_get_string(lc->config,"video","size","cif"));
#ifdef VIDEO_ENABLED
#if defined(ANDROID) || defined(__ios)
automatic_video=0;
#endif
capture=lp_config_get_int(lc->config,"video","capture",1);
display=lp_config_get_int(lc->config,"video","display",1);
self_view=lp_config_get_int(lc->config,"video","self_view",1);
vpol.automatically_initiate=lp_config_get_int(lc->config,"video","automatically_initiate",1);
vpol.automatically_accept=lp_config_get_int(lc->config,"video","automatically_accept",1);
vpol.automatically_initiate=lp_config_get_int(lc->config,"video","automatically_initiate",automatic_video);
vpol.automatically_accept=lp_config_get_int(lc->config,"video","automatically_accept",automatic_video);
linphone_core_enable_video_capture(lc, capture);
linphone_core_enable_video_display(lc, display);
linphone_core_enable_video_preview(lc,lp_config_get_int(lc->config,"video","show_local",0));
@ -1888,6 +1892,13 @@ static int apply_transports(LinphoneCore *lc){
return 0;
}
/**
* Returns TRUE if given transport type is supported by the library, FALSE otherwise.
**/
bool_t linphone_core_sip_transport_supported(const LinphoneCore *lc, LinphoneTransportType tp){
return sal_transport_available(lc->sal,(SalTransport)tp);
}
/**
* Sets the ports to be used for each of transport (UDP or TCP)
*
@ -2275,8 +2286,8 @@ LinphoneAddress * linphone_core_interpret_url(LinphoneCore *lc, const char *url)
enum_lookup_res_free(enumres);
return uri;
}
/* check if we have a "sip:" */
if (strstr(url,"sip:")==NULL){
/* check if we have a "sip:" or a "sips:" */
if ( (strstr(url,"sip:")==NULL) && (strstr(url,"sips:")==NULL) ){
/* this doesn't look like a true sip uri */
if (strchr(url,'@')!=NULL){
/* seems like sip: is missing !*/
@ -2401,11 +2412,7 @@ static MSList *make_routes_for_proxy(LinphoneProxyConfig *proxy, const LinphoneA
if (transport){
SalAddress *route=sal_address_new(NULL);
sal_address_set_domain(route,sal_address_get_domain((SalAddress*)dest));
#ifdef USE_BELLESIP
sal_address_set_port(route,sal_address_get_port((SalAddress*)dest));
#else
sal_address_set_port_int(route,sal_address_get_port_int((SalAddress*)dest));
#endif
sal_address_set_transport_name(route,transport);
ret=ms_list_append(ret,route);
}
@ -2852,6 +2859,7 @@ void linphone_core_notify_incoming_call(LinphoneCore *lc, LinphoneCall *call){
if (md){
if (sal_media_description_empty(md) || linphone_core_incompatible_security(lc,md)){
sal_call_decline(call->op,SalReasonMedia,NULL);
linphone_call_stop_media_streams(call);
linphone_core_del_call(lc,call);
linphone_call_unref(call);
return;
@ -4896,8 +4904,10 @@ unsigned long linphone_core_get_native_video_window_id(const LinphoneCore *lc){
/* unsets the video id for all calls (indeed it may be kept by filters or videostream object itself by paused calls)*/
static void unset_video_window_id(LinphoneCore *lc, bool_t preview, unsigned long id){
#ifdef VIDEO_ENABLED
LinphoneCall *call;
MSList *elem;
#endif
if (id!=0 && id!=-1) {
ms_error("Invalid use of unset_video_window_id()");
@ -5495,7 +5505,7 @@ static void sound_config_uninit(LinphoneCore *lc)
if (config->local_ring) ms_free(config->local_ring);
if (config->remote_ring) ms_free(config->remote_ring);
ms_snd_card_manager_destroy();
}
static void video_config_uninit(LinphoneCore *lc)
@ -5644,11 +5654,13 @@ static void linphone_core_uninit(LinphoneCore *lc)
if(lc->rec_file!=NULL){
ms_free(lc->rec_file);
}
if(lc->presence_model){
linphone_presence_model_unref(lc->presence_model);
}
linphone_core_free_payload_types(lc);
linphone_core_message_storage_close(lc);
ortp_exit();
ms_exit();
linphone_core_set_state(lc,LinphoneGlobalOff,"Off");
}

View file

@ -89,6 +89,19 @@ typedef struct _LCSipTransports{
} LCSipTransports;
/**
* Enum describing transport type for LinphoneAddress.
**/
enum _LinphoneTransportType{
LinphoneTransportUdp,
LinphoneTransportTcp,
LinphoneTransportTls,
LinphoneTransportDtls
};
/*this enum MUST be kept in sync with the SalTransport from sal.h*/
typedef enum _LinphoneTransportType LinphoneTransportType;
/**
* Object that represents a SIP address.
*
@ -191,6 +204,9 @@ LINPHONE_PUBLIC void linphone_address_set_domain(LinphoneAddress *uri, const cha
LINPHONE_PUBLIC void linphone_address_set_port(LinphoneAddress *uri, int port);
/*remove tags, params etc... so that it is displayable to the user*/
LINPHONE_PUBLIC void linphone_address_clean(LinphoneAddress *uri);
LINPHONE_PUBLIC bool_t linphone_address_is_secure(const LinphoneAddress *uri);
LINPHONE_PUBLIC LinphoneTransportType linphone_address_get_transport(const LinphoneAddress *uri);
LINPHONE_PUBLIC void linphone_address_set_transport(LinphoneAddress *uri,LinphoneTransportType type);
LINPHONE_PUBLIC char *linphone_address_as_string(const LinphoneAddress *u);
LINPHONE_PUBLIC char *linphone_address_as_string_uri_only(const LinphoneAddress *u);
LINPHONE_PUBLIC bool_t linphone_address_weak_equal(const LinphoneAddress *a1, const LinphoneAddress *a2);
@ -1526,6 +1542,8 @@ LINPHONE_PUBLIC int linphone_core_get_sip_port(LinphoneCore *lc);
LINPHONE_PUBLIC int linphone_core_set_sip_transports(LinphoneCore *lc, const LCSipTransports *transports);
LINPHONE_PUBLIC int linphone_core_get_sip_transports(LinphoneCore *lc, LCSipTransports *transports);
LINPHONE_PUBLIC bool_t linphone_core_sip_transport_supported(const LinphoneCore *lc, LinphoneTransportType tp);
/**
*
* Give access to the UDP sip socket. Can be useful to configure this socket as persistent I.E kCFStreamNetworkServiceType set to kCFStreamNetworkServiceTypeVoIP)

View file

@ -3102,7 +3102,7 @@ extern "C" jstring Java_org_linphone_core_LinphoneCoreImpl_getUpnpExternalIpaddr
* Signature: (JJLjava/lang/String;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;
*/
JNIEXPORT jobject JNICALL Java_org_linphone_core_LinphoneCoreImpl_subscribe(JNIEnv *env, jobject jcore, jlong coreptr, jlong addrptr,
jstring jevname, jint expires, jstring jtype, jstring jsubtype, jstring jdata){
jstring jevname, jint expires, jstring jtype, jstring jsubtype, jbyteArray jdata, jstring jencoding){
LinphoneCore *lc=(LinphoneCore*)coreptr;
LinphoneAddress *addr=(LinphoneAddress*)addrptr;
LinphoneContent content={0};
@ -3114,14 +3114,16 @@ JNIEXPORT jobject JNICALL Java_org_linphone_core_LinphoneCoreImpl_subscribe(JNIE
if (jtype){
content.type=(char*)env->GetStringUTFChars(jtype,NULL);
content.subtype=(char*)env->GetStringUTFChars(jsubtype,NULL);
content.data=(void*)env->GetStringUTFChars(jdata,NULL);
content.size=strlen((char*)content.data);
content.encoding=jencoding ? (char*)env->GetStringUTFChars(jsubtype,NULL) : NULL;
content.data=(void*)env->GetByteArrayElements(jdata,NULL);
content.size=env->GetArrayLength(jdata);
}
ev=linphone_core_subscribe(lc,addr,evname,expires,content.type ? &content : NULL);
if (jtype){
env->ReleaseStringUTFChars(jtype,content.type);
env->ReleaseStringUTFChars(jsubtype,content.subtype);
env->ReleaseStringUTFChars(jdata,(char*)content.data);
if (jencoding) env->ReleaseStringUTFChars(jencoding,content.encoding);
env->ReleaseByteArrayElements(jdata,(jbyte*)content.data,JNI_ABORT);
}
env->ReleaseStringUTFChars(jevname,evname);
if (ev){
@ -3136,7 +3138,7 @@ JNIEXPORT jobject JNICALL Java_org_linphone_core_LinphoneCoreImpl_subscribe(JNIE
* Signature: (JJLjava/lang/String;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;
*/
JNIEXPORT jobject JNICALL Java_org_linphone_core_LinphoneCoreImpl_publish(JNIEnv *env, jobject jobj, jlong coreptr, jlong addrptr, jstring jevname, jint expires,
jstring jtype, jstring jsubtype, jstring jdata){
jstring jtype, jstring jsubtype, jbyteArray jdata, jstring jencoding){
LinphoneCore *lc=(LinphoneCore*)coreptr;
LinphoneAddress *addr=(LinphoneAddress*)addrptr;
LinphoneContent content={0};
@ -3148,14 +3150,16 @@ JNIEXPORT jobject JNICALL Java_org_linphone_core_LinphoneCoreImpl_publish(JNIEnv
if (jtype){
content.type=(char*)env->GetStringUTFChars(jtype,NULL);
content.subtype=(char*)env->GetStringUTFChars(jsubtype,NULL);
content.data=(void*)env->GetStringUTFChars(jdata,NULL);
content.size=strlen((char*)content.data);
content.encoding=jencoding ? (char*)env->GetStringUTFChars(jsubtype,NULL) : NULL;
content.data=(void*)env->GetByteArrayElements(jdata,NULL);
content.size=env->GetArrayLength(jdata);
}
ev=linphone_core_publish(lc,addr,evname,expires,content.type ? &content : NULL);
if (jtype){
env->ReleaseStringUTFChars(jtype,content.type);
env->ReleaseStringUTFChars(jsubtype,content.subtype);
env->ReleaseStringUTFChars(jdata,(char*)content.data);
if (jencoding) env->ReleaseStringUTFChars(jencoding,content.encoding);
env->ReleaseByteArrayElements(jdata,(jbyte*)content.data,JNI_ABORT);
}
env->ReleaseStringUTFChars(jevname,evname);
if (ev){
@ -3295,15 +3299,22 @@ extern "C" jintArray Java_org_linphone_core_LpConfigImpl_getIntRange(JNIEnv *env
static jobject create_java_linphone_content(JNIEnv *env, const LinphoneContent *content){
jclass contentClass;
jmethodID ctor;
jstring jtype, jsubtype, jdata;
jstring jtype, jsubtype, jencoding;
jbyteArray jdata=NULL;
contentClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneContentImpl"));
ctor = env->GetMethodID(contentClass,"<init>", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
ctor = env->GetMethodID(contentClass,"<init>", "(Ljava/lang/String;Ljava/lang/String;[BLjava/lang/String;)V");
jtype=env->NewStringUTF(content->type);
jsubtype=env->NewStringUTF(content->subtype);
jdata=content->data ? env->NewStringUTF((const char*)content->data) : NULL;
jobject jobj=env->NewObject(contentClass,ctor,jtype, jsubtype, jdata);
jencoding=content->encoding ? env->NewStringUTF(content->encoding) : NULL;
if (content->data){
jdata=env->NewByteArray(content->size);
env->SetByteArrayRegion(jdata,0,content->size,(jbyte*)content->data);
}
jobject jobj=env->NewObject(contentClass,ctor,jtype, jsubtype, jdata,jencoding);
env->DeleteGlobalRef(contentClass);
return jobj;
}
@ -3327,7 +3338,7 @@ JNIEXPORT jobject JNICALL Java_org_linphone_core_LinphoneInfoMessageImpl_getCont
* Signature: (JLjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneInfoMessageImpl_setContent(JNIEnv *env, jobject jobj, jlong infoptr, jstring jtype, jstring jsubtype, jstring jdata){
LinphoneContent content;
LinphoneContent content={0};
content.type=(char*)env->GetStringUTFChars(jtype,NULL);
content.subtype=(char*)env->GetStringUTFChars(jsubtype,NULL);
@ -3428,7 +3439,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneEventImpl_denySubscription
* Method: notify
* Signature: (JLjava/lang/String;Ljava/lang/String;Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneEventImpl_notify(JNIEnv *env, jobject jobj, jlong evptr, jstring jtype, jstring jsubtype, jstring jdata){
JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneEventImpl_notify(JNIEnv *env, jobject jobj, jlong evptr, jstring jtype, jstring jsubtype, jbyteArray jdata, jstring jencoding){
LinphoneContent content={0};
LinphoneEvent *ev=(LinphoneEvent*)evptr;
jint err;
@ -3436,8 +3447,9 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneEventImpl_notify(JNIEnv *e
if (jtype){
content.type=(char*)env->GetStringUTFChars(jtype,NULL);
content.subtype=(char*)env->GetStringUTFChars(jsubtype,NULL);
content.data=(void*)env->GetStringUTFChars(jdata,NULL);
content.size=strlen((char*)content.data);
content.encoding=jencoding ? (char*)env->GetStringUTFChars(jsubtype,NULL) : NULL;
content.data=(void*)env->GetByteArrayElements(jdata,NULL);
content.size=env->GetArrayLength(jdata);
}
err=linphone_event_notify(ev,content.type ? &content : NULL);
@ -3445,7 +3457,8 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneEventImpl_notify(JNIEnv *e
if (jtype){
env->ReleaseStringUTFChars(jtype,content.type);
env->ReleaseStringUTFChars(jsubtype,content.subtype);
env->ReleaseStringUTFChars(jdata,(char*)content.data);
if (jencoding) env->ReleaseStringUTFChars(jencoding,content.encoding);
env->ReleaseByteArrayElements(jdata,(jbyte*)content.data,JNI_ABORT);
}
return err;
}
@ -3455,7 +3468,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneEventImpl_notify(JNIEnv *e
* Method: updateSubscribe
* Signature: (JLjava/lang/String;Ljava/lang/String;Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneEventImpl_updateSubscribe(JNIEnv *env, jobject jobj, jlong evptr, jstring jtype, jstring jsubtype, jstring jdata){
JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneEventImpl_updateSubscribe(JNIEnv *env, jobject jobj, jlong evptr, jstring jtype, jstring jsubtype, jbyteArray jdata, jstring jencoding){
LinphoneContent content={0};
LinphoneEvent *ev=(LinphoneEvent*)evptr;
jint err;
@ -3463,8 +3476,9 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneEventImpl_updateSubscribe(
if (jtype){
content.type=(char*)env->GetStringUTFChars(jtype,NULL);
content.subtype=(char*)env->GetStringUTFChars(jsubtype,NULL);
content.data=(void*)env->GetStringUTFChars(jdata,NULL);
content.size=strlen((char*)content.data);
content.encoding=jencoding ? (char*)env->GetStringUTFChars(jsubtype,NULL) : NULL;
content.data=(void*)env->GetByteArrayElements(jdata,NULL);
content.size=env->GetArrayLength(jdata);
}
err=linphone_event_update_subscribe(ev,content.type ? &content : NULL);
@ -3472,7 +3486,8 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneEventImpl_updateSubscribe(
if (jtype){
env->ReleaseStringUTFChars(jtype,content.type);
env->ReleaseStringUTFChars(jsubtype,content.subtype);
env->ReleaseStringUTFChars(jdata,(char*)content.data);
if (jencoding) env->ReleaseStringUTFChars(jencoding,content.encoding);
env->ReleaseByteArrayElements(jdata,(jbyte*)content.data,JNI_ABORT);
}
return err;
}
@ -3482,7 +3497,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneEventImpl_updateSubscribe(
* Method: updatePublish
* Signature: (JLjava/lang/String;Ljava/lang/String;Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneEventImpl_updatePublish(JNIEnv *env, jobject jobj, jlong evptr, jstring jtype, jstring jsubtype, jstring jdata){
JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneEventImpl_updatePublish(JNIEnv *env, jobject jobj, jlong evptr, jstring jtype, jstring jsubtype, jbyteArray jdata, jstring jencoding){
LinphoneContent content={0};
LinphoneEvent *ev=(LinphoneEvent*)evptr;
jint err;
@ -3490,8 +3505,9 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneEventImpl_updatePublish(JN
if (jtype){
content.type=(char*)env->GetStringUTFChars(jtype,NULL);
content.subtype=(char*)env->GetStringUTFChars(jsubtype,NULL);
content.data=(void*)env->GetStringUTFChars(jdata,NULL);
content.size=strlen((char*)content.data);
content.encoding=jencoding ? (char*)env->GetStringUTFChars(jsubtype,NULL) : NULL;
content.data=(void*)env->GetByteArrayElements(jdata,NULL);
content.size=env->GetArrayLength(jdata);
}
err=linphone_event_update_publish(ev,content.type ? &content : NULL);
@ -3499,7 +3515,8 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneEventImpl_updatePublish(JN
if (jtype){
env->ReleaseStringUTFChars(jtype,content.type);
env->ReleaseStringUTFChars(jsubtype,content.subtype);
env->ReleaseStringUTFChars(jdata,(char*)content.data);
if (jencoding) env->ReleaseStringUTFChars(jencoding,content.encoding);
env->ReleaseByteArrayElements(jdata,(jbyte*)content.data,JNI_ABORT);
}
return err;
}

View file

@ -633,7 +633,7 @@ static void stun_server_resolved(LinphoneCore *lc, const char *name, struct addr
ms_warning("Stun server resolution failed.");
}
lc->net_conf.stun_addrinfo=addrinfo;
lc->net_conf.stun_res_id=0;
lc->net_conf.stun_res=NULL;
}
void linphone_core_resolve_stun_server(LinphoneCore *lc){
@ -642,7 +642,7 @@ void linphone_core_resolve_stun_server(LinphoneCore *lc){
char host[NI_MAXHOST];
int port=3478;
linphone_parse_host_port(server,host,sizeof(host),&port);
lc->net_conf.stun_res_id=sal_resolve_a(lc->sal,host,port,AF_UNSPEC,(SalResolverCallback)stun_server_resolved,lc);
lc->net_conf.stun_res=sal_resolve_a(lc->sal,host,port,AF_UNSPEC,(SalResolverCallback)stun_server_resolved,lc);
}
}
@ -663,7 +663,7 @@ const struct addrinfo *linphone_core_get_stun_server_addrinfo(LinphoneCore *lc){
int wait_ms=0;
int wait_limit=1000;
linphone_core_resolve_stun_server(lc);
while (!lc->net_conf.stun_addrinfo && lc->net_conf.stun_res_id!=0 && wait_ms<wait_limit){
while (!lc->net_conf.stun_addrinfo && lc->net_conf.stun_res!=NULL && wait_ms<wait_limit){
sal_iterate(lc->sal);
ms_usleep(50000);
wait_ms+=50;

View file

@ -199,6 +199,8 @@ struct _LinphoneCall
unsigned int remote_session_ver;
LinphoneCall *referer; /*when this call is the result of a transfer, referer is set to the original call that caused the transfer*/
LinphoneCall *transfer_target;/*if this call received a transfer request, then transfer_target points to the new call created to the refer target */
int localdesc_changed;
bool_t refer_pending;
bool_t media_pending;
bool_t audio_muted;
@ -498,7 +500,7 @@ typedef struct net_config
char *nat_address_ip; /* ip translated from nat_address */
char *stun_server;
struct addrinfo *stun_addrinfo;
unsigned long stun_res_id;
SalResolverContext * stun_res;
int download_bw;
int upload_bw;
int mtu;

View file

@ -26,6 +26,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "config.h"
#endif
#include "sal/sal.h"
#include <ctype.h>
const char* sal_transport_to_string(SalTransport transport) {
switch (transport) {
case SalTransportUDP:return "udp";
@ -483,6 +486,9 @@ void sal_auth_info_delete(SalAuthInfo* auth_info) {
if (auth_info->realm) ms_free(auth_info->realm);
if (auth_info->domain) ms_free(auth_info->domain);
if (auth_info->password) ms_free(auth_info->password);
if (auth_info->ha1) ms_free(auth_info->ha1);
if (auth_info->certificates) sal_certificates_chain_delete(auth_info->certificates);
if (auth_info->key) sal_signing_key_delete(auth_info->key);
ms_free(auth_info);
}
@ -569,3 +575,55 @@ const char* sal_privacy_to_string(SalPrivacy privacy) {
default: return NULL;
}
}
static void remove_trailing_spaces(char *line){
int i;
for(i=strlen(line)-1;i>=0;--i){
if (isspace(line[i])) line[i]='\0';
else break;
}
}
static int line_get_value(const char *input, const char *key, char *value, size_t value_size, int *read){
const char *end=strchr(input,'\n');
char line[256]={0};
char key_candidate[256];
char *equal;
size_t len;
if (!end) len=strlen(input);
else len=end +1 -input;
*read=len;
strncpy(line,input,MIN(len,sizeof(line)));
equal=strchr(line,'=');
if (!equal) return FALSE;
*equal='\0';
if (sscanf(line,"%s",key_candidate)!=1) return FALSE;
if (strcasecmp(key,key_candidate)==0){
equal++;
remove_trailing_spaces(equal);
strncpy(value,equal,value_size-1);
value[value_size-1]='\0';
return TRUE;
}
return FALSE;
}
int sal_lines_get_value(const char *data, const char *key, char *value, size_t value_size){
int read=0;
do{
if (line_get_value(data,key,value,value_size,&read))
return TRUE;
data+=read;
}while(read!=0);
return FALSE;
}
int sal_body_has_type(const SalBody *body, const char *type, const char *subtype){
return body->type && body->subtype
&& strcmp(body->type,type)==0
&& strcmp(body->subtype,subtype)==0;
}

View file

@ -8,8 +8,11 @@
<object class="GtkFrame" id="frame3">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="events">GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_STRUCTURE_MASK</property>
<property name="label_xalign">0.5</property>
<property name="shadow_type">none</property>
<signal name="key-release-event" handler="linphone_gtk_keypad_key_released" swapped="no"/>
<signal name="key-press-event" handler="linphone_gtk_keypad_key_pressed" swapped="no"/>
<child>
<object class="GtkAspectFrame" id="aspectframe1">
<property name="visible">True</property>

View file

@ -64,6 +64,7 @@ static void linphone_gtk_call_log_updated(LinphoneCore *lc, LinphoneCallLog *cl)
static void linphone_gtk_call_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cs, const char *msg);
static void linphone_gtk_call_encryption_changed(LinphoneCore *lc, LinphoneCall *call, bool_t enabled, const char *token);
static void linphone_gtk_transfer_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cstate);
static void linphone_gtk_dtmf_received(LinphoneCore *lc, LinphoneCall *call, int dtmf);
void linphone_gtk_save_main_window_position(GtkWindow* mw, GdkEvent *event, gpointer data);
static gboolean linphone_gtk_auto_answer(LinphoneCall *call);
void linphone_gtk_status_icon_set_blinking(gboolean val);
@ -251,6 +252,7 @@ static void linphone_gtk_init_liblinphone(const char *config_file,
vtable.buddy_info_updated=linphone_gtk_buddy_info_updated;
vtable.call_encryption_changed=linphone_gtk_call_encryption_changed;
vtable.transfer_state_changed=linphone_gtk_transfer_state_changed;
vtable.dtmf_received=linphone_gtk_dtmf_received;
the_core=linphone_core_new(&vtable,config_file,factory_config_file,NULL);
//lp_config_set_int(linphone_core_get_config(the_core), "sip", "store_auth_info", 0);
@ -797,6 +799,9 @@ gchar *linphone_gtk_get_record_path(const LinphoneAddress *address, gboolean is_
date,
id);
}
if (!dir) {
ms_message ("No directory for music, using [%s] instead",dir=getenv("HOME"));
}
return g_build_filename(dir,filename,NULL);
}
@ -1046,6 +1051,10 @@ static void linphone_gtk_auth_info_requested(LinphoneCore *lc, const char *realm
auth_timeout_new(w);
}
static void linphone_gtk_dtmf_received(LinphoneCore *lc, LinphoneCall *call, int dtmf){
ms_message("Dtmf %c received.",dtmf);
}
static void linphone_gtk_display_status(LinphoneCore *lc, const char *status){
GtkWidget *w=linphone_gtk_get_main_window();
GtkWidget *status_bar=linphone_gtk_get_widget(w,"status_bar");
@ -1712,6 +1721,40 @@ void linphone_gtk_init_dtmf_table(GtkWidget *mw){
g_object_set_data(G_OBJECT(linphone_gtk_get_widget(mw,"dtmf_*")),"label","*");
}
static gboolean key_allowed(guint32 code){
static const char *allowed="1234567890#*ABCD";
return code!=0 && strchr(allowed,(char)code)!=NULL;
}
static GtkButton *get_button_from_key(GtkWidget *w, GdkEvent *event){
guint keyval=event->key.keyval;
guint32 code=gdk_keyval_to_unicode(keyval);
code=g_unichar_toupper(code);
if (key_allowed(code)){
char widgetname[16];
w=gtk_widget_get_toplevel(w);
snprintf(widgetname,sizeof(widgetname),"dtmf_%c",code);
return GTK_BUTTON(linphone_gtk_get_widget(w,widgetname));
}
return NULL;
}
void linphone_gtk_keypad_key_pressed(GtkWidget *w, GdkEvent *event, gpointer userdata){
GtkButton *button=get_button_from_key(w,event);
if (button) {
linphone_gtk_dtmf_pressed(button);
/*g_signal_emit_by_name(button, "button-press-event");*/
}
}
void linphone_gtk_keypad_key_released(GtkWidget *w, GdkEvent *event, gpointer userdata){
GtkButton *button=get_button_from_key(w,event);
if (button) {
linphone_gtk_dtmf_released(button);
/*g_signal_emit_by_name(button, "button-release-event");*/
}
}
void linphone_gtk_create_keypad(GtkWidget *button){
GtkWidget *mw=linphone_gtk_get_main_window();
GtkWidget *k=(GtkWidget *)g_object_get_data(G_OBJECT(mw),"keypad");

View file

@ -1548,6 +1548,7 @@
<child>
<object class="GtkButton" id="proxy_refresh_button">
<property name="can_focus">True</property>
<property name="visible">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<property name="relief">none</property>

View file

@ -48,6 +48,12 @@
<property name="step_increment">1</property>
<property name="page_increment">9.9999999995529656</property>
</object>
<object class="GtkAdjustment" id="adjustment8">
<property name="upper">65535</property>
<property name="value">5060</property>
<property name="step_increment">1</property>
<property name="page_increment">10</property>
</object>
<object class="GtkAdjustment" id="adjustment_max_audio_port">
<property name="upper">65535</property>
<property name="step_increment">2</property>
@ -324,23 +330,10 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="n_rows">7</property>
<property name="n_rows">8</property>
<property name="n_columns">2</property>
<child>
<object class="GtkComboBox" id="proto_combo">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="model">model8</property>
<child>
<object class="GtkCellRendererText" id="renderer1"/>
<attributes>
<attribute name="text">0</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkSpinButton" id="proto_port">
<object class="GtkSpinButton" id="sip_udp_port">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="invisible_char">•</property>
@ -350,6 +343,7 @@
<property name="primary_icon_sensitive">True</property>
<property name="secondary_icon_sensitive">True</property>
<property name="adjustment">adjustment7</property>
<signal name="value-changed" handler="linphone_gtk_udp_port_value_changed" swapped="no"/>
</object>
<packing>
<property name="left_attach">1</property>
@ -363,8 +357,8 @@
<property name="label" translatable="yes">Media encryption type</property>
</object>
<packing>
<property name="top_attach">3</property>
<property name="bottom_attach">5</property>
<property name="top_attach">4</property>
<property name="bottom_attach">6</property>
</packing>
</child>
<child>
@ -376,24 +370,8 @@
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
</packing>
</child>
<child>
<object class="GtkButton" id="tunnel_edit_button">
<property name="label">gtk-edit</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
<signal name="clicked" handler="linphone_gtk_edit_tunnel" swapped="no"/>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">6</property>
<property name="bottom_attach">7</property>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
</packing>
</child>
<child>
@ -405,8 +383,8 @@
<property name="justify">right</property>
</object>
<packing>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
</packing>
</child>
<child>
@ -418,36 +396,8 @@
<property name="justify">right</property>
</object>
<packing>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label13">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">DSCP fields</property>
</object>
<packing>
<property name="top_attach">5</property>
<property name="bottom_attach">6</property>
</packing>
</child>
<child>
<object class="GtkButton" id="dscp_edit_button">
<property name="label">gtk-edit</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
<signal name="clicked" handler="linphone_gtk_dscp_edit" swapped="no"/>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">5</property>
<property name="bottom_attach">6</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
</packing>
</child>
<child>
@ -513,8 +463,8 @@
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
</packing>
</child>
<child>
@ -580,18 +530,8 @@
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="tunnel_label">
<property name="can_focus">False</property>
<property name="label" translatable="yes">Tunnel</property>
</object>
<packing>
<property name="top_attach">6</property>
<property name="bottom_attach">7</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
</packing>
</child>
<child>
@ -607,10 +547,102 @@
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="top_attach">5</property>
<property name="bottom_attach">6</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="tunnel_label">
<property name="can_focus">False</property>
<property name="label" translatable="yes">Tunnel</property>
</object>
<packing>
<property name="top_attach">7</property>
<property name="bottom_attach">8</property>
</packing>
</child>
<child>
<object class="GtkButton" id="tunnel_edit_button">
<property name="label">gtk-edit</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
<signal name="clicked" handler="linphone_gtk_edit_tunnel" swapped="no"/>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">7</property>
<property name="bottom_attach">8</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label13">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">DSCP fields</property>
</object>
<packing>
<property name="top_attach">6</property>
<property name="bottom_attach">7</property>
</packing>
</child>
<child>
<object class="GtkButton" id="dscp_edit_button">
<property name="label">gtk-edit</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
<signal name="clicked" handler="linphone_gtk_dscp_edit" swapped="no"/>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">6</property>
<property name="bottom_attach">7</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label14">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">SIP/TCP port</property>
</object>
<packing>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
</packing>
</child>
<child>
<object class="GtkSpinButton" id="sip_tcp_port">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="invisible_char">•</property>
<property name="invisible_char_set">True</property>
<property name="primary_icon_activatable">False</property>
<property name="secondary_icon_activatable">False</property>
<property name="primary_icon_sensitive">True</property>
<property name="secondary_icon_sensitive">True</property>
<property name="adjustment">adjustment8</property>
<signal name="value-changed" handler="linphone_gtk_tcp_port_value_changed" swapped="no"/>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label15">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">SIP/UDP port</property>
</object>
</child>
</object>
</child>
</object>

View file

@ -102,49 +102,6 @@ void linphone_gtk_update_my_contact(GtkWidget *w){
linphone_gtk_load_identities();
}
void linphone_gtk_update_my_port(GtkWidget *w){
GtkWidget *pb=gtk_widget_get_toplevel(GTK_WIDGET(w));
LCSipTransports tr;
LinphoneCore *lc=linphone_gtk_get_core();
GtkComboBox *combo = GTK_COMBO_BOX(linphone_gtk_get_widget(pb, "proto_combo"));
gint port = (gint)gtk_spin_button_get_value(GTK_SPIN_BUTTON(w));
if (port == 1) { // We use default port if not specified
if (strcmp(gtk_combo_box_get_active_text(combo), "SIP (UDP)") == 0) {
gtk_spin_button_set_value(GTK_SPIN_BUTTON(w),
5060);
}
else if (strcmp(gtk_combo_box_get_active_text(combo), "SIP (TCP)") == 0) {
gtk_spin_button_set_value(GTK_SPIN_BUTTON(w),
5060);
}
else if (strcmp(gtk_combo_box_get_active_text(combo), "SIP (TLS)") == 0) {
gtk_spin_button_set_value(GTK_SPIN_BUTTON(w),
5061);
}
}
linphone_core_get_sip_transports(lc,&tr);
gchar *selected = gtk_combo_box_get_active_text(combo);
if (strcmp(selected, "SIP (TCP)") == 0) {
tr.tcp_port = (gint)gtk_spin_button_get_value(GTK_SPIN_BUTTON(w));
tr.udp_port = 0;
tr.tls_port = 0;
}
else if (strcmp(gtk_combo_box_get_active_text(GTK_COMBO_BOX(linphone_gtk_get_widget(pb, "proto_combo"))), "SIP (UDP)") == 0) {
tr.udp_port = (gint)gtk_spin_button_get_value(GTK_SPIN_BUTTON(w));
tr.tcp_port = 0;
tr.tls_port = 0;
}
else if (strcmp(gtk_combo_box_get_active_text(GTK_COMBO_BOX(linphone_gtk_get_widget(pb, "proto_combo"))), "SIP (TLS)") == 0){
tr.udp_port = 0;
tr.tcp_port = 0;
tr.tls_port = (gint)gtk_spin_button_get_value(GTK_SPIN_BUTTON(w));
}
linphone_core_set_sip_transports(lc,&tr);
}
void linphone_gtk_set_propety_entry(GtkWidget *w, gboolean stunServer, gboolean ip){
GtkWidget *stun_entry=linphone_gtk_get_widget(gtk_widget_get_toplevel(w),"stun_server");
GtkWidget *ip_entry=linphone_gtk_get_widget(gtk_widget_get_toplevel(w),"nat_address");
@ -691,6 +648,77 @@ static void linphone_gtk_proxy_closed(GtkWidget *w){
}
}
static void fill_transport_combo_box(GtkWidget *combo, LinphoneTransportType choice, gboolean is_sensitive){
GtkTreeModel *model;
GtkTreeIter iter;
if (GPOINTER_TO_INT(g_object_get_data(G_OBJECT(combo),"combo-updating"))) return;
if ((model=gtk_combo_box_get_model(GTK_COMBO_BOX(combo)))==NULL){
/*case where combo box is created with no model*/
GtkCellRenderer *renderer=gtk_cell_renderer_text_new();
model=GTK_TREE_MODEL(gtk_list_store_new(1,G_TYPE_STRING));
gtk_combo_box_set_model(GTK_COMBO_BOX(combo),model);
gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo),renderer,TRUE);
gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combo),renderer,"markup",0,NULL);
}
if (!gtk_tree_model_get_iter_first(model,&iter)){
gtk_list_store_append(GTK_LIST_STORE(model),&iter);
gtk_list_store_set(GTK_LIST_STORE(model),&iter,0,"UDP",-1);
gtk_list_store_append(GTK_LIST_STORE(model),&iter);
gtk_list_store_set(GTK_LIST_STORE(model),&iter,0,"TCP",-1);
if (linphone_core_sip_transport_supported(linphone_gtk_get_core(),LinphoneTransportTls)){
gtk_list_store_append(GTK_LIST_STORE(model),&iter);
gtk_list_store_set(GTK_LIST_STORE(model),&iter,0,"TLS",-1);
}
}
gtk_combo_box_set_active(GTK_COMBO_BOX(combo),(int)choice);
gtk_widget_set_sensitive(combo,is_sensitive);
}
static void update_proxy_transport(GtkWidget *w){
const char *addr=gtk_entry_get_text(GTK_ENTRY(linphone_gtk_get_widget(w,"proxy")));
LinphoneAddress *laddr=linphone_address_new(addr);
if (laddr){
GtkWidget *combo=linphone_gtk_get_widget(w,"transport");
if (linphone_address_is_secure(laddr)){
fill_transport_combo_box(combo,LinphoneTransportTls,FALSE);
}else{
fill_transport_combo_box(combo,linphone_address_get_transport(laddr),TRUE);
}
linphone_address_destroy(laddr);
}
}
void linphone_gtk_proxy_transport_changed(GtkWidget *combo){
GtkWidget *w=gtk_widget_get_toplevel(combo);
int index=gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
GtkWidget *proxy=linphone_gtk_get_widget(w,"proxy");
const char *addr=gtk_entry_get_text(GTK_ENTRY(proxy));
LinphoneAddress *laddr;
LinphoneTransportType new_transport=(LinphoneTransportType)index;
if (index==-1) return;
g_object_set_data(G_OBJECT(w),"combo-updating",GINT_TO_POINTER(1));
laddr=linphone_address_new(addr);
if (laddr){
if (linphone_address_get_transport(laddr)!=new_transport){
char *newaddr;
linphone_address_set_transport(laddr,new_transport);
newaddr=linphone_address_as_string(laddr);
gtk_entry_set_text(GTK_ENTRY(proxy),newaddr);
ms_free(newaddr);
}
linphone_address_destroy(laddr);
}
g_object_set_data(G_OBJECT(w),"combo-updating",GINT_TO_POINTER(0));
}
void linphone_gtk_proxy_address_changed(GtkEditable *editable){
update_proxy_transport(gtk_widget_get_toplevel(GTK_WIDGET(editable)));
}
void linphone_gtk_show_proxy_config(GtkWidget *pb, LinphoneProxyConfig *cfg){
GtkWidget *w=linphone_gtk_create_window("sip_account");
const char *tmp;
@ -698,8 +726,7 @@ void linphone_gtk_show_proxy_config(GtkWidget *pb, LinphoneProxyConfig *cfg){
linphone_proxy_config_edit(cfg);
gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(w,"identity")),
linphone_proxy_config_get_identity(cfg));
gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(w,"proxy")),
linphone_proxy_config_get_addr(cfg));
gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(w,"proxy")),linphone_proxy_config_get_addr(cfg));
tmp=linphone_proxy_config_get_route(cfg);
if (tmp) gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(w,"route")),tmp);
tmp=linphone_proxy_config_get_contact_parameters(cfg);
@ -723,17 +750,36 @@ void linphone_gtk_proxy_cancel(GtkButton *button){
}
void linphone_gtk_proxy_ok(GtkButton *button){
LinphoneCore *lc=linphone_gtk_get_core();
GtkWidget *w=gtk_widget_get_toplevel(GTK_WIDGET(button));
LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)g_object_get_data(G_OBJECT(w),"config");
int index=gtk_combo_box_get_active(GTK_COMBO_BOX(linphone_gtk_get_widget(w,"transport")));
LinphoneTransportType tport=(LinphoneTransportType)index;
gboolean was_editing=TRUE;
if (!cfg){
was_editing=FALSE;
cfg=linphone_proxy_config_new();
}
linphone_proxy_config_set_identity(cfg,
gtk_entry_get_text(GTK_ENTRY(linphone_gtk_get_widget(w,"identity"))));
linphone_proxy_config_set_server_addr(cfg,
gtk_entry_get_text(GTK_ENTRY(linphone_gtk_get_widget(w,"proxy"))));
if (linphone_proxy_config_set_server_addr(cfg,
gtk_entry_get_text(GTK_ENTRY(linphone_gtk_get_widget(w,"proxy"))))==0){
if (index!=-1){
/*make sure transport was added to proxy address*/
LinphoneAddress *laddr=linphone_address_new(linphone_proxy_config_get_addr(cfg));
if (laddr){
if (linphone_address_get_transport(laddr)!=tport){
char *tmp;
linphone_address_set_transport(laddr,tport);
tmp=linphone_address_as_string(laddr);
linphone_proxy_config_set_server_addr(cfg,tmp);
ms_free(tmp);
}
linphone_address_destroy(laddr);
}
}
}
linphone_proxy_config_set_route(cfg,
gtk_entry_get_text(GTK_ENTRY(linphone_gtk_get_widget(w,"route"))));
linphone_proxy_config_set_contact_parameters(cfg,
@ -747,6 +793,17 @@ void linphone_gtk_proxy_ok(GtkButton *button){
linphone_proxy_config_enable_register(cfg,
gtk_toggle_button_get_active(
GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"register"))));
/* check if tls was asked but is not enabled in transport configuration*/
if (tport==LinphoneTransportTls){
LCSipTransports tports;
linphone_core_get_sip_transports(lc,&tports);
if (tports.tls_port==LC_SIP_TRANSPORT_DISABLED){
tports.tls_port=LC_SIP_TRANSPORT_RANDOM;
}
linphone_core_set_sip_transports(lc,&tports);
}
if (was_editing){
if (linphone_proxy_config_done(cfg)==-1)
return;
@ -901,14 +958,6 @@ void linphone_gtk_lang_changed(GtkComboBox *combo){
}
}
void linphone_gtk_proto_changed(GtkComboBox *combo){
GtkWidget *pb=gtk_widget_get_toplevel(GTK_WIDGET(combo));
GtkWidget *proto_port = linphone_gtk_get_widget(pb, "proto_port");
// When we change the network protocol, we call update_my_port to move the port number from the old protocol to the new one
linphone_gtk_update_my_port(proto_port);
}
static void linphone_gtk_ui_level_adapt(GtkWidget *top) {
gboolean ui_advanced;
const char *simple_ui = linphone_gtk_get_ui_config("simple_ui", "parameters.codec_tab parameters.transport_frame parameters.ports_frame");
@ -1074,6 +1123,48 @@ void linphone_gtk_fill_video_renderers(GtkWidget *pb){
if (active!=-1) gtk_combo_box_set_active(GTK_COMBO_BOX(combo),active);
}
typedef struct {
guint timeout_id;
LCSipTransports tp;
}PortConfigCtx;
static void port_config_free(PortConfigCtx *ctx){
g_free(ctx);
}
static void apply_transports(PortConfigCtx *ctx){
GtkWidget *mw=linphone_gtk_get_main_window();
LCSipTransports tp;
LinphoneCore *lc=linphone_gtk_get_core();
linphone_core_get_sip_transports(lc,&tp);
tp.udp_port=ctx->tp.udp_port;
tp.tcp_port=ctx->tp.tcp_port;
linphone_core_set_sip_transports(lc,&tp);
g_object_set_data(G_OBJECT(mw),"port_config",NULL);
}
static void transport_changed(GtkWidget *parameters){
GtkWidget *mw=linphone_gtk_get_main_window();
PortConfigCtx *cfg=(PortConfigCtx*)g_object_get_data(G_OBJECT(mw),"port_config");
if (cfg==NULL){
cfg=g_new0(PortConfigCtx,1);
g_object_set_data_full(G_OBJECT(mw),"port_config",cfg,(GDestroyNotify)port_config_free);
}
if (cfg->timeout_id!=0)
g_source_remove(cfg->timeout_id);
cfg->tp.udp_port=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(linphone_gtk_get_widget(parameters,"sip_udp_port")));
cfg->tp.tcp_port=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(linphone_gtk_get_widget(parameters,"sip_tcp_port")));
cfg->timeout_id=g_timeout_add_seconds(2,(GSourceFunc)apply_transports,cfg);
}
void linphone_gtk_udp_port_value_changed(GtkSpinButton *button){
transport_changed(gtk_widget_get_toplevel((GtkWidget*)button));
}
void linphone_gtk_tcp_port_value_changed(GtkSpinButton *button){
transport_changed(gtk_widget_get_toplevel((GtkWidget*)button));
}
void linphone_gtk_show_parameters(void){
GtkWidget *mw=linphone_gtk_get_main_window();
GtkWidget *pb=(GtkWidget*)g_object_get_data(G_OBJECT(mw),"parameters");
@ -1101,21 +1192,11 @@ void linphone_gtk_show_parameters(void){
linphone_core_ipv6_enabled(lc));
linphone_core_get_sip_transports(lc,&tr);
if (tr.tcp_port > 0) {
gtk_combo_box_set_active(GTK_COMBO_BOX(linphone_gtk_get_widget(pb,"proto_combo")), 1);
gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb,"proto_port")),
tr.tcp_port);
}
else if (tr.tls_port > 0) {
gtk_combo_box_set_active(GTK_COMBO_BOX(linphone_gtk_get_widget(pb,"proto_combo")), 2);
gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb,"proto_port")),
tr.tls_port);
}
else {
gtk_combo_box_set_active(GTK_COMBO_BOX(linphone_gtk_get_widget(pb,"proto_combo")), 0);
gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb,"proto_port")),
gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb,"sip_udp_port")),
tr.udp_port);
}
gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb,"sip_tcp_port")),
tr.tcp_port);
linphone_core_get_audio_port_range(lc, &min_port, &max_port);
gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb, "audio_min_rtp_port")), min_port);
@ -1214,10 +1295,6 @@ void linphone_gtk_show_parameters(void){
ui_advanced);
linphone_gtk_ui_level_adapt(pb);
g_signal_connect(G_OBJECT(linphone_gtk_get_widget(pb,"proto_port")),"value-changed",(GCallback)linphone_gtk_update_my_port,NULL);
g_signal_connect(G_OBJECT(linphone_gtk_get_widget(pb,"proto_combo")),"changed",(GCallback)linphone_gtk_proto_changed,NULL);
if (linphone_core_tunnel_available()){
gtk_widget_set_visible(GTK_WIDGET(linphone_gtk_get_widget(pb,"tunnel_edit_button")), TRUE);
gtk_widget_set_visible(GTK_WIDGET(linphone_gtk_get_widget(pb,"tunnel_label")), TRUE);

View file

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<!-- interface-requires gtk+ 2.6 -->
<!-- interface-naming-policy toplevel-contextual -->
<object class="GtkAdjustment" id="adjustment1">
<property name="upper">100000</property>
<property name="value">3600</property>
@ -15,13 +16,13 @@
<property name="window_position">center-on-parent</property>
<property name="type_hint">dialog</property>
<child internal-child="vbox">
<object class="GtkBox" id="dialog-vbox2">
<object class="GtkVBox" id="dialog-vbox2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="spacing">2</property>
<child internal-child="action_area">
<object class="GtkButtonBox" id="dialog-action_area2">
<object class="GtkHButtonBox" id="dialog-action_area2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
@ -91,7 +92,7 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="n_rows">5</property>
<property name="n_rows">6</property>
<property name="n_columns">2</property>
<child>
<object class="GtkLabel" id="label38">
@ -112,6 +113,8 @@
<property name="text" translatable="yes">sip:</property>
<property name="primary_icon_activatable">False</property>
<property name="secondary_icon_activatable">False</property>
<property name="primary_icon_sensitive">True</property>
<property name="secondary_icon_sensitive">True</property>
</object>
<packing>
<property name="left_attach">1</property>
@ -140,6 +143,9 @@
<property name="text" translatable="yes">sip:</property>
<property name="primary_icon_activatable">False</property>
<property name="secondary_icon_activatable">False</property>
<property name="primary_icon_sensitive">True</property>
<property name="secondary_icon_sensitive">True</property>
<signal name="changed" handler="linphone_gtk_proxy_address_changed" swapped="no"/>
</object>
<packing>
<property name="left_attach">1</property>
@ -148,19 +154,6 @@
<property name="bottom_attach">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label40">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label" translatable="yes">Route (optional):</property>
<property name="justify">right</property>
</object>
<packing>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="route">
<property name="visible">True</property>
@ -168,12 +161,14 @@
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="primary_icon_activatable">False</property>
<property name="secondary_icon_activatable">False</property>
<property name="primary_icon_sensitive">True</property>
<property name="secondary_icon_sensitive">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
</packing>
</child>
<child>
@ -185,24 +180,26 @@
<property name="justify">right</property>
</object>
<packing>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
</packing>
</child>
<child>
<object class="GtkSpinButton" id="regperiod">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="primary_icon_activatable">False</property>
<property name="secondary_icon_activatable">False</property>
<property name="primary_icon_sensitive">True</property>
<property name="secondary_icon_sensitive">True</property>
<property name="adjustment">adjustment1</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
</packing>
</child>
<child>
@ -210,12 +207,12 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label" translatable="yes">Contact params:</property>
<property name="label" translatable="yes">Contact params (optional):</property>
<property name="justify">right</property>
</object>
<packing>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="top_attach">5</property>
<property name="bottom_attach">6</property>
</packing>
</child>
<child>
@ -228,15 +225,53 @@
<property name="invisible_char_set">True</property>
<property name="primary_icon_activatable">False</property>
<property name="secondary_icon_activatable">False</property>
<property name="primary_icon_sensitive">True</property>
<property name="secondary_icon_sensitive">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">5</property>
<property name="bottom_attach">6</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label40">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label" translatable="yes">Route (optional):</property>
<property name="justify">right</property>
</object>
<packing>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Transport</property>
</object>
<packing>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
</packing>
</child>
<child>
<object class="GtkComboBox" id="transport">
<property name="visible">True</property>
<property name="can_focus">False</property>
<signal name="changed" handler="linphone_gtk_proxy_transport_changed" swapped="no"/>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
</packing>
</child>
</object>
<packing>
<property name="expand">True</property>

View file

@ -85,12 +85,9 @@ const char *sal_address_get_display_name(const SalAddress* addr);
const char *sal_address_get_display_name_unquoted(const SalAddress *addr);
const char *sal_address_get_username(const SalAddress *addr);
const char *sal_address_get_domain(const SalAddress *addr);
#ifdef USE_BELLESIP
int sal_address_get_port(const SalAddress *addr);
#else
const char * sal_address_get_port(const SalAddress *addr);
int sal_address_get_port_int(const SalAddress *addr);
#endif
bool_t sal_address_is_secure(const SalAddress *addr);
SalTransport sal_address_get_transport(const SalAddress* addr);
const char* sal_address_get_transport_name(const SalAddress* addr);
@ -169,11 +166,13 @@ typedef struct SalIceRemoteCandidate {
#define SAL_MEDIA_DESCRIPTION_MAX_ICE_UFRAG_LEN 256
#define SAL_MEDIA_DESCRIPTION_MAX_ICE_PWD_LEN 256
#define SAL_SRTP_KEY_SIZE 41
typedef struct SalSrtpCryptoAlgo {
unsigned int tag;
enum ortp_srtp_crypto_suite_t algo;
/* 41= 40 max(key_length for all algo) + '\0' */
char master_key[41];
char master_key[SAL_SRTP_KEY_SIZE];
} SalSrtpCryptoAlgo;
#define SAL_CRYPTO_ALGO_MAX 4
@ -331,6 +330,29 @@ typedef enum SalTextDeliveryStatus{
SalTextDeliveryFailed
}SalTextDeliveryStatus;
/**
* auth event mode
* */
typedef enum SalAuthMode { /*this enum must be same as belle_sip_auth_mode_t*/
SalAuthModeHttpDigest, /** Digest authentication requested*/
SalAuthModeTls /** Client certificate requested*/
}SalAuthMode;
struct _SalCertificatesChain;
typedef struct _SalCertificatesChain SalCertificatesChain;
struct _SalSigningKey;
typedef struct _SalSigningKey SalSigningKey;
/**
* Format of certificate buffer
* */
typedef enum SalCertificateRawFormat {/*this enum must be same as belle_sip_certificate_raw_format_t*/
SAL_CERTIFICATE_RAW_FORMAT_PEM, /** PEM format*/
SAL_CERTIFICATE_RAW_FORMAT_DER /** ASN.1 raw format*/
}SalCertificateRawFormat;
typedef struct SalAuthInfo{
char *username;
char *userid;
@ -338,6 +360,9 @@ typedef struct SalAuthInfo{
char *realm;
char *domain;
char *ha1;
SalAuthMode mode;
SalSigningKey *key;
SalCertificatesChain *certificates;
}SalAuthInfo;
typedef struct SalBody{
@ -424,10 +449,34 @@ SalAuthInfo* sal_auth_info_new();
SalAuthInfo* sal_auth_info_clone(const SalAuthInfo* auth_info);
void sal_auth_info_delete(SalAuthInfo* auth_info);
LINPHONE_PUBLIC int sal_auth_compute_ha1(const char* userid,const char* realm,const char* password, char ha1[33]);
SalAuthMode sal_auth_info_get_mode(const SalAuthInfo* auth_info);
SalSigningKey *sal_auth_info_get_signing_key(const SalAuthInfo* auth_info);
SalCertificatesChain *sal_auth_info_get_certificates_chain(const SalAuthInfo* auth_info);
void sal_auth_info_set_mode(SalAuthInfo* auth_info, SalAuthMode mode);
/** 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);
/**
* 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);
void sal_certificates_chain_delete(SalCertificatesChain *chain);
void sal_signing_key_delete(SalSigningKey *key);
void sal_set_callbacks(Sal *ctx, const SalCallbacks *cbs);
int sal_listen_port(Sal *ctx, const char *addr, int port, SalTransport tr, int is_secure);
int sal_unlisten_ports(Sal *ctx);
int sal_transport_available(Sal *ctx, SalTransport t);
void sal_set_dscp(Sal *ctx, int dscp);
int sal_reset_transports(Sal *ctx);
ortp_socket_t sal_get_socket(Sal *ctx);
@ -594,8 +643,10 @@ void sal_get_default_local_ip(Sal *sal, int address_family, char *ip, size_t ipl
typedef void (*SalResolverCallback)(void *data, const char *name, struct addrinfo *ai_list);
unsigned long sal_resolve_a(Sal* sal, const char *name, int port, int family, SalResolverCallback cb, void *data);
void sal_resolve_cancel(Sal *sal, unsigned long id);
typedef struct SalResolverContext SalResolverContext;
SalResolverContext * sal_resolve_a(Sal* sal, const char *name, int port, int family, SalResolverCallback cb, void *data);
//void sal_resolve_cancel(Sal *sal, SalResolverContext *ctx);
SalCustomHeader *sal_custom_header_append(SalCustomHeader *ch, const char *name, const char *value);
const char *sal_custom_header_find(const SalCustomHeader *ch, const char *name);
@ -636,4 +687,10 @@ LINPHONE_PUBLIC void sal_set_dns_timeout(Sal* sal,int timeout);
LINPHONE_PUBLIC int sal_get_dns_timeout(const Sal* sal);
LINPHONE_PUBLIC void sal_set_dns_user_hosts_file(Sal *sal, const char *hosts_file);
LINPHONE_PUBLIC const char *sal_get_dns_user_hosts_file(const Sal *sal);
unsigned char * sal_get_random_bytes(unsigned char *ret, size_t size);
int sal_body_has_type(const SalBody *body, const char *type, const char *subtype);
/*this function parses a document with key=value pairs separated by new lines, and extracts the value for a given key*/
int sal_lines_get_value(const char *data, const char *key, char *value, size_t value_size);
#endif

View file

@ -17,11 +17,19 @@ public interface LinphoneContent {
* @return the subtype
*/
String getSubtype();
/**
* Get the encoding applied to the data, can be null if no encoding.
**/
String getEncoding();
/**
* Get the data as a string.
* @return the data
*/
String getDataAsString();
/**
* Get the data as a byte array.
**/
byte [] getData();
/**
* Get the data size.
* @return the data size.
@ -38,9 +46,17 @@ public interface LinphoneContent {
* @param subtype the subtype
*/
void setSubtype(String subtype);
/**
* Set the encoding applied to the data, can be null if no encoding.
**/
void setEncoding(String encoding);
/**
* Set the data, supplied as String.
* @param data the data
*/
void setStringData(String data);
/**
* Set the data, as a byte buffer.
**/
void setData(byte data[]);
}

View file

@ -108,10 +108,15 @@ abstract public class LinphoneCoreFactory {
abstract public LinphoneFriend createLinphoneFriend();
/**
* Create a LinphoneContent object
* Create a LinphoneContent object from string data.
*/
abstract public LinphoneContent createLinphoneContent(String type, String subType, String data);
/**
* Create a LinphoneContent object from byte array.
*/
abstract public LinphoneContent createLinphoneContent(String type, String subType,byte [] data, String encoding);
/**
* Create a PresenceActivity object.
*/

View file

@ -1,11 +1,14 @@
package org.linphone.core;
public class LinphoneContentImpl implements LinphoneContent {
private String mType, mSubtype, mData;
public LinphoneContentImpl(String type, String subtype, String data){
private String mType, mSubtype, mEncoding;
private byte[] mData;
public LinphoneContentImpl(String type, String subtype, byte data[], String encoding ){
mType=type;
mSubtype=subtype;
mData=data;
mEncoding=encoding;
}
@Override
@ -20,12 +23,12 @@ public class LinphoneContentImpl implements LinphoneContent {
@Override
public String getDataAsString() {
return mData;
return new String(mData);
}
@Override
public int getSize() {
return mData.length();
return mData.length;
}
@Override
@ -40,7 +43,27 @@ public class LinphoneContentImpl implements LinphoneContent {
@Override
public void setStringData(String data) {
mData=data.getBytes();
}
@Override
public void setData(byte data[]){
mData=data;
}
@Override
public String getEncoding() {
return mEncoding;
}
@Override
public byte[] getData() {
return mData;
}
@Override
public void setEncoding(String encoding) {
mEncoding=encoding;
}
}

View file

@ -151,10 +151,16 @@ public class LinphoneCoreFactoryImpl extends LinphoneCoreFactory {
return new LinphoneAuthInfoImpl(username, userid, passwd, ha1, realm, domain);
}
@Override
public LinphoneContent createLinphoneContent(String type, String subType,
byte [] data, String encoding) {
return new LinphoneContentImpl(type,subType,data,encoding);
}
@Override
public LinphoneContent createLinphoneContent(String type, String subType,
String data) {
return new LinphoneContentImpl(type,subType,data);
return new LinphoneContentImpl(type,subType,data.getBytes(),null);
}
@Override

View file

@ -1028,19 +1028,21 @@ class LinphoneCoreImpl implements LinphoneCore {
return new LinphoneInfoMessageImpl(createInfoMessage(nativePtr));
}
private native Object subscribe(long coreptr, long addrptr, String eventname, int expires, String type, String subtype, String data);
private native Object subscribe(long coreptr, long addrptr, String eventname, int expires, String type, String subtype, byte data [], String encoding);
@Override
public LinphoneEvent subscribe(LinphoneAddress resource, String eventname,
int expires, LinphoneContent content) {
return (LinphoneEvent)subscribe(nativePtr, ((LinphoneAddressImpl)resource).nativePtr, eventname, expires,
content!=null ? content.getType() : null, content!=null ? content.getSubtype() : null, content!=null ? content.getDataAsString() : null);
content!=null ? content.getType() : null, content!=null ? content.getSubtype() : null, content!=null ? content.getData() : null,
content!=null ? content.getEncoding() : null);
}
private native Object publish(long coreptr, long addrptr, String eventname, int expires, String type, String subtype, String data);
private native Object publish(long coreptr, long addrptr, String eventname, int expires, String type, String subtype, byte data [], String encoding);
@Override
public LinphoneEvent publish(LinphoneAddress resource, String eventname,
int expires, LinphoneContent content) {
return (LinphoneEvent)publish(nativePtr, ((LinphoneAddressImpl)resource).nativePtr, eventname, expires,
content!=null ? content.getType() : null, content!=null ? content.getSubtype() : null, content!=null ? content.getDataAsString() : null);
content!=null ? content.getType() : null, content!=null ? content.getSubtype() : null, content!=null ? content.getData() : null,
content!=null ? content.getEncoding() : null);
}
public void setChatDatabasePath(String path) {

View file

@ -26,22 +26,22 @@ public class LinphoneEventImpl implements LinphoneEvent {
denySubscription(mNativePtr,reason.mValue);
}
private native int notify(long nativeptr, String type, String subtype, String data);
private native int notify(long nativeptr, String type, String subtype, byte data[], String encoding);
@Override
public void notify(LinphoneContent content) {
notify(mNativePtr,content.getType(),content.getSubtype(),content.getDataAsString());
notify(mNativePtr,content.getType(),content.getSubtype(),content.getData(),content.getEncoding());
}
private native int updateSubscribe(long nativePtr, String type, String subtype, String data);
private native int updateSubscribe(long nativePtr, String type, String subtype, byte data[], String encoding);
@Override
public void updateSubscribe(LinphoneContent content) {
updateSubscribe(mNativePtr,content.getType(), content.getSubtype(),content.getDataAsString());
updateSubscribe(mNativePtr,content.getType(), content.getSubtype(),content.getData(),content.getEncoding());
}
private native int updatePublish(long nativePtr, String type, String subtype, String data);
private native int updatePublish(long nativePtr, String type, String subtype, byte data[], String encoding);
@Override
public void updatePublish(LinphoneContent content) {
updatePublish(mNativePtr,content.getType(), content.getSubtype(),content.getDataAsString());
updatePublish(mNativePtr,content.getType(), content.getSubtype(),content.getData(),content.getEncoding());
}
private native int terminate(long nativePtr);

@ -1 +1 @@
Subproject commit 785a5d8f76c336a51f8a21997e9dcaee669d4ec4
Subproject commit 8deb23a1b03e343b753d2e896347453ada72e4df

View file

@ -382,12 +382,16 @@ static void call_failed_because_of_codecs(void) {
static void call_with_dns_time_out(void) {
LinphoneCoreManager* marie = linphone_core_manager_new2( "empty_rc", FALSE);
LCSipTransports transport = {9773,0,0,0};
int i;
linphone_core_set_sip_transports(marie->lc,&transport);
linphone_core_iterate(marie->lc);
sal_set_dns_timeout(marie->lc->sal,0);
linphone_core_invite(marie->lc,"sip:toto@toto.com");
linphone_core_iterate(marie->lc);
linphone_core_iterate(marie->lc);
for(i=0;i<10;i++){
ms_usleep(200000);
linphone_core_iterate(marie->lc);
}
CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallOutgoingInit,1);
CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallOutgoingProgress,1);
CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallError,1);
@ -1023,9 +1027,10 @@ static void srtp_ice_call(void) {
CU_ASSERT_TRUE(check_ice(pauline,marie,LinphoneIceStateHostConnection));
check_rtcp(marie,pauline);
#endif
/*wait for ice to found the direct path*/
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_IframeDecoded,1));
#endif
/*just to sleep*/
linphone_core_terminate_all_calls(marie->lc);

View file

@ -107,7 +107,7 @@ static LinphoneCore* configure_lc_from(LinphoneCoreVTable* v_table, const char*
lc = linphone_core_new(v_table,NULL,*filepath!='\0' ? filepath : NULL,NULL);
sal_enable_test_features(lc->sal,TRUE);
snprintf(rootcapath, sizeof(rootcapath), "%s/certificates/cn/cacert.pem", path);
snprintf(rootcapath, sizeof(rootcapath), "%s/certificates/cn/cafile.pem", path);
linphone_core_set_root_ca(lc,rootcapath);
sprintf(dnsuserhostspath, "%s/%s", path, userhostsfile);
@ -178,7 +178,7 @@ LinphoneCoreManager *get_manager(LinphoneCore *lc){
LinphoneCoreManager* linphone_core_manager_new2(const char* rc_file, int check_for_proxies) {
LinphoneCoreManager* mgr= ms_new0(LinphoneCoreManager,1);
LinphoneProxyConfig* proxy;
int proxy_count=check_for_proxies?(rc_file?1:0):0;
int proxy_count;
int retry=0;
mgr->v_table.registration_state_changed=registration_state_changed;
@ -197,8 +197,12 @@ LinphoneCoreManager* linphone_core_manager_new2(const char* rc_file, int check_f
linphone_core_set_user_data(mgr->lc,mgr);
reset_counters(&mgr->stat);
/*CU_ASSERT_EQUAL(ms_list_size(linphone_core_get_proxy_config_list(lc)),proxy_count);*/
if (check_for_proxies && rc_file) /**/
proxy_count=ms_list_size(linphone_core_get_proxy_config_list(mgr->lc));
else
proxy_count=0;
while (mgr->stat.number_of_LinphoneRegistrationOk<proxy_count && retry++ <20) {
while (mgr->stat.number_of_LinphoneRegistrationOk<proxy_count && retry++ <(20+ (proxy_count>2?(proxy_count-2)*10:0))) {
linphone_core_iterate(mgr->lc);
ms_usleep(100000);
}

View file

@ -220,7 +220,7 @@ static void info_message_with_args(bool_t with_content) {
info=linphone_core_create_info_message(marie->lc);
linphone_info_message_add_header(info,"Weather","still bad");
if (with_content) {
LinphoneContent ct;
LinphoneContent ct={0};
ct.type="application";
ct.subtype="somexml";
ct.data=(void*)info_content;

View file

@ -537,7 +537,7 @@ static void tls_certificate_failure(){
linphone_core_set_root_ca(mgr->lc,NULL); /*no root ca*/
linphone_core_refresh_registers(mgr->lc);
CU_ASSERT_TRUE(wait_for(lc,lc,&mgr->stat.number_of_LinphoneRegistrationFailed,2));
snprintf(rootcapath,sizeof(rootcapath), "%s/certificates/cn/cacert.pem", liblinphone_tester_file_prefix); /*goot root ca*/
snprintf(rootcapath,sizeof(rootcapath), "%s/certificates/cn/cafile.pem", liblinphone_tester_file_prefix); /*goot root ca*/
linphone_core_set_root_ca(mgr->lc,rootcapath);
linphone_core_refresh_registers(mgr->lc);
CU_ASSERT_TRUE(wait_for(lc,lc,&mgr->stat.number_of_LinphoneRegistrationOk,1));
@ -575,7 +575,7 @@ static void tls_alt_name_register(){
mgr=linphone_core_manager_new2("pauline_alt_rc",FALSE);
lc=mgr->lc;
snprintf(rootcapath,sizeof(rootcapath), "%s/certificates/cn/cacert.pem", liblinphone_tester_file_prefix);
snprintf(rootcapath,sizeof(rootcapath), "%s/certificates/cn/cafile.pem", liblinphone_tester_file_prefix);
linphone_core_set_root_ca(mgr->lc,rootcapath);
linphone_core_refresh_registers(mgr->lc);
CU_ASSERT_TRUE(wait_for(lc,lc,&mgr->stat.number_of_LinphoneRegistrationOk,1));
@ -590,7 +590,7 @@ static void tls_wildcard_register(){
mgr=linphone_core_manager_new2("pauline_wild_rc",FALSE);
lc=mgr->lc;
snprintf(rootcapath,sizeof(rootcapath), "%s/certificates/cn/cacert.pem", liblinphone_tester_file_prefix);
snprintf(rootcapath,sizeof(rootcapath), "%s/certificates/cn/cafile.pem", liblinphone_tester_file_prefix);
linphone_core_set_root_ca(mgr->lc,rootcapath);
linphone_core_refresh_registers(mgr->lc);
CU_ASSERT_TRUE(wait_for(lc,lc,&mgr->stat.number_of_LinphoneRegistrationOk,2));

View file

@ -68,11 +68,35 @@ static void core_sip_transport_test(void) {
linphone_core_destroy(lc);
}
static void linphone_interpret_url_test()
{
LinphoneCoreVTable v_table;
LinphoneCore* lc;
const char* sips_address = "sips:margaux@sip.linphone.org";
LinphoneAddress* address;
memset ( &v_table,0,sizeof ( v_table ) );
lc = linphone_core_new ( &v_table,NULL,NULL,NULL );
CU_ASSERT_PTR_NOT_NULL_FATAL ( lc );
address = linphone_core_interpret_url(lc, sips_address);
CU_ASSERT_PTR_NOT_NULL_FATAL(address);
CU_ASSERT_STRING_EQUAL_FATAL(linphone_address_get_scheme(address), "sips");
CU_ASSERT_STRING_EQUAL_FATAL(linphone_address_get_username(address), "margaux");
CU_ASSERT_STRING_EQUAL_FATAL(linphone_address_get_domain(address), "sip.linphone.org");
linphone_address_destroy(address);
linphone_core_destroy ( lc );
}
test_t setup_tests[] = {
{ "Linphone Address", linphone_address_test },
{ "Linphone core init/uninit", core_init_test },
{ "Linphone random transport port",core_sip_transport_test}
{ "Linphone random transport port",core_sip_transport_test},
{ "Linphone interpret url", linphone_interpret_url_test }
};
test_suite_t setup_test_suite = {

View file

@ -12,7 +12,7 @@ COMMON_CFLAGS=\
$(LIBXML2_CFLAGS)
#-fpermissive to workaround a g++ bug on macos 32bit SDK.
AM_CXXFLAGS=$(LIBXML2_CFLAGS) $(STRICT_OPTIONS) -fpermissive
AM_CXXFLAGS=$(LIBXML2_CFLAGS) -fpermissive $(STRICT_OPTIONS)
EXTRA_DIST=xml2lpc_jni.cc lpc2xml_jni.cc