diff --git a/.gitignore b/.gitignore
index d5a842ef1..85a6aed1d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -76,3 +76,5 @@ tester/tmp.db
.DS_Store
Linphone.app
*.dmg
+tester/linphone*.log
+tester/linphone_log.txt
diff --git a/README.macos.md b/README.macos.md
index cbdd4c24c..6dd8b4625 100644
--- a/README.macos.md
+++ b/README.macos.md
@@ -34,7 +34,7 @@ In order to enable generation of bundle for multiple MacOS version and 32 bit pr
sudo port install gtk-osx-application -python27
sudo port install hicolor-icon-theme
- #### Using HomeBrew
+#### Using HomeBrew
brew install automake intltool libtool pkg-config coreutils \
yasm nasm wget imagemagick gettext gtk+ speex ffmpeg pygtk
@@ -112,25 +112,24 @@ The next pieces need to be compiled manually.
The libvpx build isn't able to produce dual architecture files. To workaround this, configure libvpx twice and use lipo to create a dual architecture `libvpx.a`.
* (Optional, proprietary extension only) Compile and install the tunnel library
-
If you got the source code from git, run `./autogen.sh` first.
Then or otherwise, do:
./configure --prefix=/opt/local && make && sudo make install
* Compile Linphone
-
If you got the source code from git, run `./autogen.sh` first.
+ Then or otherwise, :
- Then or otherwise, do:
-
- PKG_CONFIG_PATH=/usr/local/lib/pkgconfig ./configure --prefix=/opt/local --with-readline=/opt/local --disable-x11 --with-srtp=/opt/local --with-gsm=/opt/local --enable-zrtp --disable-strict && make
+ # HomeBrew
+ PKG_CONFIG_PATH=/usr/local/lib/pkgconfig ./configure --prefix=/opt/local --disable-x11 --with-srtp=/opt/local --with-gsm=/opt/local --enable-zrtp --disable-strict --with-readline=/usr/local && make
+ # MacPorts
+ PKG_CONFIG_PATH=/usr/local/lib/pkgconfig ./configure --prefix=/opt/local --disable-x11 --with-srtp=/opt/local --with-gsm=/opt/local --enable-zrtp --disable-strict --with-readline=/opt/local && make
* Install on the system
sudo make install
-
-You are done.
+ You are done.
### Generate portable bundle
diff --git a/build/android/Android.mk b/build/android/Android.mk
index d8c8a1269..fe020f4f4 100755
--- a/build/android/Android.mk
+++ b/build/android/Android.mk
@@ -258,9 +258,7 @@ LOCAL_EXPORT_CFLAGS := $(LOCAL_CFLAGS)
ifeq ($(_BUILD_VIDEO),1)
LOCAL_SHARED_LIBRARIES += \
- libavcodec-linphone \
- libswscale-linphone \
- libavutil-linphone
+ libffmpeg-linphone
endif
LOCAL_MODULE := liblinphone
diff --git a/build/android/liblinphone_tester.mk b/build/android/liblinphone_tester.mk
index b23a381bd..430f203be 100644
--- a/build/android/liblinphone_tester.mk
+++ b/build/android/liblinphone_tester.mk
@@ -14,8 +14,10 @@ common_SRC_FILES := \
tester.c \
remote_provisioning_tester.c \
quality_reporting_tester.c \
+ log_collection_tester.c \
transport_tester.c \
- player_tester.c
+ player_tester.c \
+ dtmf_tester.c
common_C_INCLUDES += \
$(LOCAL_PATH) \
diff --git a/build/wp8/LibLinphone.vcxproj b/build/wp8/LibLinphone.vcxproj
index 876c93d2a..cca41bb87 100644
--- a/build/wp8/LibLinphone.vcxproj
+++ b/build/wp8/LibLinphone.vcxproj
@@ -53,8 +53,8 @@
Level4
- $(ProjectDir)..\..\..\belle-sip\include;$(ProjectDir)..\..\oRTP\include;$(ProjectDir)..\..\mediastreamer2\include;$(ProjectDir)..\..\..\tunnel\include;$(ProjectDir)..\..\coreapi;$(ProjectDir)..\..\include;$(SolutionDir)$(Platform)\$(Configuration)\include;$(ProjectDir)..\..\..\zlib;$(ProjectDir)..\..\..\sqlite\;%(AdditionalIncludeDirectories)
- __STDC_CONSTANT_MACROS;_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;_USRDLL;WINDOW_NATIVE;_TRUE_TIME;IN_LINPHONE;USE_BELLESIP;TUNNEL_ENABLED;VIDEO_ENABLED;LINPHONE_PACKAGE_NAME="linphone";LINPHONE_VERSION="Devel";LIBLINPHONE_EXPORTS;LINPHONE_PLUGINS_DIR=".";UNICODE;_XKEYCHECK_H;HAVE_ZLIB;%(PreprocessorDefinitions)
+ $(ProjectDir)..\..\..\belle-sip\include;$(ProjectDir)..\..\oRTP\include;$(ProjectDir)..\..\mediastreamer2\include;$(ProjectDir)..\..\..\tunnel\include;$(ProjectDir)..\..\coreapi;$(ProjectDir)..\..\include;$(SolutionDir)$(Platform)\$(Configuration)\include;$(ProjectDir)..\..\..\zlib;$(ProjectDir)..\..\..\sqlite\;$(ProjectDir);%(AdditionalIncludeDirectories)
+ __STDC_CONSTANT_MACROS;_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;_USRDLL;WINDOW_NATIVE;_TRUE_TIME;IN_LINPHONE;USE_BELLESIP;TUNNEL_ENABLED;VIDEO_ENABLED;LINPHONE_PACKAGE_NAME="linphone";LIBLINPHONE_EXPORTS;LINPHONE_PLUGINS_DIR=".";UNICODE;_XKEYCHECK_H;HAVE_ZLIB;HAVE_CONFIG_H;%(PreprocessorDefinitions)
Default
NotUsing
false
@@ -68,9 +68,12 @@
$(SolutionDir)$(Platform)\$(Configuration);%(AdditionalLibraryDirectories)
$(TargetDir)$(TargetName).lib
-
- $(TargetDir)$(TargetName)_dll.lib;%(Outputs)
-
+
+ version.bat
+
+
+ Batch script to get the git version
+
@@ -152,6 +155,8 @@
+
+
diff --git a/build/wp8/LibLinphoneTester-native/LibLinphoneTester-native.vcxproj b/build/wp8/LibLinphoneTester-native/LibLinphoneTester-native.vcxproj
index 0512be517..6bc245f9f 100644
--- a/build/wp8/LibLinphoneTester-native/LibLinphoneTester-native.vcxproj
+++ b/build/wp8/LibLinphoneTester-native/LibLinphoneTester-native.vcxproj
@@ -100,12 +100,15 @@
+
+
+
true
diff --git a/build/wp8/version.bat b/build/wp8/version.bat
new file mode 100644
index 000000000..55ee42831
--- /dev/null
+++ b/build/wp8/version.bat
@@ -0,0 +1,22 @@
+@ECHO off
+
+SET gitlog=
+FOR /f "delims=" %%a IN ('git log -1 "--pretty=format:%%H" ../../configure.ac') DO SET gitlog=%%a
+
+IF [%gitlog%] == [] GOTO UnknownGitVersion
+
+FOR /f "delims=" %%a IN ('git describe --always') DO SET gitdescribe=%%a
+GOTO End
+
+:UnknownGitVersion
+SET gitdescribe=unknown
+
+:End
+ECHO #define LIBLINPHONE_GIT_VERSION "%gitdescribe%" > liblinphone_gitversion.h
+
+
+FOR /F "delims=" %%a IN ('findstr /B AC_INIT ..\..\configure.ac') DO (
+ FOR /F "tokens=1,2,3 delims=[,]" %%1 IN ("%%a") DO (
+ ECHO #define LIBLINPHONE_VERSION "%%3" > config.h
+ )
+)
diff --git a/coreapi/TunnelManager.cc b/coreapi/TunnelManager.cc
index 77e26fb1b..9b4cebda3 100644
--- a/coreapi/TunnelManager.cc
+++ b/coreapi/TunnelManager.cc
@@ -106,6 +106,7 @@ void TunnelManager::startClient() {
}
mTunnelClient->setHttpProxy(mHttpProxyHost.c_str(), mHttpProxyPort, mHttpUserName.c_str(), mHttpPasswd.c_str());
mTunnelClient->start();
+ sal_set_tunnel(mCore->sal, mTunnelClient);
}
bool TunnelManager::isConnected() const {
@@ -185,12 +186,13 @@ void TunnelManager::processTunnelEvent(const Event &ev){
ms_message("TunnelManager: tunnel is connected");
if(mState == connecting) {
linphone_core_set_rtp_transport_factories(mCore,&mTransportFactories);
+ mState = ready;
if(mTunnelizeSipPackets) {
doUnregistration();
- sal_enable_tunnel(mCore->sal, mTunnelClient);
+ _linphone_core_apply_transports(mCore);
doRegistration();
}
- mState = ready;
+
}
} else {
ms_error("TunnelManager: tunnel has been disconnected");
@@ -219,17 +221,15 @@ void TunnelManager::setMode(LinphoneTunnelMode mode) {
case LinphoneTunnelModeDisable:
if(mState == ready) {
linphone_core_set_rtp_transport_factories(mCore,NULL);
- if(mTunnelizeSipPackets) {
- doUnregistration();
- sal_disable_tunnel(mCore->sal);
- }
- delete mTunnelClient;
- mTunnelClient=NULL;
- if(mTunnelizeSipPackets) {
- doRegistration();
- }
mState = disabled;
mMode = mode;
+ if(mTunnelizeSipPackets) {
+ doUnregistration();
+ _linphone_core_apply_transports(mCore);
+ }
+ sal_set_tunnel(mCore->sal,NULL);
+ delete mTunnelClient;
+ mTunnelClient=NULL;
} else {
ms_error("TunnelManager: could not change mode. Bad state");
}
@@ -385,6 +385,18 @@ bool TunnelManager::startAutoDetection() {
return true;
}
+bool TunnelManager::isActivated() const{
+ switch(getMode()){
+ case LinphoneTunnelModeAuto:
+ return !mState==disabled;
+ case LinphoneTunnelModeDisable:
+ return false;
+ case LinphoneTunnelModeEnable:
+ return true;
+ }
+ return false;
+}
+
void TunnelManager::setHttpProxyAuthInfo(const char* username,const char* passwd) {
mHttpUserName=username?username:"";
mHttpPasswd=passwd?passwd:"";
@@ -392,7 +404,7 @@ void TunnelManager::setHttpProxyAuthInfo(const char* username,const char* passwd
}
void TunnelManager::tunnelizeSipPackets(bool enable){
- mTunnelizeSipPackets = enable;
+ mTunnelizeSipPackets = enable;
}
bool TunnelManager::tunnelizeSipPacketsEnabled() const {
diff --git a/coreapi/TunnelManager.hh b/coreapi/TunnelManager.hh
index 58475aab3..0af89fce9 100644
--- a/coreapi/TunnelManager.hh
+++ b/coreapi/TunnelManager.hh
@@ -142,6 +142,7 @@ namespace belledonnecomm {
*/
bool isConnected() const;
+ bool isActivated() const;
private:
enum State {
disabled,
@@ -199,10 +200,6 @@ namespace belledonnecomm {
LinphoneRtpTransportFactories mTransportFactories;
Mutex mMutex;
std::queue mEvq;
-#ifndef USE_BELLESIP
- TunnelSocket *mSipSocket;
- eXosip_transport_hooks_t mExosipTransport;
-#endif
};
/**
diff --git a/coreapi/bellesip_sal/sal_impl.c b/coreapi/bellesip_sal/sal_impl.c
index 6c2e84483..052c83971 100644
--- a/coreapi/bellesip_sal/sal_impl.c
+++ b/coreapi/bellesip_sal/sal_impl.c
@@ -554,19 +554,29 @@ int sal_transport_available(Sal *sal, SalTransport t){
return FALSE;
}
-int sal_add_listen_port(Sal *ctx, SalAddress* addr){
+static int sal_add_listen_port(Sal *ctx, SalAddress* addr, bool_t is_tunneled){
int result;
- belle_sip_listening_point_t* lp = belle_sip_stack_create_listening_point(ctx->stack,
+ belle_sip_listening_point_t* lp;
+ if (is_tunneled){
+#ifdef TUNNEL_ENABLED
+ if (sal_address_get_transport(addr)!=SalTransportUDP){
+ ms_error("Tunneled mode is only available for UDP kind of transports.");
+ return -1;
+ }
+ lp = belle_sip_tunnel_listening_point_new(ctx->stack, ctx->tunnel_client);
+ if (!lp){
+ ms_error("Could not create tunnel listening point.");
+ return -1;
+ }
+#else
+ ms_error("No tunnel support in library.");
+ return -1;
+#endif
+ }else{
+ lp = belle_sip_stack_create_listening_point(ctx->stack,
sal_address_get_domain(addr),
sal_address_get_port(addr),
sal_transport_to_string(sal_address_get_transport(addr)));
- if (sal_address_get_port(addr)==-1 && lp==NULL){
- int random_port=(0xDFFF&ortp_random())+1024;
- ms_warning("This version of belle-sip doesn't support random port, choosing one here.");
- lp = belle_sip_stack_create_listening_point(ctx->stack,
- sal_address_get_domain(addr),
- random_port,
- sal_transport_to_string(sal_address_get_transport(addr)));
}
if (lp) {
belle_sip_listening_point_set_keep_alive(lp,ctx->keep_alive);
@@ -578,13 +588,13 @@ int sal_add_listen_port(Sal *ctx, SalAddress* addr){
return result;
}
-int sal_listen_port(Sal *ctx, const char *addr, int port, SalTransport tr, int is_secure) {
+int sal_listen_port(Sal *ctx, const char *addr, int port, SalTransport tr, int is_tunneled) {
SalAddress* sal_addr = sal_address_new(NULL);
int result;
sal_address_set_domain(sal_addr,addr);
sal_address_set_port(sal_addr,port);
sal_address_set_transport(sal_addr,tr);
- result = sal_add_listen_port(ctx,sal_addr);
+ result = sal_add_listen_port(ctx, sal_addr, is_tunneled);
sal_address_destroy(sal_addr);
return result;
}
@@ -646,43 +656,15 @@ void sal_set_keepalive_period(Sal *ctx,unsigned int value){
}
}
}
-int sal_enable_tunnel(Sal *ctx, void *tunnelclient) {
+int sal_set_tunnel(Sal *ctx, void *tunnelclient) {
#ifdef TUNNEL_ENABLED
- belle_sip_listening_point_t *lp_udp = NULL;
- if(ctx->lp_tunnel != NULL) {
- ortp_error("sal_enable_tunnel(): tunnel is already enabled");
- return -1;
- }
- while((lp_udp = belle_sip_provider_get_listening_point(ctx->prov, "udp")) != NULL) {
- belle_sip_object_ref(lp_udp);
- belle_sip_provider_remove_listening_point(ctx->prov, lp_udp);
- ctx->udp_listening_points = ms_list_append(ctx->udp_listening_points, lp_udp);
- }
- ctx->lp_tunnel = belle_sip_tunnel_listening_point_new(ctx->stack, tunnelclient);
- if(ctx->lp_tunnel == NULL) return -1;
- belle_sip_listening_point_set_keep_alive(ctx->lp_tunnel, ctx->keep_alive);
- belle_sip_provider_add_listening_point(ctx->prov, ctx->lp_tunnel);
- belle_sip_object_ref(ctx->lp_tunnel);
+ ctx->tunnel_client=tunnelclient;
return 0;
#else
- return 0;
-#endif
-}
-void sal_disable_tunnel(Sal *ctx) {
-#ifdef TUNNEL_ENABLED
- MSList *it;
- if(ctx->lp_tunnel) {
- belle_sip_provider_remove_listening_point(ctx->prov, ctx->lp_tunnel);
- belle_sip_object_unref(ctx->lp_tunnel);
- ctx->lp_tunnel = NULL;
- for(it=ctx->udp_listening_points; it!=NULL; it=it->next) {
- belle_sip_provider_add_listening_point(ctx->prov, (belle_sip_listening_point_t *)it->data);
- }
- ms_list_free_with_data(ctx->udp_listening_points, belle_sip_object_unref);
- ctx->udp_listening_points = NULL;
- }
+ return -1;
#endif
}
+
/**
* returns keepalive period in ms
* 0 desactiaved
@@ -953,7 +935,7 @@ static void make_supported_header(Sal *sal){
char *alltags=NULL;
size_t buflen=64;
size_t written=0;
-
+
if (sal->supported){
belle_sip_object_unref(sal->supported);
sal->supported=NULL;
@@ -1003,7 +985,7 @@ void sal_add_supported_tag(Sal *ctx, const char* tag){
ctx->supported_tags=ms_list_append(ctx->supported_tags,ms_strdup(tag));
make_supported_header(ctx);
}
-
+
}
void sal_remove_supported_tag(Sal *ctx, const char* tag){
@@ -1101,3 +1083,7 @@ void sal_enable_sip_update_method(Sal *ctx,bool_t value) {
ctx->enable_sip_update=value;
}
+void sal_default_enable_sdp_removal(Sal *sal, bool_t enable) {
+ if (enable) ms_message("Enabling SDP removal feature by default for all new SalOp in Sal[%p]!", sal);
+ sal->default_sdp_removal = enable;
+}
diff --git a/coreapi/bellesip_sal/sal_impl.h b/coreapi/bellesip_sal/sal_impl.h
index 07124feb3..21aeadc74 100644
--- a/coreapi/bellesip_sal/sal_impl.h
+++ b/coreapi/bellesip_sal/sal_impl.h
@@ -33,8 +33,7 @@ struct Sal{
belle_sip_provider_t *prov;
belle_sip_header_user_agent_t* user_agent;
belle_sip_listener_t *listener;
- belle_sip_listening_point_t *lp_tunnel;
- MSList *udp_listening_points;
+ void *tunnel_client;
void *up; /*user pointer*/
int session_expires;
unsigned int keep_alive;
@@ -53,6 +52,7 @@ struct Sal{
bool_t enable_test_features;
bool_t no_initial_route;
bool_t enable_sip_update; /*true by default*/
+ bool_t default_sdp_removal;
};
typedef enum SalOpState {
@@ -107,6 +107,7 @@ struct SalOp{
bool_t call_released;
bool_t manual_refresher;
bool_t has_auth_pending;
+ bool_t sdp_removal; /* do not add SDP in outgoing INVITE and remove it from incoming INVITE */
int auth_requests; /*number of auth requested for this op*/
};
diff --git a/coreapi/bellesip_sal/sal_op_call.c b/coreapi/bellesip_sal/sal_op_call.c
index fbed2cf18..c2e9a4a64 100644
--- a/coreapi/bellesip_sal/sal_op_call.c
+++ b/coreapi/bellesip_sal/sal_op_call.c
@@ -19,7 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "sal_impl.h"
#include "offeranswer.h"
-static int extract_sdp(belle_sip_message_t* message,belle_sdp_session_description_t** session_desc, SalReason *error);
+static int extract_sdp(SalOp* op,belle_sip_message_t* message,belle_sdp_session_description_t** session_desc, SalReason *error);
/*used for calls terminated before creation of a dialog*/
static void call_set_released(SalOp* op){
@@ -41,7 +41,12 @@ static void sdp_process(SalOp *h){
ms_message("Doing SDP offer/answer process of type %s",h->sdp_offering ? "outgoing" : "incoming");
if (h->result){
sal_media_description_unref(h->result);
+ h->result = NULL;
}
+
+ /* if SDP was invalid */
+ if (h->base.remote_media == NULL) return;
+
h->result=sal_media_description_new();
if (h->sdp_offering){
offer_answer_initiate_outgoing(h->base.local_media,h->base.remote_media,h->result);
@@ -162,13 +167,14 @@ static void handle_sdp_from_response(SalOp* op,belle_sip_response_t* response) {
sal_media_description_unref(op->base.remote_media);
op->base.remote_media=NULL;
}
- if (extract_sdp(BELLE_SIP_MESSAGE(response),&sdp,&reason)==0) {
+ if (extract_sdp(op,BELLE_SIP_MESSAGE(response),&sdp,&reason)==0) {
if (sdp){
op->base.remote_media=sal_media_description_new();
sdp_to_media_description(sdp,op->base.remote_media);
- if (op->base.local_media) sdp_process(op);
}/*if no sdp in response, what can we do ?*/
}
+ /* process sdp in any case to reset result media description*/
+ if (op->base.local_media) sdp_process(op);
}
static void cancelling_invite(SalOp* op ){
@@ -330,7 +336,7 @@ static void call_process_transaction_terminated(void *user_ctx, const belle_sip_
belle_sip_request_t* req;
belle_sip_response_t* resp;
bool_t release_call=FALSE;
-
+
if (client_transaction) {
req=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction));
resp=belle_sip_transaction_get_response(BELLE_SIP_TRANSACTION(client_transaction));
@@ -378,8 +384,16 @@ static void unsupported_method(belle_sip_server_transaction_t* server_transactio
* If body was present is not a SDP or parsing of SDP failed, -1 is returned and SalReason is set appropriately.
*
**/
-static int extract_sdp(belle_sip_message_t* message,belle_sdp_session_description_t** session_desc, SalReason *error) {
+static int extract_sdp(SalOp *op, belle_sip_message_t* message,belle_sdp_session_description_t** session_desc, SalReason *error) {
belle_sip_header_content_type_t* content_type=belle_sip_message_get_header_by_type(message,belle_sip_header_content_type_t);
+
+ if (op&&op->sdp_removal){
+ ms_error("Removed willingly SDP because sal_call_enable_sdp_removal was set to TRUE.");
+ *session_desc=NULL;
+ *error=SalReasonNotAcceptable;
+ return -1;
+ }
+
if (content_type){
if (strcmp("application",belle_sip_header_content_type_get_type(content_type))==0
&& strcmp("sdp",belle_sip_header_content_type_get_subtype(content_type))==0) {
@@ -409,7 +423,7 @@ static int process_sdp_for_invite(SalOp* op,belle_sip_request_t* invite) {
belle_sdp_session_description_t* sdp;
int err=0;
SalReason reason;
- if (extract_sdp(BELLE_SIP_MESSAGE(invite),&sdp,&reason)==0) {
+ if (extract_sdp(op,BELLE_SIP_MESSAGE(invite),&sdp,&reason)==0) {
if (sdp){
op->sdp_offering=FALSE;
op->base.remote_media=sal_media_description_new();
@@ -484,15 +498,15 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t
ms_warning("replace header already set");
}
- process_sdp_for_invite(op,req);
-
- if ((call_info=belle_sip_message_get_header(BELLE_SIP_MESSAGE(req),"Call-Info"))) {
- if( strstr(belle_sip_header_get_unparsed_value(call_info),"answer-after=") != NULL) {
- op->auto_answer_asked=TRUE;
- ms_message("The caller asked to automatically answer the call(Emergency?)\n");
+ if (process_sdp_for_invite(op,req) == 0) {
+ if ((call_info=belle_sip_message_get_header(BELLE_SIP_MESSAGE(req),"Call-Info"))) {
+ if( strstr(belle_sip_header_get_unparsed_value(call_info),"answer-after=") != NULL) {
+ op->auto_answer_asked=TRUE;
+ ms_message("The caller asked to automatically answer the call(Emergency?)\n");
+ }
}
+ op->base.root->callbacks.call_received(op);
}
- op->base.root->callbacks.call_received(op);
break;
} /* else same behavior as for EARLY state*/
}
@@ -532,7 +546,7 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t
if (strcmp("ACK",method)==0) {
if (op->sdp_offering){
SalReason reason;
- if (extract_sdp(BELLE_SIP_MESSAGE(req),&sdp,&reason)==0){
+ if (extract_sdp(op,BELLE_SIP_MESSAGE(req),&sdp,&reason)==0){
if (sdp){
if (op->base.remote_media)
sal_media_description_unref(op->base.remote_media);
diff --git a/coreapi/bellesip_sal/sal_op_impl.c b/coreapi/bellesip_sal/sal_op_impl.c
index ed18f52d0..5acfd5eae 100644
--- a/coreapi/bellesip_sal/sal_op_impl.c
+++ b/coreapi/bellesip_sal/sal_op_impl.c
@@ -18,7 +18,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "sal_impl.h"
-
/*create an operation */
SalOp * sal_op_new(Sal *sal){
SalOp *op=ms_new0(SalOp,1);
@@ -26,6 +25,7 @@ SalOp * sal_op_new(Sal *sal){
op->type=SalOpUnknown;
op->privacy=SalPrivacyNone;
op->manual_refresher=FALSE;/*tells that requests with expiry (SUBSCRIBE, PUBLISH) will be automatically refreshed*/
+ op->sdp_removal=sal->default_sdp_removal;
sal_op_ref(op);
return op;
}
@@ -285,6 +285,7 @@ static int _sal_op_send_request_with_contact(SalOp* op, belle_sip_request_t* req
const MSList *elem=sal_op_get_route_addresses(op);
const char *transport;
const char *method=belle_sip_request_get_method(request);
+ belle_sip_listening_point_t *udplp=belle_sip_provider_get_listening_point(prov,"UDP");
if (elem) {
outbound_proxy=belle_sip_header_address_get_uri((belle_sip_header_address_t*)elem->data);
@@ -297,7 +298,7 @@ static int _sal_op_send_request_with_contact(SalOp* op, belle_sip_request_t* req
/*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_uri_is_secure(next_hop_uri)){
- if (belle_sip_provider_get_listening_point(prov,"UDP")==0){
+ if (udplp==NULL){
if (belle_sip_provider_get_listening_point(prov,"TCP")!=NULL){
transport="tcp";
}else if (belle_sip_provider_get_listening_point(prov,"TLS")!=NULL ){
@@ -309,6 +310,13 @@ static int _sal_op_send_request_with_contact(SalOp* op, belle_sip_request_t* req
belle_sip_uri_set_transport_param(next_hop_uri,transport);
}
}
+ }else{
+#ifdef TUNNEL_ENABLED
+ if (BELLE_SIP_OBJECT_IS_INSTANCE_OF(udplp,belle_sip_tunnel_listening_point_t)){
+ /* our tunnel mode only supports UDP. Force transport to be set to UDP */
+ belle_sip_uri_set_transport_param(next_hop_uri,"udp");
+ }
+#endif
}
if ((strcmp(method,"REGISTER")==0 || strcmp(method,"SUBSCRIBE")==0) && transport &&
(strcasecmp(transport,"TCP")==0 || strcasecmp(transport,"TLS")==0)){
@@ -770,3 +778,7 @@ void sal_op_stop_refreshing(SalOp *op){
}
}
+void sal_call_enable_sdp_removal(SalOp *h, bool_t enable) {
+ if (enable) ms_message("Enabling SDP removal feature for SalOp[%p]!", h);
+ h->sdp_removal = enable;
+}
diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c
index bb6b5b9fb..bc58f3c7d 100644
--- a/coreapi/callbacks.c
+++ b/coreapi/callbacks.c
@@ -224,7 +224,8 @@ static bool_t already_a_call_pending(LinphoneCore *lc){
|| call->state==LinphoneCallOutgoingInit
|| call->state==LinphoneCallOutgoingProgress
|| call->state==LinphoneCallOutgoingEarlyMedia
- || call->state==LinphoneCallOutgoingRinging){
+ || call->state==LinphoneCallOutgoingRinging
+ || call->state==LinphoneCallIdle){ /*case of an incoming call for which ICE candidate gathering is pending.*/
return TRUE;
}
}
@@ -239,6 +240,7 @@ static void call_received(SalOp *h){
LinphoneAddress *to_addr=NULL;
/*this mode is deprcated because probably useless*/
bool_t prevent_colliding_calls=lp_config_get_int(lc->config,"sip","prevent_colliding_calls",FALSE);
+ SalMediaDescription *md;
/* first check if we can answer successfully to this invite */
if (linphone_presence_model_get_basic_status(lc->presence_model) == LinphonePresenceBasicStatusClosed) {
@@ -301,8 +303,19 @@ static void call_received(SalOp *h){
linphone_address_destroy(to_addr);
return;
}
-
+
call=linphone_call_new_incoming(lc,from_addr,to_addr,h);
+
+ linphone_call_make_local_media_description(lc,call);
+ sal_call_set_local_media_description(call->op,call->localdesc);
+ md=sal_call_get_final_media_description(call->op);
+ if (md){
+ if (sal_media_description_empty(md) || linphone_core_incompatible_security(lc,md)){
+ sal_call_decline(call->op,SalReasonNotAcceptable,NULL);
+ linphone_call_unref(call);
+ return;
+ }
+ }
/* the call is acceptable so we can now add it to our list */
linphone_core_add_call(lc,call);
@@ -372,6 +385,10 @@ static void call_ringing(SalOp *h){
md=sal_call_get_final_media_description(h);
if (md==NULL){
linphone_core_stop_dtmf_stream(lc);
+ if (call->state==LinphoneCallOutgoingEarlyMedia){
+ /*already doing early media */
+ return;
+ }
if (lc->ringstream!=NULL) return;/*already ringing !*/
if (lc->sound_conf.play_sndcard!=NULL){
MSSndCard *ringcard=lc->sound_conf.lsd_card ? lc->sound_conf.lsd_card : lc->sound_conf.play_sndcard;
@@ -422,7 +439,7 @@ static void call_accepted(SalOp *op){
/* Handle remote ICE attributes if any. */
if (call->ice_session != NULL) {
- linphone_core_update_ice_from_remote_media_description(call, sal_call_get_remote_media_description(op));
+ linphone_call_update_ice_from_remote_media_description(call, sal_call_get_remote_media_description(op));
}
#ifdef BUILD_UPNP
if (call->upnp_session != NULL) {
@@ -448,7 +465,7 @@ static void call_accepted(SalOp *op){
default:
break;
}
-
+
if (md && !sal_media_description_empty(md) && !linphone_core_incompatible_security(lc,md)){
linphone_call_update_remote_session_id_and_ver(call);
if (sal_media_description_has_dir(md,SalStreamSendOnly) ||
@@ -498,9 +515,21 @@ static void call_accepted(SalOp *op){
if (update_state) linphone_call_set_state(call, LinphoneCallStreamsRunning, "Streams running");
}
}else{
- /*send a bye*/
- ms_error("Incompatible SDP offer received in 200Ok, need to abort the call");
- linphone_core_abort_call(lc,call,_("Incompatible, check codecs or security settings..."));
+ switch (call->prevstate){
+ /*send a bye only in case of outgoing state*/
+ case LinphoneCallOutgoingInit:
+ case LinphoneCallOutgoingProgress:
+ case LinphoneCallOutgoingRinging:
+ case LinphoneCallOutgoingEarlyMedia:
+ ms_error("Incompatible SDP offer received in 200 OK, need to abort the call");
+ linphone_core_abort_call(lc,call,_("Incompatible, check codecs or security settings..."));
+ break;
+ /*otherwise we are able to resume previous state*/
+ default:
+ ms_message("Incompatible SDP offer received in 200 OK, restoring previous state[%s]",linphone_call_state_to_string(call->prevstate));
+ linphone_call_set_state(call,call->prevstate,_("Incompatible media parameters."));
+ break;
+ }
}
}
diff --git a/coreapi/chat.c b/coreapi/chat.c
index d48609fad..5ed99c769 100644
--- a/coreapi/chat.c
+++ b/coreapi/chat.c
@@ -597,9 +597,10 @@ void linphone_chat_room_send_message(LinphoneChatRoom *cr, const char *msg) {
}
void linphone_chat_room_message_received(LinphoneChatRoom *cr, LinphoneCore *lc, LinphoneChatMessage *msg){
- if (msg->message)
- //legacy API
+ if (msg->message){
+ /*legacy API*/
linphone_core_notify_text_message_received(lc, cr, msg->from, msg->message);
+ }
linphone_core_notify_message_received(lc, cr,msg);
cr->remote_is_composing = LinphoneIsComposingIdle;
linphone_core_notify_is_composing_received(cr->lc, cr);
@@ -627,8 +628,7 @@ void linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessag
msg = linphone_chat_room_create_message(cr, NULL); /* create a message with empty body */
msg->content_type = ms_strdup(sal_msg->content_type); /* add the content_type "application/vnd.gsma.rcs-ft-http+xml" */
- msg->file_transfer_information = (LinphoneContent *)malloc(sizeof(LinphoneContent));
- memset(msg->file_transfer_information, 0, sizeof(*(msg->file_transfer_information)));
+ msg->file_transfer_information = ms_new0(LinphoneContent,1);
/* parse the message body to get all informations from it */
xmlMessageBody = xmlParseDoc((const xmlChar *)sal_msg->text);
@@ -1147,7 +1147,7 @@ static void on_recv_body(belle_sip_user_body_handler_t *bh, belle_sip_message_t
static LinphoneContent* linphone_chat_create_file_transfer_information_from_headers(const belle_sip_message_t* message ){
- LinphoneContent *content = ms_malloc0(sizeof(LinphoneContent));
+ LinphoneContent *content = ms_new0(LinphoneContent,1);
belle_sip_header_content_length_t* content_length_hdr = BELLE_SIP_HEADER_CONTENT_LENGTH(belle_sip_message_get_header(message, "Content-Length"));
belle_sip_header_content_type_t* content_type_hdr = BELLE_SIP_HEADER_CONTENT_TYPE(belle_sip_message_get_header(message, "Content-Type"));
@@ -1263,7 +1263,7 @@ void linphone_chat_message_start_file_download(LinphoneChatMessage *message, Lin
* Cancel an ongoing file transfer attached to this message.(upload or download)
* @param msg #LinphoneChatMessage
*/
-void linphone_chat_room_cancel_file_transfer(LinphoneChatMessage *msg) {
+void linphone_chat_message_cancel_file_transfer(LinphoneChatMessage *msg) {
ms_message("Cancelled file transfer %s - msg [%p] chat room[%p]", (msg->external_body_url==NULL)?linphone_core_get_file_transfer_server(msg->chat_room->lc):msg->external_body_url, msg, msg->chat_room);
/* TODO: here we shall call the cancel http request from bellesip API when it is available passing msg->http_request */
/* waiting for this API, just set to NULL the reference to the request in the message and any request */
@@ -1520,8 +1520,7 @@ LinphoneChatMessage* linphone_chat_room_create_file_transfer_message(LinphoneCha
LinphoneChatMessage* msg = belle_sip_object_new(LinphoneChatMessage);
msg->chat_room=(LinphoneChatRoom*)cr;
msg->message = NULL;
- msg->file_transfer_information = (LinphoneContent *)malloc(sizeof(LinphoneContent));
- memset(msg->file_transfer_information, 0, sizeof(LinphoneContent));
+ msg->file_transfer_information = ms_new0(LinphoneContent,1);
linphone_content_copy(msg->file_transfer_information, initial_content);
msg->dir=LinphoneChatMessageOutgoing;
linphone_chat_message_set_to(msg, linphone_chat_room_get_peer_address(cr));
diff --git a/coreapi/linphone_tunnel.cc b/coreapi/linphone_tunnel.cc
index beabd43a8..9dd4e8adf 100644
--- a/coreapi/linphone_tunnel.cc
+++ b/coreapi/linphone_tunnel.cc
@@ -246,6 +246,10 @@ bool_t linphone_tunnel_connected(const LinphoneTunnel *tunnel){
return bcTunnel(tunnel)->isConnected();
}
+bool_t linphone_tunnel_get_activated(const LinphoneTunnel *tunnel){
+ return bcTunnel(tunnel)->isActivated();
+}
+
static OrtpLogFunc tunnelOrtpLogHandler=NULL;
/*
diff --git a/coreapi/linphone_tunnel.h b/coreapi/linphone_tunnel.h
index 8bf94fcef..f071f3c37 100644
--- a/coreapi/linphone_tunnel.h
+++ b/coreapi/linphone_tunnel.h
@@ -60,7 +60,7 @@ typedef enum _LinphoneTunnelMode {
} LinphoneTunnelMode;
/**
- * @brief Convert a string into LinphoneTunnelMode enum
+ * Convert a string into LinphoneTunnelMode enum
* @param string String to convert
* @return An LinphoneTunnelMode enum. If the passed string is NULL or
* does not match with any mode, the LinphoneTunnelModeDisable is returned.
@@ -68,7 +68,7 @@ typedef enum _LinphoneTunnelMode {
LINPHONE_PUBLIC LinphoneTunnelMode string_to_tunnel_mode(const char *string);
/**
- * @brief Convert a tunnel mode enum into string
+ * Convert a tunnel mode enum into string
* @param mode Enum to convert
* @return "disable", "enable" or "auto"
*/
@@ -80,170 +80,175 @@ LINPHONE_PUBLIC const char *tunnel_mode_to_string(LinphoneTunnelMode mode);
LINPHONE_PUBLIC LinphoneTunnelConfig *linphone_tunnel_config_new(void);
/**
- * Set address of server.
- *
- * @param tunnel configuration object
- * @param host tunnel server ip address
+ * Set the IP address or hostname of the tunnel server.
+ * @param tunnel LinphoneTunnelConfig object
+ * @param host The tunnel server IP address or hostname
*/
LINPHONE_PUBLIC void linphone_tunnel_config_set_host(LinphoneTunnelConfig *tunnel, const char *host);
/**
- * Get address of server.
- *
- * @param tunnel configuration object
+ * Get the IP address or hostname of the tunnel server.
+ * @param tunnel LinphoneTunnelConfig object
+ * @return The tunnel server IP address or hostname
*/
LINPHONE_PUBLIC const char *linphone_tunnel_config_get_host(const LinphoneTunnelConfig *tunnel);
/**
* Set tls port of server.
- *
- * @param tunnel configuration object
- * @param port tunnel server tls port, recommended value is 443
+ * @param tunnel LinphoneTunnelConfig object
+ * @param port The tunnel server TLS port, recommended value is 443
*/
LINPHONE_PUBLIC void linphone_tunnel_config_set_port(LinphoneTunnelConfig *tunnel, int port);
/**
- * Get tls port of server.
- *
- * @param tunnel configuration object
+ * Get the TLS port of the tunnel server.
+ * @param tunnel LinphoneTunnelConfig object
+ * @return The TLS port of the tunnel server
*/
LINPHONE_PUBLIC int linphone_tunnel_config_get_port(const LinphoneTunnelConfig *tunnel);
/**
- * Set the remote port on the tunnel server side used to test udp reachability.
- *
- * @param tunnel configuration object
- * @param remote_udp_mirror_port remote port on the tunnel server side used to test udp reachability, set to -1 to disable the feature
+ * Set the remote port on the tunnel server side used to test UDP reachability.
+ * This is used when the mode is set auto, to detect whether the tunnel has to be enabled or not.
+ * @param tunnel LinphoneTunnelConfig object
+ * @param remote_udp_mirror_port The remote port on the tunnel server side used to test UDP reachability, set to -1 to disable the feature
*/
LINPHONE_PUBLIC void linphone_tunnel_config_set_remote_udp_mirror_port(LinphoneTunnelConfig *tunnel, int remote_udp_mirror_port);
/**
- * Get the remote port on the tunnel server side used to test udp reachability.
- *
- * @param tunnel configuration object
+ * Get the remote port on the tunnel server side used to test UDP reachability.
+ * This is used when the mode is set auto, to detect whether the tunnel has to be enabled or not.
+ * @param tunnel LinphoneTunnelConfig object
+ * @return The remote port on the tunnel server side used to test UDP reachability
*/
LINPHONE_PUBLIC int linphone_tunnel_config_get_remote_udp_mirror_port(const LinphoneTunnelConfig *tunnel);
/**
- * Set the udp packet round trip delay in ms for a tunnel configuration.
- *
- * @param tunnel configuration object
- * @param delay udp packet round trip delay in ms considered as acceptable. recommended value is 1000 ms.
+ * Set the UDP packet round trip delay in ms for a tunnel configuration.
+ * @param tunnel LinphoneTunnelConfig object
+ * @param delay The UDP packet round trip delay in ms considered as acceptable (recommended value is 1000 ms).
*/
LINPHONE_PUBLIC void linphone_tunnel_config_set_delay(LinphoneTunnelConfig *tunnel, int delay);
/**
- * Get the udp packet round trip delay in ms for a tunnel configuration.
- *
- * @param tunnel configuration object
+ * Get the UDP packet round trip delay in ms for a tunnel configuration.
+ * @param tunnel LinphoneTunnelConfig object
+ * @return The UDP packet round trip delay in ms.
*/
LINPHONE_PUBLIC int linphone_tunnel_config_get_delay(const LinphoneTunnelConfig *tunnel);
/**
* Destroy a tunnel configuration
- *
- * @param tunnel configuration object
+ * @param tunnel LinphoneTunnelConfig object
*/
LINPHONE_PUBLIC void linphone_tunnel_config_destroy(LinphoneTunnelConfig *tunnel);
/**
- * Add tunnel server configuration
- *
- * @param tunnel object
- * @param tunnel_config object
+ * Add a tunnel server configuration.
+ * @param tunnel LinphoneTunnel object
+ * @param tunnel_config LinphoneTunnelConfig object
*/
LINPHONE_PUBLIC void linphone_tunnel_add_server(LinphoneTunnel *tunnel, LinphoneTunnelConfig *tunnel_config);
/**
- * @brief Remove tunnel server configuration
- * @param tunnel object
- * @param tunnel_config object
+ * Remove a tunnel server configuration.
+ * @param tunnel LinphoneTunnel object
+ * @param tunnel_config LinphoneTunnelConfig object
*/
LINPHONE_PUBLIC void linphone_tunnel_remove_server(LinphoneTunnel *tunnel, LinphoneTunnelConfig *tunnel_config);
/**
- * @brief Get added servers
- * @param tunnel A LinphoneTunnel object
- * @return A list of LinphoneTunnelConfig objects
+ * Get added servers
+ * @param tunnel LinphoneTunnel object
+ * @return \mslist{LinphoneTunnelConfig}
*/
LINPHONE_PUBLIC const MSList *linphone_tunnel_get_servers(const LinphoneTunnel *tunnel);
/**
- * @brief Removes all tunnel server address previously entered with addServer()
- * @param tunnel A LinphoneTunnel object
+ * Remove all tunnel server addresses previously entered with linphone_tunnel_add_server()
+ * @param tunnel LinphoneTunnel object
**/
LINPHONE_PUBLIC void linphone_tunnel_clean_servers(LinphoneTunnel *tunnel);
/**
- * @brief Set tunnel mode
+ * Set the tunnel mode.
* The tunnel mode can be 'enable', 'disable' or 'auto'
* If the mode is set to 'auto', the tunnel manager will try to established an RTP session
* with the tunnel server on the UdpMirrorPort. If the connection fail, the tunnel is automatically
* activated whereas the tunnel is automatically disabled if the connection succeed.
- * @param tunnel object
- * @param mode See #LinphoneTunnelMode
+ * @param tunnel LinphoneTunnel object
+ * @param mode The desired LinphoneTunnelMode
**/
LINPHONE_PUBLIC void linphone_tunnel_set_mode(LinphoneTunnel *tunnel, LinphoneTunnelMode mode);
/**
- * @brief Get the tunnel mode
- * @param tunnel A LinphoneTunnel object
- * @return Return a #LinphoneTunnelMode enumeration
+ * Get the tunnel mode
+ * @param tunnel LinphoneTunnel object
+ * @return The current LinphoneTunnelMode
**/
LINPHONE_PUBLIC LinphoneTunnelMode linphone_tunnel_get_mode(const LinphoneTunnel *tunnel);
/**
- * @brief Check whether the tunnel is connected
- * @param tunnel LinphoneTunnel object
- * @return True if the tunnel is connected
+ * Returns whether the tunnel is activated. If mode is set to auto, this gives indication whether the automatic detection determined
+ * that tunnel was necessary or not.
+ * @param tunnel the tunnel
+ * @return TRUE if tunnel is in use, FALSE otherwise.
+**/
+LINPHONE_PUBLIC bool_t linphone_tunnel_get_activated(const LinphoneTunnel *tunnel);
+
+
+/**
+ * Check whether the tunnel is connected
+ * @param tunnel LinphoneTunnel object
+ * @return A boolean value telling if the tunnel is connected
**/
LINPHONE_PUBLIC bool_t linphone_tunnel_connected(const LinphoneTunnel *tunnel);
/**
- * @param tunnel object
- * Forces reconnection to the tunnel server.
+ * Force reconnection to the tunnel server.
* This method is useful when the device switches from wifi to Edge/3G or vice versa. In most cases the tunnel client socket
* won't be notified promptly that its connection is now zombie, so it is recommended to call this method that will cause
* the lost connection to be closed and new connection to be issued.
+ * @param tunnel LinphoneTunnel object
**/
LINPHONE_PUBLIC void linphone_tunnel_reconnect(LinphoneTunnel *tunnel);
/**
- * @brief Set whether SIP packets must be directly sent to a UA or pass through the tunnel
- * @param tunnel Tunnel to configure
+ * Set whether SIP packets must be directly sent to a UA or pass through the tunnel
+ * @param tunnel LinphoneTunnel object
* @param enable If true, SIP packets shall pass through the tunnel
*/
LINPHONE_PUBLIC void linphone_tunnel_enable_sip(LinphoneTunnel *tunnel, bool_t enable);
/**
- * @brief Check whether tunnel is set to transport SIP packets
- * @param tunnel Tunnel to check
- * @return True, SIP packets shall pass through through tunnel
+ * Check whether tunnel is set to transport SIP packets
+ * @param tunnel LinphoneTunnel object
+ * @return A boolean value telling whether SIP packets shall pass through the tunnel
*/
LINPHONE_PUBLIC bool_t linphone_tunnel_sip_enabled(const LinphoneTunnel *tunnel);
/**
* Set an optional http proxy to go through when connecting to tunnel server.
* @param tunnel LinphoneTunnel object
- * @param host Http proxy host.
- * @param port http proxy port.
- * @param username optional http proxy username if the proxy request authentication. Currently only basic authentication is supported. Use NULL if not needed.
- * @param passwd optional http proxy password. Use NULL if not needed.
+ * @param host http proxy host
+ * @param port http proxy port
+ * @param username Optional http proxy username if the proxy request authentication. Currently only basic authentication is supported. Use NULL if not needed.
+ * @param passwd Optional http proxy password. Use NULL if not needed.
**/
LINPHONE_PUBLIC void linphone_tunnel_set_http_proxy(LinphoneTunnel *tunnel, const char *host, int port, const char* username,const char* passwd);
/**
* Retrieve optional http proxy configuration previously set with linphone_tunnel_set_http_proxy().
* @param tunnel LinphoneTunnel object
- * @param host Http proxy host.
- * @param port http proxy port.
- * @param username optional http proxy username if the proxy request authentication. Currently only basic authentication is supported. Use NULL if not needed.
- * @param passwd optional http proxy password. Use NULL if not needed.
+ * @param host http proxy host
+ * @param port http proxy port
+ * @param username Optional http proxy username if the proxy request authentication. Currently only basic authentication is supported. Use NULL if not needed.
+ * @param passwd Optional http proxy password. Use NULL if not needed.
**/
LINPHONE_PUBLIC void linphone_tunnel_get_http_proxy(LinphoneTunnel*tunnel,const char **host, int *port, const char **username, const char **passwd);
/**
- * @brief Set authentication info for the http proxy
+ * Set authentication info for the http proxy
* @param tunnel LinphoneTunnel object
* @param username User name
* @param passwd Password
@@ -251,38 +256,37 @@ LINPHONE_PUBLIC void linphone_tunnel_get_http_proxy(LinphoneTunnel*tunnel,const
LINPHONE_PUBLIC void linphone_tunnel_set_http_proxy_auth_info(LinphoneTunnel*tunnel, const char* username,const char* passwd);
/**
- * @deprecated Replaced by linphone_tunnel_set_mode()
- * @brief Sets whether tunneling of SIP and RTP is required.
- * @param tunnel object
+ * Sets whether tunneling of SIP and RTP is required.
+ * @param tunnel object
* @param enabled If true enter in tunneled mode, if false exits from tunneled mode.
* The TunnelManager takes care of refreshing SIP registration when switching on or off the tunneled mode.
- *
+ * @deprecated Replaced by linphone_tunnel_set_mode()
**/
LINPHONE_PUBLIC void linphone_tunnel_enable(LinphoneTunnel *tunnel, bool_t enabled);
/**
- * @deprecated Replaced by linphone_tunnel_get_mode()
- * @brief Check whether tunnel is enabled
- * @param tunnel Tunnel object
+ * Check whether tunnel is enabled
+ * @param tunnel Tunnel object
* @return Returns a boolean indicating whether tunneled operation is enabled.
+ * @deprecated Replaced by linphone_tunnel_get_mode()
**/
LINPHONE_PUBLIC bool_t linphone_tunnel_enabled(const LinphoneTunnel *tunnel);
/**
- * @deprecated Replaced by linphone_tunnel_set_mode(LinphoneTunnelModeAuto)
- * @brief Start tunnel need detection.
+ * Start tunnel need detection.
* @param tunnel object
- * In auto detect mode, the tunnel manager try to establish a real time rtp cummunication with the tunnel server on specified port.
- *
In case of success, the tunnel is automatically turned off. Otherwise, if no udp commmunication is feasible, tunnel mode is turned on.
+ * In auto detect mode, the tunnel manager try to establish a real time rtp communication with the tunnel server on specified port.
+ *
In case of success, the tunnel is automatically turned off. Otherwise, if no udp communication is feasible, tunnel mode is turned on.
*
Call this method each time to run the auto detection algorithm
+ * @deprecated Replaced by linphone_tunnel_set_mode(LinphoneTunnelModeAuto)
*/
LINPHONE_PUBLIC void linphone_tunnel_auto_detect(LinphoneTunnel *tunnel);
/**
- * @deprecated Replaced by linphone_tunnel_get_mode()
- * @brief Tells whether tunnel auto detection is enabled.
+ * Tell whether tunnel auto detection is enabled.
* @param[in] tunnel LinphoneTunnel object.
* @return TRUE if auto detection is enabled, FALSE otherwise.
+ * @deprecated Replaced by linphone_tunnel_get_mode()
*/
LINPHONE_PUBLIC bool_t linphone_tunnel_auto_detect_enabled(LinphoneTunnel *tunnel);
diff --git a/coreapi/linphone_tunnel_stubs.c b/coreapi/linphone_tunnel_stubs.c
index 72693463b..bfe793be6 100644
--- a/coreapi/linphone_tunnel_stubs.c
+++ b/coreapi/linphone_tunnel_stubs.c
@@ -63,6 +63,9 @@ bool_t linphone_tunnel_connected(const LinphoneTunnel *tunnel){
return FALSE;
}
+bool_t linphone_tunnel_get_activated(const LinphoneTunnel *tunnel){
+ return FALSE;
+}
void linphone_tunnel_enable_logs_with_handler(LinphoneTunnel *tunnel, bool_t enabled, OrtpLogFunc logHandler){
}
diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c
index e4766a7ed..8315540ec 100644
--- a/coreapi/linphonecall.c
+++ b/coreapi/linphonecall.c
@@ -183,7 +183,7 @@ static void linphone_call_audiostream_encryption_changed(void *data, bool_t encr
{
const LinphoneCallParams *params=linphone_call_get_current_params(call);
if (params->has_video) {
- OrtpZrtpParams params;
+ MSZrtpParams params;
ms_message("Trying to enable encryption on video stream");
params.zid_file=NULL; //unused
video_stream_enable_zrtp(call->videostream,call->audiostream,¶ms);
@@ -219,9 +219,9 @@ void linphone_call_set_authentication_token_verified(LinphoneCall *call, bool_t
ms_error("linphone_call_set_authentication_token_verified(): No zrtp context.");
}
if (!call->auth_token_verified && verified){
- ortp_zrtp_sas_verified(call->audiostream->ms.sessions.zrtp_context);
+ ms_zrtp_sas_verified(call->audiostream->ms.sessions.zrtp_context);
}else if (call->auth_token_verified && !verified){
- ortp_zrtp_sas_reset_verified(call->audiostream->ms.sessions.zrtp_context);
+ ms_zrtp_sas_reset_verified(call->audiostream->ms.sessions.zrtp_context);
}
call->auth_token_verified=verified;
propagate_encryption_changed(call);
@@ -381,6 +381,19 @@ void linphone_call_increment_local_media_description(LinphoneCall *call){
md->session_ver++;
}
+void linphone_call_update_local_media_description_from_ice_or_upnp(LinphoneCall *call){
+ if (call->ice_session != NULL) {
+ _update_local_media_description_from_ice(call->localdesc, call->ice_session);
+ linphone_core_update_ice_state_in_call_stats(call);
+ }
+#ifdef BUILD_UPNP
+ if(call->upnp_session != NULL) {
+ linphone_core_update_local_media_description_from_upnp(call->localdesc, call->upnp_session);
+ linphone_core_update_upnp_state_in_call_stats(call);
+ }
+#endif //BUILD_UPNP
+}
+
void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *call){
MSList *l;
PayloadType *pt;
@@ -463,18 +476,9 @@ void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *
setup_rtcp_xr(call, md);
update_media_description_from_stun(md,&call->ac,&call->vc);
- if (call->ice_session != NULL) {
- linphone_core_update_local_media_description_from_ice(md, call->ice_session);
- linphone_core_update_ice_state_in_call_stats(call);
- }
-#ifdef BUILD_UPNP
- if(call->upnp_session != NULL) {
- linphone_core_update_local_media_description_from_upnp(md, call->upnp_session);
- linphone_core_update_upnp_state_in_call_stats(call);
- }
-#endif //BUILD_UPNP
- linphone_address_destroy(addr);
call->localdesc=md;
+ linphone_call_update_local_media_description_from_ice_or_upnp(call);
+ linphone_address_destroy(addr);
if (old_md){
call->localdesc_changed=sal_media_description_equals(md,old_md);
sal_media_description_unref(old_md);
@@ -840,7 +844,50 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro
return call;
}
-/* this function is called internally to get rid of a call.
+/*
+ * Frees the media resources of the call.
+ * This has to be done at the earliest, unlike signaling resources that sometimes need to be kept a bit more longer.
+ * It is called by linphone_call_set_terminated() (for termination of calls signaled to the application), or directly by the destructor of LinphoneCall
+ * (_linphone_call_destroy) if the call was never notified to the application.
+ */
+void linphone_call_free_media_resources(LinphoneCall *call){
+ linphone_call_stop_media_streams(call);
+ ms_media_stream_sessions_uninit(&call->sessions[0]);
+ ms_media_stream_sessions_uninit(&call->sessions[1]);
+ linphone_call_delete_upnp_session(call);
+ linphone_call_delete_ice_session(call);
+ linphone_call_stats_uninit(&call->stats[0]);
+ linphone_call_stats_uninit(&call->stats[1]);
+}
+
+/*
+ * Called internally when reaching the Released state, to perform cleanups to break circular references.
+**/
+static void linphone_call_set_released(LinphoneCall *call){
+ if (call->op!=NULL) {
+ /*transfer the last error so that it can be obtained even in Released state*/
+ if (call->non_op_error.reason==SalReasonNone){
+ const SalErrorInfo *ei=sal_op_get_error_info(call->op);
+ sal_error_info_set(&call->non_op_error,ei->reason,ei->protocol_code,ei->status_string,ei->warnings);
+ }
+ /* so that we cannot have anymore upcalls for SAL
+ concerning this call*/
+ sal_op_release(call->op);
+ call->op=NULL;
+ }
+ /*it is necessary to reset pointers to other call to prevent circular references that would result in memory never freed.*/
+ if (call->referer){
+ linphone_call_unref(call->referer);
+ call->referer=NULL;
+ }
+ if (call->transfer_target){
+ linphone_call_unref(call->transfer_target);
+ call->transfer_target=NULL;
+ }
+ linphone_call_unref(call);
+}
+
+/* this function is called internally to get rid of a call that was notified to the application, because it reached the end or error state.
It performs the following tasks:
- remove the call from the internal list of calls
- update the call logs accordingly
@@ -849,17 +896,9 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro
static void linphone_call_set_terminated(LinphoneCall *call){
LinphoneCore *lc=call->core;
- linphone_call_stop_media_streams(call);
- ms_media_stream_sessions_uninit(&call->sessions[0]);
- ms_media_stream_sessions_uninit(&call->sessions[1]);
- linphone_call_delete_upnp_session(call);
- linphone_call_delete_ice_session(call);
- linphone_core_update_allocated_audio_bandwidth(lc);
- linphone_call_stats_uninit(&call->stats[0]);
- linphone_call_stats_uninit(&call->stats[1]);
+ linphone_call_free_media_resources(call);
linphone_call_log_completed(call);
-
if (call == lc->current_call){
ms_message("Resetting the current call");
lc->current_call=NULL;
@@ -868,7 +907,6 @@ static void linphone_call_set_terminated(LinphoneCall *call){
if (linphone_core_del_call(lc,call) != 0){
ms_error("Could not remove the call from the list !!!");
}
-
linphone_core_conference_check_uninit(lc);
if (call->ringing_beep){
linphone_core_stop_dtmf(lc);
@@ -931,11 +969,7 @@ const char *linphone_call_state_to_string(LinphoneCallState cs){
return "undefined state";
}
-void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const char *message) {
- linphone_call_set_state_base(call, cstate, message,FALSE);
-}
-
-void linphone_call_set_state_base(LinphoneCall *call, LinphoneCallState cstate, const char *message,bool_t silently){
+void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const char *message){
LinphoneCore *lc=call->core;
if (call->state!=cstate){
@@ -974,40 +1008,24 @@ void linphone_call_set_state_base(LinphoneCall *call, LinphoneCallState cstate,
call->log->connected_date_time=time(NULL);
}
- if (!silently)
- linphone_core_notify_call_state_changed(lc,call,cstate,message);
-
+ linphone_core_notify_call_state_changed(lc,call,cstate,message);
linphone_reporting_call_state_updated(call);
-
+
+ /*cancelling DTMF sequence, if any*/
+ if (cstate!=LinphoneCallStreamsRunning && call->dtmfs_timer!=NULL){
+ linphone_call_cancel_dtmfs(call);
+ }
if (cstate==LinphoneCallReleased){
- if (call->op!=NULL) {
- /*transfer the last error so that it can be obtained even in Released state*/
- if (call->non_op_error.reason==SalReasonNone){
- const SalErrorInfo *ei=sal_op_get_error_info(call->op);
- sal_error_info_set(&call->non_op_error,ei->reason,ei->protocol_code,ei->status_string,ei->warnings);
- }
- /* so that we cannot have anymore upcalls for SAL
- concerning this call*/
- sal_op_release(call->op);
- call->op=NULL;
- }
- /*it is necessary to reset pointers to other call to prevent circular references that would result in memory never freed.*/
- if (call->referer){
- linphone_call_unref(call->referer);
- call->referer=NULL;
- }
- if (call->transfer_target){
- linphone_call_unref(call->transfer_target);
- call->transfer_target=NULL;
- }
- linphone_call_unref(call);
+ linphone_call_set_released(call);
}
}
}
-static void linphone_call_destroy(LinphoneCall *obj)
-{
+static void linphone_call_destroy(LinphoneCall *obj){
ms_message("Call [%p] freed.",obj);
+ if (obj->audiostream || obj->videostream){
+ linphone_call_free_media_resources(obj);
+ }
if (obj->op!=NULL) {
sal_op_release(obj->op);
obj->op=NULL;
@@ -1026,9 +1044,11 @@ static void linphone_call_destroy(LinphoneCall *obj)
}
if (obj->ping_op) {
sal_op_release(obj->ping_op);
+ obj->ping_op=NULL;
}
if (obj->refer_to){
ms_free(obj->refer_to);
+ obj->refer_to=NULL;
}
if (obj->referer){
linphone_call_unref(obj->referer);
@@ -1036,16 +1056,30 @@ static void linphone_call_destroy(LinphoneCall *obj)
}
if (obj->transfer_target){
linphone_call_unref(obj->transfer_target);
+ obj->transfer_target=NULL;
}
- if (obj->log)
+ if (obj->log) {
linphone_call_log_unref(obj->log);
+ obj->log=NULL;
+ }
if (obj->auth_token) {
ms_free(obj->auth_token);
+ obj->auth_token=NULL;
+ }
+ if (obj->dtmfs_timer) {
+ linphone_call_cancel_dtmfs(obj);
+ }
+ if (obj->params){
+ linphone_call_params_unref(obj->params);
+ obj->params=NULL;
+ }
+ if (obj->current_params){
+ linphone_call_params_unref(obj->current_params);
+ obj->current_params=NULL;
}
- linphone_call_params_unref(obj->params);
- linphone_call_params_unref(obj->current_params);
if (obj->remote_params != NULL) {
linphone_call_params_unref(obj->remote_params);
+ obj->remote_params=NULL;
}
sal_error_info_reset(&obj->non_op_error);
}
@@ -1488,7 +1522,7 @@ int linphone_call_prepare_ice(LinphoneCall *call, bool_t incoming_offer){
if (has_video) _linphone_call_prepare_ice_for_stream(call,1,TRUE);
/*start ICE gathering*/
if (incoming_offer)
- linphone_core_update_ice_from_remote_media_description(call,remote); /*this may delete the ice session*/
+ linphone_call_update_ice_from_remote_media_description(call,remote); /*this may delete the ice session*/
if (call->ice_session && !ice_session_candidates_gathered(call->ice_session)){
if (call->audiostream->ms.state==MSStreamInitialized)
audio_stream_prepare_sound(call->audiostream, NULL, NULL);
@@ -1879,11 +1913,14 @@ static void configure_rtp_session_for_rtcp_xr(LinphoneCore *lc, LinphoneCall *ca
OrtpRtcpXrConfiguration currentconfig;
const SalStreamDescription *localstream;
const SalStreamDescription *remotestream;
+ SalMediaDescription *remotedesc = sal_call_get_remote_media_description(call->op);
+
+ if (!remotedesc) return;
localstream = sal_media_description_find_best_stream(call->localdesc, type);
if (!localstream) return;
localconfig = &localstream->rtcp_xr;
- remotestream = sal_media_description_find_best_stream(sal_call_get_remote_media_description(call->op), type);
+ remotestream = sal_media_description_find_best_stream(remotedesc, type);
if (!remotestream) return;
remoteconfig = &remotestream->rtcp_xr;
@@ -1989,8 +2026,8 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cna
crypto_idx = find_crypto_index_from_tag(local_st_desc->crypto, stream->crypto_local_tag);
if (crypto_idx >= 0) {
- media_stream_set_srtp_recv_key(&call->audiostream->ms,stream->crypto[0].algo,stream->crypto[0].master_key);
- media_stream_set_srtp_send_key(&call->audiostream->ms,stream->crypto[0].algo,local_st_desc->crypto[crypto_idx].master_key);
+ media_stream_set_srtp_recv_key(&call->audiostream->ms,stream->crypto[0].algo,stream->crypto[0].master_key, TRUE);
+ media_stream_set_srtp_send_key(&call->audiostream->ms,stream->crypto[0].algo,local_st_desc->crypto[crypto_idx].master_key, TRUE);
} else {
ms_warning("Failed to find local crypto algo with tag: %d", stream->crypto_local_tag);
}
@@ -2111,8 +2148,8 @@ static void linphone_call_start_video_stream(LinphoneCall *call, const char *cna
if (sal_stream_description_has_srtp(vstream) == TRUE) {
int crypto_idx = find_crypto_index_from_tag(local_st_desc->crypto, vstream->crypto_local_tag);
if (crypto_idx >= 0) {
- media_stream_set_srtp_recv_key(&call->videostream->ms,vstream->crypto[0].algo,vstream->crypto[0].master_key);
- media_stream_set_srtp_send_key(&call->videostream->ms,vstream->crypto[0].algo,local_st_desc->crypto[crypto_idx].master_key);
+ media_stream_set_srtp_recv_key(&call->videostream->ms,vstream->crypto[0].algo,vstream->crypto[0].master_key, TRUE);
+ media_stream_set_srtp_send_key(&call->videostream->ms,vstream->crypto[0].algo,local_st_desc->crypto[crypto_idx].master_key, TRUE);
}
}
configure_rtp_session_for_rtcp_xr(lc, call, SalVideo);
@@ -2192,8 +2229,8 @@ void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_mut
call->up_bw=linphone_core_get_upload_bandwidth(lc);
if (call->params->media_encryption==LinphoneMediaEncryptionZRTP) {
- OrtpZrtpParams params;
- memset(¶ms,0,sizeof(OrtpZrtpParams));
+ MSZrtpParams params;
+ memset(¶ms,0,sizeof(MSZrtpParams));
/*call->current_params.media_encryption will be set later when zrtp is activated*/
params.zid_file=lc->zrtp_secrets_cache;
@@ -2202,7 +2239,7 @@ void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_mut
#if VIDEO_ENABLED
if (media_stream_secured((MediaStream *)call->audiostream) && media_stream_get_state((MediaStream *)call->videostream) == MSStreamStarted) {
/*audio stream is already encrypted and video stream is active*/
- memset(¶ms,0,sizeof(OrtpZrtpParams));
+ memset(¶ms,0,sizeof(MSZrtpParams));
video_stream_enable_zrtp(call->videostream,call->audiostream,¶ms);
}
#endif
@@ -2234,9 +2271,9 @@ static bool_t update_stream_crypto_params(LinphoneCall *call, const SalStreamDes
int crypto_idx = find_crypto_index_from_tag(local_st_desc->crypto, new_stream->crypto_local_tag);
if (crypto_idx >= 0) {
if (call->localdesc_changed & SAL_MEDIA_DESCRIPTION_CRYPTO_KEYS_CHANGED)
- media_stream_set_srtp_send_key(ms,new_stream->crypto[0].algo,local_st_desc->crypto[crypto_idx].master_key);
+ media_stream_set_srtp_send_key(ms,new_stream->crypto[0].algo,local_st_desc->crypto[crypto_idx].master_key, TRUE);
if (strcmp(old_stream->crypto[0].master_key,new_stream->crypto[0].master_key)!=0){
- media_stream_set_srtp_recv_key(ms,new_stream->crypto[0].algo,new_stream->crypto[0].master_key);
+ media_stream_set_srtp_recv_key(ms,new_stream->crypto[0].algo,new_stream->crypto[0].master_key,TRUE);
}
return TRUE;
} else {
@@ -2531,6 +2568,27 @@ const LinphoneCallStats *linphone_call_get_video_stats(LinphoneCall *call) {
return stats;
}
+static bool_t ice_in_progress(LinphoneCallStats *stats){
+ return stats->ice_state==LinphoneIceStateInProgress;
+}
+
+/**
+ * Indicates whether an operation is in progress at the media side.
+ * It can a bad idea to initiate signaling operations (adding video, pausing the call, removing video, changing video parameters) while
+ * the media is busy in establishing the connection (typically ICE connectivity checks). It can result in failures generating loss of time
+ * in future operations in the call.
+ * Applications are invited to check this function after each call state change to decide whether certain operations are permitted or not.
+ * @param call the call
+ * @return TRUE if media is busy in establishing the connection, FALSE otherwise.
+**/
+bool_t linphone_call_media_in_progress(LinphoneCall *call){
+ bool_t ret=FALSE;
+ if (ice_in_progress(&call->stats[LINPHONE_CALL_STATS_AUDIO]) || ice_in_progress(&call->stats[LINPHONE_CALL_STATS_VIDEO]))
+ ret=TRUE;
+ /*TODO: could check zrtp state, upnp state*/
+ return ret;
+}
+
/**
* Get the local loss rate since last report
* @return The sender loss rate
@@ -2808,6 +2866,8 @@ static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){
break;
case LinphoneCallIdle:
linphone_call_stop_media_streams_for_ice_gathering(call);
+ linphone_call_update_local_media_description_from_ice_or_upnp(call);
+ sal_call_set_local_media_description(call->op,call->localdesc);
linphone_core_notify_incoming_call(call->core, call);
break;
default:
@@ -2944,7 +3004,8 @@ void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapse
linphone_call_handle_stream_events(call,0);
linphone_call_handle_stream_events(call,1);
- if (call->state==LinphoneCallStreamsRunning && one_second_elapsed && call->audiostream!=NULL && disconnect_timeout>0 )
+ if (call->state==LinphoneCallStreamsRunning && one_second_elapsed && call->audiostream!=NULL
+ && call->audiostream->ms.state==MSStreamStarted && disconnect_timeout>0 )
disconnected=!audio_stream_alive(call->audiostream,disconnect_timeout);
if (disconnected)
linphone_core_disconnected(call->core,call);
@@ -3102,3 +3163,76 @@ void linphone_call_set_new_params(LinphoneCall *call, const LinphoneCallParams *
if (call->params) linphone_call_params_unref(call->params);
call->params=cp;
}
+
+static int send_dtmf_handler(void *data, unsigned int revents){
+ LinphoneCall *call = (LinphoneCall*)data;
+ /*By default we send DTMF RFC2833 if we do not have enabled SIP_INFO but we can also send RFC2833 and SIP_INFO*/
+ if (linphone_core_get_use_rfc2833_for_dtmf(call->core)!=0 || linphone_core_get_use_info_for_dtmf(call->core)==0)
+ {
+ /* In Band DTMF */
+ if (call->audiostream!=NULL){
+ audio_stream_send_dtmf(call->audiostream,*call->dtmf_sequence);
+ }
+ else
+ {
+ ms_error("Cannot send RFC2833 DTMF when we are not in communication.");
+ return FALSE;
+ }
+ }
+ if (linphone_core_get_use_info_for_dtmf(call->core)!=0){
+ /* Out of Band DTMF (use INFO method) */
+ sal_call_send_dtmf(call->op,*call->dtmf_sequence);
+ }
+
+ /*this check is needed because linphone_call_send_dtmf does not set the timer since its a single character*/
+ if (call->dtmfs_timer!=NULL) {
+ memmove(call->dtmf_sequence, call->dtmf_sequence+1, strlen(call->dtmf_sequence));
+ }
+ /* continue only if the dtmf sequence is not empty*/
+ if (call->dtmf_sequence!=NULL&&*call->dtmf_sequence!='\0') {
+ return TRUE;
+ } else {
+ linphone_call_cancel_dtmfs(call);
+ return FALSE;
+ }
+}
+int linphone_call_send_dtmf(LinphoneCall *call,char dtmf){
+ if (call==NULL){
+ ms_warning("linphone_call_send_dtmf(): invalid call, canceling DTMF.");
+ return -1;
+ }
+ call->dtmf_sequence = &dtmf;
+ send_dtmf_handler(call,0);
+ call->dtmf_sequence = NULL;
+ return 0;
+}
+
+int linphone_call_send_dtmfs(LinphoneCall *call,char *dtmfs) {
+ if (call==NULL){
+ ms_warning("linphone_call_send_dtmfs(): invalid call, canceling DTMF sequence.");
+ return -1;
+ }
+ if (call->dtmfs_timer!=NULL){
+ ms_warning("linphone_call_send_dtmfs(): a DTMF sequence is already in place, canceling DTMF sequence.");
+ return -2;
+ }
+ if (dtmfs != NULL) {
+ int delay_ms = lp_config_get_int(call->core->config,"net","dtmf_delay_ms",200);
+ call->dtmf_sequence = ms_strdup(dtmfs);
+ call->dtmfs_timer = sal_create_timer(call->core->sal, send_dtmf_handler, call, delay_ms, "DTMF sequence timer");
+ }
+ return 0;
+}
+
+void linphone_call_cancel_dtmfs(LinphoneCall *call) {
+ /*nothing to do*/
+ if (!call || !call->dtmfs_timer) return;
+
+ sal_cancel_timer(call->core->sal, call->dtmfs_timer);
+ belle_sip_object_unref(call->dtmfs_timer);
+ call->dtmfs_timer = NULL;
+ if (call->dtmf_sequence != NULL) {
+ ms_free(call->dtmf_sequence);
+ call->dtmf_sequence = NULL;
+ }
+}
diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c
index 1e20f8fb5..63da7cf0e 100644
--- a/coreapi/linphonecore.c
+++ b/coreapi/linphonecore.c
@@ -27,7 +27,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include
#include
#include
-#include
+#include
#include "mediastreamer2/mediastream.h"
#include "mediastreamer2/mseventqueue.h"
#include "mediastreamer2/msvolume.h"
@@ -56,7 +56,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#endif
#ifdef HAVE_ZLIB
-#define COMPRESSED_LOG_COLLECTION_FILENAME "linphone_log.gz"
+#define COMPRESSED_LOG_COLLECTION_EXTENSION "gz"
#ifdef WIN32
#include
#include
@@ -66,8 +66,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#endif
#include
#else
-#define COMPRESSED_LOG_COLLECTION_FILENAME "linphone_log.txt"
+#define COMPRESSED_LOG_COLLECTION_EXTENSION "txt"
#endif
+#define LOG_COLLECTION_DEFAULT_PATH "."
+#define LOG_COLLECTION_DEFAULT_PREFIX "linphone"
+#define LOG_COLLECTION_DEFAULT_MAX_FILE_SIZE (10 * 1024 * 1024)
+
/*#define UNSTANDART_GSM_11K 1*/
@@ -81,8 +85,10 @@ static const char *liblinphone_version=
#endif
;
static OrtpLogFunc liblinphone_log_func = NULL;
-static bool_t liblinphone_log_collection_enabled = FALSE;
+static LinphoneLogCollectionState liblinphone_log_collection_state = LinphoneLogCollectionDisabled;
static char * liblinphone_log_collection_path = NULL;
+static char * liblinphone_log_collection_prefix = NULL;
+static int liblinphone_log_collection_max_file_size = LOG_COLLECTION_DEFAULT_MAX_FILE_SIZE;
static ortp_mutex_t liblinphone_log_collection_mutex;
static bool_t liblinphone_serialize_logs = FALSE;
static void set_network_reachable(LinphoneCore* lc,bool_t isReachable, time_t curtime);
@@ -164,8 +170,6 @@ void linphone_core_set_log_level(OrtpLogLevel loglevel) {
}
}
-#define LOGFILE_MAXSIZE (10 * 1024 * 1024)
-
static void linphone_core_log_collection_handler(OrtpLogLevel level, const char *fmt, va_list args) {
const char *lname="undef";
char *msg;
@@ -205,16 +209,20 @@ static void linphone_core_log_collection_handler(OrtpLogLevel level, const char
}
msg = ortp_strdup_vprintf(fmt, args);
- log_filename1 = ortp_strdup_printf("%s/%s", liblinphone_log_collection_path ? liblinphone_log_collection_path : ".", "linphone1.log");
- log_filename2 = ortp_strdup_printf("%s/%s", liblinphone_log_collection_path ? liblinphone_log_collection_path : ".", "linphone2.log");
+ log_filename1 = ortp_strdup_printf("%s/%s1.log",
+ liblinphone_log_collection_path ? liblinphone_log_collection_path : LOG_COLLECTION_DEFAULT_PATH,
+ liblinphone_log_collection_prefix ? liblinphone_log_collection_prefix : LOG_COLLECTION_DEFAULT_PREFIX);
+ log_filename2 = ortp_strdup_printf("%s/%s2.log",
+ liblinphone_log_collection_path ? liblinphone_log_collection_path : LOG_COLLECTION_DEFAULT_PATH,
+ liblinphone_log_collection_prefix ? liblinphone_log_collection_prefix : LOG_COLLECTION_DEFAULT_PREFIX);
ortp_mutex_lock(&liblinphone_log_collection_mutex);
log_file = fopen(log_filename1, "a");
fstat(fileno(log_file), &statbuf);
- if (statbuf.st_size > LOGFILE_MAXSIZE) {
+ if (statbuf.st_size > liblinphone_log_collection_max_file_size) {
fclose(log_file);
log_file = fopen(log_filename2, "a");
fstat(fileno(log_file), &statbuf);
- if (statbuf.st_size > LOGFILE_MAXSIZE) {
+ if (statbuf.st_size > liblinphone_log_collection_max_file_size) {
fclose(log_file);
unlink(log_filename1);
rename(log_filename2, log_filename1);
@@ -232,6 +240,13 @@ static void linphone_core_log_collection_handler(OrtpLogLevel level, const char
ortp_free(msg);
}
+const char * linphone_core_get_log_collection_path(void) {
+ if (liblinphone_log_collection_path != NULL) {
+ return liblinphone_log_collection_path;
+ }
+ return LOG_COLLECTION_DEFAULT_PATH;
+}
+
void linphone_core_set_log_collection_path(const char *path) {
if (liblinphone_log_collection_path != NULL) {
ms_free(liblinphone_log_collection_path);
@@ -242,6 +257,31 @@ void linphone_core_set_log_collection_path(const char *path) {
}
}
+const char * linphone_core_get_log_collection_prefix(void) {
+ if (liblinphone_log_collection_prefix != NULL) {
+ return liblinphone_log_collection_prefix;
+ }
+ return LOG_COLLECTION_DEFAULT_PREFIX;
+}
+
+void linphone_core_set_log_collection_prefix(const char *prefix) {
+ if (liblinphone_log_collection_prefix != NULL) {
+ ms_free(liblinphone_log_collection_prefix);
+ liblinphone_log_collection_prefix = NULL;
+ }
+ if (prefix != NULL) {
+ liblinphone_log_collection_prefix = ms_strdup(prefix);
+ }
+}
+
+int linphone_core_get_log_collection_max_file_size(void) {
+ return liblinphone_log_collection_max_file_size;
+}
+
+void linphone_core_set_log_collection_max_file_size(int size) {
+ liblinphone_log_collection_max_file_size = size;
+}
+
const char *linphone_core_get_log_collection_upload_server_url(LinphoneCore *core) {
return lp_config_get_string(core->config, "misc", "log_collection_upload_server_url", NULL);
}
@@ -250,14 +290,20 @@ void linphone_core_set_log_collection_upload_server_url(LinphoneCore *core, cons
lp_config_set_string(core->config, "misc", "log_collection_upload_server_url", server_url);
}
+LinphoneLogCollectionState linphone_core_log_collection_enabled(void) {
+ return liblinphone_log_collection_state;
+}
+
void linphone_core_enable_log_collection(LinphoneLogCollectionState state) {
+ if (liblinphone_log_collection_state == state) return;
+
/* at first call of this function, set liblinphone_log_func to the current
* ortp log function */
if( liblinphone_log_func == NULL ){
liblinphone_log_func = ortp_logv_out;
}
- if ((state != LinphoneLogCollectionDisabled) && (liblinphone_log_collection_enabled == FALSE)) {
- liblinphone_log_collection_enabled = TRUE;
+ liblinphone_log_collection_state = state;
+ if (state != LinphoneLogCollectionDisabled) {
ortp_mutex_init(&liblinphone_log_collection_mutex, NULL);
if (state == LinphoneLogCollectionEnabledWithoutPreviousLogHandler) {
liblinphone_log_func = NULL;
@@ -266,13 +312,15 @@ void linphone_core_enable_log_collection(LinphoneLogCollectionState state) {
}
ortp_set_log_handler(linphone_core_log_collection_handler);
} else {
- liblinphone_log_collection_enabled = FALSE;
ortp_set_log_handler(liblinphone_log_func);
}
}
static void delete_log_collection_upload_file(void) {
- char *filename = ms_strdup_printf("%s/%s", liblinphone_log_collection_path ? liblinphone_log_collection_path : ".", COMPRESSED_LOG_COLLECTION_FILENAME);
+ char *filename = ms_strdup_printf("%s/%s_log.%s",
+ liblinphone_log_collection_path ? liblinphone_log_collection_path : LOG_COLLECTION_DEFAULT_PATH,
+ liblinphone_log_collection_prefix ? liblinphone_log_collection_prefix : LOG_COLLECTION_DEFAULT_PREFIX,
+ COMPRESSED_LOG_COLLECTION_EXTENSION);
unlink(filename);
ms_free(filename);
}
@@ -307,7 +355,10 @@ static int log_collection_upload_on_send_body(belle_sip_user_body_handler_t *bh,
/* If we've not reach the end of file yet, fill the buffer with more data */
if (offset < core->log_collection_upload_information->size) {
- char *log_filename = ms_strdup_printf("%s/%s", liblinphone_log_collection_path ? liblinphone_log_collection_path : ".", COMPRESSED_LOG_COLLECTION_FILENAME);
+ char *log_filename = ms_strdup_printf("%s/%s_log.%s",
+ liblinphone_log_collection_path ? liblinphone_log_collection_path : LOG_COLLECTION_DEFAULT_PATH,
+ liblinphone_log_collection_prefix ? liblinphone_log_collection_prefix : LOG_COLLECTION_DEFAULT_PREFIX,
+ COMPRESSED_LOG_COLLECTION_EXTENSION);
#ifdef HAVE_ZLIB
FILE *log_file = fopen(log_filename, "rb");
#else
@@ -328,7 +379,7 @@ static int log_collection_upload_on_send_body(belle_sip_user_body_handler_t *bh,
*/
static void log_collection_upload_on_progress(belle_sip_body_handler_t *bh, belle_sip_message_t *msg, void *data, size_t offset, size_t total) {
LinphoneCore *core = (LinphoneCore *)data;
- linphone_core_notify_log_collection_upload_progress_indication(core, (size_t)(((double)offset / (double)total) * 100.0));
+ linphone_core_notify_log_collection_upload_progress_indication(core, offset, total);
}
/**
@@ -453,17 +504,22 @@ static int prepare_log_collection_file_to_upload(const char *filename) {
int ret = 0;
ortp_mutex_lock(&liblinphone_log_collection_mutex);
- output_filename = ms_strdup_printf("%s/%s", liblinphone_log_collection_path ? liblinphone_log_collection_path : ".", filename);
- output_file = COMPRESS_OPEN(output_filename, "a");
+ output_filename = ms_strdup_printf("%s/%s",
+ liblinphone_log_collection_path ? liblinphone_log_collection_path : LOG_COLLECTION_DEFAULT_PATH, filename);
+ output_file = COMPRESS_OPEN(output_filename, "w");
if (output_file == NULL) goto error;
- input_filename = ms_strdup_printf("%s/%s", liblinphone_log_collection_path ? liblinphone_log_collection_path : ".", "linphone1.log");
+ input_filename = ms_strdup_printf("%s/%s1.log",
+ liblinphone_log_collection_path ? liblinphone_log_collection_path : LOG_COLLECTION_DEFAULT_PATH,
+ liblinphone_log_collection_prefix ? liblinphone_log_collection_prefix : LOG_COLLECTION_DEFAULT_PREFIX);
input_file = fopen(input_filename, "r");
if (input_file == NULL) goto error;
ret = compress_file(input_file, output_file);
if (ret < 0) goto error;
fclose(input_file);
ms_free(input_filename);
- input_filename = ms_strdup_printf("%s/%s", liblinphone_log_collection_path ? liblinphone_log_collection_path : ".", "linphone2.log");
+ input_filename = ms_strdup_printf("%s/%s2.log",
+ liblinphone_log_collection_path ? liblinphone_log_collection_path : LOG_COLLECTION_DEFAULT_PATH,
+ liblinphone_log_collection_prefix ? liblinphone_log_collection_prefix : LOG_COLLECTION_DEFAULT_PREFIX);
input_file = fopen(input_filename, "r");
if (input_file != NULL) {
ret = compress_file(input_file, output_file);
@@ -481,7 +537,8 @@ error:
static size_t get_size_of_file_to_upload(const char *filename) {
struct stat statbuf;
- char *output_filename = ms_strdup_printf("%s/%s", liblinphone_log_collection_path ? liblinphone_log_collection_path : ".", filename);
+ char *output_filename = ms_strdup_printf("%s/%s",
+ liblinphone_log_collection_path ? liblinphone_log_collection_path : LOG_COLLECTION_DEFAULT_PATH, filename);
FILE *output_file = fopen(output_filename, "rb");
fstat(fileno(output_file), &statbuf);
fclose(output_file);
@@ -490,7 +547,7 @@ static size_t get_size_of_file_to_upload(const char *filename) {
}
void linphone_core_upload_log_collection(LinphoneCore *core) {
- if ((core->log_collection_upload_information == NULL) && (linphone_core_get_log_collection_upload_server_url(core) != NULL) && (liblinphone_log_collection_enabled == TRUE)) {
+ if ((core->log_collection_upload_information == NULL) && (linphone_core_get_log_collection_upload_server_url(core) != NULL) && (liblinphone_log_collection_state != LinphoneLogCollectionDisabled)) {
/* open a transaction with the server and send an empty request(RCS5.1 section 3.5.4.8.3.1) */
belle_http_request_listener_callbacks_t cbs = { 0 };
belle_http_request_listener_t *l;
@@ -506,7 +563,9 @@ void linphone_core_upload_log_collection(LinphoneCore *core) {
core->log_collection_upload_information->type = "text";
core->log_collection_upload_information->subtype = "plain";
#endif
- core->log_collection_upload_information->name = COMPRESSED_LOG_COLLECTION_FILENAME;
+ core->log_collection_upload_information->name = ms_strdup_printf("%s_log.%s",
+ liblinphone_log_collection_prefix ? liblinphone_log_collection_prefix : LOG_COLLECTION_DEFAULT_PREFIX,
+ COMPRESSED_LOG_COLLECTION_EXTENSION);
if (prepare_log_collection_file_to_upload(core->log_collection_upload_information->name) < 0) return;
core->log_collection_upload_information->size = get_size_of_file_to_upload(core->log_collection_upload_information->name);
uri = belle_generic_uri_parse(linphone_core_get_log_collection_upload_server_url(core));
@@ -519,20 +578,35 @@ void linphone_core_upload_log_collection(LinphoneCore *core) {
}
}
-char * linphone_core_compress_log_collection(LinphoneCore *core) {
- if (liblinphone_log_collection_enabled == FALSE) return NULL;
- if (prepare_log_collection_file_to_upload(COMPRESSED_LOG_COLLECTION_FILENAME) < 0) return NULL;
- return ms_strdup_printf("%s/%s", liblinphone_log_collection_path ? liblinphone_log_collection_path : ".", COMPRESSED_LOG_COLLECTION_FILENAME);
+char * linphone_core_compress_log_collection() {
+ char *filename = NULL;
+ if (liblinphone_log_collection_state == LinphoneLogCollectionDisabled) return NULL;
+ filename = ms_strdup_printf("%s_log.%s",
+ liblinphone_log_collection_prefix ? liblinphone_log_collection_prefix : LOG_COLLECTION_DEFAULT_PREFIX,
+ COMPRESSED_LOG_COLLECTION_EXTENSION);
+ if (prepare_log_collection_file_to_upload(filename) < 0) {
+ ms_free(filename);
+ return NULL;
+ }
+ ms_free(filename);
+ return ms_strdup_printf("%s/%s_log.%s",
+ liblinphone_log_collection_path ? liblinphone_log_collection_path : LOG_COLLECTION_DEFAULT_PATH,
+ liblinphone_log_collection_prefix ? liblinphone_log_collection_prefix : LOG_COLLECTION_DEFAULT_PREFIX,
+ COMPRESSED_LOG_COLLECTION_EXTENSION);
}
-void linphone_core_reset_log_collection(LinphoneCore *core) {
+void linphone_core_reset_log_collection() {
char *filename;
ortp_mutex_lock(&liblinphone_log_collection_mutex);
delete_log_collection_upload_file();
- filename = ms_strdup_printf("%s/%s", liblinphone_log_collection_path ? liblinphone_log_collection_path : ".", "linphone1.log");
+ filename = ms_strdup_printf("%s/%s1.log",
+ liblinphone_log_collection_path ? liblinphone_log_collection_path : LOG_COLLECTION_DEFAULT_PATH,
+ liblinphone_log_collection_prefix ? liblinphone_log_collection_prefix : LOG_COLLECTION_DEFAULT_PREFIX);
unlink(filename);
ms_free(filename);
- filename = ms_strdup_printf("%s/%s", liblinphone_log_collection_path ? liblinphone_log_collection_path : ".", "linphone2.log");
+ filename = ms_strdup_printf("%s/%s2.log",
+ liblinphone_log_collection_path ? liblinphone_log_collection_path : LOG_COLLECTION_DEFAULT_PATH,
+ liblinphone_log_collection_prefix ? liblinphone_log_collection_prefix : LOG_COLLECTION_DEFAULT_PREFIX);
unlink(filename);
ms_free(filename);
ortp_mutex_unlock(&liblinphone_log_collection_mutex);
@@ -1227,6 +1301,7 @@ bool_t linphone_core_rtcp_enabled(const LinphoneCore *lc){
*/
void linphone_core_set_download_bandwidth(LinphoneCore *lc, int bw){
lc->net_conf.download_bw=bw;
+ linphone_core_update_allocated_audio_bandwidth(lc);
if (linphone_core_ready(lc)) lp_config_set_int(lc->config,"net","download_bw",bw);
}
@@ -1243,6 +1318,7 @@ void linphone_core_set_download_bandwidth(LinphoneCore *lc, int bw){
*/
void linphone_core_set_upload_bandwidth(LinphoneCore *lc, int bw){
lc->net_conf.upload_bw=bw;
+ linphone_core_update_allocated_audio_bandwidth(lc);
if (linphone_core_ready(lc)) lp_config_set_int(lc->config,"net","upload_bw",bw);
}
@@ -1449,7 +1525,7 @@ void linphone_configuring_terminated(LinphoneCore *lc, LinphoneConfiguringState
static void linphone_core_init(LinphoneCore * lc, const LinphoneCoreVTable *vtable, LpConfig *config, void * userdata)
{
const char *remote_provisioning_uri = NULL;
- const char *aac_ftmp162248, *aac_ftmp3244;
+ const char *aac_fmtp162248, *aac_fmtp3244;
LinphoneCoreVTable* local_vtable= linphone_core_v_table_new();
ms_message("Initializing LinphoneCore %s", linphone_core_get_version());
memset (lc, 0, sizeof (LinphoneCore));
@@ -1506,11 +1582,11 @@ static void linphone_core_init(LinphoneCore * lc, const LinphoneCoreVTable *vtab
* for the mpeg4-generic mime type, setting this flag to 1 will break compatibility with other clients. */
if( lp_config_get_int(lc->config, "misc", "aac_use_sbr", FALSE) ) {
ms_message("Using SBR for AAC");
- aac_ftmp162248 = "config=F8EE2000; constantDuration=512; indexDeltaLength=3; indexLength=3; mode=AAC-hbr; profile-level-id=76; sizeLength=13; streamType=5 SBR-enabled=1;";
- aac_ftmp3244 = "config=F8E82000; constantDuration=512; indexDeltaLength=3; indexLength=3; mode=AAC-hbr; profile-level-id=76; sizeLength=13; streamType=5 SBR-enabled=1;";
+ aac_fmtp162248 = "config=F8EE2000; constantDuration=512; indexDeltaLength=3; indexLength=3; mode=AAC-hbr; profile-level-id=76; sizeLength=13; streamType=5; SBR-enabled=1";
+ aac_fmtp3244 = "config=F8E82000; constantDuration=512; indexDeltaLength=3; indexLength=3; mode=AAC-hbr; profile-level-id=76; sizeLength=13; streamType=5; SBR-enabled=1";
} else {
- aac_ftmp162248 = "config=F8EE2000; constantDuration=512; indexDeltaLength=3; indexLength=3; mode=AAC-hbr; profile-level-id=76; sizeLength=13; streamType=5";
- aac_ftmp3244 = "config=F8E82000; constantDuration=512; indexDeltaLength=3; indexLength=3; mode=AAC-hbr; profile-level-id=76; sizeLength=13; streamType=5";
+ aac_fmtp162248 = "config=F8EE2000; constantDuration=512; indexDeltaLength=3; indexLength=3; mode=AAC-hbr; profile-level-id=76; sizeLength=13; streamType=5";
+ aac_fmtp3244 = "config=F8E82000; constantDuration=512; indexDeltaLength=3; indexLength=3; mode=AAC-hbr; profile-level-id=76; sizeLength=13; streamType=5";
}
@@ -1532,11 +1608,11 @@ static void linphone_core_init(LinphoneCore * lc, const LinphoneCoreVTable *vtab
linphone_core_assign_payload_type(lc,&payload_type_silk_wb,-1,NULL);
linphone_core_assign_payload_type(lc,&payload_type_silk_swb,-1,NULL);
linphone_core_assign_payload_type(lc,&payload_type_g729,18,"annexb=no");
- linphone_core_assign_payload_type(lc,&payload_type_aaceld_16k,-1,aac_ftmp162248);
- linphone_core_assign_payload_type(lc,&payload_type_aaceld_22k,-1,aac_ftmp162248);
- linphone_core_assign_payload_type(lc,&payload_type_aaceld_32k,-1,aac_ftmp3244);
- linphone_core_assign_payload_type(lc,&payload_type_aaceld_44k,-1,aac_ftmp3244);
- linphone_core_assign_payload_type(lc,&payload_type_aaceld_48k,-1,aac_ftmp162248);
+ linphone_core_assign_payload_type(lc,&payload_type_aaceld_16k,-1,aac_fmtp162248);
+ linphone_core_assign_payload_type(lc,&payload_type_aaceld_22k,-1,aac_fmtp162248);
+ linphone_core_assign_payload_type(lc,&payload_type_aaceld_32k,-1,aac_fmtp3244);
+ linphone_core_assign_payload_type(lc,&payload_type_aaceld_44k,-1,aac_fmtp3244);
+ linphone_core_assign_payload_type(lc,&payload_type_aaceld_48k,-1,aac_fmtp162248);
linphone_core_assign_payload_type(lc,&payload_type_opus,-1,"useinbandfec=1; stereo=0; sprop-stereo=0");
linphone_core_assign_payload_type(lc,&payload_type_isac,-1,NULL);
linphone_core_handle_static_payloads(lc);
@@ -1758,6 +1834,7 @@ int linphone_core_set_audio_codecs(LinphoneCore *lc, MSList *codecs)
if (lc->codecs_conf.audio_codecs!=NULL) ms_list_free(lc->codecs_conf.audio_codecs);
lc->codecs_conf.audio_codecs=codecs;
_linphone_core_codec_config_write(lc);
+ linphone_core_update_allocated_audio_bandwidth(lc);
return 0;
}
@@ -2088,7 +2165,7 @@ static bool_t transports_unchanged(const LCSipTransports * tr1, const LCSipTrans
tr2->tls_port==tr1->tls_port;
}
-static int apply_transports(LinphoneCore *lc){
+int _linphone_core_apply_transports(LinphoneCore *lc){
Sal *sal=lc->sal;
const char *anyaddr;
LCSipTransports *tr=&lc->sip_conf.transports;
@@ -2102,20 +2179,26 @@ static int apply_transports(LinphoneCore *lc){
anyaddr="0.0.0.0";
sal_unlisten_ports(sal);
- if (tr->udp_port!=0){
- if (sal_listen_port (sal,anyaddr,tr->udp_port,SalTransportUDP,FALSE)!=0){
- transport_error(lc,"udp",tr->udp_port);
+ if (lc->tunnel && linphone_tunnel_sip_enabled(lc->tunnel) && linphone_tunnel_get_activated(lc->tunnel)){
+ if (sal_listen_port(sal,anyaddr,tr->udp_port,SalTransportUDP,TRUE)!=0){
+ transport_error(lc,"udp+tunnel",tr->udp_port);
}
- }
- if (tr->tcp_port!=0){
- if (sal_listen_port (sal,anyaddr,tr->tcp_port,SalTransportTCP,FALSE)!=0){
- transport_error(lc,"tcp",tr->tcp_port);
+ }else{
+ if (tr->udp_port!=0){
+ if (sal_listen_port(sal,anyaddr,tr->udp_port,SalTransportUDP,FALSE)!=0){
+ transport_error(lc,"udp",tr->udp_port);
+ }
}
- }
- if (linphone_core_sip_transport_supported(lc,LinphoneTransportTls)){
- if (tr->tls_port!=0){
- if (sal_listen_port (sal,anyaddr,tr->tls_port,SalTransportTLS,TRUE)!=0){
- transport_error(lc,"tls",tr->tls_port);
+ if (tr->tcp_port!=0){
+ if (sal_listen_port (sal,anyaddr,tr->tcp_port,SalTransportTCP,FALSE)!=0){
+ transport_error(lc,"tcp",tr->tcp_port);
+ }
+ }
+ if (linphone_core_sip_transport_supported(lc,LinphoneTransportTls)){
+ if (tr->tls_port!=0){
+ if (sal_listen_port (sal,anyaddr,tr->tls_port,SalTransportTLS,FALSE)!=0){
+ transport_error(lc,"tls",tr->tls_port);
+ }
}
}
}
@@ -2168,7 +2251,7 @@ int linphone_core_set_sip_transports(LinphoneCore *lc, const LCSipTransports * t
}
if (lc->sal==NULL) return 0;
- return apply_transports(lc);
+ return _linphone_core_apply_transports(lc);
}
/**
@@ -2232,8 +2315,13 @@ void linphone_core_enable_ipv6(LinphoneCore *lc, bool_t val){
if (lc->sip_conf.ipv6_enabled!=val){
lc->sip_conf.ipv6_enabled=val;
if (lc->sal){
- /* we need to restart eXosip */
- apply_transports(lc);
+ /* we need to update the sip stack */
+ _linphone_core_apply_transports(lc);
+ }
+ /*update the localip immediately for the network monitor to avoid to "discover" later that we switched to ipv6*/
+ linphone_core_get_local_ip(lc,AF_UNSPEC,NULL,lc->localip);
+ if (linphone_core_ready(lc)){
+ lp_config_set_int(lc->config,"sip","use_ipv6",(int)val);
}
}
}
@@ -3142,22 +3230,9 @@ void linphone_core_notify_incoming_call(LinphoneCore *lc, LinphoneCall *call){
char *barmesg;
char *tmp;
LinphoneAddress *from_parsed;
- SalMediaDescription *md;
bool_t propose_early_media=lp_config_get_int(lc->config,"sip","incoming_calls_early_media",FALSE);
const char *ringback_tone=linphone_core_get_remote_ringback_tone (lc);
- linphone_call_make_local_media_description(lc,call);
- sal_call_set_local_media_description(call->op,call->localdesc);
- md=sal_call_get_final_media_description(call->op);
- if (md){
- if (sal_media_description_empty(md) || linphone_core_incompatible_security(lc,md)){
- sal_call_decline(call->op,SalReasonNotAcceptable,NULL);
- linphone_call_set_state_base(call, LinphoneCallError, NULL,TRUE);
- linphone_call_unref(call);
- return;
- }
- }
-
from_parsed=linphone_address_new(sal_op_get_from(call->op));
linphone_address_clean(from_parsed);
tmp=linphone_address_as_string(from_parsed);
@@ -4617,7 +4692,10 @@ const char * linphone_core_get_ringback(const LinphoneCore *lc){
}
/**
- * Enables or disable echo cancellation. Value is saved an used for subsequent calls
+ * Enables or disable echo cancellation. Value is saved and used for subsequent calls.
+ * This actually controls software echo cancellation. If hardware echo cancellation is available, it will be always used and activated for calls, regardless
+ * of the value passed to this function.
+ * When hardware echo cancellation is available, the software one is of course not activated.
*
* @ingroup media_parameters
**/
@@ -4712,38 +4790,10 @@ bool_t linphone_core_agc_enabled(const LinphoneCore *lc){
return lc->sound_conf.agc;
}
-/**
- * Send the specified dtmf.
- *
- * @ingroup media_parameters
- * This function only works during calls. The dtmf is automatically played to the user.
- * @param lc The LinphoneCore object
- * @param dtmf The dtmf name specified as a char, such as '0', '#' etc...
- *
-**/
void linphone_core_send_dtmf(LinphoneCore *lc, char dtmf)
{
LinphoneCall *call=linphone_core_get_current_call(lc);
- if (call==NULL){
- ms_warning("linphone_core_send_dtmf(): no active call");
- return;
- }
- /*By default we send DTMF RFC2833 if we do not have enabled SIP_INFO but we can also send RFC2833 and SIP_INFO*/
- if (linphone_core_get_use_rfc2833_for_dtmf(lc)!=0 || linphone_core_get_use_info_for_dtmf(lc)==0)
- {
- /* In Band DTMF */
- if (call->audiostream!=NULL){
- audio_stream_send_dtmf(call->audiostream,dtmf);
- }
- else
- {
- ms_error("we cannot send RFC2833 dtmf when we are not in communication");
- }
- }
- if (linphone_core_get_use_info_for_dtmf(lc)!=0){
- /* Out of Band DTMF (use INFO method) */
- sal_call_send_dtmf(call->op,dtmf);
- }
+ linphone_call_send_dtmf(call, dtmf);
}
void linphone_core_set_stun_server(LinphoneCore *lc, const char *server){
@@ -6216,6 +6266,9 @@ static void linphone_core_uninit(LinphoneCore *lc)
if(lc->rec_file!=NULL){
ms_free(lc->rec_file);
}
+ if (lc->chat_db_file){
+ ms_free(lc->chat_db_file);
+ }
if(lc->presence_model){
linphone_presence_model_unref(lc->presence_model);
}
@@ -6343,11 +6396,17 @@ bool_t linphone_core_can_we_add_call(LinphoneCore *lc)
return FALSE;
}
+static void notify_soundcard_usage(LinphoneCore *lc, bool_t used){
+ MSSndCard *card=lc->sound_conf.capt_sndcard;
+ if (card && ms_snd_card_get_capabilities(card) & MS_SND_CARD_CAP_IS_SLOW){
+ ms_snd_card_set_usage_hint(card,used);
+ }
+}
int linphone_core_add_call( LinphoneCore *lc, LinphoneCall *call)
{
- if(linphone_core_can_we_add_call(lc))
- {
+ if (linphone_core_can_we_add_call(lc)){
+ if (lc->calls==NULL) notify_soundcard_usage(lc,TRUE);
lc->calls = ms_list_append(lc->calls,call);
return 0;
}
@@ -6370,6 +6429,7 @@ int linphone_core_del_call( LinphoneCore *lc, LinphoneCall *call)
return -1;
}
lc->calls = the_calls;
+ if (lc->calls==NULL) notify_soundcard_usage(lc,FALSE);
return 0;
}
@@ -6709,7 +6769,7 @@ bool_t linphone_core_media_encryption_supported(const LinphoneCore *lc, Linphone
case LinphoneMediaEncryptionSRTP:
return media_stream_srtp_supported();
case LinphoneMediaEncryptionZRTP:
- return ortp_zrtp_available();
+ return ms_zrtp_available();
case LinphoneMediaEncryptionNone:
return TRUE;
}
@@ -6726,7 +6786,7 @@ int linphone_core_set_media_encryption(LinphoneCore *lc, LinphoneMediaEncryption
ret=-1;
}else type="srtp";
}else if (menc == LinphoneMediaEncryptionZRTP){
- if (!ortp_zrtp_available()){
+ if (!ms_zrtp_available()){
ms_warning("ZRTP not supported by library.");
type="none";
ret=-1;
@@ -6784,7 +6844,7 @@ void linphone_core_set_sip_dscp(LinphoneCore *lc, int dscp){
sal_set_dscp(lc->sal,dscp);
if (linphone_core_ready(lc)){
lp_config_set_int_hex(lc->config,"sip","dscp",dscp);
- apply_transports(lc);
+ _linphone_core_apply_transports(lc);
}
}
@@ -7078,8 +7138,8 @@ void linphone_core_notify_publish_state_changed(LinphoneCore *lc, LinphoneEvent
void linphone_core_notify_log_collection_upload_state_changed(LinphoneCore *lc, LinphoneCoreLogCollectionUploadState state, const char *info) {
NOTIFY_IF_EXIST(log_collection_upload_state_changed)(lc, state, info);
}
-void linphone_core_notify_log_collection_upload_progress_indication(LinphoneCore *lc, size_t progress) {
- NOTIFY_IF_EXIST(log_collection_upload_progress_indication)(lc, progress);
+void linphone_core_notify_log_collection_upload_progress_indication(LinphoneCore *lc, size_t offset, size_t total) {
+ NOTIFY_IF_EXIST(log_collection_upload_progress_indication)(lc, offset, total);
}
void linphone_core_add_listener(LinphoneCore *lc, LinphoneCoreVTable *vtable) {
ms_message("Vtable [%p] registered on core [%p]",lc,vtable);
diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h
index 8cd4ea4f8..af0d4b5fc 100644
--- a/coreapi/linphonecore.h
+++ b/coreapi/linphonecore.h
@@ -483,7 +483,7 @@ typedef struct _LinphoneVideoPolicy LinphoneVideoPolicy;
* @ingroup initializing
**/
enum _LinphoneIceState{
- LinphoneIceStateNotActivated, /**< ICE has not been activated for this call */
+ LinphoneIceStateNotActivated, /**< ICE has not been activated for this call or stream*/
LinphoneIceStateFailed, /**< ICE processing has failed */
LinphoneIceStateInProgress, /**< ICE process is in progress */
LinphoneIceStateHostConnection, /**< ICE has established a direct connection to the remote host */
@@ -605,10 +605,10 @@ void linphone_player_destroy(LinphonePlayer *obj);
* @param lc A LinphoneCore object
* @param snd_card Playback sound card. If NULL, the sound card set in LinphoneCore will be used
* @param video_out Video display. If NULL, the video display set in LinphoneCore will be used
- * @param window_id Pointer on the drawing window
+ * @param window_id Id of the drawing window. Depend of video out
* @return A pointer on the new instance. NULL if faild.
*/
-LINPHONE_PUBLIC LinphonePlayer *linphone_core_create_local_player(LinphoneCore *lc, MSSndCard *snd_card, const char *video_out, void *window_id);
+LINPHONE_PUBLIC LinphonePlayer *linphone_core_create_local_player(LinphoneCore *lc, MSSndCard *snd_card, const char *video_out, unsigned long window_id);
/**
* @brief Check whether Matroksa format is supported by the player
@@ -732,6 +732,38 @@ LINPHONE_PUBLIC void linphone_call_zoom_video(LinphoneCall* call, float zoom_fac
LINPHONE_PUBLIC void linphone_call_start_recording(LinphoneCall *call);
LINPHONE_PUBLIC void linphone_call_stop_recording(LinphoneCall *call);
LINPHONE_PUBLIC LinphonePlayer * linphone_call_get_player(LinphoneCall *call);
+LINPHONE_PUBLIC bool_t linphone_call_media_in_progress(LinphoneCall *call);
+/**
+ * Send the specified dtmf.
+ *
+ * The dtmf is automatically played to the user.
+ * @param call The LinphoneCall object
+ * @param dtmf The dtmf name specified as a char, such as '0', '#' etc...
+ * @returns 0 if successful, -1 on error.
+**/
+LINPHONE_PUBLIC int linphone_call_send_dtmf(LinphoneCall *lc,char dtmf);
+
+/**
+ * Send a list of dtmf.
+ *
+ * The dtmfs are automatically sent to remote, separated by some needed customizable delay.
+ * Sending is canceled if the call state changes to something not LinphoneCallStreamsRunning.
+ * @param call The LinphoneCall object
+ * @param dtmfs A dtmf sequence such as '123#123123'
+ * @returns -2 if there is already a DTMF sequence, -1 if call is not ready, 0 otherwise.
+**/
+LINPHONE_PUBLIC int linphone_call_send_dtmfs(LinphoneCall *call,char *dtmfs);
+
+/**
+ * Stop current DTMF sequence sending.
+ *
+ * Please note that some DTMF could be already sent,
+ * depending on when this function call is delayed from #linphone_call_send_dtmfs. This
+ * function will be automatically called if call state change to anything but LinphoneCallStreamsRunning.
+ *
+ * @param call The LinphoneCall object
+**/
+LINPHONE_PUBLIC void linphone_call_cancel_dtmfs(LinphoneCall *call);
/**
* Return TRUE if this call is currently part of a conference
@@ -1426,7 +1458,7 @@ LINPHONE_PUBLIC const char* linphone_chat_message_get_external_body_url(const Li
LINPHONE_PUBLIC void linphone_chat_message_set_external_body_url(LinphoneChatMessage* message,const char* url);
LINPHONE_PUBLIC const LinphoneContent* linphone_chat_message_get_file_transfer_information(const LinphoneChatMessage* message);
LINPHONE_PUBLIC void linphone_chat_message_start_file_download(LinphoneChatMessage* message, LinphoneChatMessageStateChangedCb status_cb, void* ud);
-LINPHONE_PUBLIC void linphone_chat_room_cancel_file_transfer(LinphoneChatMessage* msg);
+LINPHONE_PUBLIC void linphone_chat_message_cancel_file_transfer(LinphoneChatMessage* msg);
LINPHONE_PUBLIC const char* linphone_chat_message_get_appdata(const LinphoneChatMessage* message);
LINPHONE_PUBLIC void linphone_chat_message_set_appdata(LinphoneChatMessage* message, const char* data);
LINPHONE_PUBLIC const char* linphone_chat_message_get_text(const LinphoneChatMessage* message);
@@ -1696,7 +1728,7 @@ typedef void (*LinphoneCoreLogCollectionUploadStateChangedCb)(LinphoneCore *lc,
* @param[in] lc LinphoneCore object
* @param[in] progress Percentage of the file size of the log collection already uploaded.
*/
-typedef void (*LinphoneCoreLogCollectionUploadProgressIndicationCb)(LinphoneCore *lc, size_t progress);
+typedef void (*LinphoneCoreLogCollectionUploadProgressIndicationCb)(LinphoneCore *lc, size_t offset, size_t total);
/**
* This structure holds all callbacks that the application should implement.
@@ -1788,6 +1820,13 @@ typedef enum _LinphoneLogCollectionState {
LinphoneLogCollectionEnabledWithoutPreviousLogHandler
} LinphoneLogCollectionState;
+/**
+ * Tells whether the linphone core log collection is enabled.
+ * @ingroup misc
+ * @returns The state of the linphone core log collection.
+ */
+LINPHONE_PUBLIC LinphoneLogCollectionState linphone_core_log_collection_enabled(void);
+
/**
* Enable the linphone core log collection to upload logs on a server.
* @ingroup misc
@@ -1795,6 +1834,13 @@ typedef enum _LinphoneLogCollectionState {
*/
LINPHONE_PUBLIC void linphone_core_enable_log_collection(LinphoneLogCollectionState state);
+/**
+ * Get the path where the log files will be written for log collection.
+ * @ingroup misc
+ * @returns The path where the log files will be written.
+ */
+LINPHONE_PUBLIC const char * linphone_core_get_log_collection_path(void);
+
/**
* Set the path where the log files will be written for log collection.
* @ingroup misc
@@ -1802,6 +1848,38 @@ LINPHONE_PUBLIC void linphone_core_enable_log_collection(LinphoneLogCollectionSt
*/
LINPHONE_PUBLIC void linphone_core_set_log_collection_path(const char *path);
+/**
+ * Get the prefix of the filenames that will be used for log collection.
+ * @ingroup misc
+ * @returns The prefix of the filenames used for log collection.
+ */
+LINPHONE_PUBLIC const char * linphone_core_get_log_collection_prefix(void);
+
+/**
+ * Set the prefix of the filenames that will be used for log collection.
+ * @ingroup misc
+ * @param[in] prefix The prefix to use for the filenames for log collection.
+ */
+LINPHONE_PUBLIC void linphone_core_set_log_collection_prefix(const char *prefix);
+
+/**
+ * Get the max file size in bytes of the files used for log collection.
+ * @ingroup misc
+ * @returns The max file size in bytes of the files used for log collection.
+ */
+LINPHONE_PUBLIC int linphone_core_get_log_collection_max_file_size(void);
+
+/**
+ * Set the max file size in bytes of the files used for log collection.
+ * Warning: this function should only not be used to change size
+ * dynamically but instead only before calling @see
+ * linphone_core_enable_log_collection. If you increase max size
+ * on runtime, logs chronological order COULD be broken.
+ * @ingroup misc
+ * @param[in] size The max file size in bytes of the files used for log collection.
+ */
+LINPHONE_PUBLIC void linphone_core_set_log_collection_max_file_size(int size);
+
/**
* Set the url of the server where to upload the collected log files.
* @ingroup misc
@@ -1820,17 +1898,15 @@ LINPHONE_PUBLIC void linphone_core_upload_log_collection(LinphoneCore *core);
/**
* Compress the log collection in a single file.
* @ingroup misc
- * @param[in] core LinphoneCore object
* @return The path of the compressed log collection file (to be freed calling ms_free()).
*/
-LINPHONE_PUBLIC char * linphone_core_compress_log_collection(LinphoneCore *core);
+LINPHONE_PUBLIC char * linphone_core_compress_log_collection();
/**
* Reset the log collection by removing the log files.
* @ingroup misc
- * @param[in] core LinphoneCore object
*/
-LINPHONE_PUBLIC void linphone_core_reset_log_collection(LinphoneCore *core);
+LINPHONE_PUBLIC void linphone_core_reset_log_collection();
/**
* Define a log handler.
@@ -2006,6 +2082,16 @@ LINPHONE_PUBLIC LinphoneCallParams *linphone_core_create_call_params(LinphoneCor
LINPHONE_PUBLIC LinphoneCall *linphone_core_get_call_by_remote_address(LinphoneCore *lc, const char *remote_address);
+/**
+ * Send the specified dtmf.
+ *
+ * @ingroup media_parameters
+ * @deprecated Use #linphone_call_send_dtmf instead.
+ * This function only works during calls. The dtmf is automatically played to the user.
+ * @param lc The LinphoneCore object
+ * @param dtmf The dtmf name specified as a char, such as '0', '#' etc...
+ *
+**/
LINPHONE_PUBLIC void linphone_core_send_dtmf(LinphoneCore *lc,char dtmf);
LINPHONE_PUBLIC int linphone_core_set_primary_contact(LinphoneCore *lc, const char *contact);
@@ -2719,7 +2805,7 @@ LINPHONE_PUBLIC void linphone_core_set_native_preview_window_id(LinphoneCore *lc
**/
LINPHONE_PUBLIC void linphone_core_use_preview_window(LinphoneCore *lc, bool_t yesno);
-int linphone_core_get_device_rotation(LinphoneCore *lc );
+LINPHONE_PUBLIC int linphone_core_get_device_rotation(LinphoneCore *lc );
LINPHONE_PUBLIC void linphone_core_set_device_rotation(LinphoneCore *lc, int rotation);
/**
diff --git a/coreapi/linphonecore_jni.cc b/coreapi/linphonecore_jni.cc
index 241f130cc..2a985519e 100644
--- a/coreapi/linphonecore_jni.cc
+++ b/coreapi/linphonecore_jni.cc
@@ -2685,8 +2685,8 @@ extern "C" jlong Java_org_linphone_core_LinphoneChatRoomImpl_createFileTransferM
return (jlong) message;
}
-extern "C" void Java_org_linphone_core_LinphoneChatRoomImpl_cancelFileTransfer(JNIEnv* env, jobject thiz, jlong ptr, jlong message) {
- linphone_chat_room_cancel_file_transfer((LinphoneChatMessage *)message);
+extern "C" void Java_org_linphone_core_LinphoneChatMessageImpl_cancelFileTransfer(JNIEnv* env, jobject thiz, jlong ptr) {
+ linphone_chat_message_cancel_file_transfer((LinphoneChatMessage *)ptr);
}
extern "C" jobject Java_org_linphone_core_LinphoneChatMessageImpl_getFileTransferInformation(JNIEnv* env, jobject thiz, jlong ptr) {
@@ -5320,13 +5320,8 @@ extern "C" void Java_org_linphone_core_LinphonePlayerImpl_destroy(JNIEnv *env, j
extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_createLocalPlayer(JNIEnv *env, jobject jobj, jlong ptr, jobject window) {
jobject window_ref = NULL;
- MSSndCard *snd_card = ms_snd_card_manager_get_default_playback_card(ms_snd_card_manager_get());
- if(snd_card == NULL) {
- ms_error("No default playback sound card found");
- return 0;
- }
window_ref = env->NewGlobalRef(window);
- LinphonePlayer *player = linphone_core_create_local_player((LinphoneCore *)ptr, snd_card, "MSAndroidDisplay", window_ref);
+ LinphonePlayer *player = linphone_core_create_local_player((LinphoneCore *)ptr, NULL, "MSAndroidDisplay", (unsigned long)window_ref);
if(player == NULL) {
ms_error("Fails to create a player");
if(window_ref) env->DeleteGlobalRef(window_ref);
diff --git a/coreapi/localplayer.c b/coreapi/localplayer.c
index ad06e1751..964c1c920 100644
--- a/coreapi/localplayer.c
+++ b/coreapi/localplayer.c
@@ -32,9 +32,9 @@ static void _local_player_close(LinphonePlayer *obj);
static void _local_player_destroy(LinphonePlayer *obj);
static void _local_player_eof_callback(void *user_data);
-LinphonePlayer *linphone_core_create_local_player(LinphoneCore *lc, MSSndCard *snd_card, const char *video_out, void *window_id) {
+LinphonePlayer *linphone_core_create_local_player(LinphoneCore *lc, MSSndCard *snd_card, const char *video_out, unsigned long window_id) {
LinphonePlayer *obj = ms_new0(LinphonePlayer, 1);
- if(snd_card == NULL) snd_card = lc->sound_conf.play_sndcard;
+ if(snd_card == NULL) snd_card = lc->sound_conf.ring_sndcard;
if(video_out == NULL) video_out = linphone_core_get_video_display_filter(lc);
obj->impl = ms_media_player_new(snd_card, video_out, window_id);
obj->open = _local_player_open;
diff --git a/coreapi/message_storage.c b/coreapi/message_storage.c
index 8cbd088f2..feb243ba7 100644
--- a/coreapi/message_storage.c
+++ b/coreapi/message_storage.c
@@ -364,7 +364,7 @@ void linphone_chat_room_delete_history(LinphoneChatRoom *cr){
MSList *linphone_chat_room_get_history_range(LinphoneChatRoom *cr, int startm, int endm){
LinphoneCore *lc=linphone_chat_room_get_lc(cr);
MSList *ret;
- char *buf;
+ char *buf,*buf2;
char *peer;
uint64_t begin,end;
int buf_max_size = 512;
@@ -378,17 +378,24 @@ MSList *linphone_chat_room_get_history_range(LinphoneChatRoom *cr, int startm, i
buf=ms_malloc(buf_max_size);
buf=sqlite3_snprintf(buf_max_size-1,buf,"SELECT * FROM history WHERE remoteContact = %Q ORDER BY id DESC",peer);
+
if (startm<0) startm=0;
if (endm>0&&endm>=startm){
- buf=sqlite3_snprintf(buf_max_size-1,buf,"%s LIMIT %i ",buf,endm+1-startm);
+ buf2=ms_strdup_printf("%s LIMIT %i ",buf,endm+1-startm);
+ ms_free(buf);
+ buf = buf2;
}else if(startm>0){
- ms_message("%s(): end is lower than start (%d < %d). No end assumed.",__FUNCTION__,endm,startm);
- buf=sqlite3_snprintf(buf_max_size-1,buf,"%s LIMIT -1",buf);
+ ms_message("%s(): end is lower than start (%d < %d). Assuming no end limit.",__FUNCTION__,endm,startm);
+ buf2=ms_strdup_printf("%s LIMIT -1",buf);
+ ms_free(buf);
+ buf = buf2;
}
if (startm>0){
- buf=sqlite3_snprintf(buf_max_size-1,buf,"%s OFFSET %i ",buf,startm);
+ buf2=ms_strdup_printf("%s OFFSET %i ",buf,startm);
+ ms_free(buf);
+ buf = buf2;
}
begin=ortp_get_cur_time_ms();
@@ -403,7 +410,7 @@ MSList *linphone_chat_room_get_history_range(LinphoneChatRoom *cr, int startm, i
}
MSList *linphone_chat_room_get_history(LinphoneChatRoom *cr,int nb_message){
- return linphone_chat_room_get_history_range(cr, 0, nb_message);
+ return linphone_chat_room_get_history_range(cr, 0, nb_message-1);
}
@@ -462,7 +469,7 @@ static int migrate_messages_timestamp(void* data,int argc, char** argv, char** c
time_t new_time = parse_time_from_db(argv[1]);
if( new_time ){
/* replace 'time' by -1 and set 'utc' to the timestamp */
- char *buf = sqlite3_mprintf("UPDATE history SET utc=%lld,time='-1' WHERE id=%i;", new_time, atoi(argv[0]));
+ char *buf = sqlite3_mprintf("UPDATE history SET utc=%lld,time='-1' WHERE id=%i;", (int64_t)new_time, atoi(argv[0]));
if( buf) {
linphone_sql_request((sqlite3*)data, buf);
sqlite3_free(buf);
diff --git a/coreapi/misc.c b/coreapi/misc.c
index 81365f5a2..5de319246 100644
--- a/coreapi/misc.c
+++ b/coreapi/misc.c
@@ -86,6 +86,7 @@ int linphone_core_enable_payload_type(LinphoneCore *lc, LinphonePayloadType *pt,
if (ms_list_find(lc->codecs_conf.audio_codecs,pt) || ms_list_find(lc->codecs_conf.video_codecs,pt)){
payload_type_set_enable(pt,enabled);
_linphone_core_codec_config_write(lc);
+ linphone_core_update_allocated_audio_bandwidth(lc);
return 0;
}
ms_error("Enabling codec not in audio or video list of PayloadType !");
@@ -113,12 +114,14 @@ void linphone_core_set_payload_type_bitrate(LinphoneCore *lc, LinphonePayloadTyp
if (pt->type==PAYLOAD_VIDEO || pt->flags & PAYLOAD_TYPE_IS_VBR){
pt->normal_bitrate=bitrate*1000;
pt->flags|=PAYLOAD_TYPE_BITRATE_OVERRIDE;
+ linphone_core_update_allocated_audio_bandwidth(lc);
}else{
ms_error("Cannot set an explicit bitrate for codec %s/%i, because it is not VBR.",pt->mime_type,pt->clock_rate);
return;
}
+ } else {
+ ms_error("linphone_core_set_payload_type_bitrate() payload type not in audio or video list !");
}
- ms_error("linphone_core_set_payload_type_bitrate() payload type not in audio or video list !");
}
@@ -188,7 +191,6 @@ int linphone_core_get_payload_type_bitrate(LinphoneCore *lc, const LinphonePaylo
return get_audio_payload_bandwidth(lc,pt,maxbw);
}else if (pt->type==PAYLOAD_VIDEO){
int video_bw;
- linphone_core_update_allocated_audio_bandwidth(lc);
if (maxbw<=0) {
video_bw=1500; /*default bitrate for video stream when no bandwidth limit is set, around 1.5 Mbit/s*/
}else{
@@ -685,7 +687,7 @@ void linphone_core_update_ice_state_in_call_stats(LinphoneCall *call)
} else {
call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state = LinphoneIceStateFailed;
}
- }
+ }else call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state = LinphoneIceStateNotActivated;
} else if (session_state == IS_Running) {
call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state = LinphoneIceStateInProgress;
if (call->params->has_video && (video_check_list != NULL)) {
@@ -699,7 +701,7 @@ void linphone_core_update_ice_state_in_call_stats(LinphoneCall *call)
}
}
-void linphone_core_update_local_media_description_from_ice(SalMediaDescription *desc, IceSession *session)
+void _update_local_media_description_from_ice(SalMediaDescription *desc, IceSession *session)
{
const char *rtp_addr, *rtcp_addr;
IceSessionState session_state = ice_session_state(session);
@@ -820,7 +822,7 @@ static void clear_ice_check_list(LinphoneCall *call, IceCheckList *removed){
call->videostream->ms.ice_check_list=NULL;
}
-void linphone_core_update_ice_from_remote_media_description(LinphoneCall *call, const SalMediaDescription *md)
+void linphone_call_update_ice_from_remote_media_description(LinphoneCall *call, const SalMediaDescription *md)
{
bool_t ice_restarted = FALSE;
diff --git a/coreapi/private.h b/coreapi/private.h
index 8b47ba07e..49df6c1d7 100644
--- a/coreapi/private.h
+++ b/coreapi/private.h
@@ -102,7 +102,7 @@ struct _LinphoneCallParams{
bool_t real_early_media; /*send real media even during early media (for outgoing calls)*/
bool_t in_conference; /*in conference mode */
bool_t low_bandwidth;
- bool_t no_user_consent;/*when set to TRUE an UPDATE request will be used instead of reINVITE*/
+ bool_t no_user_consent;/*when set to TRUE an UPDATE request will be used instead of reINVITE*/
uint16_t avpf_rr_interval; /*in milliseconds*/
LinphonePrivacyMask privacy;
};
@@ -188,8 +188,7 @@ typedef struct _PortConfig{
int rtcp_port;
}PortConfig;
-struct _LinphoneCall
-{
+struct _LinphoneCall{
belle_sip_object_t base;
void *user_data;
struct _LinphoneCore *core;
@@ -239,6 +238,9 @@ struct _LinphoneCall
int localdesc_changed;/*not a boolean, contains a mask representing changes*/
LinphonePlayer *player;
+ char *dtmf_sequence; /*DTMF sequence needed to be sent using #dtmfs_timer*/
+ belle_sip_source_t *dtmfs_timer; /*DTMF timer needed to send a DTMF sequence*/
+
bool_t refer_pending;
bool_t expect_media_in_ack;
bool_t audio_muted;
@@ -374,8 +376,9 @@ void linphone_core_adapt_to_network(LinphoneCore *lc, int ping_time_ms, Linphone
int linphone_core_gather_ice_candidates(LinphoneCore *lc, LinphoneCall *call);
void linphone_core_update_ice_state_in_call_stats(LinphoneCall *call);
void linphone_call_stats_fill(LinphoneCallStats *stats, MediaStream *ms, OrtpEvent *ev);
-void linphone_core_update_local_media_description_from_ice(SalMediaDescription *desc, IceSession *session);
-void linphone_core_update_ice_from_remote_media_description(LinphoneCall *call, const SalMediaDescription *md);
+void _update_local_media_description_from_ice(SalMediaDescription *desc, IceSession *session);
+void linphone_call_update_local_media_description_from_ice_or_upnp(LinphoneCall *call);
+void linphone_call_update_ice_from_remote_media_description(LinphoneCall *call, const SalMediaDescription *md);
bool_t linphone_core_media_description_contains_video_stream(const SalMediaDescription *md);
void linphone_core_send_initial_subscribes(LinphoneCore *lc);
@@ -410,8 +413,7 @@ void linphone_call_delete_upnp_session(LinphoneCall *call);
void linphone_call_stop_media_streams_for_ice_gathering(LinphoneCall *call);
void linphone_call_update_crypto_parameters(LinphoneCall *call, SalMediaDescription *old_md, SalMediaDescription *new_md);
void linphone_call_update_remote_session_id_and_ver(LinphoneCall *call);
-void linphone_call_set_state_base(LinphoneCall *call, LinphoneCallState cstate, const char *message,bool_t silently);
-
+int _linphone_core_apply_transports(LinphoneCore *lc);
const char * linphone_core_get_identity(LinphoneCore *lc);
void linphone_core_start_waiting(LinphoneCore *lc, const char *purpose);
@@ -464,17 +466,17 @@ struct _LinphoneProxyConfig
LinphoneRegistrationState state;
SalOp *publish_op;
LinphoneAVPFMode avpf_mode;
-
+
bool_t commit;
bool_t reg_sendregister;
bool_t publish;
bool_t dial_escape_plus;
-
+
bool_t send_publish;
bool_t quality_reporting_enabled;
uint8_t avpf_rr_interval;
uint8_t quality_reporting_interval;
-
+
time_t deletion_date;
LinphonePrivacyMask privacy;
/*use to check if server config has changed between edit() and done()*/
@@ -1028,7 +1030,7 @@ void linphone_core_notify_notify_received(LinphoneCore *lc, LinphoneEvent *lev,
void linphone_core_notify_subscription_state_changed(LinphoneCore *lc, LinphoneEvent *lev, LinphoneSubscriptionState state);
void linphone_core_notify_publish_state_changed(LinphoneCore *lc, LinphoneEvent *lev, LinphonePublishState state);
void linphone_core_notify_log_collection_upload_state_changed(LinphoneCore *lc, LinphoneCoreLogCollectionUploadState state, const char *info);
-void linphone_core_notify_log_collection_upload_progress_indication(LinphoneCore *lc, size_t progress);
+void linphone_core_notify_log_collection_upload_progress_indication(LinphoneCore *lc, size_t offset, size_t total);
void set_mic_gain_db(AudioStream *st, float gain);
void set_playback_gain_db(AudioStream *st, float gain);
diff --git a/coreapi/proxy.c b/coreapi/proxy.c
index 7e0e35c8a..ca9c21c9d 100644
--- a/coreapi/proxy.c
+++ b/coreapi/proxy.c
@@ -924,7 +924,7 @@ int linphone_proxy_config_normalize_number(LinphoneProxyConfig *proxy, const cha
if (is_a_phone_number(username)){
char *flatten;
flatten=flatten_number(username);
- ms_message("Flattened number is '%s'",flatten);
+ ms_debug("Flattened number is '%s'",flatten);
if (proxy->dial_prefix==NULL || proxy->dial_prefix[0]=='\0'){
/*no prefix configured, nothing else to do*/
@@ -934,10 +934,10 @@ int linphone_proxy_config_normalize_number(LinphoneProxyConfig *proxy, const cha
}else{
dial_plan_t dialplan;
lookup_dial_plan(proxy->dial_prefix,&dialplan);
- ms_message("Using dialplan '%s'",dialplan.country);
+ ms_debug("Using dialplan '%s'",dialplan.country);
if (flatten[0]=='+' || strstr(flatten,dialplan.icp)==flatten){
/* the number has international prefix or +, so nothing to do*/
- ms_message("Prefix already present.");
+ ms_debug("Prefix already present.");
/*eventually replace the plus*/
replace_plus(flatten,result,result_len,proxy->dial_escape_plus ? dialplan.icp : NULL);
ms_free(flatten);
diff --git a/coreapi/quality_reporting.c b/coreapi/quality_reporting.c
index 9e2e6c7ea..52d88a7a2 100644
--- a/coreapi/quality_reporting.c
+++ b/coreapi/quality_reporting.c
@@ -18,7 +18,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
-#include "../config.h"
+#include "config.h"
#endif
#include "linphonecore.h"
@@ -386,7 +386,7 @@ static void update_ip(LinphoneCall * call, int stats_type) {
if (local_desc != NULL) {
/*since this function might be called for video stream AFTER it has been uninitialized, local description might
be invalid. In any other case, IP/port should be always filled and valid*/
- if (local_desc->rtp_addr != NULL && strlen(local_desc->rtp_addr) > 0) {
+ if (strlen(local_desc->rtp_addr) > 0) {
call->log->reporting.reports[stats_type]->info.local_addr.port = local_desc->rtp_port;
STR_REASSIGN(call->log->reporting.reports[stats_type]->info.local_addr.ip, ms_strdup(local_desc->rtp_addr));
}
@@ -397,7 +397,7 @@ static void update_ip(LinphoneCall * call, int stats_type) {
call->log->reporting.reports[stats_type]->info.remote_addr.port = remote_desc->rtp_port;
/*for IP it can be not set if we are using a direct route*/
- if (remote_desc->rtp_addr != NULL && strlen(remote_desc->rtp_addr) > 0) {
+ if (strlen(remote_desc->rtp_addr) > 0) {
STR_REASSIGN(call->log->reporting.reports[stats_type]->info.remote_addr.ip, ms_strdup(remote_desc->rtp_addr));
} else {
STR_REASSIGN(call->log->reporting.reports[stats_type]->info.remote_addr.ip, ms_strdup(sal_call_get_remote_media_description(call->op)->addr));
diff --git a/coreapi/sipsetup.c b/coreapi/sipsetup.c
index 91abf5d62..bf1b411e8 100644
--- a/coreapi/sipsetup.c
+++ b/coreapi/sipsetup.c
@@ -18,7 +18,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
-#include "../config.h"
+#include "config.h"
#endif
#include "linphonecore.h"
diff --git a/coreapi/upnp.c b/coreapi/upnp.c
index c8082514f..83ab387c4 100644
--- a/coreapi/upnp.c
+++ b/coreapi/upnp.c
@@ -840,6 +840,8 @@ int linphone_upnp_call_process(LinphoneCall *call) {
linphone_core_proceed_with_invite_if_ready(lc, call, NULL);
break;
case LinphoneCallIdle:
+ linphone_call_update_local_media_description_from_ice_or_upnp(call);
+ sal_call_set_local_media_description(call->op,call->localdesc);
linphone_core_notify_incoming_call(lc, call);
break;
default:
diff --git a/gtk/incall_view.c b/gtk/incall_view.c
index 5329508b6..4fa0bd66b 100644
--- a/gtk/incall_view.c
+++ b/gtk/incall_view.c
@@ -426,7 +426,9 @@ void linphone_gtk_update_video_button(LinphoneCall *call){
GtkWidget *conf_frame;
const LinphoneCallParams *params=linphone_call_get_current_params(call);
gboolean has_video=linphone_call_params_video_enabled(params);
+ gboolean button_sensitive=FALSE;
if (call_view==NULL) return;
+
button=linphone_gtk_get_widget(call_view,"video_button");
gtk_button_set_image(GTK_BUTTON(button),
@@ -436,12 +438,20 @@ void linphone_gtk_update_video_button(LinphoneCall *call){
gtk_widget_set_sensitive(button,FALSE);
return;
}
+ switch(linphone_call_get_state(call)){
+ case LinphoneCallStreamsRunning:
+ button_sensitive=!linphone_call_media_in_progress(call);
+ break;
+ default:
+ button_sensitive=FALSE;
+ break;
+ }
+ gtk_widget_set_sensitive(button,button_sensitive);
if (GPOINTER_TO_INT(g_object_get_data(G_OBJECT(button),"signal_connected"))==0){
g_signal_connect(G_OBJECT(button),"clicked",(GCallback)video_button_clicked,call);
g_object_set_data(G_OBJECT(button),"signal_connected",GINT_TO_POINTER(1));
}
conf_frame=(GtkWidget *)g_object_get_data(G_OBJECT(linphone_gtk_get_main_window()),"conf_frame");
- gtk_widget_set_sensitive(button,linphone_call_get_state(call)==LinphoneCallStreamsRunning);
if(conf_frame!=NULL){
gtk_widget_set_sensitive(button,FALSE);
}
diff --git a/gtk/videowindow.c b/gtk/videowindow.c
index 24dc584f7..f2247e573 100644
--- a/gtk/videowindow.c
+++ b/gtk/videowindow.c
@@ -74,7 +74,7 @@ static void drag_data_received(GtkWidget *widget, GdkDragContext *context, gint
}
static gboolean drag_drop(GtkWidget *widget, GdkDragContext *drag_context, gint x, gint y, guint time, gpointer user_data){
-#if GTK_CHECK_VERSION(2,20,0)
+#if GTK_CHECK_VERSION(2,21,0)
GList *l=gdk_drag_context_list_targets(drag_context);
GList *elem;
diff --git a/include/sal/sal.h b/include/sal/sal.h
index 3b6c08a9a..09e762576 100644
--- a/include/sal/sal.h
+++ b/include/sal/sal.h
@@ -65,7 +65,7 @@ typedef enum {
SalTransportUDP, /*UDP*/
SalTransportTCP, /*TCP*/
SalTransportTLS, /*TLS*/
- SalTransportDTLS /*DTLS*/
+ SalTransportDTLS, /*DTLS*/
}SalTransport;
#define SAL_MEDIA_DESCRIPTION_UNCHANGED 0x00
@@ -516,7 +516,7 @@ 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_listen_port(Sal *ctx, const char *addr, int port, SalTransport tr, int is_tunneled);
int sal_get_listening_port(Sal *ctx, SalTransport tr);
int sal_unlisten_ports(Sal *ctx);
int sal_transport_available(Sal *ctx, SalTransport t);
@@ -533,8 +533,7 @@ void sal_append_stack_string_to_user_agent(Sal *ctx);
/*keepalive period in ms*/
void sal_set_keepalive_period(Sal *ctx,unsigned int value);
void sal_use_tcp_tls_keepalive(Sal *ctx, bool_t enabled);
-int sal_enable_tunnel(Sal *ctx, void *tunnelclient);
-void sal_disable_tunnel(Sal *ctx);
+int sal_set_tunnel(Sal *ctx, void *tunnelclient);
/*Default value is true*/
void sal_enable_sip_update_method(Sal *ctx,bool_t value);
@@ -639,6 +638,12 @@ bool_t sal_call_autoanswer_asked(SalOp *op);
void sal_call_send_vfu_request(SalOp *h);
int sal_call_is_offerer(const SalOp *h);
int sal_call_notify_refer_state(SalOp *h, SalOp *newcall);
+/* Call test API */
+/*willingly fails to parse SDP from received packets (INVITE and/or ACK) if value=true */
+/* First version: for all new SalOp created (eg. each incoming or outgoing call). Do not forget to reset previous value when you are done!*/
+void sal_default_enable_sdp_removal(Sal* h, bool_t enable) ;
+/* Second version: for a specific call*/
+void sal_call_enable_sdp_removal(SalOp *h, bool_t enable) ;
/*Registration*/
int sal_register(SalOp *op, const char *proxy, const char *from, int expires);
diff --git a/java/common/org/linphone/core/LinphoneChatMessage.java b/java/common/org/linphone/core/LinphoneChatMessage.java
index 930a064db..b1b839b5e 100644
--- a/java/common/org/linphone/core/LinphoneChatMessage.java
+++ b/java/common/org/linphone/core/LinphoneChatMessage.java
@@ -163,6 +163,10 @@ public interface LinphoneChatMessage {
*/
void startFileDownload(LinphoneChatMessage.StateListener listener);
+ /**
+ * Cancel an ongoing file transfer attached to this message.(upload or download).
+ */
+ void cancelFileTransfer();
/**
* Get the file_transfer_information (used by call backs to recover informations during a rcs file transfer)
* @return a pointer to the LinphoneContent structure or NULL if not present.
@@ -179,4 +183,5 @@ public interface LinphoneChatMessage {
* @return the data stored in the chat message if any, else null
*/
String getAppData();
+
}
diff --git a/java/common/org/linphone/core/LinphoneChatRoom.java b/java/common/org/linphone/core/LinphoneChatRoom.java
index 1f8c58f8c..b18e79d0c 100644
--- a/java/common/org/linphone/core/LinphoneChatRoom.java
+++ b/java/common/org/linphone/core/LinphoneChatRoom.java
@@ -144,9 +144,4 @@ public interface LinphoneChatRoom {
*/
LinphoneChatMessage createFileTransferMessage(LinphoneContent content);
- /**
- * Cancel an ongoing file transfer attached to this message (upload or download)
- * @param message
- */
- void cancelFileTransfer(LinphoneChatMessage message);
}
diff --git a/java/impl/org/linphone/core/LinphoneChatMessageImpl.java b/java/impl/org/linphone/core/LinphoneChatMessageImpl.java
index d25ae426a..7e6d474a2 100644
--- a/java/impl/org/linphone/core/LinphoneChatMessageImpl.java
+++ b/java/impl/org/linphone/core/LinphoneChatMessageImpl.java
@@ -127,4 +127,10 @@ public class LinphoneChatMessageImpl implements LinphoneChatMessage {
public String getAppData() {
return getAppData(nativePtr);
}
+
+ private native void cancelFileTransfer(long messagePtr);
+ @Override
+ public void cancelFileTransfer() {
+ cancelFileTransfer(nativePtr);
+ }
}
diff --git a/java/impl/org/linphone/core/LinphoneChatRoomImpl.java b/java/impl/org/linphone/core/LinphoneChatRoomImpl.java
index d47e4e47e..9236bce03 100644
--- a/java/impl/org/linphone/core/LinphoneChatRoomImpl.java
+++ b/java/impl/org/linphone/core/LinphoneChatRoomImpl.java
@@ -177,11 +177,4 @@ class LinphoneChatRoomImpl implements LinphoneChatRoom {
}
}
- private native void cancelFileTransfer(long ptr, long messagePtr);
- @Override
- public void cancelFileTransfer(LinphoneChatMessage message) {
- synchronized(getCore()) {
- cancelFileTransfer(nativePtr, ((LinphoneChatMessageImpl)message).getNativePtr());
- }
- }
}
diff --git a/java/impl/org/linphone/core/LinphoneCoreFactoryImpl.java b/java/impl/org/linphone/core/LinphoneCoreFactoryImpl.java
index f0d3ae064..925bae78d 100644
--- a/java/impl/org/linphone/core/LinphoneCoreFactoryImpl.java
+++ b/java/impl/org/linphone/core/LinphoneCoreFactoryImpl.java
@@ -48,13 +48,9 @@ public class LinphoneCoreFactoryImpl extends LinphoneCoreFactory {
// FFMPEG (audio/video)
if (Version.isX86()) {
- loadOptionalLibrary("avutil-linphone-x86");
- loadOptionalLibrary("swscale-linphone-x86");
- loadOptionalLibrary("avcodec-linphone-x86");
+ loadOptionalLibrary("ffmpeg-linphone-x86");
} else if (Version.isArmv7()) {
- loadOptionalLibrary("avutil-linphone-arm");
- loadOptionalLibrary("swscale-linphone-arm");
- loadOptionalLibrary("avcodec-linphone-arm");
+ loadOptionalLibrary("ffmpeg-linphone-arm");
}
//Main library
@@ -102,7 +98,9 @@ public class LinphoneCoreFactoryImpl extends LinphoneCoreFactory {
public LinphoneCore createLinphoneCore(LinphoneCoreListener listener, Object context) throws LinphoneCoreException {
try {
MediastreamerAndroidContext.setContext(context);
- return new LinphoneCoreImpl(listener);
+ LinphoneCore lc = new LinphoneCoreImpl(listener);
+ if(context!=null) lc.setContext(context);
+ return lc;
} catch (IOException e) {
throw new LinphoneCoreException("Cannot create LinphoneCore",e);
}
diff --git a/java/impl/org/linphone/core/LinphoneCoreImpl.java b/java/impl/org/linphone/core/LinphoneCoreImpl.java
index 6e6f5a21f..ee360e13c 100644
--- a/java/impl/org/linphone/core/LinphoneCoreImpl.java
+++ b/java/impl/org/linphone/core/LinphoneCoreImpl.java
@@ -268,6 +268,7 @@ class LinphoneCoreImpl implements LinphoneCore {
return logs;
}
public synchronized void destroy() {
+ setAndroidPowerManager(null);
delete(nativePtr);
nativePtr=0;
}
diff --git a/mediastreamer2 b/mediastreamer2
index 9dd1d9633..71115380b 160000
--- a/mediastreamer2
+++ b/mediastreamer2
@@ -1 +1 @@
-Subproject commit 9dd1d9633e66ea018d346cc79a6d93ff6daeddf1
+Subproject commit 71115380b55d0a3f5a40405baaed2535b1913dda
diff --git a/oRTP b/oRTP
index 90a19604d..15f1e5f89 160000
--- a/oRTP
+++ b/oRTP
@@ -1 +1 @@
-Subproject commit 90a19604d061d7f23189feb925847e66d366898e
+Subproject commit 15f1e5f89c7381f580190432f33a7f9e86c32e7f
diff --git a/tester/Makefile.am b/tester/Makefile.am
index d8877119d..ec5366726 100644
--- a/tester/Makefile.am
+++ b/tester/Makefile.am
@@ -22,8 +22,10 @@ liblinphonetester_la_SOURCES = tester.c \
stun_tester.c \
remote_provisioning_tester.c \
quality_reporting_tester.c \
+ log_collection_tester.c \
transport_tester.c \
- player_tester.c
+ player_tester.c \
+ dtmf_tester.c
liblinphonetester_la_LDFLAGS= -no-undefined
liblinphonetester_la_LIBADD= ../coreapi/liblinphone.la $(CUNIT_LIBS)
diff --git a/tester/call_tester.c b/tester/call_tester.c
index 62b4d55b5..fbc413905 100644
--- a/tester/call_tester.c
+++ b/tester/call_tester.c
@@ -145,7 +145,7 @@ void liblinphone_tester_check_rtcp(LinphoneCoreManager* caller, LinphoneCoreMana
if (!c1 || !c2) return;
linphone_call_ref(c1);
linphone_call_ref(c2);
-
+
liblinphone_tester_clock_start(&ts);
do {
if (linphone_call_get_audio_stats(c1)->round_trip_delay >0.0
@@ -171,13 +171,21 @@ void liblinphone_tester_check_rtcp(LinphoneCoreManager* caller, LinphoneCoreMana
bool_t call_with_params2(LinphoneCoreManager* caller_mgr
,LinphoneCoreManager* callee_mgr
- , const LinphoneCallParams *caller_params
- , const LinphoneCallParams *callee_params, bool_t build_callee_params) {
+ , const LinphoneCallTestParams *caller_test_params
+ , const LinphoneCallTestParams *callee_test_params
+ , bool_t build_callee_params) {
int retry=0;
stats initial_caller=caller_mgr->stat;
stats initial_callee=callee_mgr->stat;
bool_t result=FALSE;
char hellopath[256];
+ LinphoneCallParams *caller_params = caller_test_params->base;
+ LinphoneCallParams *callee_params = callee_test_params->base;
+ bool_t did_received_call;
+
+ sal_default_enable_sdp_removal(caller_mgr->lc->sal, caller_test_params->sdp_removal);
+ sal_default_enable_sdp_removal(callee_mgr->lc->sal, callee_test_params->sdp_removal);
+
/*use playfile for callee to avoid locking on capture card*/
linphone_core_use_files (callee_mgr->lc,TRUE);
snprintf(hellopath,sizeof(hellopath), "%s/sounds/hello8000.wav", liblinphone_tester_file_prefix);
@@ -188,12 +196,21 @@ bool_t call_with_params2(LinphoneCoreManager* caller_mgr
CU_ASSERT_PTR_NOT_NULL(linphone_core_invite_address_with_params(caller_mgr->lc,callee_mgr->identity,caller_params));
}
+
/*linphone_core_invite(caller_mgr->lc,"pauline");*/
- CU_ASSERT_TRUE(wait_for(callee_mgr->lc
- ,caller_mgr->lc
- ,&callee_mgr->stat.number_of_LinphoneCallIncomingReceived
- ,initial_callee.number_of_LinphoneCallIncomingReceived+1));
+ did_received_call = wait_for(callee_mgr->lc
+ ,caller_mgr->lc
+ ,&callee_mgr->stat.number_of_LinphoneCallIncomingReceived
+ ,initial_callee.number_of_LinphoneCallIncomingReceived+1);
+ CU_ASSERT_EQUAL(did_received_call, !callee_test_params->sdp_removal);
+
+ sal_default_enable_sdp_removal(caller_mgr->lc->sal, FALSE);
+ sal_default_enable_sdp_removal(callee_mgr->lc->sal, FALSE);
+
+ if (!did_received_call) return 0;
+
+
CU_ASSERT_TRUE(linphone_core_inc_invite_pending(callee_mgr->lc));
CU_ASSERT_EQUAL(caller_mgr->stat.number_of_LinphoneCallOutgoingProgress,initial_caller.number_of_LinphoneCallOutgoingProgress+1);
@@ -212,9 +229,9 @@ bool_t call_with_params2(LinphoneCoreManager* caller_mgr
CU_ASSERT_PTR_NOT_NULL(linphone_core_get_current_call_remote_address(callee_mgr->lc));
- if(!linphone_core_get_current_call(caller_mgr->lc) || !linphone_core_get_current_call(callee_mgr->lc) || !linphone_core_get_current_call_remote_address(callee_mgr->lc))
+ if(!linphone_core_get_current_call(caller_mgr->lc) || !linphone_core_get_current_call(callee_mgr->lc) || !linphone_core_get_current_call_remote_address(callee_mgr->lc)) {
return 0;
- else {
+ } else {
LinphoneAddress* callee_from=linphone_address_clone(caller_mgr->identity);
linphone_address_set_port(callee_from,0); /*remove port because port is never present in from header*/
@@ -264,9 +281,19 @@ bool_t call_with_params2(LinphoneCoreManager* caller_mgr
bool_t call_with_params(LinphoneCoreManager* caller_mgr
,LinphoneCoreManager* callee_mgr
- , const LinphoneCallParams *caller_params
- , const LinphoneCallParams *callee_params){
- return call_with_params2(caller_mgr,callee_mgr,caller_params,callee_params,FALSE);
+ ,const LinphoneCallParams *caller_params
+ ,const LinphoneCallParams *callee_params){
+ LinphoneCallTestParams caller_test_params = {0}, callee_test_params = {0};
+ caller_test_params.base = (LinphoneCallParams*)caller_params;
+ callee_test_params.base = (LinphoneCallParams*)caller_params;
+ return call_with_params2(caller_mgr,callee_mgr,&caller_test_params,&callee_test_params,FALSE);
+}
+
+bool_t call_with_test_params(LinphoneCoreManager* caller_mgr
+ ,LinphoneCoreManager* callee_mgr
+ ,const LinphoneCallTestParams *caller_test_params
+ ,const LinphoneCallTestParams *callee_test_params){
+ return call_with_params2(caller_mgr,callee_mgr,caller_test_params,callee_test_params,FALSE);
}
bool_t call_with_caller_params(LinphoneCoreManager* caller_mgr,LinphoneCoreManager* callee_mgr, const LinphoneCallParams *params) {
@@ -290,13 +317,31 @@ static void simple_call(void) {
int leaked_objects;
LinphoneCoreManager* marie;
LinphoneCoreManager* pauline;
+ const LinphoneAddress *from;
+ LinphoneCall *pauline_call;
belle_sip_object_enable_leak_detector(TRUE);
begin=belle_sip_object_get_object_count();
marie = linphone_core_manager_new( "marie_rc");
pauline = linphone_core_manager_new( "pauline_rc");
- CU_ASSERT_TRUE(call(pauline,marie));
+ CU_ASSERT_TRUE(call(marie,pauline));
+ pauline_call=linphone_core_get_current_call(pauline->lc);
+ CU_ASSERT_PTR_NOT_NULL(pauline_call);
+ /*check that display name is correctly propagated in From */
+ if (pauline_call){
+ from=linphone_call_get_remote_address(linphone_core_get_current_call(pauline->lc));
+ CU_ASSERT_PTR_NOT_NULL(from);
+ if (from){
+ const char *dname=linphone_address_get_display_name(from);
+ CU_ASSERT_PTR_NOT_NULL(dname);
+ if (dname){
+ CU_ASSERT_STRING_EQUAL(dname, "Super Marie");
+ }
+ }
+ }
+
+
liblinphone_tester_check_rtcp(marie,pauline);
end_call(marie,pauline);
linphone_core_manager_destroy(marie);
@@ -309,6 +354,45 @@ static void simple_call(void) {
}
}
+static void direct_call_over_ipv6(){
+ LinphoneCoreManager* marie;
+ LinphoneCoreManager* pauline;
+
+ if (liblinphone_tester_ipv6_available()){
+ LCSipTransports pauline_transports;
+ LinphoneAddress* pauline_dest = linphone_address_new("sip:[::1];transport=tcp");
+ marie = linphone_core_manager_new( "marie_rc");
+ pauline = linphone_core_manager_new( "pauline_tcp_rc");
+
+ linphone_core_use_files (pauline->lc,TRUE);
+
+ linphone_core_enable_ipv6(marie->lc,TRUE);
+ linphone_core_enable_ipv6(pauline->lc,TRUE);
+ linphone_core_set_default_proxy_config(marie->lc,NULL);
+ /*wait for register in v6 mode, however sip2.linphone.org has an ipv6 address but doesn't listen to it*/
+#if 0
+ CU_ASSERT_TRUE(wait_for_until(pauline->lc, NULL, &pauline->stat.number_of_LinphoneRegistrationOk, 2, 2000));
+ CU_ASSERT_TRUE(wait_for_until(pauline->lc, NULL, &marie->stat.number_of_LinphoneRegistrationOk, 2, 2000));
+#endif
+
+ linphone_core_get_sip_transports_used(pauline->lc,&pauline_transports);
+ linphone_address_set_port(pauline_dest,pauline_transports.tcp_port);
+ linphone_core_invite_address(marie->lc,pauline_dest);
+
+ CU_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallOutgoingRinging,1));
+ CU_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&pauline->stat.number_of_LinphoneCallIncomingReceived,1));
+ linphone_core_accept_call(pauline->lc,linphone_core_get_current_call(pauline->lc));
+ CU_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallStreamsRunning,1));
+ CU_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&pauline->stat.number_of_LinphoneCallStreamsRunning,1));
+
+ liblinphone_tester_check_rtcp(marie,pauline);
+ end_call(marie,pauline);
+ linphone_core_manager_destroy(marie);
+ linphone_core_manager_destroy(pauline);
+ linphone_address_destroy(pauline_dest);
+ }else ms_warning("Test skipped, no ipv6 available");
+}
+
static void call_outbound_with_multiple_proxy() {
LinphoneCoreManager* pauline = linphone_core_manager_new2( "pauline_rc", FALSE);
LinphoneCoreManager* marie = linphone_core_manager_new2( "marie_rc", FALSE);
@@ -620,24 +704,37 @@ static void disable_all_video_codecs_except_one(LinphoneCore *lc, const char *mi
#endif
static void call_failed_because_of_codecs(void) {
- LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
- LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
- LinphoneCall* out_call;
+ int begin,leaked_objects;
+
+ belle_sip_object_enable_leak_detector(TRUE);
+ begin=belle_sip_object_get_object_count();
+
+ {
+ LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
+ LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
+ LinphoneCall* out_call;
- disable_all_audio_codecs_except_one(marie->lc,"pcmu",-1);
- disable_all_audio_codecs_except_one(pauline->lc,"pcma",-1);
- out_call = linphone_core_invite(pauline->lc,"marie");
- linphone_call_ref(out_call);
- CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallOutgoingInit,1));
+ disable_all_audio_codecs_except_one(marie->lc,"pcmu",-1);
+ disable_all_audio_codecs_except_one(pauline->lc,"pcma",-1);
+ out_call = linphone_core_invite(pauline->lc,"marie");
+ linphone_call_ref(out_call);
+ CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallOutgoingInit,1));
- /*flexisip will retain the 488 until the "urgent reply" timeout (I.E 5s) arrives.*/
- CU_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallError,1,7000));
- CU_ASSERT_EQUAL(linphone_call_get_reason(out_call),LinphoneReasonNotAcceptable);
- CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallIncomingReceived,0);
+ /*flexisip will retain the 488 until the "urgent reply" timeout (I.E 5s) arrives.*/
+ CU_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallError,1,7000));
+ CU_ASSERT_EQUAL(linphone_call_get_reason(out_call),LinphoneReasonNotAcceptable);
+ CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallIncomingReceived,0);
+ CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallReleased,0);
- linphone_call_unref(out_call);
- linphone_core_manager_destroy(marie);
- linphone_core_manager_destroy(pauline);
+ linphone_call_unref(out_call);
+ linphone_core_manager_destroy(marie);
+ linphone_core_manager_destroy(pauline);
+ }
+ leaked_objects=belle_sip_object_get_object_count()-begin;
+ CU_ASSERT_TRUE(leaked_objects==0);
+ if (leaked_objects>0){
+ belle_sip_object_dump_active_objects();
+ }
}
static void call_with_dns_time_out(void) {
@@ -1137,12 +1234,10 @@ static void call_paused_resumed_from_callee(void) {
}
#ifdef VIDEO_ENABLED
-static bool_t add_video(LinphoneCoreManager* caller,LinphoneCoreManager* callee) {
+static LinphoneCall* setup_video(LinphoneCoreManager* caller,LinphoneCoreManager* callee) {
LinphoneVideoPolicy caller_policy;
LinphoneCallParams* callee_params;
LinphoneCall* call_obj;
- stats initial_caller_stat=caller->stat;
- stats initial_callee_stat=callee->stat;
if (!linphone_core_get_current_call(callee->lc) || linphone_call_get_state(linphone_core_get_current_call(callee->lc)) != LinphoneCallStreamsRunning
|| !linphone_core_get_current_call(caller->lc) || linphone_call_get_state(linphone_core_get_current_call(caller->lc)) != LinphoneCallStreamsRunning ) {
@@ -1158,14 +1253,20 @@ static bool_t add_video(LinphoneCoreManager* caller,LinphoneCoreManager* callee)
linphone_core_enable_video_display(caller->lc, FALSE);
linphone_core_set_video_policy(caller->lc,&caller_policy);
-
-
if ((call_obj = linphone_core_get_current_call(callee->lc))) {
callee_params = linphone_call_params_copy(linphone_call_get_current_params(call_obj));
/*add video*/
linphone_call_params_enable_video(callee_params,TRUE);
linphone_core_update_call(callee->lc,call_obj,callee_params);
+ }
+ return call_obj;
+}
+static bool_t add_video(LinphoneCoreManager* caller,LinphoneCoreManager* callee) {
+ stats initial_caller_stat=caller->stat;
+ stats initial_callee_stat=callee->stat;
+ LinphoneCall *call_obj;
+ if ((call_obj=setup_video(caller, callee))){
CU_ASSERT_TRUE(wait_for(caller->lc,callee->lc,&caller->stat.number_of_LinphoneCallUpdatedByRemote,initial_caller_stat.number_of_LinphoneCallUpdatedByRemote+1));
CU_ASSERT_TRUE(wait_for(caller->lc,callee->lc,&callee->stat.number_of_LinphoneCallUpdating,initial_callee_stat.number_of_LinphoneCallUpdating+1));
CU_ASSERT_TRUE(wait_for(caller->lc,callee->lc,&callee->stat.number_of_LinphoneCallStreamsRunning,initial_callee_stat.number_of_LinphoneCallStreamsRunning+1));
@@ -1320,11 +1421,10 @@ static void srtp_call_with_several_video_switches(void) {
static void call_with_declined_video_base(bool_t using_policy) {
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
- LinphoneCallParams* callee_params=NULL;
- LinphoneCallParams* caller_params;
LinphoneCall* marie_call;
LinphoneCall* pauline_call;
LinphoneVideoPolicy marie_policy, pauline_policy;
+ LinphoneCallTestParams caller_test_params = {0}, callee_test_params = {0};
linphone_core_enable_video_capture(marie->lc, TRUE);
linphone_core_enable_video_display(marie->lc, TRUE);
linphone_core_enable_video_capture(pauline->lc, TRUE);
@@ -1340,19 +1440,19 @@ static void call_with_declined_video_base(bool_t using_policy) {
linphone_core_set_video_policy(pauline->lc,&pauline_policy);
}
- caller_params=linphone_core_create_default_call_parameters(pauline->lc);
+ caller_test_params.base=linphone_core_create_default_call_parameters(pauline->lc);
if (!using_policy)
- linphone_call_params_enable_video(caller_params,TRUE);
-
+ linphone_call_params_enable_video(caller_test_params.base,TRUE);
+
if (!using_policy){
- callee_params=linphone_core_create_default_call_parameters(marie->lc);
- linphone_call_params_enable_video(callee_params,FALSE);
+ callee_test_params.base=linphone_core_create_default_call_parameters(marie->lc);
+ linphone_call_params_enable_video(callee_test_params.base,FALSE);
}
- CU_ASSERT_TRUE(call_with_params2(pauline,marie,caller_params,callee_params,using_policy));
-
- linphone_call_params_destroy(caller_params);
- if (callee_params) linphone_call_params_destroy(callee_params);
+ CU_ASSERT_TRUE(call_with_params2(pauline,marie,&caller_test_params,&callee_test_params,using_policy));
+
+ linphone_call_params_destroy(caller_test_params.base);
+ if (callee_test_params.base) linphone_call_params_destroy(callee_test_params.base);
marie_call=linphone_core_get_current_call(marie->lc);
pauline_call=linphone_core_get_current_call(pauline->lc);
@@ -1375,8 +1475,7 @@ static void call_with_declined_video_using_policy(void) {
}
static void video_call_base(LinphoneCoreManager* pauline,LinphoneCoreManager* marie, bool_t using_policy) {
- LinphoneCallParams* callee_params=NULL;
- LinphoneCallParams* caller_params;
+ LinphoneCallTestParams caller_test_params = {0}, callee_test_params = {0};
LinphoneCall* marie_call;
LinphoneCall* pauline_call;
LinphoneVideoPolicy marie_policy, pauline_policy;
@@ -1395,21 +1494,21 @@ static void video_call_base(LinphoneCoreManager* pauline,LinphoneCoreManager* ma
linphone_core_set_video_policy(pauline->lc,&pauline_policy);
}
- caller_params=linphone_core_create_default_call_parameters(pauline->lc);
+ caller_test_params.base=linphone_core_create_default_call_parameters(pauline->lc);
if (!using_policy)
- linphone_call_params_enable_video(caller_params,TRUE);
-
+ linphone_call_params_enable_video(caller_test_params.base,TRUE);
+
if (!using_policy){
- callee_params=linphone_core_create_default_call_parameters(marie->lc);
- linphone_call_params_enable_video(callee_params,TRUE);
+ callee_test_params.base=linphone_core_create_default_call_parameters(marie->lc);
+ linphone_call_params_enable_video(callee_test_params.base,TRUE);
}
- CU_ASSERT_TRUE(call_with_params2(pauline,marie,caller_params,callee_params,using_policy));
+ CU_ASSERT_TRUE(call_with_params2(pauline,marie,&caller_test_params,&callee_test_params,using_policy));
marie_call=linphone_core_get_current_call(marie->lc);
pauline_call=linphone_core_get_current_call(pauline->lc);
- linphone_call_params_destroy(caller_params);
- if (callee_params) linphone_call_params_destroy(callee_params);
+ linphone_call_params_destroy(caller_test_params.base);
+ if (callee_test_params.base) linphone_call_params_destroy(callee_test_params.base);
if (marie_call && pauline_call ) {
CU_ASSERT_TRUE(linphone_call_log_video_enabled(linphone_call_get_call_log(marie_call)));
@@ -1808,7 +1907,7 @@ static void simple_conference_base(LinphoneCoreManager* marie, LinphoneCoreManag
CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallStreamsRunning,initial_marie_stat.number_of_LinphoneCallStreamsRunning+2,3000));
CU_ASSERT_TRUE(linphone_core_is_in_conference(marie->lc));
- CU_ASSERT_EQUAL(linphone_core_get_conference_size(marie->lc),3)
+ CU_ASSERT_EQUAL(linphone_core_get_conference_size(marie->lc),3);
/*
* FIXME: check_ice cannot work as it is today because there is no current call for the party that hosts the conference
@@ -1902,21 +2001,21 @@ static void call_with_file_player(void) {
char hellopath[256];
char *recordpath = create_filepath(liblinphone_tester_writable_dir_prefix, "record", "wav");
double similar;
-
+
/*make sure the record file doesn't already exists, otherwise this test will append new samples to it*/
unlink(recordpath);
-
+
snprintf(hellopath,sizeof(hellopath), "%s/sounds/hello8000.wav", liblinphone_tester_file_prefix);
-
+
/*caller uses files instead of soundcard in order to avoid mixing soundcard input with file played using call's player*/
linphone_core_use_files(pauline->lc,TRUE);
linphone_core_set_play_file(pauline->lc,NULL);
-
+
/*callee is recording and plays file*/
linphone_core_use_files(pauline->lc,TRUE);
linphone_core_set_play_file(pauline->lc,hellopath);
linphone_core_set_record_file(pauline->lc,recordpath);
-
+
CU_ASSERT_TRUE(call(marie,pauline));
player=linphone_call_get_player(linphone_core_get_current_call(marie->lc));
@@ -1926,7 +2025,7 @@ static void call_with_file_player(void) {
CU_ASSERT_TRUE(linphone_player_start(player)==0);
}
CU_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&marie->stat.number_of_player_eof,1,12000));
-
+
/*just to sleep*/
linphone_core_terminate_all_calls(marie->lc);
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallEnd,1));
@@ -1956,8 +2055,6 @@ static void call_with_mkv_file_player(void) {
char *recordpath;
double similar;
- ortp_set_log_level_mask(ORTP_ERROR | ORTP_FATAL | ORTP_MESSAGE | ORTP_WARNING);
-
if (!is_format_supported(marie->lc,"mkv")){
ms_warning("Test skipped, no mkv support.");
goto end;
@@ -1965,10 +2062,10 @@ static void call_with_mkv_file_player(void) {
recordpath = create_filepath(liblinphone_tester_writable_dir_prefix, "record", "wav");
/*make sure the record file doesn't already exists, otherwise this test will append new samples to it*/
unlink(recordpath);
-
+
snprintf(hellowav,sizeof(hellowav), "%s/sounds/hello8000.wav", liblinphone_tester_file_prefix);
snprintf(hellomkv,sizeof(hellomkv), "%s/sounds/hello8000.mkv", liblinphone_tester_file_prefix);
-
+
/*caller uses files instead of soundcard in order to avoid mixing soundcard input with file played using call's player*/
linphone_core_use_files(marie->lc,TRUE);
linphone_core_set_play_file(marie->lc,NULL);
@@ -1976,7 +2073,7 @@ static void call_with_mkv_file_player(void) {
linphone_core_use_files(pauline->lc,TRUE);
linphone_core_set_play_file(pauline->lc,hellowav); /*just to send something but we are not testing what is sent by pauline*/
linphone_core_set_record_file(pauline->lc,recordpath);
-
+
CU_ASSERT_TRUE(call(marie,pauline));
player=linphone_call_get_player(linphone_core_get_current_call(marie->lc));
@@ -1987,7 +2084,7 @@ static void call_with_mkv_file_player(void) {
CU_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&marie->stat.number_of_player_eof,1,12000));
linphone_player_close(player);
}
-
+
/*just to sleep*/
linphone_core_terminate_all_calls(marie->lc);
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallEnd,1));
@@ -1996,11 +2093,11 @@ static void call_with_mkv_file_player(void) {
CU_ASSERT_TRUE(similar>0.6);
CU_ASSERT_TRUE(similar<=1.0);
ms_free(recordpath);
-
+
end:
linphone_core_manager_destroy(marie);
linphone_core_manager_destroy(pauline);
-
+
}
@@ -2182,7 +2279,7 @@ static void early_media_call_with_ringing(void){
CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallEnd,1,1000));
CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallEnd,1,1000));
ended_time=time(NULL);
- CU_ASSERT_TRUE (abs (linphone_call_log_get_duration(marie_call_log) - (ended_time - connected_time)) <1 );
+ CU_ASSERT_TRUE (labs (linphone_call_log_get_duration(marie_call_log) - (ended_time - connected_time)) <1 );
ms_list_free(lcs);
}
@@ -3138,7 +3235,7 @@ static void call_with_custom_supported_tags(void) {
marie = linphone_core_manager_new( "marie_rc");
pauline = linphone_core_manager_new( "pauline_rc");
-
+
linphone_core_add_supported_tag(marie->lc,"pouet-tag");
CU_ASSERT_TRUE(call(pauline,marie));
liblinphone_tester_check_rtcp(marie,pauline);
@@ -3167,7 +3264,7 @@ static void call_log_from_taken_from_p_asserted_id(void) {
const char* paulie_asserted_id ="\"Paupauche\" ";
LinphoneAddress *paulie_asserted_id_addr = linphone_address_new(paulie_asserted_id);
LpConfig *marie_lp;
-
+
params=linphone_core_create_default_call_parameters(pauline->lc);
linphone_call_params_add_custom_header(params,"P-Asserted-Identity",paulie_asserted_id);
@@ -3198,6 +3295,124 @@ static void call_log_from_taken_from_p_asserted_id(void) {
linphone_core_manager_destroy(marie);
linphone_core_manager_destroy(pauline);
}
+
+static void incoming_invite_without_sdp() {
+ LinphoneCoreManager* caller = linphone_core_manager_new( "pauline_rc");
+ LinphoneCoreManager* callee = linphone_core_manager_new( "marie_rc");
+ LinphoneCallTestParams caller_test_params = {0}, callee_test_params = {0};
+
+ callee_test_params.sdp_removal = TRUE;
+ CU_ASSERT_FALSE(call_with_params2(caller,callee,&caller_test_params, &callee_test_params, FALSE));
+
+ CU_ASSERT_PTR_NULL(linphone_core_get_current_call(callee->lc));
+ CU_ASSERT_EQUAL(caller->stat.number_of_LinphoneCallError,1);
+ /*call will be drop before presented to the application, because it is invalid*/
+ CU_ASSERT_EQUAL(callee->stat.number_of_LinphoneCallIncomingReceived,0);
+
+ linphone_core_manager_destroy(callee);
+ linphone_core_manager_destroy(caller);
+}
+
+static void outgoing_invite_without_sdp() {
+ LinphoneCoreManager* caller = linphone_core_manager_new( "pauline_rc");
+ LinphoneCoreManager* callee = linphone_core_manager_new( "marie_rc");
+ LinphoneCallTestParams caller_test_params = {0}, callee_test_params = {0};
+
+ caller_test_params.sdp_removal = TRUE;
+ CU_ASSERT_FALSE(call_with_params2(caller,callee,&caller_test_params, &callee_test_params, FALSE));
+
+ CU_ASSERT_PTR_NULL(linphone_core_get_current_call(callee->lc));
+ CU_ASSERT_EQUAL(callee->stat.number_of_LinphoneCallIncomingReceived,1);
+ CU_ASSERT_EQUAL(caller->stat.number_of_LinphoneCallError,1);
+ // actually callee does not receive error, because it just get a BYE from the other part
+ CU_ASSERT_EQUAL(callee->stat.number_of_LinphoneCallError,0);
+ CU_ASSERT_EQUAL(callee->stat.number_of_LinphoneCallEnd,1);
+
+ linphone_core_manager_destroy(callee);
+ linphone_core_manager_destroy(caller);
+}
+
+static void incoming_reinvite_without_ack_sdp() {
+#ifdef VIDEO_ENABLED
+ LinphoneCoreManager* caller = linphone_core_manager_new( "pauline_rc");
+ LinphoneCoreManager* callee = linphone_core_manager_new( "marie_rc");
+ LinphoneCall * inc_call;
+ CU_ASSERT_TRUE(call(caller,callee));
+ inc_call = linphone_core_get_current_call(callee->lc);
+
+ CU_ASSERT_PTR_NOT_NULL(inc_call);
+ if (inc_call) {
+ const LinphoneCallParams *caller_params;
+ stats initial_caller_stat=caller->stat;
+ stats initial_callee_stat=callee->stat;
+ sal_call_enable_sdp_removal(inc_call->op, TRUE);
+ CU_ASSERT_PTR_NOT_NULL(setup_video(caller, callee));
+ CU_ASSERT_TRUE(wait_for(caller->lc,callee->lc,&callee->stat.number_of_LinphoneCallUpdating,initial_callee_stat.number_of_LinphoneCallUpdating+1));
+ CU_ASSERT_TRUE(wait_for(caller->lc,callee->lc,&callee->stat.number_of_LinphoneCallStreamsRunning,initial_callee_stat.number_of_LinphoneCallStreamsRunning+1));
+ CU_ASSERT_TRUE(wait_for(caller->lc,callee->lc,&caller->stat.number_of_LinphoneCallStreamsRunning,initial_caller_stat.number_of_LinphoneCallStreamsRunning));
+ /*Basically the negotiation failed but since the call was already running, we expect it to restore to
+ the previous state so error stats should not be changed*/
+ CU_ASSERT_EQUAL(callee->stat.number_of_LinphoneCallError,initial_callee_stat.number_of_LinphoneCallError);
+ /*and remote should have received an update notification*/
+ CU_ASSERT_EQUAL(caller->stat.number_of_LinphoneCallUpdatedByRemote,initial_caller_stat.number_of_LinphoneCallUpdatedByRemote+1);
+
+
+ CU_ASSERT_FALSE(linphone_call_params_video_enabled(linphone_call_get_current_params(linphone_core_get_current_call(callee->lc))));
+ caller_params = linphone_call_get_current_params(linphone_core_get_current_call(caller->lc));
+ CU_ASSERT_TRUE(wait_for(caller->lc,callee->lc,(int*)&caller_params->has_video,FALSE));
+
+ sal_call_enable_sdp_removal(inc_call->op, FALSE);
+ }
+ linphone_core_terminate_all_calls(caller->lc);
+ CU_ASSERT_TRUE(wait_for(caller->lc,callee->lc,&caller->stat.number_of_LinphoneCallEnd,1));
+ CU_ASSERT_TRUE(wait_for(caller->lc,callee->lc,&callee->stat.number_of_LinphoneCallEnd,1));
+
+ linphone_core_manager_destroy(callee);
+ linphone_core_manager_destroy(caller);
+#else
+ ms_warning("not tested because video not available");
+#endif
+}
+
+static void outgoing_reinvite_without_ack_sdp() {
+#ifdef VIDEO_ENABLED
+ LinphoneCoreManager* caller = linphone_core_manager_new( "pauline_rc");
+ LinphoneCoreManager* callee = linphone_core_manager_new( "marie_rc");
+ LinphoneCall * out_call;
+ CU_ASSERT_TRUE(call(caller,callee));
+ out_call = linphone_core_get_current_call(caller->lc);
+
+ CU_ASSERT_PTR_NOT_NULL(out_call);
+ if (out_call) {
+ stats initial_caller_stat=caller->stat;
+ stats initial_callee_stat=callee->stat;
+ sal_call_enable_sdp_removal(out_call->op, TRUE);
+ CU_ASSERT_PTR_NOT_NULL(setup_video(caller, callee));
+ CU_ASSERT_TRUE(wait_for(caller->lc,callee->lc,&callee->stat.number_of_LinphoneCallUpdating,initial_callee_stat.number_of_LinphoneCallUpdating+1));
+ CU_ASSERT_TRUE(wait_for(caller->lc,callee->lc,&callee->stat.number_of_LinphoneCallStreamsRunning,initial_callee_stat.number_of_LinphoneCallStreamsRunning+1));
+ CU_ASSERT_TRUE(wait_for(caller->lc,callee->lc,&caller->stat.number_of_LinphoneCallStreamsRunning,initial_caller_stat.number_of_LinphoneCallStreamsRunning));
+ /*Basically the negotiation failed but since the call was already running, we expect it to restore to
+ the previous state so error stats should not be changed*/
+ CU_ASSERT_EQUAL(callee->stat.number_of_LinphoneCallError,initial_callee_stat.number_of_LinphoneCallError);
+ /*and remote should not have received any update notification*/
+ CU_ASSERT_EQUAL(caller->stat.number_of_LinphoneCallUpdatedByRemote,initial_caller_stat.number_of_LinphoneCallUpdatedByRemote);
+
+ CU_ASSERT_FALSE(linphone_call_params_video_enabled(linphone_call_get_current_params(linphone_core_get_current_call(callee->lc))));
+ CU_ASSERT_FALSE(linphone_call_params_video_enabled(linphone_call_get_current_params(linphone_core_get_current_call(caller->lc))));
+
+ sal_call_enable_sdp_removal(out_call->op, FALSE);
+ }
+ linphone_core_terminate_all_calls(caller->lc);
+ CU_ASSERT_TRUE(wait_for(caller->lc,callee->lc,&caller->stat.number_of_LinphoneCallEnd,1));
+ CU_ASSERT_TRUE(wait_for(caller->lc,callee->lc,&callee->stat.number_of_LinphoneCallEnd,1));
+
+ linphone_core_manager_destroy(callee);
+ linphone_core_manager_destroy(caller);
+#else
+ ms_warning("not tested because video not available");
+#endif
+}
+
test_t call_tests[] = {
{ "Early declined call", early_declined_call },
{ "Call declined", call_declined },
@@ -3207,6 +3422,7 @@ test_t call_tests[] = {
{ "Cancelled ringing call", cancelled_ringing_call },
{ "Call failed because of codecs", call_failed_because_of_codecs },
{ "Simple call", simple_call },
+ { "Direct call over IPv6", direct_call_over_ipv6},
{ "Outbound call with multiple proxy possible", call_outbound_with_multiple_proxy },
{ "Audio call recording", audio_call_recording_test },
#if 0 /* not yet activated because not implemented */
@@ -3298,7 +3514,11 @@ test_t call_tests[] = {
{ "Call with in-dialog codec change", call_with_in_dialog_codec_change },
{ "Call with in-dialog codec change no sdp", call_with_in_dialog_codec_change_no_sdp },
{ "Call with custom supported tags", call_with_custom_supported_tags },
- { "Call log from taken from asserted id",call_log_from_taken_from_p_asserted_id}
+ { "Call log from taken from asserted id",call_log_from_taken_from_p_asserted_id},
+ { "Incoming INVITE without SDP",incoming_invite_without_sdp},
+ { "Outgoing INVITE without ACK SDP",outgoing_invite_without_sdp},
+ { "Incoming REINVITE without SDP",incoming_reinvite_without_ack_sdp},
+ { "Outgoing REINVITE without ACK SDP",outgoing_reinvite_without_ack_sdp},
};
test_suite_t call_test_suite = {
diff --git a/tester/dtmf_tester.c b/tester/dtmf_tester.c
new file mode 100644
index 000000000..fa627cfd4
--- /dev/null
+++ b/tester/dtmf_tester.c
@@ -0,0 +1,148 @@
+/*
+ liblinphone_tester - liblinphone test suite
+ Copyright (C) 2013 Belledonne Communications SARL
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include "liblinphone_tester.h"
+#include "private.h"
+
+LinphoneCoreManager* marie;
+LinphoneCoreManager* pauline;
+LinphoneCall *marie_call;
+
+void dtmf_received(LinphoneCore *lc, LinphoneCall *call, int dtmf) {
+ stats* counters = get_stats(lc);
+ char** dst = &counters->dtmf_list_received;
+ *dst = *dst ?
+ ms_strcat_printf(*dst, "%c", dtmf)
+ : ms_strdup_printf("%c", dtmf);
+}
+
+void send_dtmf_base(bool_t use_rfc2833, bool_t use_sipinfo, char dtmf, char* dtmf_seq) {
+ char* expected = NULL;
+ marie = linphone_core_manager_new( "marie_rc");
+ pauline = linphone_core_manager_new( "pauline_rc");
+
+ linphone_core_set_use_rfc2833_for_dtmf(marie->lc, use_rfc2833);
+ linphone_core_set_use_info_for_dtmf(marie->lc, use_sipinfo);
+ linphone_core_set_use_rfc2833_for_dtmf(pauline->lc, use_rfc2833);
+ linphone_core_set_use_info_for_dtmf(pauline->lc, use_sipinfo);
+
+ CU_ASSERT_TRUE(call(pauline,marie));
+
+ marie_call = linphone_core_get_current_call(marie->lc);
+
+ if (dtmf != '\0') {
+ linphone_call_send_dtmf(marie_call, dtmf);
+
+ /*wait for the DTMF to be received from pauline*/
+ wait_for_until(marie->lc, pauline->lc, NULL, 0, 1000);
+ expected = ms_strdup_printf("%c", dtmf);
+ }
+
+ if (dtmf_seq != NULL) {
+ int dtmf_delay_ms = lp_config_get_int(marie_call->core->config,"net","dtmf_delay_ms",200);
+ linphone_call_send_dtmfs(marie_call, dtmf_seq);
+
+ /*wait for the DTMF sequence to be received from pauline*/
+ wait_for_until(marie->lc, pauline->lc, NULL, 0, 1000 + dtmf_delay_ms * strlen(dtmf_seq));
+ expected = (dtmf!='\0')?ms_strdup_printf("%c%s",dtmf,dtmf_seq):ms_strdup(dtmf_seq);
+ }
+
+ if (expected != NULL) {
+ CU_ASSERT_PTR_NOT_NULL(pauline->stat.dtmf_list_received);
+ if (pauline->stat.dtmf_list_received) {
+ CU_ASSERT_STRING_EQUAL(pauline->stat.dtmf_list_received, expected);
+ }
+ ms_free(expected);
+ } else {
+ CU_ASSERT_PTR_NULL(pauline->stat.dtmf_list_received);
+ }
+}
+
+void send_dtmf_cleanup() {
+ CU_ASSERT_PTR_NULL(marie_call->dtmfs_timer);
+ CU_ASSERT_PTR_NULL(marie_call->dtmf_sequence);
+
+ /*just to sleep*/
+ linphone_core_terminate_all_calls(pauline->lc);
+ CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallEnd,1));
+ CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallEnd,1));
+
+ linphone_core_manager_destroy(marie);
+ linphone_core_manager_destroy(pauline);
+}
+
+static void send_dtmf_rfc2833() {
+ send_dtmf_base(TRUE,FALSE,'1',NULL);
+ send_dtmf_cleanup();
+}
+
+static void send_dtmf_sip_info() {
+ send_dtmf_base(FALSE,TRUE,'#',NULL);
+ send_dtmf_cleanup();
+}
+
+static void send_dtmfs_sequence_rfc2833() {
+ send_dtmf_base(TRUE,FALSE,'\0',"1230#");
+ send_dtmf_cleanup();
+}
+
+static void send_dtmfs_sequence_sip_info() {
+ send_dtmf_base(FALSE,TRUE,'\0',"1230#");
+ send_dtmf_cleanup();
+}
+
+static void send_dtmfs_sequence_not_ready() {
+ marie = linphone_core_manager_new( "marie_rc");
+ CU_ASSERT_EQUAL(linphone_call_send_dtmfs(linphone_core_get_current_call(marie->lc), "123"), -1);
+ linphone_core_manager_destroy(marie);
+}
+
+static void send_dtmfs_sequence_call_state_changed() {
+ send_dtmf_base(FALSE,TRUE,'\0',NULL);
+
+ /*very long DTMF(around 4 sec to be sent)*/
+ linphone_call_send_dtmfs(marie_call, "123456789123456789");
+ /*just after, change call state, and expect DTMF to be canceled*/
+ linphone_core_pause_call(marie_call->core,marie_call);
+ CU_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallPausing,1));
+ CU_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallPaused,1));
+
+ /*wait a few time to ensure that no DTMF are received*/
+ wait_for_until(marie->lc, pauline->lc, NULL, 0, 1000);
+
+ CU_ASSERT_PTR_NULL(pauline->stat.dtmf_list_received);
+
+ send_dtmf_cleanup();
+}
+
+test_t dtmf_tests[] = {
+ { "Send DTMF using RFC2833",send_dtmf_rfc2833},
+ { "Send DTMF using SIP INFO",send_dtmf_sip_info},
+ { "Send DTMF sequence using RFC2833",send_dtmfs_sequence_rfc2833},
+ { "Send DTMF sequence using SIP INFO",send_dtmfs_sequence_sip_info},
+ { "DTMF sequence not sent if invalid call",send_dtmfs_sequence_not_ready},
+ { "DTMF sequence canceled if call state changed",send_dtmfs_sequence_call_state_changed},
+};
+
+test_suite_t dtmf_test_suite = {
+ "DTMF",
+ NULL,
+ NULL,
+ sizeof(dtmf_tests) / sizeof(dtmf_tests[0]),
+ dtmf_tests
+};
diff --git a/tester/liblinphone_tester.c b/tester/liblinphone_tester.c
index 5fb91605c..171f4eae9 100644
--- a/tester/liblinphone_tester.c
+++ b/tester/liblinphone_tester.c
@@ -80,6 +80,7 @@ void cunit_android_trace_handler(int level, const char *fmt, va_list args) {
jmethodID method = (*env)->GetMethodID(env, cls, "printLog", "(ILjava/lang/String;)V");
(*env)->CallVoidMethod(env, current_obj, method, javaLevel, javaString);
(*env)->DeleteLocalRef(env,javaString);
+ (*env)->DeleteLocalRef(env,cls);
}
JNIEXPORT jint JNICALL Java_org_linphone_tester_Tester_run(JNIEnv *env, jobject obj, jobjectArray stringArray) {
@@ -114,8 +115,6 @@ static void liblinphone_tester_qnx_log_handler(OrtpLogLevel lev, const char *fmt
}
#endif /* __QNX__ */
-
-
void helper(const char *name) {
liblinphone_tester_fprintf(stderr,"%s --help\n"
"\t\t\t--verbose\n"
diff --git a/tester/liblinphone_tester.h b/tester/liblinphone_tester.h
index 18990f313..4bbe1fa3a 100644
--- a/tester/liblinphone_tester.h
+++ b/tester/liblinphone_tester.h
@@ -58,8 +58,10 @@ extern test_suite_t flexisip_test_suite;
extern test_suite_t stun_test_suite;
extern test_suite_t remote_provisioning_test_suite;
extern test_suite_t quality_reporting_test_suite;
+extern test_suite_t log_collection_test_suite;
extern test_suite_t transport_test_suite;
extern test_suite_t player_test_suite;
+extern test_suite_t dtmf_test_suite;
extern int liblinphone_tester_nb_test_suites(void);
@@ -75,6 +77,7 @@ extern void liblinphone_tester_uninit(void);
extern int liblinphone_tester_run_tests(const char *suite_name, const char *test_name);
extern void liblinphone_tester_set_fileprefix(const char* file_prefix);
extern void liblinphone_tester_set_writable_dir_prefix(const char* writable_dir_prefix);
+extern int liblinphone_tester_ipv6_available(void);
#ifdef __cplusplus
};
@@ -200,6 +203,8 @@ typedef struct _stats {
int number_of_NetworkReachableFalse;
int number_of_player_eof;
LinphoneChatMessage* last_received_chat_message;
+
+ char * dtmf_list_received;
}stats;
typedef struct _LinphoneCoreManager {
@@ -211,6 +216,11 @@ typedef struct _LinphoneCoreManager {
bool_t decline_subscribe;
} LinphoneCoreManager;
+typedef struct _LinphoneCallTestParams {
+ LinphoneCallParams *base;
+ bool_t sdp_removal;
+} LinphoneCallTestParams;
+
LinphoneCoreManager* linphone_core_manager_new2(const char* rc_file, int check_for_proxies);
LinphoneCoreManager* linphone_core_manager_new(const char* rc_file);
void linphone_core_manager_stop(LinphoneCoreManager *mgr);
@@ -235,6 +245,7 @@ void linphone_publish_state_changed(LinphoneCore *lc, LinphoneEvent *ev, Linphon
void linphone_notify_received(LinphoneCore *lc, LinphoneEvent *lev, const char *eventname, const LinphoneContent *content);
void linphone_configuration_status(LinphoneCore *lc, LinphoneConfiguringState status, const char *message);
void linphone_call_encryption_changed(LinphoneCore *lc, LinphoneCall *call, bool_t on, const char *authentication_token);
+void dtmf_received(LinphoneCore *lc, LinphoneCall *call, int dtmf);
LinphoneAddress * create_linphone_address(const char * domain);
bool_t wait_for(LinphoneCore* lc_1, LinphoneCore* lc_2,int* counter,int value);
@@ -245,6 +256,11 @@ bool_t call_with_params(LinphoneCoreManager* caller_mgr
,LinphoneCoreManager* callee_mgr
, const LinphoneCallParams *caller_params
, const LinphoneCallParams *callee_params);
+bool_t call_with_test_params(LinphoneCoreManager* caller_mgr
+ ,LinphoneCoreManager* callee_mgr
+ ,const LinphoneCallTestParams *caller_test_params
+ ,const LinphoneCallTestParams *callee_test_params);
+
bool_t call(LinphoneCoreManager* caller_mgr,LinphoneCoreManager* callee_mgr);
void end_call(LinphoneCoreManager *m1, LinphoneCoreManager *m2);
stats * get_stats(LinphoneCore *lc);
diff --git a/tester/log_collection_tester.c b/tester/log_collection_tester.c
new file mode 100644
index 000000000..b9c1835c5
--- /dev/null
+++ b/tester/log_collection_tester.c
@@ -0,0 +1,212 @@
+/*
+ belle-sip - SIP (RFC3261) library.
+ Copyright (C) 2010 Belledonne Communications SARL
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include
+#ifndef __USE_XOPEN
+ /*on Debian OS, time.h does declare strptime only if __USE_XOPEN is declared */
+ #define __USE_XOPEN
+#endif
+#include
+#include "CUnit/Basic.h"
+#include "linphonecore.h"
+#include "private.h"
+#include "liblinphone_tester.h"
+
+
+/*getline is not available on android...*/
+#ifdef ANDROID
+/* This code is public domain -- Will Hartung 4/9/09 */
+size_t getline(char **lineptr, size_t *n, FILE *stream) {
+ char *bufptr = NULL;
+ char *p = bufptr;
+ size_t size;
+ int c;
+
+ if (lineptr == NULL) {
+ return -1;
+ }
+ if (stream == NULL) {
+ return -1;
+ }
+ if (n == NULL) {
+ return -1;
+ }
+ bufptr = *lineptr;
+ size = *n;
+
+ c = fgetc(stream);
+ if (c == EOF) {
+ return -1;
+ }
+ if (bufptr == NULL) {
+ bufptr = malloc(128);
+ if (bufptr == NULL) {
+ return -1;
+ }
+ size = 128;
+ }
+ p = bufptr;
+ while(c != EOF) {
+ if ((p - bufptr) > (size - 1)) {
+ size = size + 128;
+ bufptr = realloc(bufptr, size);
+ if (bufptr == NULL) {
+ return -1;
+ }
+ }
+ *p++ = c;
+ if (c == '\n') {
+ break;
+ }
+ c = fgetc(stream);
+ }
+
+ *p++ = '\0';
+ *lineptr = bufptr;
+ *n = size;
+
+ return p - bufptr - 1;
+}
+#endif
+
+LinphoneCoreManager* setup(bool_t enable_logs) {
+ LinphoneCoreManager *marie;
+ int timeout = 300;
+
+ linphone_core_enable_log_collection(enable_logs);
+
+ marie = linphone_core_manager_new( "marie_rc");
+ // wait a few seconds to generate some traffic
+ while (--timeout){
+ // Generate some logs - error logs because we must ensure that
+ // even if user did not enable logs, we will see them
+ ms_error("(test error)Timeout in %d...", timeout);
+ }
+ return marie;
+}
+
+time_t check_file(char * filepath) {
+ time_t time_curr = -1;
+ if (filepath != NULL) {
+ int line_count = 0;
+ FILE *file = fopen(filepath, "r");
+ char *line = NULL;
+ size_t line_size = 256;
+ struct tm tm_curr;
+ time_t time_prev = -1;
+
+ // 1) expect to find folder name in filename path
+ CU_ASSERT_PTR_NOT_NULL(strstr(filepath, liblinphone_tester_writable_dir_prefix));
+
+ // 2) check file contents
+ while (getline(&line, &line_size, file) != -1) {
+ // a) there should be at least 25 lines
+ ++line_count;
+
+ // b) logs should be ordered by date (format: 2014-11-04 15:22:12:606)
+ if (strlen(line) > 24) {
+ char date[24] = {'\0'};
+ memcpy(date, line, 23);
+ if (strptime(date, "%Y-%m-%d %H:%M:%S", &tm_curr) != NULL) {
+ time_curr = mktime(&tm_curr);
+ CU_ASSERT_TRUE(time_curr >= time_prev);
+ time_prev = time_curr;
+ }
+ }
+ }
+ CU_ASSERT_TRUE(line_count > 25);
+ free(line);
+ fclose(file);
+ ms_free(filepath);
+ }
+ // return latest time in file
+ return time_curr;
+}
+
+static LinphoneLogCollectionState old_collection_state;
+static int collect_init() {
+ old_collection_state = linphone_core_log_collection_enabled();
+ linphone_core_set_log_collection_path(liblinphone_tester_writable_dir_prefix);
+ return 0;
+}
+
+static int collect_cleanup() {
+ linphone_core_enable_log_collection(old_collection_state);
+ linphone_core_reset_log_collection();
+ return 0;
+}
+
+static void collect_files_disabled() {
+ LinphoneCoreManager* marie = setup(FALSE);
+ CU_ASSERT_PTR_NULL(linphone_core_compress_log_collection(marie->lc));
+ linphone_core_manager_destroy(marie);
+}
+
+static void collect_files_filled() {
+ LinphoneCoreManager* marie = setup(TRUE);
+ char * filepath = linphone_core_compress_log_collection(marie->lc);
+ CU_ASSERT_PTR_NOT_NULL(filepath);
+ CU_ASSERT_EQUAL(ms_time(0), check_file(filepath));
+ linphone_core_manager_destroy(marie);
+}
+
+static void collect_files_small_size() {
+ LinphoneCoreManager* marie = setup(TRUE);
+ char * filepath;
+ linphone_core_set_log_collection_max_file_size(5000);
+ filepath = linphone_core_compress_log_collection(marie->lc);
+ CU_ASSERT_PTR_NOT_NULL(filepath);
+ CU_ASSERT_EQUAL(ms_time(0), check_file(filepath));
+ linphone_core_manager_destroy(marie);
+}
+
+static void collect_files_changing_size() {
+ LinphoneCoreManager* marie = setup(TRUE);
+ char * filepath;
+ int waiting = 100;
+
+ filepath = linphone_core_compress_log_collection(marie->lc);
+ CU_ASSERT_PTR_NOT_NULL(filepath);
+ CU_ASSERT_EQUAL(ms_time(0), check_file(filepath));
+
+ linphone_core_set_log_collection_max_file_size(5000);
+ // Generate some logs
+ while (--waiting) ms_error("(test error)Waiting %d...", waiting);
+
+ filepath = linphone_core_compress_log_collection(marie->lc);
+ CU_ASSERT_PTR_NOT_NULL(filepath);
+ CU_ASSERT_EQUAL(ms_time(0), check_file(filepath));
+
+ linphone_core_manager_destroy(marie);
+}
+
+test_t log_collection_tests[] = {
+ { "No file when disabled", collect_files_disabled},
+ { "Collect files filled when enabled", collect_files_filled},
+ { "Logs collected into small file", collect_files_small_size},
+ { "Logs collected when decreasing max size", collect_files_changing_size},
+};
+
+test_suite_t log_collection_test_suite = {
+ "LogCollection",
+ collect_init,
+ collect_cleanup,
+ sizeof(log_collection_tests) / sizeof(log_collection_tests[0]),
+ log_collection_tests
+};
+
diff --git a/tester/message_tester.c b/tester/message_tester.c
index 62a365233..60834ea4c 100644
--- a/tester/message_tester.c
+++ b/tester/message_tester.c
@@ -734,7 +734,7 @@ static void file_transfer_message_upload_cancelled(void) {
/*wait for file to be 50% uploaded and cancel the transfer */
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.progress_of_LinphoneFileTransfer, 50));
- linphone_chat_room_cancel_file_transfer(message);
+ linphone_chat_message_cancel_file_transfer(message);
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneMessageNotDelivered,1));
@@ -800,7 +800,7 @@ static void file_transfer_message_download_cancelled(void) {
/* wait for file to be 50% downloaded */
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.progress_of_LinphoneFileTransfer, 50));
/* and cancel the transfer */
- linphone_chat_room_cancel_file_transfer(marie->stat.last_received_chat_message);
+ linphone_chat_message_cancel_file_transfer(marie->stat.last_received_chat_message);
}
CU_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageInProgress,1);
@@ -1253,7 +1253,9 @@ message_tester_copy_file(const char *from, const char *to)
}
static int check_no_strange_time(void* data,int argc, char** argv,char** cNames) {
- CU_ASSERT_EQUAL(argc, 0);
+ CU_ASSERT_EQUAL(argc, 1);
+ CU_ASSERT_STRING_EQUAL(cNames[0], "COUNT(*)"); // count of non updated messages should be 0
+ CU_ASSERT_STRING_EQUAL(argv[0], "0"); // count of non updated messages should be 0
return 0;
}
@@ -1278,7 +1280,7 @@ static void message_storage_migration() {
CU_ASSERT(ms_list_size(chatrooms) > 0);
// check that all messages have been migrated to the UTC time storage
- CU_ASSERT(sqlite3_exec(marie->lc->db, "SELECT * FROM history WHERE time != '-1';", check_no_strange_time, NULL, NULL) == SQLITE_OK );
+ CU_ASSERT(sqlite3_exec(marie->lc->db, "SELECT COUNT(*) FROM history WHERE time != '-1';", check_no_strange_time, NULL, NULL) == SQLITE_OK );
linphone_core_manager_destroy(marie);
remove(tmp_db);
@@ -1301,25 +1303,37 @@ static void history_messages_count() {
chatroom = linphone_core_get_chat_room(marie->lc, jehan_addr);
CU_ASSERT_PTR_NOT_NULL(chatroom);
if (chatroom){
- MSList *history=linphone_chat_room_get_history(chatroom,0);
+ messages=linphone_chat_room_get_history(chatroom,10);
+ CU_ASSERT_EQUAL(ms_list_size(messages), 10);
+ ms_list_free_with_data(messages, (void (*)(void*))linphone_chat_message_unref);
+
+ messages=linphone_chat_room_get_history(chatroom,0);
CU_ASSERT_EQUAL(linphone_chat_room_get_history_size(chatroom), 1270);
- CU_ASSERT_EQUAL(ms_list_size(history), linphone_chat_room_get_history_size(chatroom));
+ CU_ASSERT_EQUAL(ms_list_size(messages), 1270);
/*check the second most recent message*/
- CU_ASSERT_STRING_EQUAL(linphone_chat_message_get_text((LinphoneChatMessage *)history->next->data), "Fore and aft follow each other.");
+ CU_ASSERT_STRING_EQUAL(linphone_chat_message_get_text((LinphoneChatMessage *)messages->next->data), "Fore and aft follow each other.");
+ ms_list_free_with_data(messages, (void (*)(void*))linphone_chat_message_unref);
/*test offset+limit: retrieve the 42th latest message only and check its content*/
messages=linphone_chat_room_get_history_range(chatroom, 42, 42);
CU_ASSERT_EQUAL(ms_list_size(messages), 1);
CU_ASSERT_STRING_EQUAL(linphone_chat_message_get_text((LinphoneChatMessage *)messages->data), "If you open yourself to the Tao is intangible and evasive, yet prefers to keep us at the mercy of the kingdom, then all of the streams of hundreds of valleys because of its limitless possibilities.");
+ ms_list_free_with_data(messages, (void (*)(void*))linphone_chat_message_unref);
/*test offset without limit*/
- CU_ASSERT_EQUAL(ms_list_size(linphone_chat_room_get_history_range(chatroom, 1265, -1)), 1270-1265);
+ messages = linphone_chat_room_get_history_range(chatroom, 1265, -1);
+ CU_ASSERT_EQUAL(ms_list_size(messages), 1270-1265);
+ ms_list_free_with_data(messages, (void (*)(void*))linphone_chat_message_unref);
/*test limit without offset*/
- CU_ASSERT_EQUAL(ms_list_size(linphone_chat_room_get_history_range(chatroom, 0, 5)), 6);
+ messages = linphone_chat_room_get_history_range(chatroom, 0, 5);
+ CU_ASSERT_EQUAL(ms_list_size(messages), 6);
+ ms_list_free_with_data(messages, (void (*)(void*))linphone_chat_message_unref);
/*test invalid start*/
- CU_ASSERT_EQUAL(ms_list_size(linphone_chat_room_get_history_range(chatroom, 1265, 1260)), 1270-1265);
+ messages = linphone_chat_room_get_history_range(chatroom, 1265, 1260);
+ CU_ASSERT_EQUAL(ms_list_size(messages), 1270-1265);
+ ms_list_free_with_data(messages, (void (*)(void*))linphone_chat_message_unref);
}
linphone_core_manager_destroy(marie);
linphone_address_destroy(jehan_addr);
diff --git a/tester/player_tester.c b/tester/player_tester.c
index 17e692d23..be0b47284 100644
--- a/tester/player_tester.c
+++ b/tester/player_tester.c
@@ -18,23 +18,23 @@
#include "liblinphone_tester.h"
-static const char *_get_default_video_renderer(void){
-#ifdef WIN32
- return "MSDrawDibDisplay";
-#elif defined(ANDROID)
- return "MSAndroidDisplay";
-#elif __APPLE__ && !defined(__ios)
- return "MSOSXGLDisplay";
-#elif defined (HAVE_XV)
- return "MSX11Video";
-#elif defined(HAVE_GL)
- return "MSGLXVideo";
-#elif defined(__ios)
- return "IOSDisplay";
-#else
- return "MSVideoOut";
-#endif
-}
+//static const char *_get_default_video_renderer(void){
+//#ifdef WIN32
+// return "MSDrawDibDisplay";
+//#elif defined(ANDROID)
+// return "MSAndroidDisplay";
+//#elif __APPLE__ && !defined(__ios)
+// return "MSOSXGLDisplay";
+//#elif defined (HAVE_XV)
+// return "MSX11Video";
+//#elif defined(HAVE_GL)
+// return "MSGLXVideo";
+//#elif defined(__ios)
+// return "IOSDisplay";
+//#else
+// return "MSVideoOut";
+//#endif
+//}
static bool_t wait_for_eof(bool_t *eof, int *time,int time_refresh, int timeout) {
while(*time < timeout && !*eof) {
@@ -59,7 +59,7 @@ static void play_file(const char *filename, bool_t unsupported_format) {
CU_ASSERT_PTR_NOT_NULL(lc_manager);
if(lc_manager == NULL) return;
- player = linphone_core_create_local_player(lc_manager->lc, ms_snd_card_manager_get_default_card(ms_snd_card_manager_get()), _get_default_video_renderer(), NULL);
+ player = linphone_core_create_local_player(lc_manager->lc, ms_snd_card_manager_get_default_card(ms_snd_card_manager_get()), "MSX11Video", 0);
CU_ASSERT_PTR_NOT_NULL(player);
if(player == NULL) goto fail;
@@ -84,7 +84,7 @@ static void play_file(const char *filename, bool_t unsupported_format) {
}
static void playing_test(void) {
- play_file("sounds/hello_opus_h264.mkv", !linphone_local_player_matroska_supported());
+ play_file("/home/francois/Téléchargements/test_linphone.mkv", !linphone_local_player_matroska_supported());
}
test_t player_tests[] = {
diff --git a/tester/quality_reporting_tester.c b/tester/quality_reporting_tester.c
index d0ad63968..1190f188f 100644
--- a/tester/quality_reporting_tester.c
+++ b/tester/quality_reporting_tester.c
@@ -17,7 +17,6 @@
*/
#include
-#include "CUnit/Basic.h"
#include "linphonecore.h"
#include "private.h"
#include "liblinphone_tester.h"
@@ -275,14 +274,14 @@ static void quality_reporting_interval_report() {
if (create_call_for_quality_reporting_tests(marie, pauline, &call_marie, &call_pauline, NULL, NULL)) {
linphone_reporting_set_on_report_send(call_marie, on_report_send_mandatory);
- linphone_proxy_config_set_quality_reporting_interval(call_marie->dest_proxy, 3);
+ linphone_proxy_config_set_quality_reporting_interval(call_marie->dest_proxy, 10);
CU_ASSERT_PTR_NOT_NULL(linphone_core_get_current_call(marie->lc));
CU_ASSERT_PTR_NOT_NULL(linphone_core_get_current_call(pauline->lc));
// PUBLISH submission to the collector should be ok
- CU_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishProgress,3,25000));
- CU_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishOk,3,25000));
+ CU_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishProgress,3,60000));
+ CU_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishOk,3,60000));
}
linphone_core_manager_destroy(marie);
linphone_core_manager_destroy(pauline);
diff --git a/tester/rcfiles/marie_rc b/tester/rcfiles/marie_rc
index a1721c22a..367353d06 100644
--- a/tester/rcfiles/marie_rc
+++ b/tester/rcfiles/marie_rc
@@ -17,7 +17,7 @@ realm=sip.example.org
[proxy_0]
reg_proxy=sip.example.org;transport=tcp
reg_route=sip.example.org;transport=tcp;lr
-reg_identity=sip:marie@sip.example.org
+reg_identity="Super Marie"
reg_expires=3600
reg_sendregister=1
publish=0
diff --git a/tester/tester.c b/tester/tester.c
index 97b45713d..aa0bd3e8b 100644
--- a/tester/tester.c
+++ b/tester/tester.c
@@ -225,6 +225,7 @@ LinphoneCoreManager* linphone_core_manager_new2(const char* rc_file, int check_f
mgr->v_table.configuring_status=linphone_configuration_status;
mgr->v_table.call_encryption_changed=linphone_call_encryption_changed;
mgr->v_table.network_reachable=network_reachable;
+ mgr->v_table.dtmf_received=dtmf_received;
reset_counters(&mgr->stat);
if (rc_file) rc_path = ms_strdup_printf("rcfiles/%s", rc_file);
@@ -387,8 +388,10 @@ void liblinphone_tester_init(void) {
add_test_suite(&flexisip_test_suite);
add_test_suite(&remote_provisioning_test_suite);
add_test_suite(&quality_reporting_test_suite);
+ add_test_suite(&log_collection_test_suite);
add_test_suite(&transport_test_suite);
add_test_suite(&player_test_suite);
+ add_test_suite(&dtmf_test_suite);
}
void liblinphone_tester_uninit(void) {
@@ -466,6 +469,7 @@ int liblinphone_tester_run_tests(const char *suite_name, const char *test_name)
CU_cleanup_registry();
return ret;
}
+
int liblinphone_tester_fprintf(FILE * stream, const char * format, ...) {
int result;
va_list args;
@@ -480,3 +484,22 @@ int liblinphone_tester_fprintf(FILE * stream, const char * format, ...) {
va_end(args);
return result;
}
+
+int liblinphone_tester_ipv6_available(void){
+ struct addrinfo *ai=belle_sip_ip_address_to_addrinfo(AF_INET6,"2a01:e00::2",53);
+ if (ai){
+ struct sockaddr_storage ss;
+ struct addrinfo src;
+ socklen_t slen=sizeof(ss);
+ char localip[128];
+ int port=0;
+ belle_sip_get_src_addr_for(ai->ai_addr,ai->ai_addrlen,(struct sockaddr*) &ss,&slen,4444);
+ src.ai_addr=(struct sockaddr*) &ss;
+ src.ai_addrlen=slen;
+ belle_sip_addrinfo_to_ip(&src,localip, sizeof(localip),&port);
+ freeaddrinfo(ai);
+ return strcmp(localip,"::1")!=0;
+ }
+ return FALSE;
+}
+
diff --git a/tester/transport_tester.c b/tester/transport_tester.c
index 8f0673d60..fdc4a194f 100644
--- a/tester/transport_tester.c
+++ b/tester/transport_tester.c
@@ -61,7 +61,6 @@ static char* get_public_contact_ip(LinphoneCore* lc) {
}
static void call_with_transport_base(LinphoneTunnelMode tunnel_mode, bool_t with_sip, LinphoneMediaEncryption encryption) {
if (linphone_core_tunnel_available()){
- char *tmp_char;
LinphoneCoreManager *pauline = linphone_core_manager_new( "pauline_rc");
LinphoneCoreManager *marie = linphone_core_manager_new( "marie_rc");
LinphoneCall *pauline_call;
@@ -81,28 +80,23 @@ static void call_with_transport_base(LinphoneTunnelMode tunnel_mode, bool_t with
LinphoneTunnel *tunnel = linphone_core_get_tunnel(pauline->lc);
LinphoneTunnelConfig *config = linphone_tunnel_config_new();
- /*tunnel works only in UDP mode*/
- linphone_proxy_config_edit(proxy);
- linphone_address_set_transport(server_addr, LinphoneTransportUdp);
- linphone_address_set_transport(route, LinphoneTransportUdp);
- tmp_char = linphone_address_as_string(server_addr);
- linphone_proxy_config_set_server_addr(proxy, tmp_char);
- ms_free(tmp_char);
- tmp_char = linphone_address_as_string(route);
- linphone_proxy_config_set_route(proxy, tmp_char);
- ms_free(tmp_char);
linphone_tunnel_config_set_host(config, "tunnel.linphone.org");
linphone_tunnel_config_set_port(config, 443);
linphone_tunnel_config_set_remote_udp_mirror_port(config, 12345);
linphone_tunnel_add_server(tunnel, config);
linphone_tunnel_set_mode(tunnel, tunnel_mode);
linphone_tunnel_enable_sip(tunnel, with_sip);
- linphone_proxy_config_done(proxy);
- /*enabling the tunnel cause another REGISTER to be made*/
- CU_ASSERT_TRUE(wait_for(pauline->lc,NULL,&pauline->stat.number_of_LinphoneRegistrationOk,2));
+ /*
+ * Enabling the tunnel with sip cause another REGISTER to be made.
+ * In automatic mode, the udp test should conclude (assuming we have a normal network), that no
+ * tunnel is needed. Thus the number of registrations should stay to 1.
+ * The library is missing a notification of "tunnel connectivity test finished" to enable the
+ * full testing of the automatic mode.
+ */
- if(tunnel_mode == LinphoneTunnelModeEnable) {
+ if(tunnel_mode == LinphoneTunnelModeEnable && with_sip) {
+ CU_ASSERT_TRUE(wait_for(pauline->lc,NULL,&pauline->stat.number_of_LinphoneRegistrationOk,2));
/* Ensure that we did use the tunnel. If so, we should see contact changed from:
Contact: ;.[...]
To:
diff --git a/tools/python/apixml2python.py b/tools/python/apixml2python.py
index 357816a5a..1fb37b9bb 100755
--- a/tools/python/apixml2python.py
+++ b/tools/python/apixml2python.py
@@ -58,7 +58,9 @@ blacklisted_functions = [
'linphone_core_publish', # missing LinphoneContent
'linphone_core_remove_listener',
'linphone_core_serialize_logs', # There is no use to wrap this function
+ 'linphone_core_set_log_collection_max_file_size', # need to handle class properties
'linphone_core_set_log_collection_path', # need to handle class properties
+ 'linphone_core_set_log_collection_prefix', # need to handle class properties
'linphone_core_set_log_file', # There is no use to wrap this function
'linphone_core_set_log_handler', # Hand-written but put directly in the linphone module
'linphone_core_set_log_level', # There is no use to wrap this function