diff --git a/CMakeLists.txt b/CMakeLists.txt
index ae3952338..c9a1db469 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,18 +1,102 @@
-cmake_minimum_required(VERSION 2.6)
-project(LINPHONE C)
+############################################################################
+# CMakeLists.txt
+# Copyright (C) 2014 Belledonne Communications, Grenoble France
+#
+############################################################################
+#
+# 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, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+############################################################################
+
+cmake_minimum_required(VERSION 2.8.12)
+project(LINPHONE C CXX)
+
+
+set(LINPHONE_MAJOR_VERSION "3")
+set(LINPHONE_MINOR_VERSION "7")
+set(LINPHONE_MICRO_VERSION "0")
+set(LINPHONE_VERSION "${LINPHONE_MAJOR_VERSION}.${LINPHONE_MINOR_VERSION}.${LINPHONE_MICRO_VERSION}")
+set(LINPHONE_SO_VERSION "6")
+
+
+include(CMakeDependentOption)
+
+option(ENABLE_STATIC "Build static library (default is shared library)." NO)
+option(ENABLE_CONSOLE_UI "Turn on or off compilation of console interface." YES)
+option(ENABLE_DATE "Use build date in internal version number." NO)
+option(ENABLE_GTK_UI "Turn on or off compilation of gtk interface." YES)
+option(ENABLE_LDAP "Enable LDAP support." NO)
+option(ENABLE_MSG_STORAGE "Turn on compilation of message storage." YES)
+option(ENABLE_NOTIFY "Enable libnotify support." YES)
+option(ENABLE_RELATIVE_PREFIX "Find resources relatively to the installation directory." NO)
+option(ENABLE_TOOLS "Turn on or off compilation of console interface" YES)
+option(ENABLE_TUNNEL "Turn on compilation of tunnel support." NO)
+option(ENABLE_TUTORIALS "Enable compilation of tutorials." YES)
+option(ENABLE_UNIT_TESTS "Enable compilation of unit tests." YES)
+option(ENABLE_UPNP "Build with uPnP support." YES)
+option(ENABLE_VIDEO "Build with video support." YES)
+cmake_dependent_option(ENABLE_ASSISTANT "Turn on assistant compiling." YES "ENABLE_GTK_UI" NO)
+
+
+list(APPEND CMAKE_MODULE_PATH ${CMAKE_PREFIX_PATH}/share/cmake/Modules)
+
+include(CheckIncludeFile)
+
+if(MSVC)
+ list(APPEND CMAKE_REQUIRED_INCLUDES ${CMAKE_PREFIX_PATH}/include/MSVC)
+endif()
+
+find_package(BelleSIP REQUIRED)
+find_package(MS2 REQUIRED)
+find_package(XML2 REQUIRED)
-option(LINPHONE_ENABLE_VIDEO "Build linphone with video support." ON)
include_directories(
include/
coreapi/
+ ${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_BINARY_DIR}/coreapi/
+ ${BELLESIP_INCLUDE_DIRS}
+ ${MS2_INCLUDE_DIRS}
+ ${XML2_INCLUDE_DIRS}
)
-include_directories(
- ${CMAKE_INSTALL_PREFIX}/include
- ${CMAKE_INSTALL_PREFIX}/include/libxml2
-)
+if(MSVC)
+ include_directories(${CMAKE_PREFIX_PATH}/include/MSVC)
+endif()
+
+
+if(ENABLE_RELATIVE_PREFIX)
+ set(LINPHONE_DATA_DIR ".")
+else()
+ set(LINPHONE_DATA_DIR "${CMAKE_INSTALL_PREFIX}")
+endif()
+set(LINPHONE_PLUGINS_DIR "${LINPHONE_DATA_DIR}/lib/liblinphone/plugins")
+set(PACKAGE_LOCALE_DIR "${LINPHONE_DATA_DIR}/share/locale")
+set(PACKAGE_DATA_DIR "${LINPHONE_DATA_DIR}/share")
+set(PACKAGE_SOUND_DIR "${LINPHONE_DATA_DIR}/share/sounds/linphone")
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)
+set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/config.h PROPERTIES GENERATED ON)
+add_definitions(-DHAVE_CONFIG_H)
+
add_subdirectory(coreapi)
add_subdirectory(share)
+
+
+install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/FindLinphone.cmake
+ DESTINATION share/cmake/Modules
+ PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
+)
diff --git a/FindLinphone.cmake b/FindLinphone.cmake
new file mode 100644
index 000000000..6c6871330
--- /dev/null
+++ b/FindLinphone.cmake
@@ -0,0 +1,74 @@
+############################################################################
+# FindLinphone.txt
+# Copyright (C) 2014 Belledonne Communications, Grenoble France
+#
+############################################################################
+#
+# 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, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+############################################################################
+#
+# - Find the linphone include file and library
+#
+# LINPHONE_FOUND - system has linphone
+# LINPHONE_INCLUDE_DIRS - the linphone include directory
+# LINPHONE_LIBRARIES - The libraries needed to use linphone
+# LINPHONE_CPPFLAGS - The compilation flags needed to use linphone
+# LINPHONE_LDFLAGS - The linking flags needed to use linphone
+
+find_package(ORTP REQUIRED)
+find_package(MS2 REQUIRED)
+find_package(XML2 REQUIRED)
+find_package(BelleSIP REQUIRED)
+
+set(_LINPHONEROOT_PATHS
+ ${WITH_LINPHONE}
+ ${CMAKE_INSTALL_PREFIX}
+)
+
+find_path(LINPHONE_INCLUDE_DIRS
+ NAMES linphone/linphonecore.h
+ HINTS _LINPHONE_ROOT_PATHS
+ PATH_SUFFIXES include
+)
+
+if(LINPHONE_INCLUDE_DIRS)
+ set(HAVE_LINPHONE_LINPHONECORE_H 1)
+endif()
+
+find_library(LINPHONE_LIBRARIES
+ NAMES linphone
+ HINTS ${_LINPHONE_ROOT_PATHS}
+ PATH_SUFFIXES bin lib
+)
+
+list(APPEND LINPHONE_INCLUDE_DIRS ${ORTP_INCLUDE_DIRS} ${MS2_INCLUDE_DIRS} ${XML2_INCLUDE_DIRS} ${BELLESIP_INCLUDE_DIRS})
+list(APPEND LINPHONE_LIBRARIES ${ORTP_LIBRARIES} ${MS2_LIBRARIES} ${XML2_LIBRARIES} ${BELLESIP_LIBRARIES})
+if(WIN32)
+ list(APPEND LINPHONE_LIBRARIES shlwapi)
+endif(WIN32)
+
+list(REMOVE_DUPLICATES LINPHONE_INCLUDE_DIRS)
+list(REMOVE_DUPLICATES LINPHONE_LIBRARIES)
+set(LINPHONE_CPPFLAGS "${MS2_CPPFLAGS}")
+set(LINPHONE_LDFLAGS "${MS2_LDFLAGS} ${BELLESIP_LDFLAGS}")
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(Linphone
+ DEFAULT_MSG
+ LINPHONE_INCLUDE_DIRS LINPHONE_LIBRARIES
+)
+
+mark_as_advanced(LINPHONE_INCLUDE_DIRS LINPHONE_LIBRARIES LINPHONE_CPPFLAGS LINPHONE_LDFLAGS)
diff --git a/README b/README
index a2fe5301e..e10ecc2d2 100644
--- a/README
+++ b/README
@@ -33,10 +33,13 @@ This is Linphone, a free (GPL) video softphone based on the SIP protocol.
Here is the command line to get these dependencies installed for Ubuntu && Debian
- $ sudo apt-get install libtool intltool libgtk2.0-dev libspeexdsp-dev libavcodec-dev libswscale-dev libx11-dev libxv-dev libgl1-mesa-dev libglew1.6-dev libv4l-dev libxml2-dev
+ $ sudo apt-get install libtool intltool libgtk2.0-dev libspeexdsp-dev \
+libavcodec-dev libswscale-dev libx11-dev libxv-dev libgl1-mesa-dev \
+libglew1.6-dev libv4l-dev libxml2-dev
+ for optional library
- $ sudo apt-get install libreadline-dev libgsm1-dev libtheora-dev libsoup2.4-dev libsqlite3-dev libupnp4-dev
+ $ sudo apt-get install libreadline-dev libgsm1-dev libtheora-dev \
+libsoup2.4-dev libsqlite3-dev libupnp4-dev
+ Install srtp (optional) for call encryption :
$ git clone git://git.linphone.org/srtp.git
diff --git a/README.macos b/README.macos
index 05a00e080..e3ffb72d5 100644
--- a/README.macos
+++ b/README.macos
@@ -4,6 +4,7 @@
You need:
- Xcode (download from apple or using appstore application)
+ - Java SE
- Macports: http://www.macports.org/
Download and install macports using its user friendly installer.
@@ -17,7 +18,7 @@ You need:
$ sudo port install automake autoconf libtool intltool wget cunit
- Install some linphone dependencies with macports
- $ sudo port install antlr3 speex libvpx readline sqlite3 libsoup openldap
+ $ sudo port install antlr3 speex libvpx readline sqlite3 libsoup openldap libupnp
$ sudo port install ffmpeg-devel -gpl2
- Install gtk. It is recommended to use the quartz backend for better integration.
diff --git a/README.mingw b/README.mingw
index 79e8ce547..57c0851c4 100644
--- a/README.mingw
+++ b/README.mingw
@@ -4,20 +4,20 @@ Software to install
Download lastest mingw-get-setup.exe from http://www.mingw.org
Run mingw-get-setup.exe.
In the package list, select and install:
-* mingw32-developer-tool
+* mingw-developer-toolkit
* mingw32-base
* mingw32-gcc-g++
+* mingw32-pthreads-w32
* msys-base
+* msys-zip
+* msys-unzip
+* msys-wget
For more information:
http://www.mingw.org/wiki/Getting_Started
In mingw shell (also refered as msys), run
-mingw-get install msys-zip
-mingw-get install msys-unzip
-mingw-get install msys-wget
-
mkdir -p /opt/perl/bin
cp /bin/perl /opt/perl/bin/.
@@ -29,7 +29,7 @@ Download lastest linphone-deps-win32 zip from
http://download.savannah.gnu.org/releases-noredirect/linphone/misc
using your browser.
-Download lastest gtk+-2.24.10 win32 _bundle_ from http://www.gtk.org
+Download gtk+-2.24.10 win32 _bundle_ from http://www.gtk.org, direct link: http://ftp.gnome.org/pub/gnome/binaries/win32/gtk+/2.24/gtk+-bundle_2.24.10-20120208_win32.zip
Install all these three package in /:
@@ -48,7 +48,7 @@ libintl.a libintl.la libintl.dll.a
* Download and install Inno Setup Compiler (required only if you run 'make setup.exe'). Add it to your windows Path environment variable.
-* Install msys-git from (http://code.google.com/p/msysgit/). During installation you are asked to make a choice about how line endings are treated by git. Choose "Checkout line endings as they are, commit as they are". THIS CHOICE IS VERY IMPORTANT. OTHERS BREAK AUTOMAKE.
+* Install msys-git from (http://msysgit.github.io/). During installation you are asked to make a choice about how line endings are treated by git. Choose "Checkout line endings as they are, commit as they are". THIS CHOICE IS VERY IMPORTANT. OTHERS BREAK AUTOMAKE.
General rules for compilation
@@ -63,6 +63,7 @@ cd /c/sources
Building belle-sip
******************
+ * make sure that java version 1.6 is available in the PATH. java-1.7 will not work with antlr generator.
* download the sources with msys-git shell using the following command:
$ git clone git://git.linphone.org/belle-sip.git
* compile and install
@@ -98,7 +99,8 @@ Building plugins (optional)
***************************
This the example for msx264 (H264 plugin), the same applies for other linphone plugins.
- $ cd mediastreamer2/plugins/msx264
+ $ git clone git://git.linphone.org/msx264.git
+ $ cd msx264
$ ./autogen.sh
$ PKG_CONFIG_PATH=/usr/lib/pkgconfig ./configure --prefix=/usr --enable-shared --disable-static
#make a binary zip of this plugin
diff --git a/build/android/Android.mk b/build/android/Android.mk
index 8f512790c..949eed600 100755
--- a/build/android/Android.mk
+++ b/build/android/Android.mk
@@ -65,11 +65,14 @@ LOCAL_SRC_FILES := \
xml2lpc.c \
lpc2xml.c \
remote_provisioning.c \
+ quality_reporting.c \
+ call_log.c \
+ call_params.c \
lime.c \
- quality_reporting.c
+ player.c
-ifndef LINPHONE_VERSION
-LINPHONE_VERSION = "Devel"
+ifndef LIBLINPHONE_VERSION
+LIBLINPHONE_VERSION = "Devel"
endif
LOCAL_CFLAGS += \
@@ -78,7 +81,7 @@ LOCAL_CFLAGS += \
-DINET6 \
-DENABLE_TRACE \
-DHAVE_CONFIG_H \
- -DLINPHONE_VERSION=\"$(LINPHONE_VERSION)\" \
+ -DLIBLINPHONE_VERSION=\"$(LIBLINPHONE_VERSION)\" \
-DLINPHONE_PLUGINS_DIR=\"\\tmp\" \
-DUSE_BELLESIP
diff --git a/build/android/liblinphone_gitversion.h b/build/android/liblinphone_gitversion.h
deleted file mode 100644
index 50e8a106e..000000000
--- a/build/android/liblinphone_gitversion.h
+++ /dev/null
@@ -1 +0,0 @@
-#define LIBLINPHONE_GIT_VERSION "unknown"
diff --git a/build/android/liblinphone_tester.mk b/build/android/liblinphone_tester.mk
index e9a2c8718..a6a2ab5f5 100644
--- a/build/android/liblinphone_tester.mk
+++ b/build/android/liblinphone_tester.mk
@@ -13,7 +13,8 @@ common_SRC_FILES := \
flexisip_tester.c \
tester.c \
remote_provisioning_tester.c \
- quality_reporting_tester.c
+ quality_reporting_tester.c \
+ transport_tester.c
common_C_INCLUDES += \
$(LOCAL_PATH) \
@@ -32,6 +33,10 @@ LOCAL_C_INCLUDES = $(common_C_INCLUDES)
LOCAL_CFLAGS = -DIN_LINPHONE
LOCAL_LDLIBS := -llog
+ifeq ($(BUILD_MATROSKA), 1)
+LOCAL_CFLAGS += -DHAVE_MATROSKA
+endif
+
LOCAL_SHARED_LIBRARIES := cunit liblinphone
include $(BUILD_SHARED_LIBRARY)
diff --git a/build/wp8/LibLinphone.vcxproj b/build/wp8/LibLinphone.vcxproj
index 797b2517d..8b0660688 100644
--- a/build/wp8/LibLinphone.vcxproj
+++ b/build/wp8/LibLinphone.vcxproj
@@ -107,6 +107,8 @@
+
+
@@ -124,6 +126,7 @@
+
diff --git a/build/wp8/LibLinphoneTester-native/LibLinphoneTester-native.vcxproj b/build/wp8/LibLinphoneTester-native/LibLinphoneTester-native.vcxproj
index 424044515..0512be517 100644
--- a/build/wp8/LibLinphoneTester-native/LibLinphoneTester-native.vcxproj
+++ b/build/wp8/LibLinphoneTester-native/LibLinphoneTester-native.vcxproj
@@ -105,6 +105,7 @@
+
true
@@ -153,4 +154,4 @@
-
\ No newline at end of file
+
diff --git a/config.h.cmake b/config.h.cmake
new file mode 100644
index 000000000..f348cf3f9
--- /dev/null
+++ b/config.h.cmake
@@ -0,0 +1,32 @@
+/***************************************************************************
+* config.h.cmake
+* Copyright (C) 2014 Belledonne Communications, Grenoble France
+*
+****************************************************************************
+*
+* 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, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+****************************************************************************/
+
+#define LINPHONE_MAJOR_VERSION ${LINPHONE_MAJOR_VERSION}
+#define LINPHONE_MINOR_VERSION ${LINPHONE_MINOR_VERSION}
+#define LINPHONE_MICRO_VERSION ${LINPHONE_MICRO_VERSION}
+#define LINPHONE_VERSION "${LINPHONE_VERSION}"
+#define LIBLINPHONE_VERSION "${LINPHONE_VERSION}"
+
+#define LINPHONE_PLUGINS_DIR "${LINPHONE_PLUGINS_DIR}"
+#define PACKAGE_LOCALE_DIR "${PACKAGE_LOCALE_DIR}"
+#define PACKAGE_DATA_DIR "${PACKAGE_DATA_DIR}"
+#define PACKAGE_SOUND_DIR "${PACKAGE_SOUND_DIR}"
diff --git a/configure.ac b/configure.ac
index 092b41129..f584f5b9a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -36,7 +36,7 @@ m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])],)
AC_SUBST([docdir], [${datadir}/doc])
AC_CONFIG_HEADERS(config.h)
AC_CONFIG_MACRO_DIR([m4])
-dnl don't put anythingelse before AC_PROG_CC unless checking if macro still work for clang
+dnl do not put anythingelse before AC_PROG_CC unless checking if macro still work for clang
AC_PROG_CXX(["xcrun clang++" g++])
AC_PROG_CC(["xcrun clang" gcc])
@@ -135,7 +135,7 @@ AC_DEFINE_UNQUOTED(LINPHONE_ALL_LANGS, "$ALL_LINGUAS", [All supported languages]
if test "$mingw_found" != "yes" ; then
dnl gettext macro does not work properly under mingw. And we want to use the one provided by GTK.
-
+
dnl AM_GNU_GETTEXT pollutes CPPFLAGS: workaround this.
CPPFLAGS_save=$CPPFLAGS
AM_GNU_GETTEXT([external])
@@ -185,29 +185,29 @@ if test "$enable_ldap" = "true"; then
[AC_MSG_ERROR([You need libldap for LDAP support])]
)
AC_CHECK_HEADERS(ldap.h, [foo=bar], [AC_MSG_ERROR( [ldap.h not found] ) ] )
- found_ldap=yes
+ found_ldap=yes
fi
-
+
PKG_CHECK_MODULES(SASL, [libsasl2],[found_sasl=yes],[found_sasl=no] )
-
+
if test "$found_sasl" = "no"; then
AC_CHECK_LIB(sasl2, sasl_client_init , [SASL_LIBS="-lsasl2"],
[AC_MSG_ERROR([You need SASL for LDAP support] ) ]
)
AC_CHECK_HEADERS(sasl/sasl.h,foo=bar, [AC_MSG_ERROR([sasl/sasl.h not found])])
- found_sasl=yes
+ found_sasl=yes
fi
-
+
AC_SUBST(LDAP_CFLAGS)
AC_SUBST(LDAP_LIBS)
-
+
AC_SUBST(SASL_CFLAGS)
AC_SUBST(SASL_LIBS)
-
+
if test "$found_ldap$found_sasl" = "yesyes"; then
AC_DEFINE(BUILD_LDAP,1,[Defined if LDAP build option enabled])
else
- AC_MSG_ERROR([Can't use LDAP due to previous errors])
+ AC_MSG_ERROR([Cannot use LDAP due to previous errors])
fi
fi
@@ -248,7 +248,7 @@ AC_ARG_ENABLE(upnp,
)
if test "$build_upnp" != "false" ; then
- PKG_CHECK_MODULES([LIBUPNP], [libupnp],
+ PKG_CHECK_MODULES([LIBUPNP], [libupnp],
[if pkg-config --atleast-version=1.6 "libupnp < 1.7"; then
build_upnp=true
else
@@ -277,7 +277,7 @@ fi
AM_CONDITIONAL(BUILD_TOOLS, test x$build_tools != xfalse)
if test "$build_tools" != "false" ; then
build_tools=true
- AC_DEFINE(BUILD_TOOLS, 1, [Define if tools enabled] )
+ AC_DEFINE(BUILD_TOOLS, 1, [Define if tools enabled] )
fi
dnl conditionnal build of gtk interface.
@@ -537,7 +537,7 @@ fi
dnl conditionnal build of video support
AC_ARG_ENABLE(video,
- [AS_HELP_STRING([--enable-video], [Turn on video support compiling])],
+ [AS_HELP_STRING([--enable-video], [Turn on video support compiling (default=yes)])],
[case "${enableval}" in
yes) video=true ;;
no) video=false ;;
@@ -553,10 +553,10 @@ AC_ARG_WITH(ffmpeg,
)
if test "$video" = "true"; then
-
+
if test "$enable_x11" = "true"; then
AC_CHECK_HEADERS(X11/Xlib.h)
- if test "$build_macos" = "yes"; then
+ if test "$build_macos" = "yes"; then
X11_LIBS="-L/usr/X11/lib -lX11"
else
AC_CHECK_LIB(X11,XUnmapWindow, X11_LIBS="-lX11")
@@ -644,7 +644,7 @@ AC_SUBST(LIBSOUP_LIBS)
AM_CONDITIONAL(BUILD_WIZARD, test x$build_wizard != xfalse)
if test "$build_wizard" != "false" ; then
build_wizard=true
- AC_DEFINE(BUILD_WIZARD, 1, [Define if wizard enabled] )
+ AC_DEFINE(BUILD_WIZARD, 1, [Define if wizard enabled] )
fi
AC_CHECK_HEADERS(libudev.h)
@@ -656,27 +656,42 @@ AC_CHECK_LIB(udev,udev_new)
AC_ARG_ENABLE(strict,
- AC_HELP_STRING([--enable-strict], [Build with stricter options (gcc only) @<:@yes@:>@]),
+ AC_HELP_STRING([--enable-strict], [Build with stricter options @<:@yes@:>@]),
[strictness="${enableval}"],
[strictness=yes]
)
-STRICT_OPTIONS="-Wall"
+STRICT_OPTIONS="-Wall -Wuninitialized"
+STRICT_OPTIONS_CC="-Wdeclaration-after-statement "
+STRICT_OPTIONS_CXX=""
#for clang
-case $CC in
+case $CC in
*clang*)
- STRICT_OPTIONS="$STRICT_OPTIONS -Qunused-arguments"
+ STRICT_OPTIONS="$STRICT_OPTIONS -Qunused-arguments "
+ #disabled due to wrong optimization false positive with small string
+ #(cf. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=35903)
+ STRICT_OPTIONS="$STRICT_OPTIONS -Wno-array-bounds "
+ ;;
+esac
+# because Darwin's gcc is actually clang, we need to check it...
+case "$target_os" in
+ *darwin*)
+ STRICT_OPTIONS="$STRICT_OPTIONS -Wno-error=unknown-warning-option -Qunused-arguments -Wno-tautological-compare -Wno-unused-function "
+ #disabled due to wrong optimization false positive with small string
+ #(cf. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=35903)
+ STRICT_OPTIONS="$STRICT_OPTIONS -Wno-array-bounds "
;;
esac
-
if test "$strictness" = "yes" ; then
STRICT_OPTIONS="$STRICT_OPTIONS -Werror"
CFLAGS="$CFLAGS -fno-strict-aliasing"
fi
AC_SUBST(STRICT_OPTIONS)
+AC_SUBST(STRICT_OPTIONS_CC)
+AC_SUBST(STRICT_OPTIONS_CXX)
top_srcdir=`dirname $0`
@@ -783,13 +798,13 @@ if test x$enable_msg_storage != xfalse; then
fi
enable_msg_storage=false
fi
-
+
AC_SUBST(SQLITE3_CFLAGS)
AC_SUBST(SQLITE3_LIBS)
fi
-
+
PKG_CHECK_MODULES(BELLESIP, [belle-sip >= 1.3.1])
SIPSTACK_CFLAGS="$BELLESIP_CFLAGS"
@@ -887,7 +902,7 @@ AC_PATH_PROG(DOXYGEN,doxygen,false)
AM_CONDITIONAL(HAVE_DOXYGEN, test $DOXYGEN != false)
-AC_CONFIG_FILES([
+AC_CONFIG_FILES([
Makefile
build/Makefile
build/macos/Makefile
diff --git a/console/Makefile.am b/console/Makefile.am
index 314f5d612..482948329 100644
--- a/console/Makefile.am
+++ b/console/Makefile.am
@@ -3,12 +3,13 @@
AM_CPPFLAGS=\
-I$(top_srcdir) \
-I$(top_srcdir)/coreapi \
- -I$(top_srcdir)/include
+ -I$(top_srcdir)/include
COMMON_CFLAGS=\
-DIN_LINPHONE \
-D_ORTP_SOURCE \
$(STRICT_OPTIONS) \
+ $(STRICT_OPTIONS_CC) \
$(ORTP_CFLAGS) \
$(MEDIASTREAMER_CFLAGS) \
$(VIDEO_CFLAGS) \
diff --git a/console/commands.c b/console/commands.c
index 009d8724b..7c5b519d8 100644
--- a/console/commands.c
+++ b/console/commands.c
@@ -515,7 +515,7 @@ lpc_cmd_help(LinphoneCore *lc, char *arg)
i=0;
while (advanced_commands[i].help)
{
- linphonec_out("%10.10s\t%s\n", advanced_commands[i].name,
+ linphonec_out("%20.20s\t%s\n", advanced_commands[i].name,
advanced_commands[i].help);
i++;
}
@@ -603,6 +603,7 @@ lpc_cmd_chat(LinphoneCore *lc, char *args)
char *arg1 = args;
char *arg2 = NULL;
char *ptr = args;
+ LinphoneChatRoom *cr;
if (!args) return 0;
@@ -619,7 +620,7 @@ lpc_cmd_chat(LinphoneCore *lc, char *args)
/* missing one parameter */
return 0;
}
- LinphoneChatRoom *cr = linphone_core_create_chat_room(lc,arg1);
+ cr = linphone_core_create_chat_room(lc,arg1);
linphone_chat_room_send_message(cr,arg2);
return 1;
}
@@ -2441,8 +2442,9 @@ static void lpc_display_call_states(LinphoneCore *lc){
}else{
for(;elem!=NULL;elem=elem->next){
const char *flag;
+ bool_t in_conference;
call=(LinphoneCall*)elem->data;
- bool_t in_conference=linphone_call_params_get_local_conference_mode(linphone_call_get_current_params(call));
+ in_conference=linphone_call_params_get_local_conference_mode(linphone_call_get_current_params(call));
tmp=linphone_call_get_remote_address_as_string (call);
flag=in_conference ? "conferencing" : "";
flag=linphone_call_has_transfer_pending(call) ? "transfer pending" : flag;
diff --git a/console/linphonec.c b/console/linphonec.c
index b8072e325..1a800fd2b 100644
--- a/console/linphonec.c
+++ b/console/linphonec.c
@@ -367,8 +367,8 @@ static void linphonec_call_state_changed(LinphoneCore *lc, LinphoneCall *call, L
if ( auto_answer) {
answer_call=TRUE;
} else if (real_early_media_sending) {
- linphonec_out("Sending early media using real hardware\n");
LinphoneCallParams* callparams = linphone_core_create_default_call_parameters(lc);
+ linphonec_out("Sending early media using real hardware\n");
linphone_call_params_enable_early_media_sending(callparams, TRUE);
if (vcap_enabled) linphone_call_params_enable_video(callparams, TRUE);
linphone_core_accept_early_media_with_params(lc, call, callparams);
@@ -536,6 +536,7 @@ char *linphonec_readline(char *prompt){
fprintf(stdout,"%s",prompt);
fflush(stdout);
while(1){
+
ms_mutex_lock(&prompt_mutex);
if (have_prompt){
char *ret=strdup(received_prompt);
@@ -546,15 +547,17 @@ char *linphonec_readline(char *prompt){
ms_mutex_unlock(&prompt_mutex);
linphonec_idle_call();
#ifdef WIN32
- Sleep(20);
- /* Following is to get the video window going as it
- should. Maybe should we only have this on when the option -V
- or -D is on? */
- MSG msg;
+ {
+ MSG msg;
+ Sleep(20);
+ /* Following is to get the video window going as it
+ should. Maybe should we only have this on when the option -V
+ or -D is on? */
- if (PeekMessage(&msg, NULL, 0, 0,1)) {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
+ if (PeekMessage(&msg, NULL, 0, 0,1)) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
}
#else
usleep(20000);
@@ -747,7 +750,7 @@ linphonec_init(int argc, char **argv)
linphone_core_enable_video_display(linphonec, display_enabled);
if (display_enabled && window_id != 0)
{
- printf ("Setting window_id: 0x%x\n", window_id);
+ printf("Setting window_id: 0x%x\n", window_id);
linphone_core_set_native_video_window_id(linphonec,window_id);
}
@@ -828,12 +831,13 @@ linphonec_prompt_for_auth_final(LinphoneCore *lc)
#ifdef HAVE_READLINE
rl_hook_func_t *old_event_hook;
#endif
+ LinphoneAuthInfo *pending_auth;
if (reentrancy!=0) return 0;
reentrancy++;
- LinphoneAuthInfo *pending_auth=auth_stack.elem[auth_stack.nitems-1];
+ pending_auth=auth_stack.elem[auth_stack.nitems-1];
snprintf(auth_prompt, 256, "Password for %s on %s: ",
pending_auth->username, pending_auth->realm);
diff --git a/console/shell.c b/console/shell.c
index bfc758bf8..016992397 100644
--- a/console/shell.c
+++ b/console/shell.c
@@ -177,12 +177,14 @@ static void spawn_linphonec(int argc, char *argv[]){
static void spawn_linphonec(int argc, char *argv[]){
PROCESS_INFORMATION pinfo;
STARTUPINFO si;
+ BOOL ret;
+
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory( &pinfo, sizeof(pinfo) );
- BOOL ret=CreateProcess(NULL,"linphoned.exe --pipe -c NUL",
+ ret=CreateProcess(NULL,"linphoned.exe --pipe -c NUL",
NULL,
NULL,
FALSE,
diff --git a/coreapi/CMakeLists.txt b/coreapi/CMakeLists.txt
index 1fb5f2add..df753c11e 100644
--- a/coreapi/CMakeLists.txt
+++ b/coreapi/CMakeLists.txt
@@ -1,47 +1,30 @@
+############################################################################
+# CMakeLists.txt
+# Copyright (C) 2014 Belledonne Communications, Grenoble France
+#
+############################################################################
+#
+# 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, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+############################################################################
+
if(MSVC)
find_library(LIBGCC NAMES gcc)
find_library(LIBMINGWEX NAMES mingwex)
endif()
-find_library(LIBORTP NAMES ortp)
-find_library(LIBMEDIASTREAMER_BASE NAMES mediastreamer_base)
-find_library(LIBMEDIASTREAMER_VOIP NAMES mediastreamer_voip)
-find_library(LIBBELLESIP NAMES bellesip)
-find_library(LIBXML2 NAMES xml2)
-find_program(GIT git)
-
-set(GIT_VERSION "unknown")
-if(GIT)
- execute_process(
- WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
- COMMAND ${GIT} describe --always
- OUTPUT_VARIABLE GIT_DESCRIBE
- OUTPUT_STRIP_TRAILING_WHITESPACE
- )
- execute_process(
- WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
- COMMAND ${GIT} describe --abbrev=0
- OUTPUT_VARIABLE GIT_TAG
- OUTPUT_STRIP_TRAILING_WHITESPACE
- )
- execute_process(
- WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
- COMMAND ${GIT} rev-parse HEAD
- OUTPUT_VARIABLE GIT_REVISION
- OUTPUT_STRIP_TRAILING_WHITESPACE
- )
- if(GIT_DESCRIBE)
- set(GIT_VERSION ${GIT_DESCRIBE})
- else(GIT_DESCRIBE)
- if(GIT_REVISION)
- set(GIT_VERSION ${GIT_REVISION})
- endif(GIT_REVISION)
- endif(GIT_DESCRIBE)
-endif(GIT)
-execute_process(
- COMMAND ${CMAKE_COMMAND} -E echo "#define LIBLINPHONE_GIT_VERSION \"${GIT_VERSION}\""
- OUTPUT_FILE ${CMAKE_CURRENT_BINARY_DIR}/liblinphone_gitversion.h
-)
set(SOURCE_FILES
address.c
@@ -59,6 +42,8 @@ set(SOURCE_FILES
bellesip_sal/sal_op_registration.c
bellesip_sal/sal_sdp.c
callbacks.c
+ call_log.c
+ call_params.c
chat.c
conference.c
ec-calibrator.c
@@ -68,7 +53,6 @@ set(SOURCE_FILES
info.c
linphonecall.c
linphonecore.c
- #linphone_tunnel.cc
linphone_tunnel_stubs.c
linphone_tunnel_config.c
lpconfig.c
@@ -76,6 +60,7 @@ set(SOURCE_FILES
message_storage.c
misc.c
offeranswer.c
+ player.c
presence.c
proxy.c
quality_reporting.c
@@ -83,7 +68,6 @@ set(SOURCE_FILES
sal.c
siplogin.c
sipsetup.c
- #TunnelManager.cc
xml.c
xml2lpc.c
bellesip_sal/sal_impl.h
@@ -99,55 +83,86 @@ set(SOURCE_FILES
sipsetup.h
xml2lpc.h
)
+if(ENABLE_TUNNEL)
+ list(APPEND SOURCE_FILES
+ linphone_tunnel.cc
+ TunnelManager.cc
+ )
+ add_definitions(-DTUNNEL_ENABLED)
+endif()
+
+set(GENERATED_SOURCE_FILES
+ ${CMAKE_CURRENT_BINARY_DIR}/liblinphone_gitversion.h
+)
+set_source_files_properties(${GENERATED_SOURCE_FILES} PROPERTIES GENERATED TRUE)
+find_package(Git)
+add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/liblinphone_gitversion.h
+ COMMAND ${CMAKE_COMMAND} -DGIT_EXECUTABLE=${GIT_EXECUTABLE} -DWORK_DIR=${CMAKE_CURRENT_SOURCE_DIR} -DOUTPUT_DIR=${CMAKE_CURRENT_BINARY_DIR} -P ${CMAKE_CURRENT_SOURCE_DIR}/gitversion.cmake)
add_definitions(
- -D_TRUE_TIME
-DIN_LINPHONE
-DUSE_BELLESIP
- #-DTUNNEL_ENABLED
- -DLINPHONE_PACKAGE_NAME="linphone"
- -DLINPHONE_VERSION="Devel"
-DLIBLINPHONE_EXPORTS
- -DLINPHONE_PLUGINS_DIR=""
)
-if(LINPHONE_ENABLE_VIDEO)
+if(ENABLE_VIDEO)
add_definitions(-DVIDEO_ENABLED)
-endif(LINPHONE_ENABLE_VIDEO)
+endif()
-if(WIN32)
-add_definitions(
- -DWINDOW_NATIVE
- /FIliblinphone_gitversion.h
+set(LIBS
+ ${LIBGCC}
+ ${LIBMINGWEX}
+ ${BELLESIP_LIBRARIES}
+ ${MS2_LIBRARIES}
+ ${XML2_LIBRARIES}
)
+if(WIN32)
+ list(APPEND LIBS shlwapi)
+endif()
-set(LIBS ws2_32)
-endif(WIN32)
-set(LIBS ${LIBS} ${LIBGCC} ${LIBMINGWEX} ${LIBORTP} ${LIBMEDIASTREAMER_BASE} ${LIBMEDIASTREAMER_VOIP} ${LIBBELLESIP} ${LIBXML2})
-
-add_library(linphone SHARED ${SOURCE_FILES})
-set_target_properties(linphone PROPERTIES VERSION 3.7.0 SOVERSION 5)
-
-target_link_libraries(linphone ${LIBS})
+if(ENABLE_STATIC)
+ add_library(linphone STATIC ${SOURCE_FILES} ${GENERATED_SOURCE_FILES})
+ target_link_libraries(linphone ${LIBS})
+else()
+ add_library(linphone SHARED ${SOURCE_FILES} ${GENERATED_SOURCE_FILES})
+ set_target_properties(linphone PROPERTIES VERSION ${LINPHONE_VERSION} SOVERSION ${LINPHONE_SO_VERSION} LINKER_LANGUAGE CXX)
+ target_link_libraries(linphone ${LIBS})
+ if(MSVC)
+ if(CMAKE_BUILD_TYPE STREQUAL "Debug")
+ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/Debug/linphone.pdb
+ DESTINATION bin
+ PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
+ )
+ endif()
+ endif()
+endif()
install(TARGETS linphone
- RUNTIME DESTINATION bin
+ RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
- PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
+ PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
+)
-file(GLOB HEADER_FILES "*.h")
+set(HEADER_FILES
+ call_log.h
+ call_params.h
+ event.h
+ linphonecore.h
+ linphonecore_utils.h
+ linphonefriend.h
+ linphonepresence.h
+ linphone_tunnel.h
+ lpc2xml.h
+ lpconfig.h
+ sipsetup.h
+ xml2lpc.h
+)
install(FILES ${HEADER_FILES}
DESTINATION include/linphone
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
)
-if(WIN32)
-if(CMAKE_BUILD_TYPE STREQUAL "Debug")
-install(FILES ${CMAKE_CURRENT_BINARY_DIR}/Debug/linphone.pdb
- DESTINATION bin
- PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
-)
-endif()
-endif(WIN32)
+
+add_subdirectory(help)
diff --git a/coreapi/Makefile.am b/coreapi/Makefile.am
index 5d5db0f4b..b13f8c5c7 100644
--- a/coreapi/Makefile.am
+++ b/coreapi/Makefile.am
@@ -5,6 +5,12 @@ GITDESCRIBE=`cd $(top_srcdir) && git describe --always`
GIT_TAG=`cd $(top_srcdir) && git describe --abbrev=0`
GITREVISION=`cd $(top_srcdir) && git rev-parse HEAD`
+## This command is used to check if the sources are cloned in a git repo.
+## We can't only depend on the presence of the .git/ directory anymore,
+## because of gits submodule handling.
+## We now simply issue a git log on configure.ac and if the output is empty (error or file not tracked), then we are not in git.
+GITLOG=$(shell git log -1 --pretty=format:%H $(top_srcdir)/configure.ac)
+
ECHO=/bin/echo
SUBDIRS=. help
@@ -18,7 +24,7 @@ CLEANFILES=$(GITVERSION_FILE)
## Process this file with automake to produce Makefile.in
linphone_includedir=$(includedir)/linphone
-linphone_include_HEADERS=linphonecore.h linphonefriend.h linphonepresence.h linphonecore_utils.h lpconfig.h sipsetup.h event.h xml2lpc.h lpc2xml.h linphone_tunnel.h
+linphone_include_HEADERS=linphonecore.h linphonefriend.h linphonepresence.h linphonecore_utils.h lpconfig.h sipsetup.h event.h xml2lpc.h lpc2xml.h linphone_tunnel.h call_log.h call_params.h
lib_LTLIBRARIES=liblinphone.la
@@ -54,12 +60,15 @@ liblinphone_la_SOURCES=\
remote_provisioning.c \
lime.c \
quality_reporting.c quality_reporting.h\
+ call_log.c \
+ call_params.c \
+ player.c \
$(GITVERSION_FILE)
if BUILD_UPNP
liblinphone_la_SOURCES+=upnp.c upnp.h
endif
-
+
liblinphone_la_SOURCES+= bellesip_sal/sal_address_impl.c \
bellesip_sal/sal_impl.c bellesip_sal/sal_impl.h \
bellesip_sal/sal_op_impl.c \
@@ -74,7 +83,7 @@ liblinphone_la_SOURCES+= bellesip_sal/sal_address_impl.c \
bellesip_sal/sal_op_events.c
if BUILD_WIZARD
-liblinphone_la_SOURCES+=sipwizard.c
+liblinphone_la_SOURCES+=sipwizard.c
endif
liblinphone_la_SOURCES+=linphone_tunnel_config.c
@@ -133,8 +142,9 @@ endif
AM_CPPFLAGS=\
-I$(top_srcdir) -I$(top_srcdir)/include -I$(builddir)
-AM_CFLAGS=\
- $(STRICT_OPTIONS) -DIN_LINPHONE \
+COMMON_CFLAGS=\
+ $(STRICT_OPTIONS) \
+ -DIN_LINPHONE \
$(ORTP_CFLAGS) \
$(MEDIASTREAMER_CFLAGS) \
$(SIPSTACK_CFLAGS) \
@@ -150,19 +160,20 @@ AM_CFLAGS=\
$(LDAP_CFLAGS) $(SASL_CFLAGS)
if BUILD_WIZARD
-AM_CFLAGS+= -DBUILD_WIZARD
+COMMON_CFLAGS+= -DBUILD_WIZARD
endif
-AM_CFLAGS+= -DUSE_BELLESIP
+COMMON_CFLAGS+= -DUSE_BELLESIP
-AM_CXXFLAGS=$(AM_CFLAGS)
+AM_CFLAGS=$(COMMON_CFLAGS) $(STRICT_OPTIONS_CC)
+AM_CXXFLAGS=$(COMMON_CFLAGS) $(STRICT_OPTIONS_CXX)
#Make sure that we are in linphone's git tree by doing git log $(top_srcdir)/configure.ac.
-#if it is something known to git, then that will be ok to check the git describe number and make sure it is consistent with
+#if it is something known to git, then that will be ok to check the git describe number and make sure it is consistent with
#the PACKAGE_VERSION given in configure.ac
make_gitversion_h:
- if test -d $(top_srcdir)/.git ; then \
+ if test -n "$(GITLOG)" ; then \
if test "$(GITDESCRIBE)" != "" ; then \
if test "$(GIT_TAG)" != "$(PACKAGE_VERSION)" ; then \
echo "*** PACKAGE_VERSION and git tag differ. Please put them identical."; \
diff --git a/coreapi/TunnelManager.cc b/coreapi/TunnelManager.cc
index 2bc8cd3e0..d88212c68 100644
--- a/coreapi/TunnelManager.cc
+++ b/coreapi/TunnelManager.cc
@@ -1,7 +1,7 @@
/*
* C Implementation: tunnel
*
- * Description:
+ * Description:
*
*
* Author: Simon Morlat , (C) 2009
@@ -19,18 +19,17 @@
#ifndef USE_BELLESIP
#include "eXosip2/eXosip_transport_hook.h"
#endif
-#include "tunnel/udp_mirror.hh"
#include "private.h"
#ifdef ANDROID
#include
#endif
+belledonnecomm::TunnelManager *bcTunnel(const LinphoneTunnel *tunnel);
using namespace belledonnecomm;
using namespace ::std;
-
void TunnelManager::addServer(const char *ip, int port,unsigned int udpMirrorPort,unsigned int delay) {
if (ip == NULL) {
ip = "";
@@ -53,7 +52,6 @@ void TunnelManager::cleanServers() {
mServerAddrs.clear();
UdpMirrorClientList::iterator it;
- mAutoDetectStarted=false;
for (it = mUdpMirrorClients.begin(); it != mUdpMirrorClients.end();) {
UdpMirrorClient& s=*it++;
s.stop();
@@ -67,11 +65,6 @@ void TunnelManager::reconnect(){
mTunnelClient->reconnect();
}
-void TunnelManager::setCallback(StateCallback cb, void *userdata) {
- mCallback=cb;
- mCallbackData=userdata;
-}
-
static void sCloseRtpTransport(RtpTransport *t, void *userData){
TunnelSocket *s=(TunnelSocket*)userData;
TunnelManager *manager=(TunnelManager*)s->getUserPointer();
@@ -79,13 +72,16 @@ static void sCloseRtpTransport(RtpTransport *t, void *userData){
}
void TunnelManager::closeRtpTransport(RtpTransport *t, TunnelSocket *s){
mTunnelClient->closeSocket(s);
- ms_free(t);
}
static RtpTransport *sCreateRtpTransport(void* userData, int port){
return ((TunnelManager *) userData)->createRtpTransport(port);
}
+void sDestroyRtpTransport(RtpTransport *t){
+ ms_free(t);
+}
+
RtpTransport *TunnelManager::createRtpTransport(int port){
TunnelSocket *socket=mTunnelClient->createSocket(port);
socket->setUserPointer(this);
@@ -94,14 +90,15 @@ RtpTransport *TunnelManager::createRtpTransport(int port){
t->t_recvfrom=customRecvfrom;
t->t_sendto=customSendto;
t->t_close=sCloseRtpTransport;
+ t->t_destroy=sDestroyRtpTransport;
t->data=socket;
return t;
}
-void TunnelManager::start() {
- if (!mTunnelClient) {
+void TunnelManager::startClient() {
+ if (mTunnelClient == NULL) {
mTunnelClient = new TunnelClient();
- mTunnelClient->setCallback((StateCallback)tunnelCallback,this);
+ mTunnelClient->setCallback((TunnelClientController::StateCallback)tunnelCallback,this);
list::iterator it;
for(it=mServerAddrs.begin();it!=mServerAddrs.end();++it){
const ServerAddr &addr=*it;
@@ -110,14 +107,23 @@ void TunnelManager::start() {
mTunnelClient->setHttpProxy(mHttpProxyHost.c_str(), mHttpProxyPort, mHttpUserName.c_str(), mHttpPasswd.c_str());
}
mTunnelClient->start();
+ linphone_core_set_rtp_transport_factories(mCore,&mTransportFactories);
+ if(mTunnelizeSipPackets) {
+ sal_enable_tunnel(mCore->sal, mTunnelClient);
+ }
}
-bool TunnelManager::isStarted() {
- return mTunnelClient != 0 && mTunnelClient->isStarted();
+void TunnelManager::stopClient(){
+ linphone_core_set_rtp_transport_factories(mCore,NULL);
+ sal_disable_tunnel(mCore->sal);
+ if (mTunnelClient){
+ delete mTunnelClient;
+ mTunnelClient=NULL;
+ }
}
-bool TunnelManager::isReady() const {
- return mTunnelClient && mTunnelClient->isReady() && mReady;
+bool TunnelManager::isConnected() const {
+ return mTunnelClient != NULL && mTunnelClient->isReady();
}
int TunnelManager::customSendto(struct _RtpTransport *t, mblk_t *msg , int flags, const struct sockaddr *to, socklen_t tolen){
@@ -135,15 +141,20 @@ int TunnelManager::customRecvfrom(struct _RtpTransport *t, mblk_t *msg, int flag
}
-TunnelManager::TunnelManager(LinphoneCore* lc) :TunnelClientController()
-,mCore(lc)
-,mCallback(NULL)
-,mEnabled(false)
-,mTunnelClient(NULL)
-,mAutoDetectStarted(false)
-,mReady(false)
-,mHttpProxyPort(0){
-
+TunnelManager::TunnelManager(LinphoneCore* lc) :
+ mCore(lc),
+#ifndef USE_BELLESIP
+ mSipSocket(NULL),
+ mExosipTransport(NULL),
+#endif
+ mMode(LinphoneTunnelModeDisable),
+ mTunnelClient(NULL),
+ mIsConnected(false),
+ mHttpProxyPort(0),
+ mPreviousRegistrationEnabled(false),
+ mTunnelizeSipPackets(true),
+ mVTable(NULL)
+{
linphone_core_add_iterate_hook(mCore,(LinphoneCoreIterateHook)sOnIterate,this);
mTransportFactories.audio_rtcp_func=sCreateRtpTransport;
mTransportFactories.audio_rtcp_func_data=this;
@@ -153,104 +164,94 @@ TunnelManager::TunnelManager(LinphoneCore* lc) :TunnelClientController()
mTransportFactories.video_rtcp_func_data=this;
mTransportFactories.video_rtp_func=sCreateRtpTransport;
mTransportFactories.video_rtp_func_data=this;
+ mVTable = linphone_vtable_new();
+ mVTable->network_reachable = networkReachableCb;
+ linphone_core_add_listener(mCore, mVTable);
}
TunnelManager::~TunnelManager(){
stopClient();
+ linphone_core_remove_listener(mCore, mVTable);
+ linphone_vtable_destroy(mVTable);
}
-void TunnelManager::stopClient(){
- sal_disable_tunnel(mCore->sal);
- if (mTunnelClient){
- delete mTunnelClient;
- mTunnelClient=NULL;
+void TunnelManager::registration(){
+ // registration occurs always after an unregistation has been made. First we
+ // need to reset the previous registration mode
+ LinphoneProxyConfig* lProxy;
+ linphone_core_get_default_proxy(mCore, &lProxy);
+ if (lProxy) {
+ linphone_proxy_config_edit(lProxy);
+ linphone_proxy_config_enable_register(lProxy,mPreviousRegistrationEnabled);
+ linphone_proxy_config_done(lProxy);
}
}
void TunnelManager::processTunnelEvent(const Event &ev){
- LinphoneProxyConfig* lProxy;
- linphone_core_get_default_proxy(mCore, &lProxy);
-
- if (mEnabled && mTunnelClient->isReady()){
+ if (ev.mData.mConnected){
ms_message("Tunnel is up, registering now");
- linphone_core_set_firewall_policy(mCore,LinphonePolicyNoFirewall);
- linphone_core_set_rtp_transport_factories(mCore,&mTransportFactories);
-
- sal_enable_tunnel(mCore->sal, mTunnelClient);
-
- //register
- if (lProxy) {
- linphone_proxy_config_refresh_register(lProxy);
- }
- mReady=true;
- }else if (mEnabled && !mTunnelClient->isReady()){
- /* we got disconnected from the tunnel */
- mReady=false;
+ registration();
+ } else {
+ ms_error("Tunnel has been disconnected");
}
}
-void TunnelManager::waitUnRegistration(){
+void TunnelManager::waitUnRegistration() {
LinphoneProxyConfig* lProxy;
+
linphone_core_get_default_proxy(mCore, &lProxy);
- if (lProxy && linphone_proxy_config_get_state(lProxy)==LinphoneRegistrationOk) {
- int i=0;
- linphone_proxy_config_edit(lProxy);
- linphone_proxy_config_enable_register(lProxy,FALSE);
- linphone_proxy_config_done(lProxy);
- //make sure unregister is sent and authenticated
- do{
- linphone_core_iterate(mCore);
- ms_usleep(20000);
- if (i>100){
- ms_message("tunnel: timeout for unregistration expired, giving up");
- break;
- }
- i++;
- }while(linphone_proxy_config_get_state(lProxy)!=LinphoneRegistrationCleared);
- }
+ if (lProxy){
+ mPreviousRegistrationEnabled=linphone_proxy_config_register_enabled(lProxy);
+ if (linphone_proxy_config_is_registered(lProxy)) {
+ int i=0;
+ linphone_proxy_config_edit(lProxy);
+ linphone_proxy_config_enable_register(lProxy,FALSE);
+ linphone_proxy_config_done(lProxy);
+ sal_unregister(lProxy->op);
+ //make sure unregister is sent and authenticated
+ do{
+ linphone_core_iterate(mCore);
+ ms_usleep(20000);
+ if (i>100){
+ ms_message("tunnel: timeout for unregistration expired, giving up");
+ break;
+ }
+ i++;
+ }while(linphone_proxy_config_is_registered(lProxy));
+ ms_message("Unregistration %s", linphone_proxy_config_is_registered(lProxy)?"failed":"succeeded");
+ }else{
+ ms_message("No registration pending");
+ }
+ }
}
-void TunnelManager::enable(bool isEnable) {
- ms_message("Turning tunnel [%s]",(isEnable?"on":"off"));
- if (isEnable && !mEnabled){
- mEnabled=true;
- //1 save transport and firewall policy
- linphone_core_get_sip_transports(mCore, &mRegularTransport);
- mPreviousFirewallPolicy=linphone_core_get_firewall_policy(mCore);
- //2 unregister
+/*Each time tunnel is enabled/disabled, we need to unregister previous session and re-register. Since tunnel initialization
+is asynchronous, we temporary disable auto register while tunnel sets up, and reenable it when re-registering. */
+void TunnelManager::setMode(LinphoneTunnelMode mode) {
+ if(mMode != mode) {
waitUnRegistration();
- //3 insert tunnel
- start();
- }else if (!isEnable && mEnabled){
- //1 unregister
- waitUnRegistration();
-
- mEnabled=false;
- stopClient();
- mReady=false;
- linphone_core_set_rtp_transport_factories(mCore,NULL);
-
- sal_disable_tunnel(mCore->sal);
- // Set empty transports to force the setting of regular transport, otherwise it is not applied
- LCSipTransports lTransport;
- lTransport.udp_port = 0;
- lTransport.tcp_port = 0;
- lTransport.tls_port = 0;
- lTransport.dtls_port = 0;
- linphone_core_set_sip_transports(mCore, &lTransport);
-
- //Restore transport and firewall policy
- linphone_core_set_sip_transports(mCore, &mRegularTransport);
- linphone_core_set_firewall_policy(mCore, mPreviousFirewallPolicy);
- //register
- LinphoneProxyConfig* lProxy;
- linphone_core_get_default_proxy(mCore, &lProxy);
- if (lProxy) {
- linphone_proxy_config_edit(lProxy);
- linphone_proxy_config_enable_register(lProxy,TRUE);
- linphone_proxy_config_done(lProxy);
+ switch(mode) {
+ case LinphoneTunnelModeEnable:
+ mMode = mode;
+ startClient();
+ /* registration is done by proccessTunnelEvent() when the tunnel
+ the tunnel succeed to connect */
+ break;
+ case LinphoneTunnelModeDisable:
+ mMode = mode;
+ stopClient();
+ registration();
+ break;
+ case LinphoneTunnelModeAuto:
+ mMode = mode;
+ autoDetect();
+ /* Registration is not needed because processUdpMirrorEvent() will
+ call either connect() or disconnect(). Should disconnect() is called,
+ processUdpMirrorEvent() care to call registratin() */
+ break;
+ default:
+ ms_error("TunnelManager::setMode(): invalid mode (%d)", mode);
}
-
}
}
@@ -320,30 +321,29 @@ void TunnelManager::enableLogs(bool isEnabled,LogHandler logHandler) {
SetLogLevel(TUNNEL_ERROR|TUNNEL_WARN);
}
}
-
-bool TunnelManager::isEnabled() {
- return mEnabled;
+
+LinphoneTunnelMode TunnelManager::getMode() const {
+ return mMode;
}
void TunnelManager::processUdpMirrorEvent(const Event &ev){
if (ev.mData.mHaveUdp) {
LOGI("Tunnel is not required, disabling");
- enable(false);
- mAutoDetectStarted = false;
+ stopClient();
+ registration();
} else {
mCurrentUdpMirrorClient++;
if (mCurrentUdpMirrorClient !=mUdpMirrorClients.end()) {
// enable tunnel but also try backup server
LOGI("Tunnel is required, enabling; Trying backup udp mirror");
-
+
UdpMirrorClient &lUdpMirrorClient=*mCurrentUdpMirrorClient;
lUdpMirrorClient.start(TunnelManager::sUdpMirrorClientCallback,(void*)this);
} else {
LOGI("Tunnel is required, enabling; no backup udp mirror available");
- mAutoDetectStarted = false;
+ startClient();
}
- enable(true);
}
}
@@ -361,21 +361,22 @@ void TunnelManager::sUdpMirrorClientCallback(bool isUdpAvailable, void* data) {
thiz->postEvent(ev);
}
+void TunnelManager::networkReachableCb(LinphoneCore *lc, bool_t reachable) {
+ TunnelManager *tunnel = bcTunnel(linphone_core_get_tunnel(lc));
+ if(reachable && tunnel->getMode() == LinphoneTunnelModeAuto) {
+ tunnel->autoDetect();
+ }
+}
+
void TunnelManager::autoDetect() {
// first check if udp mirrors was provisionned
if (mUdpMirrorClients.empty()) {
LOGE("No UDP mirror server configured aborting auto detection");
return;
}
- if (mAutoDetectStarted) {
- LOGE("auto detection already in progress, restarting");
- (*mCurrentUdpMirrorClient).stop();
- }
- mAutoDetectStarted=true;
- mCurrentUdpMirrorClient =mUdpMirrorClients.begin();
+ mCurrentUdpMirrorClient = mUdpMirrorClients.begin();
UdpMirrorClient &lUdpMirrorClient=*mCurrentUdpMirrorClient;
lUdpMirrorClient.start(TunnelManager::sUdpMirrorClientCallback,(void*)this);
-
}
void TunnelManager::setHttpProxyAuthInfo(const char* username,const char* passwd) {
@@ -384,6 +385,22 @@ void TunnelManager::setHttpProxyAuthInfo(const char* username,const char* passwd
if (mTunnelClient) mTunnelClient->setHttpProxyAuthInfo(username,passwd);
}
+void TunnelManager::tunnelizeSipPackets(bool enable){
+ if(enable != mTunnelizeSipPackets) {
+ mTunnelizeSipPackets = enable;
+ if(isConnected()) {
+ waitUnRegistration();
+ if(mTunnelizeSipPackets) sal_enable_tunnel(mCore->sal, mTunnelClient);
+ else sal_disable_tunnel(mCore->sal);
+ registration();
+ }
+ }
+}
+
+bool TunnelManager::tunnelizeSipPacketsEnabled() const {
+ return mTunnelizeSipPackets;
+}
+
void TunnelManager::setHttpProxy(const char *host,int port, const char *username, const char *passwd){
mHttpUserName=username?username:"";
mHttpPasswd=passwd?passwd:"";
@@ -392,6 +409,6 @@ void TunnelManager::setHttpProxy(const char *host,int port, const char *username
if (mTunnelClient) mTunnelClient->setHttpProxy(host, port, username, passwd);
}
-LinphoneCore *TunnelManager::getLinphoneCore(){
+LinphoneCore *TunnelManager::getLinphoneCore() const{
return mCore;
}
diff --git a/coreapi/TunnelManager.hh b/coreapi/TunnelManager.hh
index 9ca29ad86..38b6b90e3 100644
--- a/coreapi/TunnelManager.hh
+++ b/coreapi/TunnelManager.hh
@@ -1,7 +1,7 @@
/*
* C Implementation: tunnel
*
- * Description:
+ * Description:
*
*
*
@@ -12,35 +12,35 @@
#define __TUNNEL_CLIENT_MANAGER_H__
#include
#include
-#include "tunnel/client.hh"
+#include
+#include
#include "linphonecore.h"
+#include "linphone_tunnel.h"
#ifndef USE_BELLESIP
extern "C" {
- #include "eXosip2/eXosip_transport_hook.h"
+ #include
}
#endif
namespace belledonnecomm {
-class TunnelClient;
-class UdpMirrorClient;
/**
- * @addtogroup tunnel_client
+ * @addtogroup tunnel_client
* @{
**/
/**
- * The TunnelManager class extends the LinphoneCore functionnality in order to provide an easy to use API to
+ * The TunnelManager class extends the LinphoneCore functionnality in order to provide an easy to use API to
* - provision tunnel servers ip addresses and ports
* - start/stop the tunneling service
- * - be informed of of connection and disconnection events to the tunnel server
+ * - be informed of connection and disconnection events to the tunnel server
* - perform auto-detection whether tunneling is required, based on a test of sending/receiving a flow of UDP packets.
- *
+ *
* It takes in charge automatically the SIP registration procedure when connecting or disconnecting to a tunnel server.
* No other action on LinphoneCore is required to enable full operation in tunnel mode.
**/
- class TunnelManager : public TunnelClientController{
-
+ class TunnelManager {
+
public:
/**
* Add a tunnel server. At least one should be provided to be able to connect.
@@ -61,20 +61,8 @@ class UdpMirrorClient;
void addServer(const char *ip, int port,unsigned int udpMirrorPort,unsigned int delay);
/**
* Removes all tunnel server address previously entered with addServer()
- **/
- void cleanServers();
- /**
- * Register a state callback to be notified whenever the tunnel client is connected or disconnected to the tunnel server.
- * @param cb application callback function to use for notifying of connection/disconnection events.
- * @param userdata An opaque pointer passed to the callback, used optionally by the application to retrieve a context.
- **/
- void setCallback(StateCallback cb, void *userdata);
- /**
- * Start connecting to a tunnel server.
- * At this step, nothing is tunneled yet. The enable() method must be used to state whether SIP and RTP traffic
- * need to be tunneled or not.
**/
- void start();
+ void cleanServers();
/**
* Forces 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
@@ -83,22 +71,15 @@ class UdpMirrorClient;
**/
void reconnect();
/**
- * Sets whether tunneling of SIP and RTP is required.
- * @param isEnabled 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.
- *
- **/
- void enable(bool isEnabled);
- /**
- * 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.
- *
Call this method each time to run the auto detection algorithm
+ * @brief setMode
+ * @param mode
*/
- void autoDetect();
+ void setMode(LinphoneTunnelMode mode);
/**
- * Returns a boolean indicating whether tunneled operation is enabled.
- **/
- bool isEnabled();
+ * @brief Return the tunnel mode
+ * @return #LinphoneTunnelMode
+ */
+ LinphoneTunnelMode getMode() const;
/**
* Enables debug logs of the Tunnel subsystem.
**/
@@ -115,24 +96,52 @@ class UdpMirrorClient;
* @param passwd The password.
**/
void setHttpProxyAuthInfo(const char* username,const char* passwd);
- ~TunnelManager();
+ void setHttpProxy(const char *host,int port, const char *username, const char *passwd);
+ /**
+ * Indicate to the tunnel manager whether SIP packets must pass
+ * through the tunnel. That featurte is automatically enabled at
+ * the creation of the TunnelManager instance.
+ * @param enable If set to TRUE, SIP packets will pass through the tunnel.
+ * If set to FALSE, SIP packets will pass by the configured proxies.
+ */
+ void tunnelizeSipPackets(bool enable);
+ /**
+ * @brief Check whether the tunnel manager is set to tunnelize SIP packets
+ * @return True, SIP packets pass through the tunnel
+ */
+ bool tunnelizeSipPacketsEnabled() const;
+ /**
+ * @brief Constructor
+ * @param lc The LinphoneCore instance of which the TunnelManager will be associated to.
+ */
TunnelManager(LinphoneCore* lc);
/**
- * Destroy the given RtpTransport.
+ * @brief Destructor
*/
- void closeRtpTransport(RtpTransport *t, TunnelSocket *s);
-
+ ~TunnelManager();
/**
- * Create an RtpTransport.
+ * @brief Create an RtpTransport
+ * @param port
+ * @return
*/
RtpTransport *createRtpTransport(int port);
-
/**
- * Get associated Linphone Core.
+ * @brief Destroy the given RtpTransport
+ * @param t
+ * @param s
*/
- LinphoneCore *getLinphoneCore();
- virtual void setHttpProxy(const char *host,int port, const char *username, const char *passwd);
- virtual bool isReady() const;
+ void closeRtpTransport(RtpTransport *t, TunnelSocket *s);
+ /**
+ * @brief Get associated Linphone Core
+ * @return pointer on the associated LinphoneCore
+ */
+ LinphoneCore *getLinphoneCore() const;
+ /**
+ * @brief Check wehter the tunnel is connected
+ * @return True whether the tunnel is connected
+ */
+ bool isConnected() const;
+
private:
enum EventType{
UdpMirrorClientEvent,
@@ -146,8 +155,6 @@ class UdpMirrorClient;
}mData;
};
typedef std::list UdpMirrorClientList;
- virtual bool isStarted();
- void onIterate();
static int customSendto(struct _RtpTransport *t, mblk_t *msg , int flags, const struct sockaddr *to, socklen_t tolen);
static int customRecvfrom(struct _RtpTransport *t, mblk_t *msg, int flags, struct sockaddr *from, socklen_t *fromlen);
static int eXosipSendto(int fd,const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen,void* userdata);
@@ -156,35 +163,41 @@ class UdpMirrorClient;
static void tunnelCallback(bool connected, TunnelManager *zis);
static void sOnIterate(TunnelManager *zis);
static void sUdpMirrorClientCallback(bool result, void* data);
+ static void networkReachableCb(LinphoneCore *lc, bool_t reachable);
+
+ private:
+ void onIterate();
+ void registration();
void waitUnRegistration();
void processTunnelEvent(const Event &ev);
void processUdpMirrorEvent(const Event &ev);
void postEvent(const Event &ev);
+ void startClient();
+ void stopClient();
+ void autoDetect();
+
+ private:
LinphoneCore* mCore;
- LCSipTransports mRegularTransport;
#ifndef USE_BELLESIP
TunnelSocket *mSipSocket;
eXosip_transport_hooks_t mExosipTransport;
#endif
- StateCallback mCallback;
- void * mCallbackData;
- bool mEnabled;
+ LinphoneTunnelMode mMode;
std::queue mEvq;
std::list mServerAddrs;
UdpMirrorClientList mUdpMirrorClients;
UdpMirrorClientList::iterator mCurrentUdpMirrorClient;
TunnelClient* mTunnelClient;
- void stopClient();
Mutex mMutex;
- static Mutex sMutex;
- bool mAutoDetectStarted;
- bool mReady;
+ bool mIsConnected;
LinphoneRtpTransportFactories mTransportFactories;
std::string mHttpUserName;
std::string mHttpPasswd;
std::string mHttpProxyHost;
int mHttpProxyPort;
- LinphoneFirewallPolicy mPreviousFirewallPolicy;
+ bool mPreviousRegistrationEnabled;
+ bool mTunnelizeSipPackets;
+ LinphoneCoreVTable *mVTable;
};
/**
diff --git a/coreapi/address.c b/coreapi/address.c
index ec37255c1..250026911 100644
--- a/coreapi/address.c
+++ b/coreapi/address.c
@@ -184,6 +184,7 @@ bool_t linphone_address_weak_equal(const LinphoneAddress *a1, const LinphoneAddr
/**
* Destroys a LinphoneAddress object (actually calls linphone_address_unref()).
+ * @deprecated Use linphone_address_unref() instead
**/
void linphone_address_destroy(LinphoneAddress *u){
sal_address_unref(u);
diff --git a/coreapi/authentication.c b/coreapi/authentication.c
index d763f8902..de7248316 100644
--- a/coreapi/authentication.c
+++ b/coreapi/authentication.c
@@ -21,7 +21,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-
+
#include "linphonecore.h"
#include "private.h"
#include "lpconfig.h"
@@ -143,7 +143,7 @@ void linphone_auth_info_write_config(LpConfig *config, LinphoneAuthInfo *obj, in
char key[50];
sprintf(key,"auth_info_%i",pos);
lp_config_clean_section(config,key);
-
+
if (obj==NULL || lp_config_get_int(config, "sip", "store_auth_info", 1) == 0){
return;
}
@@ -176,12 +176,12 @@ LinphoneAuthInfo *linphone_auth_info_new_from_config_file(LpConfig * config, int
char key[50];
const char *username,*userid,*passwd,*ha1,*realm,*domain;
LinphoneAuthInfo *ret;
-
+
sprintf(key,"auth_info_%i",pos);
if (!lp_config_has_section(config,key)){
return NULL;
}
-
+
username=lp_config_get_string(config,key,"username",NULL);
userid=lp_config_get_string(config,key,"userid",NULL);
passwd=lp_config_get_string(config,key,"passwd",NULL);
@@ -221,7 +221,7 @@ static int realm_match(const char *realm1, const char *realm2){
static const LinphoneAuthInfo *find_auth_info(LinphoneCore *lc, const char *username, const char *realm, const char *domain){
MSList *elem;
const LinphoneAuthInfo *ret=NULL;
-
+
for (elem=lc->auth_info;elem!=NULL;elem=elem->next) {
LinphoneAuthInfo *pinfo = (LinphoneAuthInfo*)elem->data;
if (username && pinfo->username && strcmp(username,pinfo->username)==0) {
@@ -240,7 +240,7 @@ static const LinphoneAuthInfo *find_auth_info(LinphoneCore *lc, const char *user
}
} else if (domain && pinfo->domain && strcmp(domain,pinfo->domain)==0) {
return pinfo;
- } else if (!domain) {
+ } else if (!domain) {
return pinfo;
}
}
@@ -249,7 +249,7 @@ static const LinphoneAuthInfo *find_auth_info(LinphoneCore *lc, const char *user
}
/**
- * Find authentication info matching realm, username, domain criterias.
+ * Find authentication info matching realm, username, domain criteria.
* First of all, (realm,username) pair are searched. If multiple results (which should not happen because realm are supposed to be unique), then domain is added to the search.
* @param lc the LinphoneCore
* @param realm the authentication 'realm' (optional)
@@ -264,7 +264,7 @@ const LinphoneAuthInfo *linphone_core_find_auth_info(LinphoneCore *lc, const cha
if (ai==NULL && domain){
ai=find_auth_info(lc,username,realm,domain);
}
- }
+ }
if (ai == NULL && domain != NULL) {
ai=find_auth_info(lc,username,NULL,domain);
}
@@ -292,8 +292,8 @@ LinphoneAuthInfo * linphone_core_create_auth_info(LinphoneCore *lc, const char *
/**
* Adds authentication information to the LinphoneCore.
- *
- * This information will be used during all SIP transacations that require authentication.
+ *
+ * This information will be used during all SIP transactions that require authentication.
**/
void linphone_core_add_auth_info(LinphoneCore *lc, const LinphoneAuthInfo *info){
LinphoneAuthInfo *ai;
@@ -301,7 +301,7 @@ void linphone_core_add_auth_info(LinphoneCore *lc, const LinphoneAuthInfo *info)
MSList *l;
int restarted_op_count=0;
bool_t updating=FALSE;
-
+
if (info->ha1==NULL && info->passwd==NULL){
ms_error("linphone_core_add_auth_info(): info supplied with empty password or ha1.");
return;
@@ -371,7 +371,6 @@ void linphone_core_remove_auth_info(LinphoneCore *lc, const LinphoneAuthInfo *in
r=(LinphoneAuthInfo*)linphone_core_find_auth_info(lc,info->realm,info->username,info->domain);
if (r){
lc->auth_info=ms_list_remove(lc->auth_info,r);
- /*printf("len=%i newlen=%i\n",len,newlen);*/
linphone_auth_info_destroy(r);
write_auth_infos(lc);
}
@@ -379,6 +378,8 @@ void linphone_core_remove_auth_info(LinphoneCore *lc, const LinphoneAuthInfo *in
/**
* Returns an unmodifiable list of currently entered LinphoneAuthInfo.
+ * @param[in] lc The LinphoneCore object
+ * @return \mslist{LinphoneAuthInfo}
**/
const MSList *linphone_core_get_auth_info_list(const LinphoneCore *lc){
return lc->auth_info;
diff --git a/coreapi/bellesip_sal/sal_impl.c b/coreapi/bellesip_sal/sal_impl.c
index 9693226dd..6c2e84483 100644
--- a/coreapi/bellesip_sal/sal_impl.c
+++ b/coreapi/bellesip_sal/sal_impl.c
@@ -98,12 +98,16 @@ void sal_disable_logs() {
void sal_add_pending_auth(Sal *sal, SalOp *op){
if (ms_list_find(sal->pending_auths,op)==NULL){
sal->pending_auths=ms_list_append(sal->pending_auths,op);
+ op->has_auth_pending=TRUE;
}
}
void sal_remove_pending_auth(Sal *sal, SalOp *op){
- if (ms_list_find(sal->pending_auths,op)){
- sal->pending_auths=ms_list_remove(sal->pending_auths,op);
+ if (op->has_auth_pending){
+ op->has_auth_pending=FALSE;
+ if (ms_list_find(sal->pending_auths,op)){
+ sal->pending_auths=ms_list_remove(sal->pending_auths,op);
+ }
}
}
@@ -137,7 +141,7 @@ void sal_process_authentication(SalOp *op) {
return;
}
- if (belle_sip_provider_add_authorization(op->base.root->prov,new_request,response,from_uri,&auth_list)) {
+ if (belle_sip_provider_add_authorization(op->base.root->prov,new_request,response,from_uri,&auth_list,op->base.realm)) {
if (is_within_dialog) {
sal_op_send_request(op,new_request);
} else {
@@ -432,8 +436,8 @@ Sal * sal_init(){
sal->stack = belle_sip_stack_new(NULL);
sal->user_agent=belle_sip_header_user_agent_new();
-#if defined(PACKAGE_NAME) && defined(LINPHONE_VERSION)
- belle_sip_header_user_agent_add_product(sal->user_agent, PACKAGE_NAME "/" LINPHONE_VERSION);
+#if defined(PACKAGE_NAME) && defined(LIBLINPHONE_VERSION)
+ belle_sip_header_user_agent_add_product(sal->user_agent, PACKAGE_NAME "/" LIBLINPHONE_VERSION);
#endif
sal_append_stack_string_to_user_agent(sal);
belle_sip_object_ref(sal->user_agent);
@@ -530,6 +534,8 @@ void sal_uninit(Sal* sal){
belle_sip_object_unref(sal->prov);
belle_sip_object_unref(sal->stack);
belle_sip_object_unref(sal->listener);
+ if (sal->supported) belle_sip_object_unref(sal->supported);
+ ms_list_free_with_data(sal->supported_tags,ms_free);
if (sal->uuid) ms_free(sal->uuid);
if (sal->root_ca) ms_free(sal->root_ca);
ms_free(sal);
@@ -555,7 +561,7 @@ int sal_add_listen_port(Sal *ctx, SalAddress* 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&random())+1024;
+ 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),
@@ -639,28 +645,42 @@ void sal_set_keepalive_period(Sal *ctx,unsigned int value){
belle_sip_listening_point_set_keep_alive(lp,ctx->keep_alive);
}
}
- return ;
}
int sal_enable_tunnel(Sal *ctx, void *tunnelclient) {
#ifdef TUNNEL_ENABLED
- belle_sip_listening_point_t *lp;
- int result;
-
- sal_unlisten_ports(ctx);
- lp = belle_sip_tunnel_listening_point_new(ctx->stack, tunnelclient);
- if (lp == NULL) return -1;
-
- belle_sip_listening_point_set_keep_alive(lp, ctx->keep_alive);
- result = belle_sip_provider_add_listening_point(ctx->prov, lp);
- set_tls_properties(ctx);
- return result;
+ 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);
+ return 0;
#else
return 0;
#endif
}
void sal_disable_tunnel(Sal *ctx) {
#ifdef TUNNEL_ENABLED
- sal_unlisten_ports(ctx);
+ 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;
+ }
#endif
}
/**
@@ -928,10 +948,79 @@ int sal_create_uuid(Sal*ctx, char *uuid, size_t len){
return 0;
}
+static void make_supported_header(Sal *sal){
+ MSList *it;
+ char *alltags=NULL;
+ size_t buflen=64;
+ size_t written=0;
+
+ if (sal->supported){
+ belle_sip_object_unref(sal->supported);
+ sal->supported=NULL;
+ }
+ for(it=sal->supported_tags;it!=NULL;it=it->next){
+ const char *tag=(const char*)it->data;
+ size_t taglen=strlen(tag);
+ if (alltags==NULL || (written+taglen+1>=buflen)) alltags=ms_realloc(alltags,(buflen=buflen*2));
+ snprintf(alltags+written,buflen-written,it->next ? "%s, " : "%s",tag);
+ }
+ if (alltags){
+ sal->supported=belle_sip_header_create("Supported",alltags);
+ if (sal->supported){
+ belle_sip_object_ref(sal->supported);
+ }
+ ms_free(alltags);
+ }
+}
+
+void sal_set_supported_tags(Sal *ctx, const char* tags){
+ ctx->supported_tags=ms_list_free_with_data(ctx->supported_tags,ms_free);
+ if (tags){
+ char *iter;
+ char *buffer=ms_strdup(tags);
+ char *tag;
+ char *context=NULL;
+ iter=buffer;
+ while((tag=strtok_r(iter,", ",&context))!=NULL){
+ iter=NULL;
+ ctx->supported_tags=ms_list_append(ctx->supported_tags,ms_strdup(tag));
+ }
+ ms_free(buffer);
+ }
+ make_supported_header(ctx);
+}
+
+const char *sal_get_supported_tags(Sal *ctx){
+ if (ctx->supported){
+ return belle_sip_header_get_unparsed_value(ctx->supported);
+ }
+ return NULL;
+}
+
+void sal_add_supported_tag(Sal *ctx, const char* tag){
+ MSList *elem=ms_list_find_custom(ctx->supported_tags,(MSCompareFunc)strcasecmp,tag);
+ if (!elem){
+ 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){
+ MSList *elem=ms_list_find_custom(ctx->supported_tags,(MSCompareFunc)strcasecmp,tag);
+ if (elem){
+ ms_free(elem->data);
+ ctx->supported_tags=ms_list_remove_link(ctx->supported_tags,elem);
+ make_supported_header(ctx);
+ }
+}
+
+
+
belle_sip_response_t* sal_create_response_from_request ( Sal* sal, belle_sip_request_t* req, int code ) {
belle_sip_response_t *resp=belle_sip_response_create_from_request(req,code);
belle_sip_message_add_header(BELLE_SIP_MESSAGE(resp),BELLE_SIP_HEADER(sal->user_agent));
- belle_sip_message_add_header(BELLE_SIP_MESSAGE(resp),sal_make_supported_header(sal));
+ belle_sip_message_add_header(BELLE_SIP_MESSAGE(resp),sal->supported);
return resp;
}
diff --git a/coreapi/bellesip_sal/sal_impl.h b/coreapi/bellesip_sal/sal_impl.h
index a20150de2..07124feb3 100644
--- a/coreapi/bellesip_sal/sal_impl.h
+++ b/coreapi/bellesip_sal/sal_impl.h
@@ -33,12 +33,16 @@ 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 *up; /*user pointer*/
int session_expires;
unsigned int keep_alive;
char *root_ca;
char *uuid;
int refresher_retry_after; /*retry after value for refresher*/
+ MSList *supported_tags;/*list of char * */
+ belle_sip_header_t *supported;
bool_t one_matching_codec;
bool_t use_tcp_tls_keep_alive;
bool_t nat_helper_enabled;
@@ -102,6 +106,7 @@ struct SalOp{
bool_t sdp_offering;
bool_t call_released;
bool_t manual_refresher;
+ bool_t has_auth_pending;
int auth_requests; /*number of auth requested for this op*/
};
@@ -164,8 +169,6 @@ bool_t sal_op_get_body(SalOp *op, belle_sip_message_t *msg, SalBody *salbody);
SalReason sal_reason_to_sip_code(SalReason r);
-belle_sip_header_t * sal_make_supported_header(Sal *sal);
-
void _sal_op_add_custom_headers(SalOp *op, belle_sip_message_t *msg);
#endif /* SAL_IMPL_H_ */
diff --git a/coreapi/bellesip_sal/sal_op_call.c b/coreapi/bellesip_sal/sal_op_call.c
index 26bbdb038..7c9c8026c 100644
--- a/coreapi/bellesip_sal/sal_op_call.c
+++ b/coreapi/bellesip_sal/sal_op_call.c
@@ -185,6 +185,7 @@ static void call_process_response(void *op_base, const belle_sip_response_event_
int code = belle_sip_response_get_status_code(response);
belle_sip_header_content_type_t *header_content_type=NULL;
belle_sip_dialog_t *dialog=belle_sip_response_event_get_dialog(event);
+ const char *method;
if (!client_transaction) {
ms_warning("Discarding stateless response [%i] on op [%p]",code,op);
@@ -193,13 +194,13 @@ static void call_process_response(void *op_base, const belle_sip_response_event_
req=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction));
set_or_update_dialog(op,dialog);
dialog_state=dialog ? belle_sip_dialog_get_state(dialog) : BELLE_SIP_DIALOG_NULL;
-
+ method=belle_sip_request_get_method(req);
ms_message("Op [%p] receiving call response [%i], dialog is [%p] in state [%s]",op,code,dialog,belle_sip_dialog_state_to_string(dialog_state));
switch(dialog_state) {
case BELLE_SIP_DIALOG_NULL:
case BELLE_SIP_DIALOG_EARLY: {
- if (strcmp("INVITE",belle_sip_request_get_method(req))==0 ) {
+ if (strcmp("INVITE",method)==0 ) {
if (op->state == SalOpStateTerminating) {
/*check if CANCEL was sent before*/
if (strcmp("CANCEL",belle_sip_request_get_method(belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(op->pending_client_trans))))!=0) {
@@ -238,28 +239,28 @@ static void call_process_response(void *op_base, const belle_sip_response_event_
case BELLE_SIP_DIALOG_CONFIRMED: {
switch (op->state) {
case SalOpStateEarly:/*invite case*/
- case SalOpStateActive: /*re-invite case*/
- if (code >=200
- && code<300
- && strcmp("INVITE",belle_sip_request_get_method(req))==0) {
- handle_sdp_from_response(op,response);
- ack=belle_sip_dialog_create_ack(op->dialog,belle_sip_dialog_get_local_seq_number(op->dialog));
- if (ack==NULL) {
- ms_error("This call has been already terminated.");
- return ;
+ case SalOpStateActive: /*re-invite, INFO, UPDATE case*/
+ if (strcmp("INVITE",method)==0){
+ if (code >=200 && code<300) {
+ handle_sdp_from_response(op,response);
+ ack=belle_sip_dialog_create_ack(op->dialog,belle_sip_dialog_get_local_seq_number(op->dialog));
+ if (ack==NULL) {
+ ms_error("This call has been already terminated.");
+ return ;
+ }
+ if (op->sdp_answer){
+ set_sdp(BELLE_SIP_MESSAGE(ack),op->sdp_answer);
+ belle_sip_object_unref(op->sdp_answer);
+ op->sdp_answer=NULL;
+ }
+ belle_sip_dialog_send_ack(op->dialog,ack);
+ op->base.root->callbacks.call_accepted(op); /*INVITE*/
+ op->state=SalOpStateActive;
+ }else if (code >= 300){
+ call_set_error(op,response);
}
- if (op->sdp_answer){
- set_sdp(BELLE_SIP_MESSAGE(ack),op->sdp_answer);
- belle_sip_object_unref(op->sdp_answer);
- op->sdp_answer=NULL;
- }
- belle_sip_dialog_send_ack(op->dialog,ack);
- op->base.root->callbacks.call_accepted(op); /*INVITE*/
- op->state=SalOpStateActive;
- } else if (code >= 300 && strcmp("INVITE",belle_sip_request_get_method(req))==0){
- call_set_error(op,response);
- } else if (code == 491
- && strcmp("INFO",belle_sip_request_get_method(req)) == 0
+ }else if (strcmp("INFO",method)==0){
+ if (code == 491
&& (header_content_type = belle_sip_message_get_header_by_type(req,belle_sip_header_content_type_t))
&& strcmp("application",belle_sip_header_content_type_get_type(header_content_type))==0
&& strcmp("media_control+xml",belle_sip_header_content_type_get_subtype(header_content_type))==0) {
@@ -267,8 +268,11 @@ static void call_process_response(void *op_base, const belle_sip_response_event_
belle_sip_source_t *s=sal_create_timer(op->base.root,vfu_retry,sal_op_ref(op), retry_in, "vfu request retry");
ms_message("Rejected vfu request on op [%p], just retry in [%ui] ms",op,retry_in);
belle_sip_object_unref(s);
- }else {
- /*ignoring*/
+ }else {
+ /*ignoring*/
+ }
+ }else if (strcmp("UPDATE",method)==0){
+ op->base.root->callbacks.call_accepted(op); /*INVITE*/
}
break;
case SalOpStateTerminating:
@@ -419,6 +423,7 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t
belle_sip_response_t* resp;
belle_sip_header_t* call_info;
const char *method=belle_sip_request_get_method(req);
+ bool_t is_update=FALSE;
if (strcmp("ACK",method)!=0){ /*ACK does'nt create srv transaction*/
server_transaction = belle_sip_provider_create_server_transaction(op->base.root->prov,belle_sip_request_event_get_request(event));
@@ -490,7 +495,7 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t
} else if (strcmp("UPDATE",method)==0) {
sal_op_reset_descriptions(op);
if (process_sdp_for_invite(op,req)==0)
- op->base.root->callbacks.call_updating(op);
+ op->base.root->callbacks.call_updating(op,TRUE);
} else {
belle_sip_error("Unexpected method [%s] for dialog state BELLE_SIP_DIALOG_EARLY",belle_sip_request_get_method(req));
unsupported_method(server_transaction,req);
@@ -522,11 +527,20 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t
op->base.root->callbacks.call_terminated(op,op->dir==SalOpDirIncoming?sal_op_get_from(op):sal_op_get_to(op));
op->state=SalOpStateTerminating;
/*call end not notified by dialog deletion because transaction can end before dialog*/
- } else if(strcmp("INVITE",method)==0) {
- /*re-invite*/
- sal_op_reset_descriptions(op);
- if (process_sdp_for_invite(op,req)==0)
- op->base.root->callbacks.call_updating(op);
+ } else if(strcmp("INVITE",method)==0 || (is_update=(strcmp("UPDATE",method)==0)) ) {
+ if (is_update && !belle_sip_message_get_body(BELLE_SIP_MESSAGE(req))) {
+ /*session timer case*/
+ /*session expire should be handled. to be done when real session timer (rfc4028) will be implemented*/
+ resp=sal_op_create_response_from_request(op,req,200);
+ belle_sip_server_transaction_send_response(server_transaction,resp);
+ belle_sip_object_unref(op->pending_update_server_trans);
+ op->pending_update_server_trans=NULL;
+ } else {
+ /*re-invite*/
+ sal_op_reset_descriptions(op);
+ if (process_sdp_for_invite(op,req)==0)
+ op->base.root->callbacks.call_updating(op,is_update);
+ }
} else if (strcmp("INFO",method)==0){
if (belle_sip_message_get_body(BELLE_SIP_MESSAGE(req))
&& strstr(belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)),"picture_fast_update")) {
@@ -564,22 +578,6 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t
belle_sip_server_transaction_send_response(server_transaction,sal_op_create_response_from_request(op,req,481));
} else if (strcmp("MESSAGE",method)==0){
sal_process_incoming_message(op,event);
- } else if (strcmp("UPDATE",method)==0) {
-
- /*FIXME jehan: It might be better to silently accept UPDATE which do not modify either the number or the nature of streams*/
-
- /*rfc 3311
- * 5.2 Receiving an UPDATE
- * ...
- * If the UAS cannot change the session parameters without prompting the user, it SHOULD reject
- * the request with a 504 response.
- */
- resp=sal_op_create_response_from_request(op,req,504);
- belle_sip_response_set_reason_phrase(resp,"Cannot change the session parameters without prompting the user");
- /*belle_sip_message_add_header( BELLE_SIP_MESSAGE(resp)
- ,belle_sip_header_create( "Warning", "Cannot change the session parameters without prompting the user"));*/
- belle_sip_server_transaction_send_response(server_transaction,resp);
- return;
}else{
ms_error("unexpected method [%s] for dialog [%p]",belle_sip_request_get_method(req),op->dialog);
unsupported_method(server_transaction,req);
@@ -796,13 +794,15 @@ int sal_call_decline(SalOp *op, SalReason reason, const char *redirection /*opti
return 0;
}
-int sal_call_update(SalOp *op, const char *subject){
-
+int sal_call_update(SalOp *op, const char *subject, bool_t no_user_consent){
belle_sip_request_t *update;
belle_sip_dialog_state_t state=belle_sip_dialog_get_state(op->dialog);
/*check for dialog state*/
if ( state == BELLE_SIP_DIALOG_CONFIRMED) {
- update=belle_sip_dialog_create_request(op->dialog,"INVITE");
+ if (no_user_consent)
+ update=belle_sip_dialog_create_request(op->dialog,"UPDATE");
+ else
+ update=belle_sip_dialog_create_request(op->dialog,"INVITE");
} else if (state == BELLE_SIP_DIALOG_EARLY) {
update=belle_sip_dialog_create_request(op->dialog,"UPDATE");
} else {
diff --git a/coreapi/bellesip_sal/sal_op_impl.c b/coreapi/bellesip_sal/sal_op_impl.c
index 649a4e240..ed18f52d0 100644
--- a/coreapi/bellesip_sal/sal_op_impl.c
+++ b/coreapi/bellesip_sal/sal_op_impl.c
@@ -118,9 +118,7 @@ belle_sip_header_contact_t* sal_op_create_contact(SalOp *op){
return contact_header;
}
-belle_sip_header_t * sal_make_supported_header(Sal *sal){
- return belle_sip_header_create("Supported","replaces, outbound");
-}
+
static void add_initial_route_set(belle_sip_request_t *request, const MSList *list){
const MSList *elem;
@@ -137,7 +135,7 @@ static void add_initial_route_set(belle_sip_request_t *request, const MSList *li
continue;
}
}
-
+
route=belle_sip_header_route_create((belle_sip_header_address_t*)addr);
uri=belle_sip_header_address_get_uri((belle_sip_header_address_t*)route);
belle_sip_uri_set_lr_param(uri,1);
@@ -180,11 +178,11 @@ belle_sip_request_t* sal_op_build_request(SalOp *op,const char* method) {
belle_sip_header_p_preferred_identity_t* p_preferred_identity=belle_sip_header_p_preferred_identity_create(BELLE_SIP_HEADER_ADDRESS(sal_op_get_from_address(op)));
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(p_preferred_identity));
}
-
+
if (elem && strcmp(method,"REGISTER")!=0 && !op->base.root->no_initial_route){
add_initial_route_set(req,elem);
}
-
+
if (strcmp("REGISTER",method)!=0 && op->privacy!=SalPrivacyNone ){
belle_sip_header_privacy_t* privacy_header=belle_sip_header_privacy_new();
if (op->privacy&SalPrivacyCritical)
@@ -201,7 +199,7 @@ belle_sip_request_t* sal_op_build_request(SalOp *op,const char* method) {
belle_sip_header_privacy_add_privacy(privacy_header,sal_privacy_to_string(SalPrivacyUser));
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(privacy_header));
}
- belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),sal_make_supported_header(op->base.root));
+ belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),op->base.root->supported);
return req;
}
@@ -332,7 +330,7 @@ static int _sal_op_send_request_with_contact(SalOp* op, belle_sip_request_t* req
if (!belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_AUTHORIZATION)
&& !belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_PROXY_AUTHORIZATION)) {
/*hmm just in case we already have authentication param in cache*/
- belle_sip_provider_add_authorization(op->base.root->prov,request,NULL,NULL,NULL);
+ belle_sip_provider_add_authorization(op->base.root->prov,request,NULL,NULL,NULL,op->base.realm);
}
result = belle_sip_client_transaction_send_request_to(client_transaction,next_hop_uri/*might be null*/);
@@ -608,7 +606,7 @@ int sal_op_send_and_create_refresher(SalOp* op,belle_sip_request_t* req, int exp
belle_sip_object_unref(op->refresher);
}
if ((op->refresher = belle_sip_client_transaction_create_refresher(op->pending_client_trans))) {
- /*since refresher acquires the transaction, we should remove our context from the transaction, because we won't be notified
+ /*since refresher acquires the transaction, we should remove our context from the transaction, because we won't be notified
* that it is terminated anymore.*/
sal_op_unref(op);/*loose the reference that was given to the transaction when creating it*/
/* Note that the refresher will replace our data with belle_sip_transaction_set_application_data().
@@ -617,6 +615,7 @@ int sal_op_send_and_create_refresher(SalOp* op,belle_sip_request_t* req, int exp
notify the user as a normal transaction*/
belle_sip_refresher_set_listener(op->refresher,listener,op);
belle_sip_refresher_set_retry_after(op->refresher,op->base.root->refresher_retry_after);
+ belle_sip_refresher_set_realm(op->refresher,op->base.realm);
belle_sip_refresher_enable_manual_mode(op->refresher,op->manual_refresher);
return 0;
} else {
diff --git a/coreapi/bellesip_sal/sal_op_presence.c b/coreapi/bellesip_sal/sal_op_presence.c
index e1ab054aa..23db49e6f 100644
--- a/coreapi/bellesip_sal/sal_op_presence.c
+++ b/coreapi/bellesip_sal/sal_op_presence.c
@@ -35,7 +35,7 @@ void sal_add_presence_info(SalOp *op, belle_sip_message_t *notify, SalPresenceMo
belle_sip_message_remove_header(BELLE_SIP_MESSAGE(notify),BELLE_SIP_CONTENT_TYPE);
belle_sip_message_remove_header(BELLE_SIP_MESSAGE(notify),BELLE_SIP_CONTENT_LENGTH);
belle_sip_message_set_body(BELLE_SIP_MESSAGE(notify),NULL,0);
-
+
if (content){
belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify)
,BELLE_SIP_HEADER(belle_sip_header_content_type_create("application","pidf+xml")));
@@ -95,7 +95,7 @@ static void presence_response_event(void *op_base, const belle_sip_response_even
belle_sip_request_t* request=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction));
int code = belle_sip_response_get_status_code(response);
belle_sip_header_expires_t* expires;
-
+
sal_op_set_error_info_from_response(op,response);
if (code>=300) {
@@ -127,6 +127,7 @@ static void presence_response_event(void *op_base, const belle_sip_response_even
if (expires>0){
op->refresher=belle_sip_client_transaction_create_refresher(client_transaction);
belle_sip_refresher_set_listener(op->refresher,presence_refresher_listener,op);
+ belle_sip_refresher_set_realm(op->refresher,op->base.realm);
}
}
break;
@@ -164,7 +165,7 @@ static SalPresenceModel * process_presence_notification(SalOp *op, belle_sip_req
return NULL;
if (belle_sip_header_content_length_get_content_length(content_length) == 0)
return NULL;
-
+
if (body==NULL) return NULL;
op->base.root->callbacks.parse_presence_requested(op,
@@ -181,7 +182,7 @@ static void handle_notify(SalOp *op, belle_sip_request_t *req){
belle_sip_server_transaction_t* server_transaction=op->pending_server_trans;
belle_sip_header_subscription_state_t* subscription_state_header=belle_sip_message_get_header_by_type(req,belle_sip_header_subscription_state_t);
SalSubscribeStatus sub_state;
-
+
if (strcmp("NOTIFY",belle_sip_request_get_method(req))==0) {
SalPresenceModel *presence_model = NULL;
const char* body = belle_sip_message_get_body(BELLE_SIP_MESSAGE(req));
@@ -194,7 +195,7 @@ static void handle_notify(SalOp *op, belle_sip_request_t *req){
presence_model = process_presence_notification(op, req);
if (presence_model != NULL || body==NULL) {
/* Presence notification body parsed successfully. */
-
+
resp = sal_op_create_response_from_request(op, req, 200); /*create first because the op may be destroyed by notify_presence */
op->base.root->callbacks.notify_presence(op, sub_state, presence_model, NULL);
} else if (body){
@@ -214,7 +215,7 @@ static void presence_process_request_event(void *op_base, const belle_sip_reques
belle_sip_header_expires_t* expires = belle_sip_message_get_header_by_type(req,belle_sip_header_expires_t);
belle_sip_response_t* resp;
const char *method=belle_sip_request_get_method(req);
-
+
belle_sip_object_ref(server_transaction);
if (op->pending_server_trans) belle_sip_object_unref(op->pending_server_trans);
op->pending_server_trans=server_transaction;
@@ -256,7 +257,7 @@ static void presence_process_request_event(void *op_base, const belle_sip_reques
}
}
break;
- default:
+ default:
ms_error("unexpected dialog state [%s]",belle_sip_dialog_state_to_string(dialog_state));
break;
}
diff --git a/coreapi/call_log.c b/coreapi/call_log.c
new file mode 100644
index 000000000..d1e59578f
--- /dev/null
+++ b/coreapi/call_log.c
@@ -0,0 +1,299 @@
+/*
+linphone
+Copyright (C) 2010-2014 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, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#define _XOPEN_SOURCE 700 /*required for strptime of GNU libc*/
+
+#include
+#include "private.h"
+
+
+/*******************************************************************************
+ * Internal functions *
+ ******************************************************************************/
+
+/*prevent a gcc bug with %c*/
+static size_t my_strftime(char *s, size_t max, const char *fmt, const struct tm *tm){
+ return strftime(s, max, fmt, tm);
+}
+
+static time_t string_to_time(const char *date){
+#ifndef WIN32
+ struct tm tmtime={0};
+ strptime(date,"%c",&tmtime);
+ return mktime(&tmtime);
+#else
+ return 0;
+#endif
+}
+
+static void set_call_log_date(LinphoneCallLog *cl, time_t start_time){
+ struct tm loctime;
+#ifdef WIN32
+#if !defined(_WIN32_WCE)
+ loctime=*localtime(&start_time);
+ /*FIXME*/
+#endif /*_WIN32_WCE*/
+#else
+ localtime_r(&start_time,&loctime);
+#endif
+ my_strftime(cl->start_date,sizeof(cl->start_date),"%c",&loctime);
+}
+
+/*******************************************************************************
+ * Private functions *
+ ******************************************************************************/
+
+void call_logs_write_to_config_file(LinphoneCore *lc){
+ MSList *elem;
+ char logsection[32];
+ int i;
+ char *tmp;
+ LpConfig *cfg=lc->config;
+
+ if (linphone_core_get_global_state (lc)==LinphoneGlobalStartup) return;
+
+ for(i=0,elem=lc->call_logs;elem!=NULL;elem=elem->next,++i){
+ LinphoneCallLog *cl=(LinphoneCallLog*)elem->data;
+ snprintf(logsection,sizeof(logsection),"call_log_%i",i);
+ lp_config_clean_section(cfg,logsection);
+ lp_config_set_int(cfg,logsection,"dir",cl->dir);
+ lp_config_set_int(cfg,logsection,"status",cl->status);
+ tmp=linphone_address_as_string(cl->from);
+ lp_config_set_string(cfg,logsection,"from",tmp);
+ ms_free(tmp);
+ tmp=linphone_address_as_string(cl->to);
+ lp_config_set_string(cfg,logsection,"to",tmp);
+ ms_free(tmp);
+ if (cl->start_date_time)
+ lp_config_set_int64(cfg,logsection,"start_date_time",(int64_t)cl->start_date_time);
+ else lp_config_set_string(cfg,logsection,"start_date",cl->start_date);
+ lp_config_set_int(cfg,logsection,"duration",cl->duration);
+ if (cl->refkey) lp_config_set_string(cfg,logsection,"refkey",cl->refkey);
+ lp_config_set_float(cfg,logsection,"quality",cl->quality);
+ lp_config_set_int(cfg,logsection,"video_enabled", cl->video_enabled);
+ lp_config_set_string(cfg,logsection,"call_id",cl->call_id);
+ }
+ for(;imax_call_logs;++i){
+ snprintf(logsection,sizeof(logsection),"call_log_%i",i);
+ lp_config_clean_section(cfg,logsection);
+ }
+}
+
+void call_logs_read_from_config_file(LinphoneCore *lc){
+ char logsection[32];
+ int i;
+ const char *tmp;
+ uint64_t sec;
+ LpConfig *cfg=lc->config;
+ for(i=0;;++i){
+ snprintf(logsection,sizeof(logsection),"call_log_%i",i);
+ if (lp_config_has_section(cfg,logsection)){
+ LinphoneCallLog *cl;
+ LinphoneAddress *from=NULL,*to=NULL;
+ tmp=lp_config_get_string(cfg,logsection,"from",NULL);
+ if (tmp) from=linphone_address_new(tmp);
+ tmp=lp_config_get_string(cfg,logsection,"to",NULL);
+ if (tmp) to=linphone_address_new(tmp);
+ if (!from || !to)
+ continue;
+ cl=linphone_call_log_new(lp_config_get_int(cfg,logsection,"dir",0),from,to);
+ cl->status=lp_config_get_int(cfg,logsection,"status",0);
+ sec=lp_config_get_int64(cfg,logsection,"start_date_time",0);
+ if (sec) {
+ /*new call log format with date expressed in seconds */
+ cl->start_date_time=(time_t)sec;
+ set_call_log_date(cl,cl->start_date_time);
+ }else{
+ tmp=lp_config_get_string(cfg,logsection,"start_date",NULL);
+ if (tmp) {
+ strncpy(cl->start_date,tmp,sizeof(cl->start_date));
+ cl->start_date_time=string_to_time(cl->start_date);
+ }
+ }
+ cl->duration=lp_config_get_int(cfg,logsection,"duration",0);
+ tmp=lp_config_get_string(cfg,logsection,"refkey",NULL);
+ if (tmp) cl->refkey=ms_strdup(tmp);
+ cl->quality=lp_config_get_float(cfg,logsection,"quality",-1);
+ cl->video_enabled=lp_config_get_int(cfg,logsection,"video_enabled",0);
+ tmp=lp_config_get_string(cfg,logsection,"call_id",NULL);
+ if (tmp) cl->call_id=ms_strdup(tmp);
+ lc->call_logs=ms_list_append(lc->call_logs,cl);
+ }else break;
+ }
+}
+
+
+/*******************************************************************************
+ * Public functions *
+ ******************************************************************************/
+
+const char *linphone_call_log_get_call_id(const LinphoneCallLog *cl){
+ return cl->call_id;
+}
+
+LinphoneCallDir linphone_call_log_get_dir(LinphoneCallLog *cl){
+ return cl->dir;
+}
+
+int linphone_call_log_get_duration(LinphoneCallLog *cl){
+ return cl->duration;
+}
+
+LinphoneAddress *linphone_call_log_get_from_address(LinphoneCallLog *cl){
+ return cl->from;
+}
+
+const rtp_stats_t *linphone_call_log_get_local_stats(const LinphoneCallLog *cl){
+ return &cl->local_stats;
+}
+
+float linphone_call_log_get_quality(LinphoneCallLog *cl){
+ return cl->quality;
+}
+
+const char *linphone_call_log_get_ref_key(const LinphoneCallLog *cl){
+ return cl->refkey;
+}
+
+LinphoneAddress *linphone_call_log_get_remote_address(LinphoneCallLog *cl){
+ return (cl->dir == LinphoneCallIncoming) ? cl->from : cl->to;
+}
+
+const rtp_stats_t *linphone_call_log_get_remote_stats(const LinphoneCallLog *cl){
+ return &cl->remote_stats;
+}
+
+time_t linphone_call_log_get_start_date(LinphoneCallLog *cl){
+ return cl->start_date_time;
+}
+
+LinphoneCallStatus linphone_call_log_get_status(LinphoneCallLog *cl){
+ return cl->status;
+}
+
+LinphoneAddress *linphone_call_log_get_to_address(LinphoneCallLog *cl){
+ return cl->to;
+}
+
+void linphone_call_log_set_ref_key(LinphoneCallLog *cl, const char *refkey){
+ if (cl->refkey!=NULL){
+ ms_free(cl->refkey);
+ cl->refkey=NULL;
+ }
+ if (refkey) cl->refkey=ms_strdup(refkey);
+}
+
+char * linphone_call_log_to_str(LinphoneCallLog *cl){
+ char *status;
+ char *tmp;
+ char *from=linphone_address_as_string (cl->from);
+ char *to=linphone_address_as_string (cl->to);
+ switch(cl->status){
+ case LinphoneCallAborted:
+ status=_("aborted");
+ break;
+ case LinphoneCallSuccess:
+ status=_("completed");
+ break;
+ case LinphoneCallMissed:
+ status=_("missed");
+ break;
+ default:
+ status="unknown";
+ }
+ tmp=ortp_strdup_printf(_("%s at %s\nFrom: %s\nTo: %s\nStatus: %s\nDuration: %i mn %i sec\n"),
+ (cl->dir==LinphoneCallIncoming) ? _("Incoming call") : _("Outgoing call"),
+ cl->start_date,
+ from,
+ to,
+ status,
+ cl->duration/60,
+ cl->duration%60);
+ ms_free(from);
+ ms_free(to);
+ return tmp;
+}
+
+bool_t linphone_call_log_video_enabled(LinphoneCallLog *cl) {
+ return cl->video_enabled;
+}
+
+
+/*******************************************************************************
+ * Reference and user data handling functions *
+ ******************************************************************************/
+
+void *linphone_call_log_get_user_data(const LinphoneCallLog *cl) {
+ return cl->user_data;
+}
+
+void linphone_call_log_set_user_data(LinphoneCallLog *cl, void *ud) {
+ cl->user_data = ud;
+}
+
+LinphoneCallLog * linphone_call_log_ref(LinphoneCallLog *cl) {
+ belle_sip_object_ref(cl);
+ return cl;
+}
+
+void linphone_call_log_unref(LinphoneCallLog *cl) {
+ belle_sip_object_unref(cl);
+}
+
+/*******************************************************************************
+ * Constructor and destructor functions *
+ ******************************************************************************/
+
+static void _linphone_call_log_destroy(LinphoneCallLog *cl){
+ if (cl->from!=NULL) linphone_address_destroy(cl->from);
+ if (cl->to!=NULL) linphone_address_destroy(cl->to);
+ if (cl->refkey!=NULL) ms_free(cl->refkey);
+ if (cl->call_id) ms_free(cl->call_id);
+ if (cl->reporting.reports[LINPHONE_CALL_STATS_AUDIO]!=NULL) linphone_reporting_destroy(cl->reporting.reports[LINPHONE_CALL_STATS_AUDIO]);
+ if (cl->reporting.reports[LINPHONE_CALL_STATS_VIDEO]!=NULL) linphone_reporting_destroy(cl->reporting.reports[LINPHONE_CALL_STATS_VIDEO]);
+}
+
+LinphoneCallLog * linphone_call_log_new(LinphoneCallDir dir, LinphoneAddress *from, LinphoneAddress *to){
+ LinphoneCallLog *cl=belle_sip_object_new(LinphoneCallLog);
+ cl->dir=dir;
+ cl->start_date_time=time(NULL);
+ set_call_log_date(cl,cl->start_date_time);
+ cl->from=from;
+ cl->to=to;
+ cl->status=LinphoneCallAborted; /*default status*/
+ cl->quality=-1;
+
+ cl->reporting.reports[LINPHONE_CALL_STATS_AUDIO]=linphone_reporting_new();
+ cl->reporting.reports[LINPHONE_CALL_STATS_VIDEO]=linphone_reporting_new();
+ return cl;
+}
+
+/* DEPRECATED */
+void linphone_call_log_destroy(LinphoneCallLog *cl) {
+ belle_sip_object_unref(cl);
+}
+
+BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneCallLog);
+
+BELLE_SIP_INSTANCIATE_VPTR(LinphoneCallLog, belle_sip_object_t,
+ (belle_sip_object_destroy_t)_linphone_call_log_destroy,
+ NULL, // clone
+ NULL, // marshal
+ FALSE
+);
diff --git a/coreapi/call_log.h b/coreapi/call_log.h
new file mode 100644
index 000000000..d274037d2
--- /dev/null
+++ b/coreapi/call_log.h
@@ -0,0 +1,244 @@
+/*
+linphone
+Copyright (C) 2010-2014 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, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef __LINPHONE_CALL_LOG_H__
+#define __LINPHONE_CALL_LOG_H__
+
+/**
+ * @addtogroup call_logs
+ * @{
+**/
+
+
+/*******************************************************************************
+ * Structures and enums *
+ ******************************************************************************/
+
+/**
+ * Enum representing the direction of a call.
+**/
+enum _LinphoneCallDir {
+ LinphoneCallOutgoing, /**< outgoing calls*/
+ LinphoneCallIncoming /**< incoming calls*/
+};
+
+/**
+ * Typedef for enum
+**/
+typedef enum _LinphoneCallDir LinphoneCallDir;
+
+/**
+ * Enum representing the status of a call
+**/
+typedef enum _LinphoneCallStatus {
+ LinphoneCallSuccess, /**< The call was sucessful */
+ LinphoneCallAborted, /**< The call was aborted */
+ LinphoneCallMissed, /**< The call was missed (unanswered) */
+ LinphoneCallDeclined /**< The call was declined, either locally or by remote end */
+} LinphoneCallStatus;
+
+/**
+ * Structure representing a call log.
+**/
+typedef struct _LinphoneCallLog LinphoneCallLog;
+
+
+/*******************************************************************************
+ * Public functions *
+ ******************************************************************************/
+
+/**
+ * Get the call ID used by the call.
+ * @param[in] cl LinphoneCallLog object
+ * @return The call ID used by the call as a string.
+**/
+LINPHONE_PUBLIC const char * linphone_call_log_get_call_id(const LinphoneCallLog *cl);
+
+/**
+ * Get the direction of the call.
+ * @param[in] cl LinphoneCallLog object
+ * @return The direction of the call.
+**/
+LINPHONE_PUBLIC LinphoneCallDir linphone_call_log_get_dir(LinphoneCallLog *cl);
+
+/**
+ * Get the duration of the call.
+ * @param[in] cl LinphoneCallLog object
+ * @return The duration of the call in seconds.
+**/
+LINPHONE_PUBLIC int linphone_call_log_get_duration(LinphoneCallLog *cl);
+
+/**
+ * Get the origin address (ie from) of the call.
+ * @param[in] cl LinphoneCallLog object
+ * @return The origin address (ie from) of the call.
+**/
+LINPHONE_PUBLIC LinphoneAddress * linphone_call_log_get_from_address(LinphoneCallLog *cl);
+
+/**
+ * Get the RTP statistics computed locally regarding the call.
+ * @param[in] cl LinphoneCallLog object
+ * @return The RTP statistics that have been computed locally for the call.
+**/
+LINPHONE_PUBLIC const rtp_stats_t * linphone_call_log_get_local_stats(const LinphoneCallLog *cl);
+
+/**
+ * Get the overall quality indication of the call.
+ * @param[in] cl LinphoneCallLog object
+ * @return The overall quality indication of the call.
+**/
+LINPHONE_PUBLIC float linphone_call_log_get_quality(LinphoneCallLog *cl);
+
+/**
+ * Get the persistent reference key associated to the call log.
+ *
+ * The reference key can be for example an id to an external database.
+ * It is stored in the config file, thus can survive to process exits/restarts.
+ *
+ * @param[in] cl LinphoneCallLog object
+ * @return The reference key string that has been associated to the call log, or NULL if none has been associated.
+**/
+LINPHONE_PUBLIC const char * linphone_call_log_get_ref_key(const LinphoneCallLog *cl);
+
+/**
+ * Get the remote address (that is from or to depending on call direction).
+ * @param[in] cl LinphoneCallLog object
+ * @return The remote address of the call.
+**/
+LINPHONE_PUBLIC LinphoneAddress * linphone_call_log_get_remote_address(LinphoneCallLog *cl);
+
+/**
+ * Get the RTP statistics computed by the remote end and sent back via RTCP.
+ * @note Not implemented yet.
+ * @param[in] cl LinphoneCallLog object
+ * @return The RTP statistics that have been computed by the remote end for the call.
+**/
+LINPHONE_PUBLIC const rtp_stats_t * linphone_call_log_get_remote_stats(const LinphoneCallLog *cl);
+
+/**
+ * Get the start date of the call.
+ * @param[in] cl LinphoneCallLog object
+ * @return The date of the beginning of the call.
+**/
+LINPHONE_PUBLIC time_t linphone_call_log_get_start_date(LinphoneCallLog *cl);
+
+/**
+ * Get the status of the call.
+ * @param[in] cl LinphoneCallLog object
+ * @return The status of the call.
+**/
+LINPHONE_PUBLIC LinphoneCallStatus linphone_call_log_get_status(LinphoneCallLog *cl);
+
+/**
+ * Get the destination address (ie to) of the call.
+ * @param[in] cl LinphoneCallLog object
+ * @return The destination address (ie to) of the call.
+**/
+LINPHONE_PUBLIC LinphoneAddress * linphone_call_log_get_to_address(LinphoneCallLog *cl);
+
+/**
+ * Associate a persistent reference key to the call log.
+ *
+ * The reference key can be for example an id to an external database.
+ * It is stored in the config file, thus can survive to process exits/restarts.
+ *
+ * @param[in] cl LinphoneCallLog object
+ * @param[in] refkey The reference key string to associate to the call log.
+**/
+LINPHONE_PUBLIC void linphone_call_log_set_ref_key(LinphoneCallLog *cl, const char *refkey);
+
+/**
+ * Tell whether video was enabled at the end of the call or not.
+ * @param[in] cl LinphoneCallLog object
+ * @return A boolean value telling whether video was enabled at the end of the call.
+**/
+LINPHONE_PUBLIC bool_t linphone_call_log_video_enabled(LinphoneCallLog *cl);
+
+/**
+ * Get a human readable string describing the call.
+ * @note: the returned string must be freed by the application (use ms_free()).
+ * @param[in] cl LinphoneCallLog object
+ * @return A human readable string describing the call.
+**/
+LINPHONE_PUBLIC char * linphone_call_log_to_str(LinphoneCallLog *cl);
+
+
+/*******************************************************************************
+ * Reference and user data handling functions *
+ ******************************************************************************/
+
+/**
+ * Get the user data associated with the call log.
+ * @param[in] cl LinphoneCallLog object
+ * @return The user data associated with the call log.
+**/
+LINPHONE_PUBLIC void *linphone_call_log_get_user_data(const LinphoneCallLog *cl);
+
+/**
+ * Assign a user data to the call log.
+ * @param[in] cl LinphoneCallLog object
+ * @param[in] ud The user data to associate with the call log.
+**/
+LINPHONE_PUBLIC void linphone_call_log_set_user_data(LinphoneCallLog *cl, void *ud);
+
+/**
+ * Acquire a reference to the call log.
+ * @param[in] cl LinphoneCallLog object
+ * @return The same LinphoneCallLog object
+**/
+LINPHONE_PUBLIC LinphoneCallLog * linphone_call_log_ref(LinphoneCallLog *cl);
+
+/**
+ * Release a reference to the call log.
+ * @param[in] cl LinphoneCallLog object
+**/
+LINPHONE_PUBLIC void linphone_call_log_unref(LinphoneCallLog *cl);
+
+
+/*******************************************************************************
+ * DEPRECATED *
+ ******************************************************************************/
+
+/** @deprecated Use linphone_call_log_get_from_address() instead. */
+#define linphone_call_log_get_from(cl) linphone_call_log_get_from_address(cl)
+
+/** @deprecated Use linphone_call_log_get_to_address() instead. */
+#define linphone_call_log_get_to(cl) linphone_call_log_get_to_address(cl)
+
+/** @deprecated Use linphone_call_log_set_user_data() instead. */
+#define linphone_call_log_set_user_pointer(cl, ud) linphone_call_log_set_user_data(cl, ud)
+
+/** @deprecated Use linphone_call_log_get_user_data() instead. */
+#define linphone_call_log_get_user_pointer(cl) linphone_call_log_get_user_data(cl)
+
+/**
+ * Destroy a LinphoneCallLog.
+ * @param cl LinphoneCallLog object
+ * @deprecated Use linphone_call_log_unref() instead.
+ */
+LINPHONE_PUBLIC void linphone_call_log_destroy(LinphoneCallLog *cl);
+
+
+/**
+ * @}
+**/
+
+
+#endif /* __LINPHONE_CALL_LOG_H__ */
diff --git a/coreapi/call_params.c b/coreapi/call_params.c
new file mode 100644
index 000000000..a48066169
--- /dev/null
+++ b/coreapi/call_params.c
@@ -0,0 +1,207 @@
+/*
+linphone
+Copyright (C) 2010-2014 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, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "private.h"
+
+
+/*******************************************************************************
+ * Internal functions *
+ ******************************************************************************/
+
+SalMediaProto get_proto_from_call_params(const LinphoneCallParams *params) {
+ if ((params->media_encryption == LinphoneMediaEncryptionSRTP) && params->avpf_enabled) return SalProtoRtpSavpf;
+ if (params->media_encryption == LinphoneMediaEncryptionSRTP) return SalProtoRtpSavp;
+ if (params->avpf_enabled) return SalProtoRtpAvpf;
+ return SalProtoRtpAvp;
+}
+
+
+/*******************************************************************************
+ * Public functions *
+ ******************************************************************************/
+
+void linphone_call_params_add_custom_header(LinphoneCallParams *params, const char *header_name, const char *header_value){
+ params->custom_headers=sal_custom_header_append(params->custom_headers,header_name,header_value);
+}
+
+LinphoneCallParams * linphone_call_params_copy(const LinphoneCallParams *cp){
+ LinphoneCallParams *ncp=linphone_call_params_new();
+ memcpy(ncp,cp,sizeof(LinphoneCallParams));
+ if (cp->record_file) ncp->record_file=ms_strdup(cp->record_file);
+ if (cp->session_name) ncp->session_name=ms_strdup(cp->session_name);
+ /*
+ * The management of the custom headers is not optimal. We copy everything while ref counting would be more efficient.
+ */
+ if (cp->custom_headers) ncp->custom_headers=sal_custom_header_clone(cp->custom_headers);
+ return ncp;
+}
+
+bool_t linphone_call_params_early_media_sending_enabled(const LinphoneCallParams *cp){
+ return cp->real_early_media;
+}
+
+void linphone_call_params_enable_early_media_sending(LinphoneCallParams *cp, bool_t enabled){
+ cp->real_early_media=enabled;
+}
+
+void linphone_call_params_enable_low_bandwidth(LinphoneCallParams *cp, bool_t enabled){
+ cp->low_bandwidth=enabled;
+}
+
+void linphone_call_params_enable_video(LinphoneCallParams *cp, bool_t enabled){
+ cp->has_video=enabled;
+}
+
+const char *linphone_call_params_get_custom_header(const LinphoneCallParams *params, const char *header_name){
+ return sal_custom_header_find(params->custom_headers,header_name);
+}
+
+bool_t linphone_call_params_get_local_conference_mode(const LinphoneCallParams *cp){
+ return cp->in_conference;
+}
+
+LinphoneMediaEncryption linphone_call_params_get_media_encryption(const LinphoneCallParams *cp) {
+ return cp->media_encryption;
+}
+
+LinphonePrivacyMask linphone_call_params_get_privacy(const LinphoneCallParams *params) {
+ return params->privacy;
+}
+
+float linphone_call_params_get_received_framerate(const LinphoneCallParams *cp){
+ return cp->received_fps;
+}
+
+MSVideoSize linphone_call_params_get_received_video_size(const LinphoneCallParams *cp) {
+ return cp->recv_vsize;
+}
+
+const char *linphone_call_params_get_record_file(const LinphoneCallParams *cp){
+ return cp->record_file;
+}
+
+const char * linphone_call_params_get_rtp_profile(const LinphoneCallParams *cp) {
+ return sal_media_proto_to_string(get_proto_from_call_params(cp));
+}
+
+float linphone_call_params_get_sent_framerate(const LinphoneCallParams *cp){
+ return cp->sent_fps;
+}
+
+MSVideoSize linphone_call_params_get_sent_video_size(const LinphoneCallParams *cp) {
+ return cp->sent_vsize;
+}
+
+const char *linphone_call_params_get_session_name(const LinphoneCallParams *cp){
+ return cp->session_name;
+}
+
+const LinphonePayloadType* linphone_call_params_get_used_audio_codec(const LinphoneCallParams *cp) {
+ return cp->audio_codec;
+}
+
+const LinphonePayloadType* linphone_call_params_get_used_video_codec(const LinphoneCallParams *cp) {
+ return cp->video_codec;
+}
+
+bool_t linphone_call_params_low_bandwidth_enabled(const LinphoneCallParams *cp) {
+ return cp->low_bandwidth;
+}
+
+void linphone_call_params_set_audio_bandwidth_limit(LinphoneCallParams *cp, int bandwidth){
+ cp->audio_bw=bandwidth;
+}
+
+void linphone_call_params_set_media_encryption(LinphoneCallParams *cp, LinphoneMediaEncryption e) {
+ cp->media_encryption = e;
+}
+
+void linphone_call_params_set_privacy(LinphoneCallParams *params, LinphonePrivacyMask privacy) {
+ params->privacy=privacy;
+}
+
+void linphone_call_params_set_record_file(LinphoneCallParams *cp, const char *path){
+ if (cp->record_file){
+ ms_free(cp->record_file);
+ cp->record_file=NULL;
+ }
+ if (path) cp->record_file=ms_strdup(path);
+}
+
+void linphone_call_params_set_session_name(LinphoneCallParams *cp, const char *name){
+ if (cp->session_name){
+ ms_free(cp->session_name);
+ cp->session_name=NULL;
+ }
+ if (name) cp->session_name=ms_strdup(name);
+}
+
+bool_t linphone_call_params_video_enabled(const LinphoneCallParams *cp){
+ return cp->has_video;
+}
+
+
+
+/*******************************************************************************
+ * Reference and user data handling functions *
+ ******************************************************************************/
+
+void *linphone_call_params_get_user_data(const LinphoneCallParams *cp) {
+ return cp->user_data;
+}
+
+void linphone_call_params_set_user_data(LinphoneCallParams *cp, void *ud) {
+ cp->user_data = ud;
+}
+
+LinphoneCallParams * linphone_call_params_ref(LinphoneCallParams *cp) {
+ belle_sip_object_ref(cp);
+ return cp;
+}
+
+void linphone_call_params_unref(LinphoneCallParams *cp) {
+ belle_sip_object_unref(cp);
+}
+
+/*******************************************************************************
+ * Constructor and destructor functions *
+ ******************************************************************************/
+
+static void _linphone_call_params_destroy(LinphoneCallParams *cp){
+ if (cp->record_file) ms_free(cp->record_file);
+ if (cp->custom_headers) sal_custom_header_free(cp->custom_headers);
+}
+
+LinphoneCallParams * linphone_call_params_new(void) {
+ return belle_sip_object_new(LinphoneCallParams);
+}
+
+/* DEPRECATED */
+void linphone_call_params_destroy(LinphoneCallParams *cp) {
+ linphone_call_params_unref(cp);
+}
+
+BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneCallParams);
+
+BELLE_SIP_INSTANCIATE_VPTR(LinphoneCallParams, belle_sip_object_t,
+ (belle_sip_object_destroy_t)_linphone_call_params_destroy,
+ NULL, // clone
+ NULL, // marshal
+ FALSE
+);
diff --git a/coreapi/call_params.h b/coreapi/call_params.h
new file mode 100644
index 000000000..9c942826b
--- /dev/null
+++ b/coreapi/call_params.h
@@ -0,0 +1,303 @@
+/*
+linphone
+Copyright (C) 2010-2014 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, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef __LINPHONE_CALL_PARAMS_H__
+#define __LINPHONE_CALL_PARAMS_H__
+
+/**
+ * @addtogroup call_control
+ * @{
+**/
+
+
+/*******************************************************************************
+ * Structures and enums *
+ ******************************************************************************/
+
+/**
+ * Private structure definition for LinphoneCallParams.
+**/
+struct _LinphoneCallParams;
+
+/**
+ * The LinphoneCallParams is an object containing various call related parameters.
+ * It can be used to retrieve parameters from a currently running call or modify
+ * the call's characteristics dynamically.
+**/
+typedef struct _LinphoneCallParams LinphoneCallParams;
+
+
+/*******************************************************************************
+ * Public functions *
+ ******************************************************************************/
+
+/**
+ * Add a custom SIP header in the INVITE for a call.
+ * @param[in] cp The #LinphoneCallParams to add a custom SIP header to.
+ * @param[in] header_name The name of the header to add.
+ * @param[in] header_value The content of the header to add.
+**/
+LINPHONE_PUBLIC void linphone_call_params_add_custom_header(LinphoneCallParams *cp, const char *header_name, const char *header_value);
+
+/**
+ * Copy an existing LinphoneCallParams object to a new LinphoneCallParams object.
+ * @param[in] cp The LinphoneCallParams object to copy.
+ * @return A copy of the LinphoneCallParams object.
+**/
+LINPHONE_PUBLIC LinphoneCallParams * linphone_call_params_copy(const LinphoneCallParams *cp);
+
+/**
+ * Indicate whether sending of early media was enabled.
+ * @param[in] cp LinphoneCallParams object
+ * @return A boolean value telling whether sending of early media was enabled.
+**/
+LINPHONE_PUBLIC bool_t linphone_call_params_early_media_sending_enabled(const LinphoneCallParams *cp);
+
+/**
+ * Enable sending of real early media (during outgoing calls).
+ * @param[in] cp LinphoneCallParams object
+ * @param[in] enabled A boolean value telling whether to enable early media sending or not.
+**/
+LINPHONE_PUBLIC void linphone_call_params_enable_early_media_sending(LinphoneCallParams *cp, bool_t enabled);
+
+/**
+ * Indicate low bandwith mode.
+ * Configuring a call to low bandwidth mode will result in the core to activate several settings for the call in order to ensure that bitrate usage
+ * is lowered to the minimum possible. Typically, ptime (packetization time) will be increased, audio codec's output bitrate will be targetted to 20kbit/s provided
+ * that it is achievable by the codec selected after SDP handshake. Video is automatically disabled.
+ * @param[in] cp LinphoneCallParams object
+ * @param[in] enabled A boolean value telling whether to activate the low bandwidth mode or not.
+**/
+LINPHONE_PUBLIC void linphone_call_params_enable_low_bandwidth(LinphoneCallParams *cp, bool_t enabled);
+
+/**
+ * Enable video stream.
+ * @param[in] cp LinphoneCallParams object
+ * @param[in] enabled A boolean value telling whether to enable video or not.
+**/
+LINPHONE_PUBLIC void linphone_call_params_enable_video(LinphoneCallParams *cp, bool_t enabled);
+
+/**
+ * Get a custom SIP header.
+ * @param[in] cp The #LinphoneCallParams to get the custom SIP header from.
+ * @param[in] header_name The name of the header to get.
+ * @return The content of the header or NULL if not found.
+**/
+LINPHONE_PUBLIC const char *linphone_call_params_get_custom_header(const LinphoneCallParams *cp, const char *header_name);
+
+/**
+ * Tell whether the call is part of the locally managed conference.
+ * @param[in] cp LinphoneCallParams object
+ * @return A boolean value telling whether the call is part of the locally managed conference.
+**/
+LINPHONE_PUBLIC bool_t linphone_call_params_get_local_conference_mode(const LinphoneCallParams *cp);
+
+/**
+ * Get the kind of media encryption selected for the call.
+ * @param[in] cp LinphoneCallParams object
+ * @return The kind of media encryption selected for the call.
+**/
+LINPHONE_PUBLIC LinphoneMediaEncryption linphone_call_params_get_media_encryption(const LinphoneCallParams *cp);
+
+/**
+ * Get requested level of privacy for the call.
+ * @param[in] cp LinphoneCallParams object
+ * @return The privacy mode used for the call.
+**/
+LINPHONE_PUBLIC LinphonePrivacyMask linphone_call_params_get_privacy(const LinphoneCallParams *cp);
+
+/**
+ * Get the framerate of the video that is received.
+ * @param[in] cp LinphoneCallParams object
+ * @return The actual received framerate in frames per seconds, 0 if not available.
+ */
+LINPHONE_PUBLIC float linphone_call_params_get_received_framerate(const LinphoneCallParams *cp);
+
+/**
+ * Get the size of the video that is received.
+ * @param[in] cp LinphoneCallParams object
+ * @return The received video size or MS_VIDEO_SIZE_UNKNOWN if not available.
+ */
+LINPHONE_PUBLIC MSVideoSize linphone_call_params_get_received_video_size(const LinphoneCallParams *cp);
+
+/**
+ * Get the path for the audio recording of the call.
+ * @param[in] cp LinphoneCallParams object
+ * @return The path to the audio recording of the call.
+**/
+LINPHONE_PUBLIC const char *linphone_call_params_get_record_file(const LinphoneCallParams *cp);
+
+/**
+ * Get the RTP profile being used.
+ * @param[in] cp #LinphoneCallParams object
+ * @return The RTP profile.
+ */
+LINPHONE_PUBLIC const char * linphone_call_params_get_rtp_profile(const LinphoneCallParams *cp);
+
+/**
+ * Get the framerate of the video that is sent.
+ * @param[in] cp LinphoneCallParams object
+ * @return The actual sent framerate in frames per seconds, 0 if not available.
+ */
+LINPHONE_PUBLIC float linphone_call_params_get_sent_framerate(const LinphoneCallParams *cp);
+
+/**
+ * Gets the size of the video that is sent.
+ * @param[in] cp LinphoneCalParams object
+ * @return The sent video size or MS_VIDEO_SIZE_UNKNOWN if not available.
+ */
+LINPHONE_PUBLIC MSVideoSize linphone_call_params_get_sent_video_size(const LinphoneCallParams *cp);
+
+/**
+ * Get the session name of the media session (ie in SDP).
+ * Subject from the SIP message can be retrieved using linphone_call_params_get_custom_header() and is different.
+ * @param[in] cp LinphoneCallParams object
+ * @return The session name of the media session.
+**/
+LINPHONE_PUBLIC const char *linphone_call_params_get_session_name(const LinphoneCallParams *cp);
+
+/**
+ * Get the audio codec used in the call, described as a LinphonePayloadType object.
+ * @param[in] cp LinphoneCallParams object
+ * @return The LinphonePayloadType object corresponding to the audio codec being used in the call.
+**/
+LINPHONE_PUBLIC const LinphonePayloadType* linphone_call_params_get_used_audio_codec(const LinphoneCallParams *cp);
+
+/**
+ * Get the video codec used in the call, described as a LinphonePayloadType structure.
+ * @param[in] cp LinphoneCallParams object
+ * @return The LinphonePayloadType object corresponding to the video codec being used in the call.
+**/
+LINPHONE_PUBLIC const LinphonePayloadType* linphone_call_params_get_used_video_codec(const LinphoneCallParams *cp);
+
+/**
+ * Tell whether the call has been configured in low bandwidth mode or not.
+ * This mode can be automatically discovered thanks to a stun server when activate_edge_workarounds=1 in section [net] of configuration file.
+ * An application that would have reliable way to know network capacity may not use activate_edge_workarounds=1 but instead manually configure
+ * low bandwidth mode with linphone_call_params_enable_low_bandwidth().
+ * When enabled, this param may transform a call request with video in audio only mode.
+ * @param[in] cp LinphoneCallParams object
+ * @return A boolean value telling whether the low bandwidth mode has been configured/detected.
+ */
+LINPHONE_PUBLIC bool_t linphone_call_params_low_bandwidth_enabled(const LinphoneCallParams *cp);
+
+/**
+ * Refine bandwidth settings for this call by setting a bandwidth limit for audio streams.
+ * As a consequence, codecs whose bitrates are not compatible with this limit won't be used.
+ * @param[in] cp LinphoneCallParams object
+ * @param[in] bw The audio bandwidth limit to set in kbit/s.
+**/
+LINPHONE_PUBLIC void linphone_call_params_set_audio_bandwidth_limit(LinphoneCallParams *cp, int bw);
+
+/**
+ * Set requested media encryption for a call.
+ * @param[in] cp LinphoneCallParams object
+ * @param[in] enc The media encryption to use for the call.
+**/
+LINPHONE_PUBLIC void linphone_call_params_set_media_encryption(LinphoneCallParams *cp, LinphoneMediaEncryption enc);
+
+/**
+ * Set requested level of privacy for the call.
+ * \xmlonly javascript \endxmlonly
+ * @param[in] cp LinphoneCallParams object
+ * @param[in] privacy The privacy mode to used for the call.
+**/
+LINPHONE_PUBLIC void linphone_call_params_set_privacy(LinphoneCallParams *params, LinphonePrivacyMask privacy);
+
+/**
+ * Enable recording of the call.
+ * This function must be used before the call parameters are assigned to the call.
+ * The call recording can be started and paused after the call is established with
+ * linphone_call_start_recording() and linphone_call_pause_recording().
+ * @param[in] cp LinphoneCallParams object
+ * @param[in] path A string containing the path and filename of the file where audio/video streams are to be written.
+ * The filename must have either .mkv or .wav extention. The video stream will be written only if a MKV file is given.
+**/
+LINPHONE_PUBLIC void linphone_call_params_set_record_file(LinphoneCallParams *cp, const char *path);
+
+/**
+ * Set the session name of the media session (ie in SDP).
+ * Subject from the SIP message (which is different) can be set using linphone_call_params_set_custom_header().
+ * @param[in] cp LinphoneCallParams object
+ * @param[in] name The session name to be used.
+**/
+LINPHONE_PUBLIC void linphone_call_params_set_session_name(LinphoneCallParams *cp, const char *name);
+
+/**
+ * Tell whether video is enabled or not.
+ * @param[in] cp LinphoneCallParams object
+ * @return A boolean value telling whether video is enabled or not.
+**/
+LINPHONE_PUBLIC bool_t linphone_call_params_video_enabled(const LinphoneCallParams *cp);
+
+
+/*******************************************************************************
+ * Reference and user data handling functions *
+ ******************************************************************************/
+
+/**
+ * Get the user data associated with the call params.
+ * @param[in] cl LinphoneCallParams object
+ * @return The user data associated with the call params.
+**/
+LINPHONE_PUBLIC void *linphone_call_params_get_user_data(const LinphoneCallParams *cp);
+
+/**
+ * Assign a user data to the call params.
+ * @param[in] cl LinphoneCallParams object
+ * @param[in] ud The user data to associate with the call params.
+**/
+LINPHONE_PUBLIC void linphone_call_params_set_user_data(LinphoneCallParams *cp, void *ud);
+
+/**
+ * Acquire a reference to the call params.
+ * @param[in] cl LinphoneCallParams object
+ * @return The same LinphoneCallParams object
+**/
+LINPHONE_PUBLIC LinphoneCallParams * linphone_call_params_ref(LinphoneCallParams *cp);
+
+/**
+ * Release a reference to the call params.
+ * @param[in] cl LinphoneCallParams object
+**/
+LINPHONE_PUBLIC void linphone_call_params_unref(LinphoneCallParams *cp);
+
+
+/*******************************************************************************
+ * DEPRECATED *
+ ******************************************************************************/
+
+/** @deprecated Use linphone_call_params_get_local_conference_mode() instead. */
+#define linphone_call_params_local_conference_mode linphone_call_params_get_local_conference_mode
+
+/**
+ * Destroy a LinphoneCallParams object.
+ * @param[in] cp LinphoneCallParams object
+ * @deprecated Use linphone_call_params_unref() instead.
+**/
+LINPHONE_PUBLIC void linphone_call_params_destroy(LinphoneCallParams *cp);
+
+
+/**
+ * @}
+**/
+
+
+#endif /* __LINPHONE_CALL_PARAMS_H__ */
diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c
index c64a5d7e3..ef17b080b 100644
--- a/coreapi/callbacks.c
+++ b/coreapi/callbacks.c
@@ -35,7 +35,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
static void register_failure(SalOp *op);
static int media_parameters_changed(LinphoneCall *call, SalMediaDescription *oldmd, SalMediaDescription *newmd) {
- if (call->params.in_conference != call->current_params.in_conference) return SAL_MEDIA_DESCRIPTION_CHANGED;
+ if (call->params->in_conference != call->current_params->in_conference) return SAL_MEDIA_DESCRIPTION_CHANGED;
if (call->up_bw != linphone_core_get_upload_bandwidth(call->core)) return SAL_MEDIA_DESCRIPTION_CHANGED;
if (call->localdesc_changed) ms_message("Local description has changed: %i", call->localdesc_changed);
return call->localdesc_changed | sal_media_description_equals(oldmd, newmd);
@@ -96,7 +96,7 @@ static void prepare_early_media_forking(LinphoneCall *call){
if (call->videostream){
rtp_session_set_symmetric_rtp(call->videostream->ms.sessions.rtp_session,FALSE);
}
-
+
}
void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMediaDescription *new_md){
@@ -163,7 +163,7 @@ void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMedia
linphone_call_stop_media_streams (call);
linphone_call_init_media_streams (call);
}
-
+
if (call->audiostream==NULL){
/*this happens after pausing the call locally. The streams are destroyed and then we wait the 200Ok to recreate them*/
linphone_call_init_media_streams (call);
@@ -171,10 +171,10 @@ void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMedia
if (call->state==LinphoneCallIncomingEarlyMedia && linphone_core_get_remote_ringback_tone (lc)!=NULL){
send_ringbacktone=TRUE;
}
- if ((call->state==LinphoneCallIncomingEarlyMedia || call->state==LinphoneCallOutgoingEarlyMedia) && !call->params.real_early_media){
+ if ((call->state==LinphoneCallIncomingEarlyMedia || call->state==LinphoneCallOutgoingEarlyMedia) && !call->params->real_early_media){
all_muted=TRUE;
}
- if (call->params.real_early_media && call->state==LinphoneCallOutgoingEarlyMedia){
+ if (call->params->real_early_media && call->state==LinphoneCallOutgoingEarlyMedia){
prepare_early_media_forking(call);
}
linphone_call_start_media_streams(call,all_muted,send_ringbacktone);
@@ -182,9 +182,9 @@ void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMedia
linphone_core_play_named_tone(lc,LinphoneToneCallOnHold);
}
end:
- if (oldmd)
+ if (oldmd)
sal_media_description_unref(oldmd);
-
+
}
#if 0
static bool_t is_duplicate_call(LinphoneCore *lc, const LinphoneAddress *from, const LinphoneAddress *to){
@@ -192,7 +192,7 @@ static bool_t is_duplicate_call(LinphoneCore *lc, const LinphoneAddress *from, c
for(elem=lc->calls;elem!=NULL;elem=elem->next){
LinphoneCall *call=(LinphoneCall*)elem->data;
if (linphone_address_weak_equal(call->log->from,from) &&
- linphone_address_weak_equal(call->log->to, to)){
+ linphone_address_weak_equal(call->log->to, to)){
return TRUE;
}
}
@@ -220,11 +220,11 @@ static bool_t already_a_call_pending(LinphoneCore *lc){
for(elem=lc->calls;elem!=NULL;elem=elem->next){
LinphoneCall *call=(LinphoneCall*)elem->data;
if (call->state==LinphoneCallIncomingReceived
- || call->state==LinphoneCallIncomingEarlyMedia
- || call->state==LinphoneCallOutgoingInit
- || call->state==LinphoneCallOutgoingProgress
- || call->state==LinphoneCallOutgoingEarlyMedia
- || call->state==LinphoneCallOutgoingRinging){
+ || call->state==LinphoneCallIncomingEarlyMedia
+ || call->state==LinphoneCallOutgoingInit
+ || call->state==LinphoneCallOutgoingProgress
+ || call->state==LinphoneCallOutgoingEarlyMedia
+ || call->state==LinphoneCallOutgoingRinging){
return TRUE;
}
}
@@ -239,7 +239,7 @@ static void call_received(SalOp *h){
LinphoneAddress *from_addr, *to_addr;
/*this mode is deprcated because probably useless*/
bool_t prevent_colliding_calls=lp_config_get_int(lc->config,"sip","prevent_colliding_calls",FALSE);
-
+
/* first check if we can answer successfully to this invite */
if (linphone_presence_model_get_basic_status(lc->presence_model) == LinphonePresenceBasicStatusClosed) {
LinphonePresenceActivity *activity = linphone_presence_model_get_activity(lc->presence_model);
@@ -285,14 +285,14 @@ static void call_received(SalOp *h){
linphone_address_destroy(to_addr);
return;
}
-
+
call=linphone_call_new_incoming(lc,from_addr,to_addr,h);
-
+
/* the call is acceptable so we can now add it to our list */
linphone_core_add_call(lc,call);
linphone_call_ref(call); /*prevent the call from being destroyed while we are notifying, if the user declines within the state callback */
- if ((linphone_core_get_firewall_policy(lc) == LinphonePolicyUseIce) && (call->ice_session != NULL)) {
+ if ((_linphone_core_get_firewall_policy(lc) == LinphonePolicyUseIce) && (call->ice_session != NULL)) {
/* Defer ringing until the end of the ICE candidates gathering process. */
ms_message("Defer ringing to gather ICE candidates");
return;
@@ -313,7 +313,7 @@ static void try_early_media_forking(LinphoneCall *call, SalMediaDescription *md)
int i;
SalStreamDescription *ref_stream,*new_stream;
ms_message("Early media response received from another branch, checking if media can be forked to this new destination.");
-
+
for (i=0;inb_streams;++i){
if (!sal_stream_description_active(&cur_md->streams[i])) continue;
ref_stream=&cur_md->streams[i];
@@ -345,15 +345,14 @@ static void call_ringing(SalOp *h){
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(h));
LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(h);
SalMediaDescription *md;
-
- if (call==NULL) return;
-
- /*set privacy*/
- call->current_params.privacy=(LinphonePrivacyMask)sal_op_get_privacy(call->op);
- if (lc->vtable.display_status)
- lc->vtable.display_status(lc,_("Remote ringing."));
-
+ if (call==NULL) return;
+
+ /*set privacy*/
+ call->current_params->privacy=(LinphonePrivacyMask)sal_op_get_privacy(call->op);
+
+ linphone_core_notify_display_status(lc,_("Remote ringing."));
+
md=sal_call_get_final_media_description(h);
if (md==NULL){
linphone_core_stop_dtmf_stream(lc);
@@ -364,11 +363,12 @@ static void call_ringing(SalOp *h){
/*we release sound before playing ringback tone*/
if (call->audiostream)
audio_stream_unprepare_sound(call->audiostream);
- lc->ringstream=ring_start(lc->sound_conf.remote_ring,2000,ringcard);
+ if( lc->sound_conf.remote_ring ){
+ lc->ringstream=ring_start(lc->sound_conf.remote_ring,2000,ringcard);
+ }
}
ms_message("Remote ringing...");
- if (lc->vtable.display_status)
- lc->vtable.display_status(lc,_("Remote ringing..."));
+ linphone_core_notify_display_status(lc,_("Remote ringing..."));
linphone_call_set_state(call,LinphoneCallOutgoingRinging,"Remote ringing");
}else{
/*accept early media */
@@ -377,9 +377,8 @@ static void call_ringing(SalOp *h){
try_early_media_forking(call,md);
return;
}
- if (lc->vtable.show) lc->vtable.show(lc);
- if (lc->vtable.display_status)
- lc->vtable.display_status(lc,_("Early media."));
+ linphone_core_notify_show_interface(lc);
+ linphone_core_notify_display_status(lc,_("Early media."));
linphone_call_set_state(call,LinphoneCallOutgoingEarlyMedia,"Early media");
linphone_core_stop_ringing(lc);
ms_message("Doing early media...");
@@ -396,13 +395,13 @@ static void call_accepted(SalOp *op){
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op);
SalMediaDescription *md;
-
+
if (call==NULL){
ms_warning("No call to accept.");
return ;
}
/*set privacy*/
- call->current_params.privacy=(LinphonePrivacyMask)sal_op_get_privacy(call->op);
+ call->current_params->privacy=(LinphonePrivacyMask)sal_op_get_privacy(call->op);
/* Handle remote ICE attributes if any. */
if (call->ice_session != NULL) {
@@ -416,22 +415,22 @@ static void call_accepted(SalOp *op){
md=sal_call_get_final_media_description(op);
if (md) /*make sure re-invite will not propose video again*/
- call->params.has_video &= linphone_core_media_description_contains_video_stream(md);
-
+ call->params->has_video &= linphone_core_media_description_contains_video_stream(md);
+
if (call->state==LinphoneCallOutgoingProgress ||
- call->state==LinphoneCallOutgoingRinging ||
- call->state==LinphoneCallOutgoingEarlyMedia){
+ call->state==LinphoneCallOutgoingRinging ||
+ call->state==LinphoneCallOutgoingEarlyMedia){
linphone_call_set_state(call,LinphoneCallConnected,"Connected");
if (call->referer) linphone_core_notify_refer_state(lc,call->referer,call);
}
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) ||
- sal_media_description_has_dir(md,SalStreamInactive)){
- if (lc->vtable.display_status){
+ sal_media_description_has_dir(md,SalStreamInactive)){
+ {
char *tmp=linphone_call_get_remote_address_as_string (call);
char *msg=ms_strdup_printf(_("Call with %s is paused."),tmp);
- lc->vtable.display_status(lc,msg);
+ linphone_core_notify_display_status(lc,msg);
ms_free(tmp);
ms_free(msg);
}
@@ -441,10 +440,10 @@ static void call_accepted(SalOp *op){
linphone_core_start_refered_call(lc,call,NULL);
}else if (sal_media_description_has_dir(md,SalStreamRecvOnly)){
/*we are put on hold when the call is initially accepted */
- if (lc->vtable.display_status){
+ {
char *tmp=linphone_call_get_remote_address_as_string (call);
char *msg=ms_strdup_printf(_("Call answered by %s - on hold."),tmp);
- lc->vtable.display_status(lc,msg);
+ linphone_core_notify_display_status(lc,msg);
ms_free(tmp);
ms_free(msg);
}
@@ -453,14 +452,12 @@ static void call_accepted(SalOp *op){
}else{
if (call->state!=LinphoneCallUpdating){
if (call->state==LinphoneCallResuming){
- if (lc->vtable.display_status){
- lc->vtable.display_status(lc,_("Call resumed."));
- }
+ linphone_core_notify_display_status(lc,_("Call resumed."));
}else{
- if (lc->vtable.display_status){
+ {
char *tmp=linphone_call_get_remote_address_as_string (call);
char *msg=ms_strdup_printf(_("Call answered by %s."),tmp);
- lc->vtable.display_status(lc,msg);
+ linphone_core_notify_display_status(lc,msg);
ms_free(tmp);
ms_free(msg);
}
@@ -470,7 +467,7 @@ static void call_accepted(SalOp *op){
/*also reflect the change if the "wished" params, in order to avoid to propose SAVP or video again
* further in the call, for example during pause,resume, conferencing reINVITEs*/
linphone_call_fix_call_parameters(call);
- if (!call->current_params.in_conference)
+ if (!call->current_params->in_conference)
lc->current_call=call;
if (call->prevstate != LinphoneCallIncomingEarlyMedia) /*don't change state in aswer to a SIP UPDATE in early media*/
linphone_call_set_state(call, LinphoneCallStreamsRunning, "Streams running");
@@ -503,81 +500,73 @@ static void call_ack(SalOp *op){
}
}
-static void call_accept_update(LinphoneCore *lc, LinphoneCall *call){
- SalMediaDescription *md;
- SalMediaDescription *rmd=sal_call_get_remote_media_description(call->op);
- if (rmd!=NULL && call->ice_session!=NULL) {
- linphone_core_update_ice_from_remote_media_description(call,rmd);
- linphone_core_update_local_media_description_from_ice(call->localdesc,call->ice_session);
- }
-#ifdef BUILD_UPNP
- if(call->upnp_session != NULL) {
- linphone_core_update_upnp_from_remote_media_description(call, rmd);
- linphone_core_update_local_media_description_from_upnp(call->localdesc,call->upnp_session);
- }
-#endif //BUILD_UPNP
- linphone_call_update_remote_session_id_and_ver(call);
- sal_call_accept(call->op);
- md=sal_call_get_final_media_description(call->op);
- if (md && !sal_media_description_empty(md)){
- linphone_core_update_streams(lc,call,md);
- }
-}
-
static void call_resumed(LinphoneCore *lc, LinphoneCall *call){
/*when we are resumed, increment session id, because sdp is changed (a=recvonly disapears)*/
linphone_call_increment_local_media_description(call);
- call_accept_update(lc,call);
- if(lc->vtable.display_status)
- lc->vtable.display_status(lc,_("We have been resumed."));
- linphone_call_set_state(call,LinphoneCallStreamsRunning,"Connected (streams running)");
+ linphone_core_notify_display_status(lc,_("We have been resumed."));
+ _linphone_core_accept_call_update(lc,call,NULL,LinphoneCallStreamsRunning,"Connected (streams running)");
}
static void call_paused_by_remote(LinphoneCore *lc, LinphoneCall *call){
- /*when we are resumed, increment session id, because sdp is changed (a=recvonly appears)*/
+ /*when we are paused, increment session id, because sdp is changed (a=recvonly appears)*/
linphone_call_increment_local_media_description(call);
- call_accept_update(lc,call);
/* we are being paused */
- if(lc->vtable.display_status)
- lc->vtable.display_status(lc,_("We are paused by other party."));
- linphone_call_set_state (call,LinphoneCallPausedByRemote,"Call paused by remote");
+ linphone_core_notify_display_status(lc,_("We are paused by other party."));
+ _linphone_core_accept_call_update(lc,call,NULL,LinphoneCallPausedByRemote,"Call paused by remote");
+
}
-static void call_updated_by_remote(LinphoneCore *lc, LinphoneCall *call,bool_t notify_application){
+static void call_updated_by_remote(LinphoneCore *lc, LinphoneCall *call, bool_t is_update){
/*first check if media capabilities are compatible*/
- SalMediaDescription* md;
- 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 && (sal_media_description_empty(md) || linphone_core_incompatible_security(lc,md))){
- sal_call_decline(call->op,SalReasonNotAcceptable,NULL);
- return;
+ SalMediaDescription *md;
+ SalMediaDescription *rmd=sal_call_get_remote_media_description(call->op);
+ SalMediaDescription *prev_result_desc=call->resultdesc;
+
+ if (rmd!=NULL){
+ if (call->state!=LinphoneCallPaused){
+ /*in paused state, we must stay in paused state.*/
+ 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 && (sal_media_description_empty(md) || linphone_core_incompatible_security(lc,md))){
+ sal_call_decline(call->op,SalReasonNotAcceptable,NULL);
+ return;
+ }
+ if (is_update && prev_result_desc && md){
+ int diff=sal_media_description_equals(prev_result_desc,md);
+ if (diff & (SAL_MEDIA_DESCRIPTION_CRYPTO_CHANGED|SAL_MEDIA_DESCRIPTION_STREAMS_CHANGED)){
+ ms_warning("Cannot accept this update, it is changing parameters that require user approval");
+ sal_call_decline(call->op,SalReasonNotAcceptable,NULL); /*FIXME should send 504 Cannot change the session parameters without prompting the user"*/
+ return;
+ }
+ }
}
- if (notify_application) {
- if(lc->vtable.display_status)
- lc->vtable.display_status(lc,_("Call is updated by remote."));
+ if (call->state==LinphoneCallStreamsRunning) {
+ /*reINVITE and in-dialogs UPDATE go here*/
+ linphone_core_notify_display_status(lc,_("Call is updated by remote."));
call->defer_update=FALSE;
linphone_call_set_state(call, LinphoneCallUpdatedByRemote,"Call updated by remote");
if (call->defer_update==FALSE){
linphone_core_accept_call_update(lc,call,NULL);
}
- } else { /*SIP UPDATE case*/
- /*can be call from any state*/
- _linphone_core_accept_call_update(lc,call,NULL);
+ if (rmd==NULL)
+ call->expect_media_in_ack=TRUE;
+ } else if (is_update){ /*SIP UPDATE case, can occur in early states*/
+ _linphone_core_accept_call_update(lc,call,NULL,call->state,linphone_call_state_to_string(call->state));
}
}
/* this callback is called when an incoming re-INVITE/ SIP UPDATE modifies the session*/
-static void call_updating(SalOp *op){
+static void call_updating(SalOp *op, bool_t is_update){
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op);
SalMediaDescription *rmd=sal_call_get_remote_media_description(op);
if (rmd==NULL){
- /* case of a reINVITE without SDP */
- call_accept_update(lc,call);
- call->expect_media_in_ack=TRUE;
+ /* case of a reINVITE or UPDATE without SDP */
+ call_updated_by_remote(lc,call,is_update);
return;
}
@@ -585,22 +574,45 @@ static void call_updating(SalOp *op){
case LinphoneCallPausedByRemote:
if (sal_media_description_has_dir(rmd,SalStreamSendRecv) || sal_media_description_has_dir(rmd,SalStreamRecvOnly)){
call_resumed(lc,call);
- }else call_paused_by_remote(lc,call);
+ }else call_updated_by_remote(lc,call,is_update);
break;
/*SIP UPDATE CASE*/
+ case LinphoneCallOutgoingRinging:
case LinphoneCallOutgoingEarlyMedia:
- call_updated_by_remote(lc,call,FALSE);
+ case LinphoneCallIncomingEarlyMedia:
+ if (is_update) call_updated_by_remote(lc,call,is_update);
break;
case LinphoneCallStreamsRunning:
case LinphoneCallConnected:
if (sal_media_description_has_dir(rmd,SalStreamSendOnly) || sal_media_description_has_dir(rmd,SalStreamInactive)){
call_paused_by_remote(lc,call);
}else{
- call_updated_by_remote(lc,call,TRUE);
+ call_updated_by_remote(lc,call,is_update);
}
break;
- default:
- call_accept_update(lc,call);
+ case LinphoneCallPaused:
+ if (sal_media_description_has_dir(rmd,SalStreamSendOnly) || sal_media_description_has_dir(rmd,SalStreamInactive)){
+ call_paused_by_remote(lc,call);
+ }else{
+ call_updated_by_remote(lc,call,is_update);
+ }
+ break;
+ case LinphoneCallUpdating:
+ case LinphoneCallPausing:
+ case LinphoneCallResuming:
+ case LinphoneCallUpdatedByRemote:
+ sal_call_decline(call->op,SalReasonNotImplemented,NULL);
+ /*no break*/
+ case LinphoneCallIdle:
+ case LinphoneCallOutgoingInit:
+ case LinphoneCallEnd:
+ case LinphoneCallIncomingReceived:
+ case LinphoneCallOutgoingProgress:
+ case LinphoneCallRefered:
+ case LinphoneCallError:
+ case LinphoneCallReleased:
+ ms_warning("Receiving reINVITE or UPDATE while in state [%s], should not happen.",linphone_call_state_to_string(call->state));
+ break;
}
}
@@ -609,7 +621,7 @@ static void call_terminated(SalOp *op, const char *from){
LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op);
if (call==NULL) return;
-
+
switch(linphone_call_get_state(call)){
case LinphoneCallEnd:
case LinphoneCallError:
@@ -632,10 +644,8 @@ static void call_terminated(SalOp *op, const char *from){
linphone_core_stop_ringing(lc);
}
linphone_call_stop_media_streams(call);
- if (lc->vtable.show!=NULL)
- lc->vtable.show(lc);
- if (lc->vtable.display_status!=NULL)
- lc->vtable.display_status(lc,_("Call terminated."));
+ linphone_core_notify_show_interface(lc);
+ linphone_core_notify_display_status(lc,_("Call terminated."));
#ifdef BUILD_UPNP
linphone_call_delete_upnp_session(call);
@@ -648,7 +658,7 @@ static int resume_call_after_failed_transfer(LinphoneCall *call){
ms_message("!!!!!!!!!!resume_call_after_failed_transfer");
if (call->was_automatically_paused && call->state==LinphoneCallPausing)
return BELLE_SIP_CONTINUE; /*was still in pausing state*/
-
+
if (call->was_automatically_paused && call->state==LinphoneCallPaused){
if (sal_op_is_idle(call->op)){
linphone_core_resume_call(call->core,call);
@@ -677,25 +687,22 @@ static void call_failure(SalOp *op){
ms_warning("Call faillure reported on already terminated call.");
return ;
}
-
- if (lc->vtable.show) lc->vtable.show(lc);
+
+ linphone_core_notify_show_interface(lc);
switch(ei->reason){
case SalReasonNone:
break;
case SalReasonRequestTimeout:
msg=_("Request timeout.");
- if (lc->vtable.display_status)
- lc->vtable.display_status(lc,msg);
+ linphone_core_notify_display_status(lc,msg);
break;
case SalReasonDeclined:
msg=msg603;
- if (lc->vtable.display_status)
- lc->vtable.display_status(lc,msg603);
+ linphone_core_notify_display_status(lc,msg603);
break;
case SalReasonBusy:
msg=msg486;
- if (lc->vtable.display_status)
- lc->vtable.display_status(lc,msg486);
+ linphone_core_notify_display_status(lc,msg486);
break;
case SalReasonRedirect:
{
@@ -715,23 +722,19 @@ static void call_failure(SalOp *op){
}
}
msg=_("Redirected");
- if (lc->vtable.display_status)
- lc->vtable.display_status(lc,msg);
+ linphone_core_notify_display_status(lc,msg);
}
break;
case SalReasonTemporarilyUnavailable:
msg=msg480;
- if (lc->vtable.display_status)
- lc->vtable.display_status(lc,msg480);
+ linphone_core_notify_display_status(lc,msg480);
break;
case SalReasonNotFound:
- if (lc->vtable.display_status)
- lc->vtable.display_status(lc,msg);
+ linphone_core_notify_display_status(lc,msg);
break;
case SalReasonDoNotDisturb:
msg=msg600;
- if (lc->vtable.display_status)
- lc->vtable.display_status(lc,msg600);
+ linphone_core_notify_display_status(lc,msg600);
break;
case SalReasonUnsupportedContent: /*localdesc->nb_streams; i++) {
if (!sal_stream_description_active(&call->localdesc->streams[i])) continue;
- if (call->params.media_encryption == LinphoneMediaEncryptionSRTP) {
- if (call->params.avpf_enabled == TRUE) {
+ if (call->params->media_encryption == LinphoneMediaEncryptionSRTP) {
+ if (call->params->avpf_enabled == TRUE) {
if (i == 0) ms_message("Retrying call [%p] with SAVP", call);
- call->params.avpf_enabled = FALSE;
+ call->params->avpf_enabled = FALSE;
linphone_core_restart_invite(lc, call);
return;
} else if (!linphone_core_is_media_encryption_mandatory(lc)) {
if (i == 0) ms_message("Retrying call [%p] with AVP", call);
- call->params.media_encryption = LinphoneMediaEncryptionNone;
+ call->params->media_encryption = LinphoneMediaEncryptionNone;
memset(call->localdesc->streams[i].crypto, 0, sizeof(call->localdesc->streams[i].crypto));
linphone_core_restart_invite(lc, call);
return;
}
- } else if (call->params.avpf_enabled == TRUE) {
+ } else if (call->params->avpf_enabled == TRUE) {
if (i == 0) ms_message("Retrying call [%p] with AVP", call);
- call->params.avpf_enabled = FALSE;
+ call->params->avpf_enabled = FALSE;
linphone_core_restart_invite(lc, call);
return;
}
}
}
msg=_("Incompatible media parameters.");
- if (lc->vtable.display_status)
- lc->vtable.display_status(lc,msg);
+ linphone_core_notify_display_status(lc,msg);
break;
case SalReasonRequestPending:
/*restore previous state, the application will decide to resubmit the action if relevant*/
@@ -774,8 +776,7 @@ static void call_failure(SalOp *op){
return;
break;
default:
- if (lc->vtable.display_status)
- lc->vtable.display_status(lc,_("Call failed."));
+ linphone_core_notify_display_status(lc,_("Call failed."));
}
/*some call error are not fatal*/
@@ -796,7 +797,7 @@ static void call_failure(SalOp *op){
#ifdef BUILD_UPNP
linphone_call_delete_upnp_session(call);
#endif //BUILD_UPNP
-
+
if (call->state!=LinphoneCallEnd && call->state!=LinphoneCallError){
if (ei->reason==SalReasonDeclined){
linphone_call_set_state(call,LinphoneCallEnd,"Call declined.");
@@ -805,7 +806,7 @@ static void call_failure(SalOp *op){
}
if (ei->reason!=SalReasonNone) linphone_core_play_call_error_tone(lc,linphone_reason_from_sal(ei->reason));
}
-
+
if (referer){
/*notify referer of the failure*/
linphone_core_notify_refer_state(lc,referer,call);
@@ -827,35 +828,38 @@ static void call_released(SalOp *op){
static void auth_failure(SalOp *op, SalAuthInfo* info) {
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
- LinphoneAuthInfo *ai=(LinphoneAuthInfo*)linphone_core_find_auth_info(lc,info->realm,info->username,info->domain);
- if (ai){
- ms_message("%s/%s/%s authentication fails.",info->realm,info->username,info->domain);
- /*ask again for password if auth info was already supplied but apparently not working*/
- if (lc->vtable.auth_info_requested) {
- lc->vtable.auth_info_requested(lc,info->realm,info->username,info->domain);
+ LinphoneAuthInfo *ai=NULL;
+
+ if( info != NULL ){
+ ai = (LinphoneAuthInfo*)linphone_core_find_auth_info(lc,info->realm,info->username,info->domain);
+
+ if (ai){
+ ms_message("%s/%s/%s authentication fails.",info->realm,info->username,info->domain);
+ /*ask again for password if auth info was already supplied but apparently not working*/
+ linphone_core_notify_auth_info_requested(lc,info->realm,info->username,info->domain);
}
}
-
+
}
static void register_success(SalOp *op, bool_t registered){
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)sal_op_get_user_pointer(op);
char *msg;
-
- if (!cfg || cfg->deletion_date!=0){
- ms_message("Registration success for removed proxy config, ignored");
+
+ if (!cfg){
+ ms_message("Registration success for deleted proxy config, ignored");
return;
}
linphone_proxy_config_set_state(cfg, registered ? LinphoneRegistrationOk : LinphoneRegistrationCleared ,
- registered ? "Registration successful" : "Unregistration done");
- if (lc->vtable.display_status){
+ registered ? "Registration successful" : "Unregistration done");
+ {
if (registered) msg=ms_strdup_printf(_("Registration on %s successful."),sal_op_get_proxy(op));
else msg=ms_strdup_printf(_("Unregistration on %s done."),sal_op_get_proxy(op));
- lc->vtable.display_status(lc,msg);
+ linphone_core_notify_display_status(lc,msg);
ms_free(msg);
}
-
+
}
static void register_failure(SalOp *op){
@@ -868,16 +872,12 @@ static void register_failure(SalOp *op){
ms_warning("Registration failed for unknown proxy config.");
return ;
}
- if (cfg->deletion_date!=0){
- ms_message("Registration failed for removed proxy config, ignored");
- return;
- }
if (details==NULL)
details=_("no response timeout");
-
- if (lc->vtable.display_status) {
+
+ {
char *msg=ortp_strdup_printf(_("Registration on %s failed: %s"),sal_op_get_proxy(op), details);
- lc->vtable.display_status(lc,msg);
+ linphone_core_notify_display_status(lc,msg);
ms_free(msg);
}
@@ -910,8 +910,7 @@ static void vfu_request(SalOp *op){
static void dtmf_received(SalOp *op, char dtmf){
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op);
- if (lc->vtable.dtmf_received != NULL)
- lc->vtable.dtmf_received(lc, call, dtmf);
+ linphone_core_notify_dtmf_received(lc, call, dtmf);
}
static void refer_received(Sal *sal, SalOp *op, const char *referto){
@@ -924,14 +923,14 @@ static void refer_received(Sal *sal, SalOp *op, const char *referto){
call->refer_to=ms_strdup(referto);
call->refer_pending=TRUE;
linphone_call_set_state(call,LinphoneCallRefered,"Refered");
- if (lc->vtable.display_status){
+ {
char *msg=ms_strdup_printf(_("We are transferred to %s"),referto);
- lc->vtable.display_status(lc,msg);
+ linphone_core_notify_display_status(lc,msg);
ms_free(msg);
}
if (call->refer_pending) linphone_core_start_refered_call(lc,call,NULL);
- }else if (lc->vtable.refer_received){
- lc->vtable.refer_received(lc,referto);
+ }else {
+ linphone_core_notify_refer_received(lc,referto);
}
}
@@ -1051,8 +1050,8 @@ static bool_t auth_requested(Sal* sal, SalAuthInfo* sai) {
if (fill_auth_info(lc,sai)) {
return TRUE;
} else {
- if (lc->vtable.auth_info_requested) {
- lc->vtable.auth_info_requested(lc,sai->realm,sai->username,sai->domain);
+ {
+ linphone_core_notify_auth_info_requested(lc,sai->realm,sai->username,sai->domain);
if (fill_auth_info(lc,sai)) {
return TRUE;
}
@@ -1135,9 +1134,9 @@ static void info_received(SalOp *op, const SalBody *body){
static void subscribe_response(SalOp *op, SalSubscribeStatus status){
LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op);
const SalErrorInfo *ei=sal_op_get_error_info(op);
-
+
if (lev==NULL) return;
-
+
if (status==SalSubscribeActive){
linphone_event_set_state(lev,LinphoneSubscriptionActive);
}else if (status==SalSubscribePending){
@@ -1153,15 +1152,15 @@ static void subscribe_response(SalOp *op, SalSubscribeStatus status){
static void notify(SalOp *op, SalSubscribeStatus st, const char *eventname, const SalBody *body){
LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op);
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
- LinphoneContent content;
-
+ LinphoneContent content={0};
+
if (lev==NULL) {
/*out of subscribe notify */
lev=linphone_event_new_with_out_of_dialog_op(lc,op,LinphoneSubscriptionOutgoing,eventname);
}
- if (lc->vtable.notify_received){
+ {
const LinphoneContent *ct=linphone_content_from_sal_body(&content,body);
- if (ct) lc->vtable.notify_received(lc,lev,eventname,ct);
+ if (ct) linphone_core_notify_notify_received(lc,lev,eventname,ct);
}
if (st!=SalSubscribeNone){
linphone_event_set_state(lev,linphone_subscription_state_from_sal(st));
@@ -1171,31 +1170,31 @@ static void notify(SalOp *op, SalSubscribeStatus st, const char *eventname, cons
static void subscribe_received(SalOp *op, const char *eventname, const SalBody *body){
LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op);
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
-
+
if (lev==NULL) {
lev=linphone_event_new_with_op(lc,op,LinphoneSubscriptionIncoming,eventname);
linphone_event_set_state(lev,LinphoneSubscriptionIncomingReceived);
}else{
/*subscribe refresh, unhandled*/
}
-
+
}
static void subscribe_closed(SalOp *op){
LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op);
-
+
linphone_event_set_state(lev,LinphoneSubscriptionTerminated);
}
static void on_publish_response(SalOp* op){
LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op);
const SalErrorInfo *ei=sal_op_get_error_info(op);
-
+
if (lev==NULL) return;
if (ei->reason==SalReasonNone){
if (!lev->terminating)
linphone_event_set_publish_state(lev,LinphonePublishOk);
- else
+ else
linphone_event_set_publish_state(lev,LinphonePublishCleared);
}else{
if (lev->publish_state==LinphonePublishOk){
@@ -1208,9 +1207,9 @@ static void on_publish_response(SalOp* op){
static void on_expire(SalOp *op){
LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op);
-
+
if (lev==NULL) return;
-
+
if (linphone_event_get_publish_state(lev)==LinphonePublishOk){
linphone_event_set_publish_state(lev,LinphonePublishExpiring);
}else if (linphone_event_get_subscription_state(lev)==LinphoneSubscriptionActive){
diff --git a/coreapi/chat.c b/coreapi/chat.c
index 73f4d8da8..582638210 100644
--- a/coreapi/chat.c
+++ b/coreapi/chat.c
@@ -39,22 +39,37 @@
static void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatMessage* msg);
#define MULTIPART_BOUNDARY "---------------------------14737809831466499882746641449"
-#define FILEPART_HEADER_1 "Content-Disposition: form-data; name=\"File\"; filename=\""
-#define FILEPART_HEADER_2 "\"\r\n" \
- "Content-Type: "
-#define FILEPART_HEADER_3 "\r\n\r\n"
const char *multipart_boundary=MULTIPART_BOUNDARY;
-#define FILE_TRANSFER_KEY_SIZE 32
-static size_t linphone_chat_message_compute_filepart_header_size(const char *filename, const char *content_type) {
- return strlen(FILEPART_HEADER_1)+strlen(filename)+strlen(FILEPART_HEADER_2)+strlen(content_type)+strlen(FILEPART_HEADER_3);
-}
-static void process_io_error(void *data, const belle_sip_io_error_event_t *event){
+static void process_io_error_upload(void *data, const belle_sip_io_error_event_t *event){
LinphoneChatMessage* msg=(LinphoneChatMessage *)data;
- msg->cb(msg, LinphoneChatMessageStateNotDelivered, msg->chat_room->lc);
+ ms_error("I/O Error during file upload to %s - msg [%p] chat room[%p]", msg->chat_room->lc->file_transfer_server, msg, msg->chat_room);
+ if (msg->cb) {
+ msg->cb(msg, LinphoneChatMessageStateNotDelivered, msg->chat_room->lc);
+ }
+#define FILE_TRANSFER_KEY_SIZE 32
}
-static void process_auth_requested(void *data, belle_sip_auth_event_t *event){
- printf("We have a auth requested!\n");
+static void process_auth_requested_upload(void *data, belle_sip_auth_event_t *event){
+ LinphoneChatMessage* msg=(LinphoneChatMessage *)data;
+ ms_error("Error during file upload : auth requested to connect %s - msg [%p] chat room[%p]", msg->chat_room->lc->file_transfer_server, msg, msg->chat_room);
+ if (msg->cb) {
+ msg->cb(msg, LinphoneChatMessageStateNotDelivered, msg->chat_room->lc);
+ }
+}
+
+static void process_io_error_download(void *data, const belle_sip_io_error_event_t *event){
+ LinphoneChatMessage* msg=(LinphoneChatMessage *)data;
+ ms_error("I/O Error during file download %s - msg [%p] chat room[%p]", msg->external_body_url, msg, msg->chat_room);
+ if (msg->cb) {
+ msg->cb(msg, LinphoneChatMessageStateFileTransferError, msg->chat_room->lc);
+ }
+}
+static void process_auth_requested_download(void *data, belle_sip_auth_event_t *event){
+ LinphoneChatMessage* msg=(LinphoneChatMessage *)data;
+ ms_error("Error during file download : auth requested to get %s - msg [%p] chat room[%p]", msg->external_body_url, msg, msg->chat_room);
+ if (msg->cb) {
+ msg->cb(msg, LinphoneChatMessageStateFileTransferError, msg->chat_room->lc);
+ }
}
/**
@@ -65,9 +80,7 @@ static void linphone_chat_message_file_transfer_on_progress(belle_sip_body_handl
LinphoneChatMessage* chatMsg=(LinphoneChatMessage *)data;
LinphoneCore *lc = chatMsg->chat_room->lc;
/* call back given by application level */
- if (lc->vtable.file_transfer_progress_indication != NULL) {
- lc->vtable.file_transfer_progress_indication(lc, chatMsg, chatMsg->file_transfer_information, (size_t)(((double)offset/(double)total)*100.0));
- }
+ linphone_core_notify_file_transfer_progress_indication(lc, chatMsg, chatMsg->file_transfer_information, (size_t)(((double)offset/(double)total)*100.0));
return;
}
@@ -86,24 +99,11 @@ static int linphone_chat_message_file_transfer_on_send_body(belle_sip_user_body_
LinphoneChatMessage* chatMsg=(LinphoneChatMessage *)data;
LinphoneCore *lc = chatMsg->chat_room->lc;
char *buf = (char *)buffer;
-
- char *content_type=belle_sip_strdup_printf("%s/%s", chatMsg->file_transfer_information->type, chatMsg->file_transfer_information->subtype);
size_t end_of_file=linphone_chat_message_compute_filepart_header_size(chatMsg->file_transfer_information->name, content_type)+chatMsg->file_transfer_information->size;
- if (offset==0){
- int partlen=linphone_chat_message_compute_filepart_header_size(chatMsg->file_transfer_information->name, content_type);
- memcpy(buf,FILEPART_HEADER_1,strlen(FILEPART_HEADER_1));
- buf += strlen(FILEPART_HEADER_1);
- memcpy(buf,chatMsg->file_transfer_information->name,strlen(chatMsg->file_transfer_information->name));
- buf += strlen(chatMsg->file_transfer_information->name);
- memcpy(buf,FILEPART_HEADER_2,strlen(FILEPART_HEADER_2));
- buf += strlen(FILEPART_HEADER_2);
- memcpy(buf,content_type,strlen(content_type));
- buf += strlen(content_type);
- memcpy(buf,FILEPART_HEADER_3,strlen(FILEPART_HEADER_3));
-
- *size=partlen;
- }else if (offsetfile_transfer_information->size){
+
if (chatMsg->file_transfer_information->key != NULL) { /* if we have a key to cipher the message, use it! */
/* get data from callback to a plainBuffer */
/* if this chunk is not the last one, the lenght must be a multiple of block cipher size(16 bytes)*/
@@ -111,12 +111,12 @@ static int linphone_chat_message_file_transfer_on_send_body(belle_sip_user_body_
*size -=(*size%16);
}
char *plainBuffer = (char *)malloc(*size);
- lc->vtable.file_transfer_send(lc, chatMsg, chatMsg->file_transfer_information, plainBuffer, size);
+ linphone_core_notify_file_transfer_send(lc, chatMsg, chatMsg->file_transfer_information, buf, size);
lime_encryptFile(&(chatMsg->file_transfer_information->cryptoContext), chatMsg->file_transfer_information->key, *size, plainBuffer, (char*)buffer);
free(plainBuffer);
} else {
/* get data from call back directly to the output buffer */
- lc->vtable.file_transfer_send(lc, chatMsg, chatMsg->file_transfer_information, (char*)buffer, size);
+ linphone_core_notify_file_transfer_send(lc, chatMsg, chatMsg->file_transfer_information, buf, size);
}
/* DEBUG DEBUG : THIS SHALL NEVER HAPPEND */
if (*size == 0) {
@@ -129,7 +129,6 @@ static int linphone_chat_message_file_transfer_on_send_body(belle_sip_user_body_
}
}
- belle_sip_free(content_type);
return BELLE_SIP_CONTINUE;
}
@@ -159,18 +158,26 @@ static void linphone_chat_message_process_response_from_post_file(void *data, co
belle_http_request_listener_t *l;
belle_generic_uri_t *uri;
belle_http_request_t *req;
- char *content_type=belle_sip_strdup_printf("%s/%s", msg->file_transfer_information->type, msg->file_transfer_information->subtype);
+ belle_sip_multipart_body_handler_t *bh;
+ char* ua;
+ char *content_type;
+ char *first_part_header;
+ belle_sip_user_body_handler_t *first_part_bh;
- /* create a user body handler to take care of the file */
- size_t body_size = msg->file_transfer_information->size+linphone_chat_message_compute_filepart_header_size(msg->file_transfer_information->name, content_type);
+ /* temporary storage for the Content-disposition header value */
+ first_part_header = belle_sip_strdup_printf("form-data; name=\"File\"; filename=\"%s\"", msg->file_transfer_information->name);
+
+ /* create a user body handler to take care of the file and add the content disposition and content-type headers */
+ first_part_bh=belle_sip_user_body_handler_new(msg->file_transfer_information->size,NULL,NULL,linphone_chat_message_file_transfer_on_send_body,msg);
+ belle_sip_body_handler_add_header((belle_sip_body_handler_t *)first_part_bh, belle_sip_header_create("Content-disposition", first_part_header));
+ belle_sip_free(first_part_header);
+ belle_sip_body_handler_add_header((belle_sip_body_handler_t *)first_part_bh, (belle_sip_header_t *)belle_sip_header_content_type_create(msg->file_transfer_information->type, msg->file_transfer_information->subtype));
- belle_sip_user_body_handler_t *first_part_bh=belle_sip_user_body_handler_new(body_size,NULL,NULL,linphone_chat_message_file_transfer_on_send_body,msg);
/* insert it in a multipart body handler which will manage the boundaries of multipart message */
- belle_sip_multipart_body_handler_t *bh=belle_sip_multipart_body_handler_new(linphone_chat_message_file_transfer_on_progress, msg, (belle_sip_body_handler_t *)first_part_bh);
+ bh=belle_sip_multipart_body_handler_new(linphone_chat_message_file_transfer_on_progress, msg, (belle_sip_body_handler_t *)first_part_bh);
- char* ua = ms_strdup_printf("%s/%s", linphone_core_get_user_agent_name(), linphone_core_get_user_agent_version());
+ ua = ms_strdup_printf("%s/%s", linphone_core_get_user_agent_name(), linphone_core_get_user_agent_version());
- belle_sip_free(content_type);
content_type=belle_sip_strdup_printf("multipart/form-data; boundary=%s",multipart_boundary);
uri=belle_generic_uri_parse(msg->chat_room->lc->file_transfer_server);
@@ -184,13 +191,19 @@ static void linphone_chat_message_process_response_from_post_file(void *data, co
belle_sip_free(content_type);
belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(req),BELLE_SIP_BODY_HANDLER(bh));
cbs.process_response=linphone_chat_message_process_response_from_post_file;
- cbs.process_io_error=process_io_error;
- cbs.process_auth_requested=process_auth_requested;
+ cbs.process_io_error=process_io_error_upload;
+ cbs.process_auth_requested=process_auth_requested_upload;
l=belle_http_request_listener_create_from_callbacks(&cbs,msg);
+ msg->http_request=req; /* update the reference to the http request to be able to cancel it during upload */
belle_http_provider_send_request(msg->chat_room->lc->http_provider,req,l);
}
+
if (code == 200 ) { /* file has been uplaoded correctly, get server reply and send it */
const char *body = belle_sip_message_get_body((belle_sip_message_t *)event->response);
+
+ /* TODO Check that the transfer has not been cancelled, note this shall be removed once the belle sip API will provide a cancel request as we shall never reach this part if the transfer is actually cancelled */
+ if (msg->http_request == NULL) {
+ return;
/* if we have an encryption key for the file, we must insert it into the message */
if (msg->file_transfer_information->key != NULL) {
@@ -230,10 +243,6 @@ static void linphone_chat_message_process_response_from_post_file(void *data, co
} else { /* no encryption key, transfer in plain, just copy the message sent by server */
msg->message = ms_strdup(body);
}
-
- linphone_content_uninit(msg->file_transfer_information);
- ms_free(msg->file_transfer_information);
- msg->file_transfer_information = NULL;
msg->content_type = ms_strdup("application/vnd.gsma.rcs-ft-http+xml");
_linphone_chat_room_send_message(msg->chat_room, msg);
}
@@ -286,44 +295,59 @@ bool_t linphone_core_chat_enabled(const LinphoneCore *lc){
/**
* Returns an list of chat rooms
- * @param lc #LinphoneCore object
- * @return A list of #LinphoneChatRoom
+ * @param[in] lc #LinphoneCore object
+ * @return \mslist{LinphoneChatRoom}
**/
MSList* linphone_core_get_chat_rooms(LinphoneCore *lc) {
return lc->chatrooms;
}
-/**
- * Create a new chat room for messaging from a sip uri like sip:joe@sip.linphone.org
- * @param lc #LinphoneCore object
- * @param to destination address for messages
- * @return #LinphoneChatRoom where messaging can take place.
- */
-LinphoneChatRoom * linphone_core_create_chat_room(LinphoneCore *lc, const char *to){
- LinphoneAddress *parsed_url=NULL;
+static bool_t linphone_chat_room_matches(LinphoneChatRoom *cr, const LinphoneAddress *from){
+ return linphone_address_weak_equal(cr->peer_url,from);
+}
- if ((parsed_url=linphone_core_interpret_url(lc,to))!=NULL){
- LinphoneChatRoom *cr=ms_new0(LinphoneChatRoom,1);
- cr->lc=lc;
- cr->peer=linphone_address_as_string(parsed_url);
- cr->peer_url=parsed_url;
- lc->chatrooms=ms_list_append(lc->chatrooms,(void *)cr);
- return cr;
+static void _linphone_chat_room_destroy(LinphoneChatRoom *obj);
+
+BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneChatRoom);
+
+BELLE_SIP_INSTANCIATE_VPTR(LinphoneChatRoom, belle_sip_object_t,
+ (belle_sip_object_destroy_t)_linphone_chat_room_destroy,
+ NULL, // clone
+ NULL, // marshal
+ FALSE
+);
+
+static LinphoneChatRoom * _linphone_core_create_chat_room(LinphoneCore *lc, LinphoneAddress *addr) {
+ LinphoneChatRoom *cr = belle_sip_object_new(LinphoneChatRoom);
+ cr->lc = lc;
+ cr->peer = linphone_address_as_string(addr);
+ cr->peer_url = addr;
+ lc->chatrooms = ms_list_append(lc->chatrooms, (void *)cr);
+ return cr;
+}
+
+static LinphoneChatRoom * _linphone_core_create_chat_room_from_url(LinphoneCore *lc, const char *to) {
+ LinphoneAddress *parsed_url = NULL;
+ if ((parsed_url = linphone_core_interpret_url(lc, to)) != NULL) {
+ return _linphone_core_create_chat_room(lc, parsed_url);
}
return NULL;
}
-bool_t linphone_chat_room_matches(LinphoneChatRoom *cr, const LinphoneAddress *from){
- return linphone_address_weak_equal(cr->peer_url,from);
+LinphoneChatRoom * _linphone_core_get_chat_room(LinphoneCore *lc, const LinphoneAddress *addr){
+ LinphoneChatRoom *cr=NULL;
+ MSList *elem;
+ for(elem=lc->chatrooms;elem!=NULL;elem=ms_list_next(elem)){
+ cr=(LinphoneChatRoom*)elem->data;
+ if (linphone_chat_room_matches(cr,addr)){
+ break;
+ }
+ cr=NULL;
+ }
+ return cr;
}
-/**
- * Create a new chat room for messaging from a sip uri like sip:joe@sip.linphone.org if not already existing, else return exisiting one
- * @param lc #LinphoneCore object
- * @param to destination address for messages
- * @return #LinphoneChatRoom where messaging can take place.
- */
-LinphoneChatRoom* linphone_core_get_or_create_chat_room(LinphoneCore* lc, const char* to) {
+static LinphoneChatRoom * _linphone_core_get_or_create_chat_room(LinphoneCore* lc, const char* to) {
LinphoneAddress *to_addr=linphone_core_interpret_url(lc,to);
LinphoneChatRoom *ret;
@@ -331,17 +355,64 @@ LinphoneChatRoom* linphone_core_get_or_create_chat_room(LinphoneCore* lc, const
ms_error("linphone_core_get_or_create_chat_room(): Cannot make a valid address with %s",to);
return NULL;
}
- ret=linphone_core_get_chat_room(lc,to_addr);
+ ret=_linphone_core_get_chat_room(lc,to_addr);
linphone_address_destroy(to_addr);
if (!ret){
- ret=linphone_core_create_chat_room(lc,to);
+ ret=_linphone_core_create_chat_room_from_url(lc,to);
}
return ret;
}
+/**
+ * Create a new chat room for messaging from a sip uri like sip:joe@sip.linphone.org if not already existing, else return exisiting one
+ * @param lc #LinphoneCore object
+ * @param to destination address for messages
+ * @return #LinphoneChatRoom where messaging can take place.
+ * @deprecated Use linphone_core_get_chat_room() or linphone_core_get_chat_room_from_uri() instead.
+ */
+LinphoneChatRoom* linphone_core_get_or_create_chat_room(LinphoneCore* lc, const char* to) {
+ return _linphone_core_get_or_create_chat_room(lc, to);
+}
+
+/**
+ * Create a new chat room for messaging from a sip uri like sip:joe@sip.linphone.org
+ * @param lc #LinphoneCore object
+ * @param to destination address for messages
+ * @return #LinphoneChatRoom where messaging can take place.
+ * @deprecated Use linphone_core_get_chat_room() or linphone_core_get_chat_room_from_uri() instead.
+ */
+LinphoneChatRoom * linphone_core_create_chat_room(LinphoneCore *lc, const char *to) {
+ return _linphone_core_get_or_create_chat_room(lc, to);
+}
+
+/**
+ * Get a chat room whose peer is the supplied address. If it does not exist yet, it will be created.
+ * @param lc the linphone core
+ * @param addr a linphone address.
+ * @returns #LinphoneChatRoom where messaging can take place.
+**/
+LinphoneChatRoom *linphone_core_get_chat_room(LinphoneCore *lc, const LinphoneAddress *addr){
+ LinphoneChatRoom *ret = _linphone_core_get_chat_room(lc, addr);
+ if (!ret) {
+ ret = _linphone_core_create_chat_room(lc, linphone_address_clone(addr));
+ }
+ return ret;
+}
+
+/**
+ * Get a chat room for messaging from a sip uri like sip:joe@sip.linphone.org. If it does not exist yet, it will be created.
+ * @param lc The linphone core
+ * @param to The destination address for messages.
+ * @returns #LinphoneChatRoom where messaging can take place.
+**/
+LinphoneChatRoom * linphone_core_get_chat_room_from_uri(LinphoneCore *lc, const char *to) {
+ return _linphone_core_get_or_create_chat_room(lc, to);
+}
+
static void linphone_chat_room_delete_composing_idle_timer(LinphoneChatRoom *cr) {
if (cr->composing_idle_timer) {
- sal_cancel_timer(cr->lc->sal, cr->composing_idle_timer);
+ if(cr->lc->sal)
+ sal_cancel_timer(cr->lc->sal, cr->composing_idle_timer);
belle_sip_object_unref(cr->composing_idle_timer);
cr->composing_idle_timer = NULL;
}
@@ -349,7 +420,8 @@ static void linphone_chat_room_delete_composing_idle_timer(LinphoneChatRoom *cr)
static void linphone_chat_room_delete_composing_refresh_timer(LinphoneChatRoom *cr) {
if (cr->composing_refresh_timer) {
- sal_cancel_timer(cr->lc->sal, cr->composing_refresh_timer);
+ if(cr->lc->sal)
+ sal_cancel_timer(cr->lc->sal, cr->composing_refresh_timer);
belle_sip_object_unref(cr->composing_refresh_timer);
cr->composing_refresh_timer = NULL;
}
@@ -357,28 +429,55 @@ static void linphone_chat_room_delete_composing_refresh_timer(LinphoneChatRoom *
static void linphone_chat_room_delete_remote_composing_refresh_timer(LinphoneChatRoom *cr) {
if (cr->remote_composing_refresh_timer) {
- sal_cancel_timer(cr->lc->sal, cr->remote_composing_refresh_timer);
+ if(cr->lc->sal)
+ sal_cancel_timer(cr->lc->sal, cr->remote_composing_refresh_timer);
belle_sip_object_unref(cr->remote_composing_refresh_timer);
cr->remote_composing_refresh_timer = NULL;
}
}
-/**
- * Destroy a LinphoneChatRoom.
- * @param cr #LinphoneChatRoom object
- */
-void linphone_chat_room_destroy(LinphoneChatRoom *cr){
- LinphoneCore *lc=cr->lc;
+static void _linphone_chat_room_destroy(LinphoneChatRoom *cr){
ms_list_free_with_data(cr->transient_messages, (void (*)(void*))linphone_chat_message_unref);
linphone_chat_room_delete_composing_idle_timer(cr);
linphone_chat_room_delete_composing_refresh_timer(cr);
linphone_chat_room_delete_remote_composing_refresh_timer(cr);
- lc->chatrooms=ms_list_remove(lc->chatrooms,(void *) cr);
+ if (cr->lc != NULL) {
+ cr->lc->chatrooms=ms_list_remove(cr->lc->chatrooms,(void *) cr);
+ }
linphone_address_destroy(cr->peer_url);
ms_free(cr->peer);
- ms_free(cr);
}
+/**
+ * Destroy a LinphoneChatRoom.
+ * @param cr #LinphoneChatRoom object
+ * @deprecated Use linphone_chat_room_unref() instead.
+ */
+void linphone_chat_room_destroy(LinphoneChatRoom *cr) {
+ linphone_chat_room_unref(cr);
+}
+
+void linphone_chat_room_release(LinphoneChatRoom *cr) {
+ cr->lc = NULL;
+ linphone_chat_room_unref(cr);
+}
+
+LinphoneChatRoom * linphone_chat_room_ref(LinphoneChatRoom *cr) {
+ belle_sip_object_ref(cr);
+ return cr;
+}
+
+void linphone_chat_room_unref(LinphoneChatRoom *cr) {
+ belle_sip_object_unref(cr);
+}
+
+void * linphone_chat_room_get_user_data(const LinphoneChatRoom *cr) {
+ return cr->user_data;
+}
+
+void linphone_chat_room_set_user_data(LinphoneChatRoom *cr, void *ud) {
+ cr->user_data = ud;
+}
static void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatMessage* msg){
@@ -389,7 +488,7 @@ static void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatM
time_t t=time(NULL);
linphone_chat_message_ref(msg);
/* Check if we shall upload a file to a server */
- if (msg->file_transfer_information != NULL) {
+ if (msg->file_transfer_information != NULL && msg->content_type == NULL) {
/* 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;
@@ -404,9 +503,10 @@ static void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatM
NULL,
NULL);
cbs.process_response=linphone_chat_message_process_response_from_post_file;
- cbs.process_io_error=process_io_error;
- cbs.process_auth_requested=process_auth_requested;
+ cbs.process_io_error=process_io_error_upload;
+ cbs.process_auth_requested=process_auth_requested_upload;
l=belle_http_request_listener_create_from_callbacks(&cbs,msg); /* give msg to listener to be able to start the actual file upload when server answer a 204 No content */
+ msg->http_request = req; /* keep a reference on the request to be able to cancel it */
belle_http_provider_send_request(cr->lc->http_provider,req,l);
linphone_chat_message_unref(msg);
return;
@@ -487,31 +587,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 (lc->vtable.text_received!=NULL) lc->vtable.text_received(lc, cr, msg->from, msg->message);
- if (lc->vtable.message_received!=NULL) lc->vtable.message_received(lc, cr,msg);
- if (cr->lc->vtable.is_composing_received != NULL) {
- cr->remote_is_composing = LinphoneIsComposingIdle;
- cr->lc->vtable.is_composing_received(cr->lc, cr);
- }
-}
-
-/**
- * Retrieve an existing chat room whose peer is the supplied address, if exists.
- * @param lc the linphone core
- * @param addr a linphone address.
- * @returns the matching chatroom, or NULL if no such chatroom exists.
-**/
-LinphoneChatRoom *linphone_core_get_chat_room(LinphoneCore *lc, const LinphoneAddress *addr){
- LinphoneChatRoom *cr=NULL;
- MSList *elem;
- for(elem=lc->chatrooms;elem!=NULL;elem=ms_list_next(elem)){
- cr=(LinphoneChatRoom*)elem->data;
- if (linphone_chat_room_matches(cr,addr)){
- break;
- }
- cr=NULL;
- }
- return cr;
+ 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);
}
void linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessage *sal_msg){
@@ -529,8 +608,7 @@ void linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessag
/* create a new chat room */
cr=linphone_core_create_chat_room(lc,cleanfrom);
}
-
- if (sal_msg->content_type != NULL) { /* content_type field is, for now, used only for rcs file transfer bu twe shall strcmp it with "application/vnd.gsma.rcs-ft-http+xml" */
+ if (sal_msg->content_type != NULL) { /* content_type field is, for now, used only for rcs file transfer but we shall strcmp it with "application/vnd.gsma.rcs-ft-http+xml" */
xmlChar *file_url = NULL;
xmlDocPtr xmlMessageBody;
xmlNodePtr cur;
@@ -623,6 +701,7 @@ void linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessag
linphone_address_destroy(addr);
msg->storage_id=linphone_chat_message_store(msg);
linphone_chat_room_message_received(cr,lc,msg);
+ linphone_chat_message_unref(msg);
ms_free(cleanfrom);
}
@@ -631,8 +710,7 @@ static int linphone_chat_room_remote_refresh_composing_expired(void *data, unsig
belle_sip_object_unref(cr->remote_composing_refresh_timer);
cr->remote_composing_refresh_timer = NULL;
cr->remote_is_composing = LinphoneIsComposingIdle;
- if (cr->lc->vtable.is_composing_received != NULL)
- cr->lc->vtable.is_composing_received(cr->lc, cr);
+ linphone_core_notify_is_composing_received(cr->lc, cr);
return BELLE_SIP_STOP;
}
@@ -677,8 +755,7 @@ static void process_im_is_composing_notification(LinphoneChatRoom *cr, xmlparsin
}
cr->remote_is_composing = state;
- if (cr->lc->vtable.is_composing_received != NULL)
- cr->lc->vtable.is_composing_received(cr->lc, cr);
+ linphone_core_notify_is_composing_received(cr->lc, cr);
}
}
@@ -720,20 +797,6 @@ LinphoneCore* linphone_chat_room_get_core(LinphoneChatRoom *cr){
return cr->lc;
}
-/**
- * Assign a user pointer to the chat room.
-**/
-void linphone_chat_room_set_user_data(LinphoneChatRoom *cr, void * ud){
- cr->user_data=ud;
-}
-
-/**
- * Retrieve the user pointer associated with the chat room.
-**/
-void * linphone_chat_room_get_user_data(LinphoneChatRoom *cr){
- return cr->user_data;
-}
-
/**
* get peer address \link linphone_core_create_chat_room() associated to \endlink this #LinphoneChatRoom
* @param cr #LinphoneChatRoom object
@@ -756,6 +819,7 @@ LinphoneChatMessage* linphone_chat_room_create_message(LinphoneChatRoom *cr, con
msg->is_read=TRUE;
msg->content_type = NULL; /* this property is used only when transfering file */
msg->file_transfer_information = NULL; /* this property is used only when transfering file */
+ msg->http_request = NULL;
return msg;
}
@@ -945,6 +1009,7 @@ const char* linphone_chat_message_state_to_string(const LinphoneChatMessageState
case LinphoneChatMessageStateInProgress:return "LinphoneChatMessageStateInProgress";
case LinphoneChatMessageStateDelivered:return "LinphoneChatMessageStateDelivered";
case LinphoneChatMessageStateNotDelivered:return "LinphoneChatMessageStateNotDelivered";
+ case LinphoneChatMessageStateFileTransferError:return "LinphoneChatMessageStateFileTransferError";
default: return "Unknown state";
}
@@ -1047,22 +1112,22 @@ static void on_recv_body(belle_sip_user_body_handler_t *bh, belle_sip_message_t
}
LinphoneChatMessage* chatMsg=(LinphoneChatMessage *)data;
LinphoneCore *lc = chatMsg->chat_room->lc;
+ /* TODO: while belle sip doesn't implement the cancel http request method, test if a request is still linked to the message before forwarding the data to callback */
+ if (chatMsg->http_request == NULL) {
+ return;
if (chatMsg->file_transfer_information->key != NULL) { /* we have a key, we must decrypt the file */
/* get data from callback to a plainBuffer */
char *plainBuffer = (char *)malloc(size);
lime_decryptFile(&(chatMsg->file_transfer_information->cryptoContext), chatMsg->file_transfer_information->key, size, plainBuffer, (char *)buffer);
/* call back given by application level */
- if (lc->vtable.file_transfer_received != NULL) {
- lc->vtable.file_transfer_received(lc, chatMsg, chatMsg->file_transfer_information, plainBuffer, size);
- }
+ linphone_core_notify_file_transfer_rec(lc, chatMsg, chatMsg->file_transfer_information, plainBuffer, size);
free(plainBuffer);
} else { /* regular file, no deciphering */
/* call back given by application level */
- if (lc->vtable.file_transfer_received != NULL) {
- lc->vtable.file_transfer_received(lc, chatMsg, chatMsg->file_transfer_information, (char *)buffer, size);
- }
+ linphone_core_notify_file_transfer_recd(lc, chatMsg, chatMsg->file_transfer_information, (char *)buffer, size);
}
+
return;
}
@@ -1131,9 +1196,7 @@ static void linphone_chat_process_response_from_get_file(void *data, const belle
lime_decryptFile(&(chatMsg->file_transfer_information->cryptoContext), NULL, 0, NULL, NULL);
}
/* file downloaded succesfully, call again the callback with size at zero */
- if (lc->vtable.file_transfer_received != NULL) {
- lc->vtable.file_transfer_received(lc, chatMsg, chatMsg->file_transfer_information, NULL, 0);
- }
+ linphone_core_notify_file_transfer_recv(lc, chatMsg, chatMsg->file_transfer_information, NULL, 0);
}
}
}
@@ -1142,8 +1205,9 @@ static void linphone_chat_process_response_from_get_file(void *data, const belle
* Start the download of the file from remote server
*
* @param message #LinphoneChatMessage
+ * @param status_cb LinphoneChatMessageStateChangeCb status callback invoked when file is downloaded or could not be downloaded
*/
-void linphone_chat_message_start_file_download(const LinphoneChatMessage *message) {
+void linphone_chat_message_start_file_download(LinphoneChatMessage *message, LinphoneChatMessageStateChangedCb status_cb) {
belle_http_request_listener_callbacks_t cbs={0};
belle_http_request_listener_t *l;
belle_generic_uri_t *uri;
@@ -1162,47 +1226,66 @@ void linphone_chat_message_start_file_download(const LinphoneChatMessage *messag
cbs.process_response_headers=linphone_chat_process_response_headers_from_get_file;
cbs.process_response=linphone_chat_process_response_from_get_file;
- cbs.process_io_error=process_io_error;
- cbs.process_auth_requested=process_auth_requested;
+ cbs.process_io_error=process_io_error_download;
+ cbs.process_auth_requested=process_auth_requested_download;
l=belle_http_request_listener_create_from_callbacks(&cbs, (void *)message);
belle_sip_object_data_set(BELLE_SIP_OBJECT(req),"message",(void *)message,NULL);
+ message->http_request = req; /* keep a reference on the request to be able to cancel the download */
+ message->cb = status_cb;
+ message->state = LinphoneChatMessageStateInProgress; /* start the download, status is In Progress */
belle_http_provider_send_request(message->chat_room->lc->http_provider,req,l);
}
+
+/**
+ * Cancel an ongoing file transfer attached to this message.(upload or download)
+ * @param msg #LinphoneChatMessage
+ */
+void linphone_chat_room_cancel_file_transfer(LinphoneChatMessage *msg) {
+ ms_message("Cancelled file transfer %s - msg [%p] chat room[%p]", (msg->external_body_url==NULL)?msg->chat_room->lc->file_transfer_server: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 */
+ msg->http_request = NULL;
+ if (msg->cb) {
+ msg->cb(msg, LinphoneChatMessageStateNotDelivered, msg->chat_room->lc);
+ }
+}
+
+
/**
* Set origin of the message
- *@param message #LinphoneChatMessage obj
- *@param from #LinphoneAddress origin of this message (copied)
+ * @param[in] message #LinphoneChatMessage obj
+ * @param[in] from #LinphoneAddress origin of this message (copied)
*/
-void linphone_chat_message_set_from(LinphoneChatMessage* message, const LinphoneAddress* from) {
+void linphone_chat_message_set_from_address(LinphoneChatMessage* message, const LinphoneAddress* from) {
if(message->from) linphone_address_destroy(message->from);
message->from=linphone_address_clone(from);
}
/**
* Get origin of the message
- *@param message #LinphoneChatMessage obj
- *@return #LinphoneAddress
+ * @param[in] message #LinphoneChatMessage obj
+ * @return #LinphoneAddress
*/
-const LinphoneAddress* linphone_chat_message_get_from(const LinphoneChatMessage* message) {
+const LinphoneAddress* linphone_chat_message_get_from_address(const LinphoneChatMessage* message) {
return message->from;
}
/**
* Set destination of the message
- *@param message #LinphoneChatMessage obj
- *@param to #LinphoneAddress destination of this message (copied)
+ * @param[in] message #LinphoneChatMessage obj
+ * @param[in] to #LinphoneAddress destination of this message (copied)
*/
-void linphone_chat_message_set_to(LinphoneChatMessage* message, const LinphoneAddress* to) {
+void linphone_chat_message_set_to_address(LinphoneChatMessage* message, const LinphoneAddress* to) {
if(message->to) linphone_address_destroy(message->to);
message->to=linphone_address_clone(to);
}
/**
* Get destination of the message
- *@param message #LinphoneChatMessage obj
- *@return #LinphoneAddress
+ * @param[in] message #LinphoneChatMessage obj
+ * @return #LinphoneAddress
*/
-const LinphoneAddress* linphone_chat_message_get_to(const LinphoneChatMessage* message){
+const LinphoneAddress* linphone_chat_message_get_to_address(const LinphoneChatMessage* message){
if (message->to) return message->to;
if (message->dir==LinphoneChatMessageOutgoing){
return message->chat_room->peer_url;
@@ -1341,6 +1424,7 @@ static void _linphone_chat_message_destroy(LinphoneChatMessage* msg) {
linphone_content_uninit(msg->file_transfer_information);
ms_free(msg->file_transfer_information);
}
+ ms_message("LinphoneChatMessage [%p] destroyed.",msg);
}
@@ -1395,11 +1479,10 @@ LinphoneChatMessage* linphone_chat_room_create_file_transfer_message(LinphoneCha
linphone_chat_message_set_to(msg, linphone_chat_room_get_peer_address(cr));
linphone_chat_message_set_from(msg, linphone_address_new(linphone_core_get_identity(cr->lc)));
msg->content_type=NULL; /* this will be set to application/vnd.gsma.rcs-ft-http+xml when we will transfer the xml reply from server to the peers */
-
+ msg->http_request=NULL; /* this will store the http request during file upload to the server */
return msg;
}
+
/**
* @}
*/
-
-
diff --git a/coreapi/conference.c b/coreapi/conference.c
index 7bee313dd..f860c33ad 100644
--- a/coreapi/conference.c
+++ b/coreapi/conference.c
@@ -41,6 +41,7 @@ static void conference_check_init(LinphoneConference *ctx, int samplerate){
MSAudioConferenceParams params;
params.samplerate=samplerate;
ctx->conf=ms_audio_conference_new(¶ms);
+ ctx->terminated=FALSE;
}
}
@@ -74,7 +75,7 @@ void linphone_core_conference_check_uninit(LinphoneCore *lc){
if (ctx->conf){
int remote_count=remote_participants_count(ctx);
ms_message("conference_check_uninit(): size=%i",linphone_conference_get_size(ctx));
- if (remote_count==1){
+ if (remote_count==1 && !ctx->terminated){
convert_conference_to_call(lc);
}
if (remote_count==0){
@@ -98,7 +99,7 @@ void linphone_call_add_to_conf(LinphoneCall *call, bool_t muted){
LinphoneCore *lc=call->core;
LinphoneConference *conf=&lc->conf_ctx;
MSAudioEndpoint *ep;
- call->params.has_video = FALSE;
+ call->params->has_video = FALSE;
call->camera_enabled = FALSE;
ep=ms_audio_endpoint_get_from_stream(call->audiostream,TRUE);
ms_audio_conference_add_member(conf->conf,ep);
@@ -184,15 +185,15 @@ float linphone_core_get_conference_local_input_volume(LinphoneCore *lc){
int linphone_core_add_to_conference(LinphoneCore *lc, LinphoneCall *call){
LinphoneConference *conf=&lc->conf_ctx;
- if (call->current_params.in_conference){
+ if (call->current_params->in_conference){
ms_error("Already in conference");
return -1;
}
conference_check_init(&lc->conf_ctx, lp_config_get_int(lc->config, "sound","conference_rate",16000));
if (call->state==LinphoneCallPaused){
- call->params.in_conference=TRUE;
- call->params.has_video=FALSE;
+ call->params->in_conference=TRUE;
+ call->params->has_video=FALSE;
linphone_core_resume_call(lc,call);
}else if (call->state==LinphoneCallStreamsRunning){
LinphoneCallParams *params=linphone_call_params_copy(linphone_call_get_current_params(call));
@@ -222,8 +223,8 @@ static int remove_from_conference(LinphoneCore *lc, LinphoneCall *call, bool_t a
int err=0;
char *str;
- if (!call->current_params.in_conference){
- if (call->params.in_conference){
+ if (!call->current_params->in_conference){
+ if (call->params->in_conference){
ms_warning("Not (yet) in conference, be patient");
return -1;
}else{
@@ -231,7 +232,7 @@ static int remove_from_conference(LinphoneCore *lc, LinphoneCall *call, bool_t a
return -1;
}
}
- call->params.in_conference=FALSE;
+ call->params->in_conference=FALSE;
str=linphone_call_get_remote_address_as_string(call);
ms_message("%s will be removed from conference", str);
@@ -251,7 +252,6 @@ static int remove_from_conference(LinphoneCore *lc, LinphoneCall *call, bool_t a
ms_message("Pausing call to actually remove from conference");
err=_linphone_core_pause_call(lc,call);
}
-
return err;
}
@@ -267,7 +267,7 @@ static int convert_conference_to_call(LinphoneCore *lc){
while (calls) {
LinphoneCall *rc=(LinphoneCall*)calls->data;
calls=calls->next;
- if (rc->params.in_conference) { // not using current_param
+ if (rc->params->in_conference) { // not using current_param
bool_t active_after_removed=linphone_core_is_in_conference(lc);
err=remove_from_conference(lc, rc, active_after_removed);
break;
@@ -370,7 +370,7 @@ int linphone_core_add_all_to_conference(LinphoneCore *lc) {
while (calls) {
LinphoneCall *call=(LinphoneCall*)calls->data;
calls=calls->next;
- if (!call->current_params.in_conference) {
+ if (!call->current_params->in_conference) {
linphone_core_add_to_conference(lc, call);
}
}
@@ -388,10 +388,13 @@ int linphone_core_add_all_to_conference(LinphoneCore *lc) {
**/
int linphone_core_terminate_conference(LinphoneCore *lc) {
MSList *calls=lc->calls;
+ LinphoneConference *conf=&lc->conf_ctx;
+ conf->terminated=TRUE;
+
while (calls) {
LinphoneCall *call=(LinphoneCall*)calls->data;
calls=calls->next;
- if (call->current_params.in_conference) {
+ if (call->current_params->in_conference) {
linphone_core_terminate_call(lc, call);
}
}
diff --git a/coreapi/event.c b/coreapi/event.c
index 992d058ab..372e0a953 100644
--- a/coreapi/event.c
+++ b/coreapi/event.c
@@ -89,13 +89,10 @@ LinphoneEvent *linphone_event_new_with_out_of_dialog_op(LinphoneCore *lc, SalOp
}
void linphone_event_set_state(LinphoneEvent *lev, LinphoneSubscriptionState state){
- LinphoneCore *lc=lev->lc;
if (lev->subscription_state!=state){
ms_message("LinphoneEvent [%p] moving to subscription state %s",lev,linphone_subscription_state_to_string(state));
lev->subscription_state=state;
- if (lc->vtable.subscription_state_changed){
- lc->vtable.subscription_state_changed(lev->lc,lev,state);
- }
+ linphone_core_notify_subscription_state_changed(lev->lc,lev,state);
if (state==LinphoneSubscriptionTerminated){
linphone_event_unref(lev);
}
@@ -103,13 +100,10 @@ void linphone_event_set_state(LinphoneEvent *lev, LinphoneSubscriptionState stat
}
void linphone_event_set_publish_state(LinphoneEvent *lev, LinphonePublishState state){
- LinphoneCore *lc=lev->lc;
if (lev->publish_state!=state){
ms_message("LinphoneEvent [%p] moving to publish state %s",lev,linphone_publish_state_to_string(state));
lev->publish_state=state;
- if (lc->vtable.publish_state_changed){
- lc->vtable.publish_state_changed(lev->lc,lev,state);
- }
+ linphone_core_notify_publish_state_changed(lev->lc,lev,state);
switch(state){
case LinphonePublishCleared:
linphone_event_unref(lev);
diff --git a/coreapi/friend.c b/coreapi/friend.c
index 7b0ddd816..d1ecd560c 100644
--- a/coreapi/friend.c
+++ b/coreapi/friend.c
@@ -253,8 +253,7 @@ static void linphone_friend_invalidate_subscription(LinphoneFriend *lf){
linphone_presence_model_unref(lf->presence);
}
lf->presence = linphone_presence_model_new_with_activity(LinphonePresenceActivityOffline,"unknown activity");
- if (lc->vtable.notify_presence_received)
- lc->vtable.notify_presence_received(lc,lf);
+ linphone_core_notify_notify_presence_received(lc,lf);
}
lf->initial_subscribes_sent=FALSE;
}
diff --git a/coreapi/gitversion.cmake b/coreapi/gitversion.cmake
new file mode 100644
index 000000000..5c6facdab
--- /dev/null
+++ b/coreapi/gitversion.cmake
@@ -0,0 +1,39 @@
+############################################################################
+# CMakeLists.txt
+# Copyright (C) 2014 Belledonne Communications, Grenoble France
+#
+############################################################################
+#
+# 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, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+############################################################################
+
+if(GIT_EXECUTABLE)
+ execute_process(
+ COMMAND ${GIT_EXECUTABLE} describe --always
+ WORKING_DIRECTORY ${WORK_DIR}
+ OUTPUT_VARIABLE GIT_REVISION
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ )
+ execute_process(
+ COMMAND ${CMAKE_COMMAND} -E echo "#define LIBLINPHONE_GIT_VERSION \"${GIT_REVISION}\""
+ OUTPUT_FILE ${OUTPUT_DIR}/liblinphone_gitversion.h
+ )
+else()
+ execute_process(
+ COMMAND ${CMAKE_COMMAND} -E echo "#define LIBLINPHONE_GIT_VERSION \"unknown\""
+ OUTPUT_FILE ${OUTPUT_DIR}/liblinphone_gitversion.h
+ )
+endif()
diff --git a/coreapi/help/CMakeLists.txt b/coreapi/help/CMakeLists.txt
new file mode 100644
index 000000000..af624006e
--- /dev/null
+++ b/coreapi/help/CMakeLists.txt
@@ -0,0 +1,45 @@
+############################################################################
+# CMakeLists.txt
+# Copyright (C) 2014 Belledonne Communications, Grenoble France
+#
+############################################################################
+#
+# 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, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+############################################################################
+
+find_package(Doxygen)
+
+if(DOXYGEN_FOUND)
+ if(DOXYGEN_DOT_FOUND)
+ set(top_srcdir ${CMAKE_SOURCE_DIR})
+ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
+ file(GLOB DOC_INPUT_FILES
+ [^.]*.c
+ [^.]*.dox
+ ../[^.]*.h
+ ../[^.]*.c
+ )
+ add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/doc/html/index.html"
+ COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
+ DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile ${DOC_INPUT_FILES}
+ )
+ add_custom_target(doc ALL DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/doc/html/index.html")
+ install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/doc/html" "${CMAKE_CURRENT_BINARY_DIR}/doc/xml"
+ DESTINATION "${CMAKE_INSTALL_PREFIX}/share/doc/linphone-${LINPHONE_VERSION}")
+ else()
+ message(WARNING "The dot program is needed to generate the linphone documentation. You can get it from http://www.graphviz.org/.")
+ endif()
+endif()
diff --git a/coreapi/help/Doxyfile.in b/coreapi/help/Doxyfile.in
index 27068c53d..12facea9b 100644
--- a/coreapi/help/Doxyfile.in
+++ b/coreapi/help/Doxyfile.in
@@ -34,7 +34,7 @@ DETAILS_AT_TOP = NO
INHERIT_DOCS = YES
DISTRIBUTE_GROUP_DOC = NO
TAB_SIZE = 8
-ALIASES =
+ALIASES = mslist{1}="A list of \ref \1 objects. \xmlonly \1 \endxmlonly"
OPTIMIZE_OUTPUT_FOR_C = YES
OPTIMIZE_OUTPUT_JAVA = NO
SUBGROUPING = YES
diff --git a/coreapi/help/Makefile.am b/coreapi/help/Makefile.am
index 84822e51c..479d2b31d 100644
--- a/coreapi/help/Makefile.am
+++ b/coreapi/help/Makefile.am
@@ -1,7 +1,7 @@
EXTRA_DIST=Doxyfile.in doxygen.dox
-SOURCES=doxygen.dox $(top_srcdir)/coreapi/help/*.c $(top_srcdir)/coreapi/*.c $(top_srcdir)/coreapi/*.h
+SOURCES=doxygen.dox $(top_srcdir)/coreapi/help/*.c $(top_srcdir)/coreapi/*.c $(top_srcdir)/coreapi/*.h
# html doc
@@ -84,6 +84,7 @@ filetransfer_LDADD=$(helloworld_LDADD)
AM_CFLAGS=\
-I$(top_srcdir)/coreapi \
$(STRICT_OPTIONS) \
+ $(STRICT_OPTIONS_CC) \
-DIN_LINPHONE \
$(ORTP_CFLAGS) \
$(MEDIASTREAMER_CFLAGS) \
@@ -98,4 +99,4 @@ AM_CFLAGS=\
tutodir=$(datadir)/tutorials/linphone
tuto_DATA=$(LINPHONE_TUTOS)
-endif
+endif
diff --git a/coreapi/help/buddy_status.c b/coreapi/help/buddy_status.c
index 40db6458e..cd7f13d52 100644
--- a/coreapi/help/buddy_status.c
+++ b/coreapi/help/buddy_status.c
@@ -1,7 +1,7 @@
/*
buddy_status
-Copyright (C) 2010 Belledonne Communications SARL
+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
@@ -73,7 +73,7 @@ static void new_subscription_requested (LinphoneCore *lc, LinphoneFriend *frien
* Registration state notification callback
*/
static void registration_state_changed(struct _LinphoneCore *lc, LinphoneProxyConfig *cfg, LinphoneRegistrationState cstate, const char *message){
- printf("New registration state %s for user id [%s] at proxy [%s]\n"
+ printf("New registration state %s for user id [%s] at proxy [%s]"
,linphone_registration_state_to_string(cstate)
,linphone_proxy_config_get_identity(cfg)
,linphone_proxy_config_get_addr(cfg));
@@ -87,6 +87,8 @@ int main(int argc, char *argv[]){
char* identity=NULL;
char* password=NULL;
+ LinphoneFriend* my_friend=NULL;
+
/* takes sip uri identity from the command line arguments */
if (argc>1){
dest_friend=argv[1];
@@ -104,7 +106,7 @@ int main(int argc, char *argv[]){
#ifdef DEBUG
linphone_core_enable_logs(NULL); /*enable liblinphone logs.*/
#endif
- /*
+ /*
Fill the LinphoneCoreVTable with application callbacks.
All are optional. Here we only use the both notify_presence_received and new_subscription_requested callbacks
in order to get notifications about friend status.
@@ -123,11 +125,11 @@ int main(int argc, char *argv[]){
LinphoneProxyConfig* proxy_cfg = linphone_proxy_config_new();
/*parse identity*/
LinphoneAddress *from = linphone_address_new(identity);
+ LinphoneAuthInfo *info;
if (from==NULL){
printf("%s not a valid sip uri, must be like sip:toto@sip.linphone.org \n",identity);
goto end;
}
- LinphoneAuthInfo *info;
if (password!=NULL){
info=linphone_auth_info_new(linphone_address_get_username(from),NULL,password,NULL,NULL,NULL); /*create authentication structure from identity*/
linphone_core_add_auth_info(lc,info); /*add authentication info to LinphoneCore*/
@@ -152,7 +154,6 @@ int main(int argc, char *argv[]){
while( running && linphone_proxy_config_get_state(proxy_cfg) == LinphoneRegistrationProgress);
}
- LinphoneFriend* my_friend=NULL;
if (dest_friend) {
my_friend = linphone_friend_new_with_address(dest_friend); /*creates friend object from dest*/
diff --git a/coreapi/help/chatroom.c b/coreapi/help/chatroom.c
index 51fc4a237..1f0f200a0 100644
--- a/coreapi/help/chatroom.c
+++ b/coreapi/help/chatroom.c
@@ -1,7 +1,7 @@
/*
linphone
-Copyright (C) 2010 Belledonne Communications SARL
+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
@@ -55,7 +55,7 @@ int main(int argc, char *argv[]){
LinphoneCoreVTable vtable={0};
char* dest_friend=NULL;
-
+ LinphoneChatRoom* chat_room;
/* takes sip uri identity from the command line arguments */
if (argc>1){
@@ -67,7 +67,7 @@ int main(int argc, char *argv[]){
#ifdef DEBUG
linphone_core_enable_logs(NULL); /*enable liblinphone logs.*/
#endif
- /*
+ /*
Fill the LinphoneCoreVTable with application callbacks.
All are optional. Here we only use the text_received callback
in order to get notifications about incoming message.
@@ -81,7 +81,7 @@ int main(int argc, char *argv[]){
/*Next step is to create a chat root*/
- LinphoneChatRoom* chat_room = linphone_core_create_chat_room(lc,dest_friend);
+ chat_room = linphone_core_create_chat_room(lc,dest_friend);
linphone_chat_room_send_message(chat_room,"Hello world"); /*sending message*/
diff --git a/coreapi/help/filetransfer.c b/coreapi/help/filetransfer.c
index 3005fff01..7cfc2cca9 100644
--- a/coreapi/help/filetransfer.c
+++ b/coreapi/help/filetransfer.c
@@ -1,7 +1,7 @@
/*
linphone
-Copyright (C) 2010 Belledonne Communications SARL
+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
@@ -114,16 +114,6 @@ static void file_transfer_send(LinphoneCore *lc, LinphoneChatMessage *message,
}
-/*
- * Call back called when a message is received
- */
-static void message_received(LinphoneCore *lc, LinphoneChatRoom *cr, LinphoneChatMessage *msg) {
- const LinphoneContent *file_transfer_info = linphone_chat_message_get_file_transfer_information(msg);
- printf ("Do you really want to download %s (size %ld)?[Y/n]\nOk, let's go\n", file_transfer_info->name, (long int)file_transfer_info->size);
-
- linphone_chat_message_start_file_download(msg);
-
-}
/*
* Call back to get delivery status of a message
* */
@@ -135,6 +125,16 @@ static void linphone_file_transfer_state_changed(LinphoneChatMessage* msg,Linpho
free(to);
}
+/*
+ * Call back called when a message is received
+ */
+static void message_received(LinphoneCore *lc, LinphoneChatRoom *cr, LinphoneChatMessage *msg) {
+ const LinphoneContent *file_transfer_info = linphone_chat_message_get_file_transfer_information(msg);
+ printf ("Do you really want to download %s (size %ld)?[Y/n]\nOk, let's go\n", file_transfer_info->name, (long int)file_transfer_info->size);
+
+ linphone_chat_message_start_file_download(msg, linphone_file_transfer_state_changed);
+
+}
LinphoneCore *lc;
int main(int argc, char *argv[]){
@@ -143,6 +143,10 @@ int main(int argc, char *argv[]){
const char* dest_friend=NULL;
int i;
const char* big_file_content="big file";
+ LinphoneChatRoom* chat_room;
+ LinphoneContent content;
+ LinphoneChatMessage* chat_message;
+
/*seting dummy file content to something*/
for (i=0;i1){
@@ -105,7 +109,7 @@ int main(int argc, char *argv[]){
#ifdef DEBUG
linphone_core_enable_logs(NULL); /*enable liblinphone logs.*/
#endif
- /*
+ /*
Fill the LinphoneCoreVTable with application callbacks.
All are optional. Here we only use the registration_state_changed callbacks
in order to get notifications about the progress of the registration.
@@ -118,30 +122,28 @@ int main(int argc, char *argv[]){
*/
lc=linphone_core_new(&vtable,NULL,NULL,data);
- LinphoneProxyConfig* proxy_cfg;
/*create proxy config*/
proxy_cfg = linphone_proxy_config_new();
/*parse identity*/
- LinphoneAddress *from = linphone_address_new(identity);
+ from = linphone_address_new(identity);
if (from==NULL){
printf("%s not a valid sip uri, must be like sip:toto@sip.linphone.org \n",identity);
goto end;
}
- LinphoneAuthInfo *info;
- if (password!=NULL){
- info=linphone_auth_info_new(linphone_address_get_username(from),NULL,password,NULL,NULL,NULL); /*create authentication structure from identity*/
- linphone_core_add_auth_info(lc,info); /*add authentication info to LinphoneCore*/
- }
+ if (password!=NULL){
+ info=linphone_auth_info_new(linphone_address_get_username(from),NULL,password,NULL,NULL,NULL); /*create authentication structure from identity*/
+ linphone_core_add_auth_info(lc,info); /*add authentication info to LinphoneCore*/
+ }
- // configure proxy entries
- linphone_proxy_config_set_identity(proxy_cfg,identity); /*set identity with user name and domain*/
- const char* server_addr = linphone_address_get_domain(from); /*extract domain address from identity*/
- linphone_proxy_config_set_server_addr(proxy_cfg,server_addr); /* we assume domain = proxy server address*/
- linphone_proxy_config_enable_register(proxy_cfg,TRUE); /*activate registration for this proxy config*/
- linphone_address_destroy(from); /*release resource*/
+ // configure proxy entries
+ linphone_proxy_config_set_identity(proxy_cfg,identity); /*set identity with user name and domain*/
+ server_addr = linphone_address_get_domain(from); /*extract domain address from identity*/
+ linphone_proxy_config_set_server_addr(proxy_cfg,server_addr); /* we assume domain = proxy server address*/
+ linphone_proxy_config_enable_register(proxy_cfg,TRUE); /*activate registration for this proxy config*/
+ linphone_address_destroy(from); /*release resource*/
- linphone_core_add_proxy_config(lc,proxy_cfg); /*add proxy config to linphone core*/
- linphone_core_set_default_proxy(lc,proxy_cfg); /*set to default proxy*/
+ linphone_core_add_proxy_config(lc,proxy_cfg); /*add proxy config to linphone core*/
+ linphone_core_set_default_proxy(lc,proxy_cfg); /*set to default proxy*/
i=0;
/* main loop for receiving notifications and doing background linphonecore work: */
@@ -163,7 +165,7 @@ int main(int argc, char *argv[]){
linphone_proxy_config_edit(proxy_cfg); /*start editing proxy configuration*/
linphone_proxy_config_enable_register(proxy_cfg,FALSE); /*de-activate registration for this proxy config*/
linphone_proxy_config_done(proxy_cfg); /*initiate REGISTER with expire = 0*/
-
+
if (data->ev){
linphone_event_terminate(data->ev);
}
diff --git a/coreapi/help/registration.c b/coreapi/help/registration.c
index 70ab4f4ca..8dbab6440 100644
--- a/coreapi/help/registration.c
+++ b/coreapi/help/registration.c
@@ -1,7 +1,7 @@
/*
linphone
-Copyright (C) 2010 Belledonne Communications SARL
+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
@@ -60,9 +60,13 @@ static void registration_state_changed(struct _LinphoneCore *lc, LinphoneProxyCo
LinphoneCore *lc;
int main(int argc, char *argv[]){
LinphoneCoreVTable vtable={0};
+ LinphoneProxyConfig* proxy_cfg;
+ LinphoneAddress *from;
+ LinphoneAuthInfo *info;
char* identity=NULL;
char* password=NULL;
+ const char* server_addr;
/* takes sip uri identity from the command line arguments */
if (argc>1){
@@ -79,7 +83,7 @@ int main(int argc, char *argv[]){
#ifdef DEBUG
linphone_core_enable_logs(NULL); /*enable liblinphone logs.*/
#endif
- /*
+ /*
Fill the LinphoneCoreVTable with application callbacks.
All are optional. Here we only use the registration_state_changed callbacks
in order to get notifications about the progress of the registration.
@@ -91,30 +95,28 @@ int main(int argc, char *argv[]){
*/
lc=linphone_core_new(&vtable,NULL,NULL,NULL);
- LinphoneProxyConfig* proxy_cfg;
/*create proxy config*/
proxy_cfg = linphone_proxy_config_new();
/*parse identity*/
- LinphoneAddress *from = linphone_address_new(identity);
+ from = linphone_address_new(identity);
if (from==NULL){
printf("%s not a valid sip uri, must be like sip:toto@sip.linphone.org \n",identity);
goto end;
}
- LinphoneAuthInfo *info;
- if (password!=NULL){
- info=linphone_auth_info_new(linphone_address_get_username(from),NULL,password,NULL,NULL,NULL); /*create authentication structure from identity*/
- linphone_core_add_auth_info(lc,info); /*add authentication info to LinphoneCore*/
- }
+ if (password!=NULL){
+ info=linphone_auth_info_new(linphone_address_get_username(from),NULL,password,NULL,NULL,NULL); /*create authentication structure from identity*/
+ linphone_core_add_auth_info(lc,info); /*add authentication info to LinphoneCore*/
+ }
- // configure proxy entries
- linphone_proxy_config_set_identity(proxy_cfg,identity); /*set identity with user name and domain*/
- const char* server_addr = linphone_address_get_domain(from); /*extract domain address from identity*/
- linphone_proxy_config_set_server_addr(proxy_cfg,server_addr); /* we assume domain = proxy server address*/
- linphone_proxy_config_enable_register(proxy_cfg,TRUE); /*activate registration for this proxy config*/
- linphone_address_destroy(from); /*release resource*/
+ // configure proxy entries
+ linphone_proxy_config_set_identity(proxy_cfg,identity); /*set identity with user name and domain*/
+ server_addr = linphone_address_get_domain(from); /*extract domain address from identity*/
+ linphone_proxy_config_set_server_addr(proxy_cfg,server_addr); /* we assume domain = proxy server address*/
+ linphone_proxy_config_enable_register(proxy_cfg,TRUE); /*activate registration for this proxy config*/
+ linphone_address_destroy(from); /*release resource*/
- linphone_core_add_proxy_config(lc,proxy_cfg); /*add proxy config to linphone core*/
- linphone_core_set_default_proxy(lc,proxy_cfg); /*set to default proxy*/
+ linphone_core_add_proxy_config(lc,proxy_cfg); /*add proxy config to linphone core*/
+ linphone_core_set_default_proxy(lc,proxy_cfg); /*set to default proxy*/
/* main loop for receiving notifications and doing background linphonecore work: */
diff --git a/coreapi/info.c b/coreapi/info.c
index 4279a963c..ca078f29c 100644
--- a/coreapi/info.c
+++ b/coreapi/info.c
@@ -205,8 +205,7 @@ void linphone_core_notify_info_message(LinphoneCore* lc,SalOp *op, const SalBody
LinphoneInfoMessage *info=ms_new0(LinphoneInfoMessage,1);
info->headers=sal_custom_header_clone(sal_op_get_recv_custom_header(op));
if (body) linphone_content_copy_from_sal_body(&info->content,body);
- if (lc->vtable.info_received)
- lc->vtable.info_received(lc,call,info);
+ linphone_core_notify_info_received(lc,call,info);
linphone_info_message_destroy(info);
}
}
diff --git a/coreapi/ldap/ldapprovider.c b/coreapi/ldap/ldapprovider.c
index f9a4add67..75b6b19a1 100644
--- a/coreapi/ldap/ldapprovider.c
+++ b/coreapi/ldap/ldapprovider.c
@@ -567,10 +567,11 @@ LinphoneLDAPContactProvider*linphone_ldap_contact_provider_create(LinphoneCore*
belle_sip_object_unref(obj);
obj = NULL;
} else {
+ int ret;
linphone_dictionary_foreach( config, linphone_ldap_contact_provider_config_dump_cb, 0 );
linphone_ldap_contact_provider_loadconfig(obj, config);
- int ret = ldap_initialize(&(obj->ld),obj->server);
+ ret = ldap_initialize(&(obj->ld),obj->server);
if( ret != LDAP_SUCCESS ){
ms_error( "Problem initializing ldap on url '%s': %s", obj->server, ldap_err2string(ret));
@@ -617,9 +618,10 @@ static int linphone_ldap_request_entry_compare_strong(const void*a, const void*
static inline LinphoneLDAPContactSearch* linphone_ldap_contact_provider_request_search( LinphoneLDAPContactProvider* obj, int msgid )
{
LinphoneLDAPContactSearch dummy = {};
+ MSList* list_entry;
dummy.msgid = msgid;
- MSList* list_entry = ms_list_find_custom(obj->requests, linphone_ldap_request_entry_compare_weak, &dummy);
+ list_entry = ms_list_find_custom(obj->requests, linphone_ldap_request_entry_compare_weak, &dummy);
if( list_entry ) return list_entry->data;
else return NULL;
}
@@ -680,13 +682,14 @@ static LinphoneLDAPContactSearch* linphone_ldap_contact_provider_begin_search (
void* cb_data )
{
bool_t connected = obj->connected;
+ LinphoneLDAPContactSearch* request;
// if we're not yet connected, bind
if( !connected ) {
if( !obj->bind_thread ) linphone_ldap_contact_provider_bind(obj);
}
- LinphoneLDAPContactSearch* request = linphone_ldap_contact_search_create( obj, predicate, cb, cb_data );
+ request = linphone_ldap_contact_search_create( obj, predicate, cb, cb_data );
if( connected ){
int ret = linphone_ldap_contact_provider_perform_search(obj, request);
@@ -711,6 +714,7 @@ static LinphoneLDAPContactSearch* linphone_ldap_contact_provider_begin_search (
static int linphone_ldap_contact_provider_marshal(LinphoneLDAPContactProvider* obj, char* buff, size_t buff_size, size_t *offset)
{
belle_sip_error_code error = BELLE_SIP_OK;
+ char **attr;
error = belle_sip_snprintf(buff, buff_size, offset, "ld:%p,\n", obj->ld);
if(error!= BELLE_SIP_OK) return error;
@@ -741,7 +745,7 @@ static int linphone_ldap_contact_provider_marshal(LinphoneLDAPContactProvider* o
obj->sip_attr, obj->name_attr);
if(error!= BELLE_SIP_OK) return error;
- char **attr = obj->attributes;
+ attr = obj->attributes;
while( *attr ){
error = belle_sip_snprintf(buff, buff_size, offset, "- %s\n", *attr);
if(error!= BELLE_SIP_OK) return error;
diff --git a/coreapi/linphone_tunnel.cc b/coreapi/linphone_tunnel.cc
index 151755078..8abeb3b05 100644
--- a/coreapi/linphone_tunnel.cc
+++ b/coreapi/linphone_tunnel.cc
@@ -29,14 +29,18 @@
#include "private.h"
#include "lpconfig.h"
-LinphoneTunnel* linphone_core_get_tunnel(LinphoneCore *lc){
+static const char *_tunnel_mode_str[3] = { "disable", "enable", "auto" };
+
+static LinphoneTunnelMode _string_to_tunnel_mode(const char *string);
+static const char *_tunnel_mode_to_string(LinphoneTunnelMode mode);
+
+LinphoneTunnel* linphone_core_get_tunnel(const LinphoneCore *lc){
return lc->tunnel;
}
struct _LinphoneTunnel {
belledonnecomm::TunnelManager *manager;
MSList *config_list;
- bool_t auto_detect_enabled;
};
extern "C" LinphoneTunnel* linphone_core_tunnel_new(LinphoneCore *lc){
@@ -45,31 +49,37 @@ extern "C" LinphoneTunnel* linphone_core_tunnel_new(LinphoneCore *lc){
return tunnel;
}
-static inline belledonnecomm::TunnelManager *bcTunnel(LinphoneTunnel *tunnel){
+belledonnecomm::TunnelManager *bcTunnel(const LinphoneTunnel *tunnel){
return tunnel->manager;
}
-static inline _LpConfig *config(LinphoneTunnel *tunnel){
+static inline _LpConfig *config(const LinphoneTunnel *tunnel){
return tunnel->manager->getLinphoneCore()->config;
}
void linphone_tunnel_destroy(LinphoneTunnel *tunnel){
delete tunnel->manager;
+
+ ms_list_free_with_data(tunnel->config_list, (void (*)(void *))linphone_tunnel_config_destroy);
+
ms_free(tunnel);
}
static char *linphone_tunnel_config_to_string(const LinphoneTunnelConfig *tunnel_config) {
char *str = NULL;
- if(linphone_tunnel_config_get_remote_udp_mirror_port(tunnel_config) != -1) {
- str = ms_strdup_printf("%s:%d:%d:%d",
- linphone_tunnel_config_get_host(tunnel_config),
- linphone_tunnel_config_get_port(tunnel_config),
- linphone_tunnel_config_get_remote_udp_mirror_port(tunnel_config),
- linphone_tunnel_config_get_delay(tunnel_config));
- } else {
- str = ms_strdup_printf("%s:%d",
- linphone_tunnel_config_get_host(tunnel_config),
- linphone_tunnel_config_get_port(tunnel_config));
+ const char *host = linphone_tunnel_config_get_host(tunnel_config);
+ if(host != NULL) {
+ if(linphone_tunnel_config_get_remote_udp_mirror_port(tunnel_config) != -1) {
+ str = ms_strdup_printf("%s:%d:%d:%d",
+ linphone_tunnel_config_get_host(tunnel_config),
+ linphone_tunnel_config_get_port(tunnel_config),
+ linphone_tunnel_config_get_remote_udp_mirror_port(tunnel_config),
+ linphone_tunnel_config_get_delay(tunnel_config));
+ } else {
+ str = ms_strdup_printf("%s:%d",
+ linphone_tunnel_config_get_host(tunnel_config),
+ linphone_tunnel_config_get_port(tunnel_config));
+ }
}
return str;
}
@@ -97,12 +107,12 @@ static LinphoneTunnelConfig *linphone_tunnel_config_from_string(const char *str)
break;
case 3:
delay = atoi(pch);
- break;
+ break;
default:
// Abort
pos = 0;
break;
-
+
}
++pos;
pch = strtok(NULL, ":");
@@ -118,26 +128,27 @@ static LinphoneTunnelConfig *linphone_tunnel_config_from_string(const char *str)
if(pos == 4) {
linphone_tunnel_config_set_delay(tunnel_config, delay);
}
- ms_free(dstr);
+ ms_free(dstr);
return tunnel_config;
}
-static void linphone_tunnel_save_config(LinphoneTunnel *tunnel) {
- MSList *elem = tunnel->config_list;
+static void linphone_tunnel_save_config(const LinphoneTunnel *tunnel) {
+ MSList *elem = NULL;
char *tmp = NULL, *old_tmp = NULL, *tc_str = NULL;
- while(elem != NULL) {
+ for(elem = tunnel->config_list; elem != NULL; elem = elem->next) {
LinphoneTunnelConfig *tunnel_config = (LinphoneTunnelConfig *)elem->data;
tc_str = linphone_tunnel_config_to_string(tunnel_config);
- if(tmp != NULL) {
- old_tmp = tmp;
- tmp = ms_strdup_printf("%s %s", old_tmp, tc_str);
- ms_free(old_tmp);
- ms_free(tc_str);
- } else {
- tmp = tc_str;
+ if(tc_str != NULL) {
+ if(tmp != NULL) {
+ old_tmp = tmp;
+ tmp = ms_strdup_printf("%s %s", old_tmp, tc_str);
+ ms_free(old_tmp);
+ ms_free(tc_str);
+ } else {
+ tmp = tc_str;
+ }
}
- elem = elem->next;
}
lp_config_set_string(config(tunnel), "tunnel", "server_addresses", tmp);
if(tmp != NULL) {
@@ -148,12 +159,12 @@ static void linphone_tunnel_save_config(LinphoneTunnel *tunnel) {
static void linphone_tunnel_add_server_intern(LinphoneTunnel *tunnel, LinphoneTunnelConfig *tunnel_config) {
if(linphone_tunnel_config_get_remote_udp_mirror_port(tunnel_config) == -1) {
- bcTunnel(tunnel)->addServer(linphone_tunnel_config_get_host(tunnel_config),
+ bcTunnel(tunnel)->addServer(linphone_tunnel_config_get_host(tunnel_config),
linphone_tunnel_config_get_port(tunnel_config));
} else {
- bcTunnel(tunnel)->addServer(linphone_tunnel_config_get_host(tunnel_config),
- linphone_tunnel_config_get_port(tunnel_config),
- linphone_tunnel_config_get_remote_udp_mirror_port(tunnel_config),
+ bcTunnel(tunnel)->addServer(linphone_tunnel_config_get_host(tunnel_config),
+ linphone_tunnel_config_get_port(tunnel_config),
+ linphone_tunnel_config_get_remote_udp_mirror_port(tunnel_config),
linphone_tunnel_config_get_delay(tunnel_config));
}
tunnel->config_list = ms_list_append(tunnel->config_list, tunnel_config);
@@ -205,38 +216,37 @@ void linphone_tunnel_remove_server(LinphoneTunnel *tunnel, LinphoneTunnelConfig
MSList *elem = ms_list_find(tunnel->config_list, tunnel_config);
if(elem != NULL) {
tunnel->config_list = ms_list_remove(tunnel->config_list, tunnel_config);
- linphone_tunnel_config_destroy(tunnel_config);
+ linphone_tunnel_config_destroy(tunnel_config);
linphone_tunnel_refresh_config(tunnel);
linphone_tunnel_save_config(tunnel);
- }
+ }
}
-const MSList *linphone_tunnel_get_servers(LinphoneTunnel *tunnel){
+const MSList *linphone_tunnel_get_servers(const LinphoneTunnel *tunnel){
return tunnel->config_list;
}
void linphone_tunnel_clean_servers(LinphoneTunnel *tunnel){
bcTunnel(tunnel)->cleanServers();
-
+
/* Free the list */
- ms_list_for_each(tunnel->config_list, (void (*)(void *))linphone_tunnel_config_destroy);
- tunnel->config_list = ms_list_free(tunnel->config_list);
-
+ ms_list_free_with_data(tunnel->config_list, (void (*)(void *))linphone_tunnel_config_destroy);
+ tunnel->config_list = NULL;
+
linphone_tunnel_save_config(tunnel);
}
-void linphone_tunnel_enable(LinphoneTunnel *tunnel, bool_t enabled){
- tunnel->auto_detect_enabled = FALSE;
- lp_config_set_int(config(tunnel),"tunnel","enabled",(int)enabled);
- bcTunnel(tunnel)->enable(enabled);
+void linphone_tunnel_set_mode(LinphoneTunnel *tunnel, LinphoneTunnelMode mode){
+ lp_config_set_string(config(tunnel),"tunnel","mode", _tunnel_mode_to_string(mode));
+ bcTunnel(tunnel)->setMode(mode);
}
-bool_t linphone_tunnel_enabled(LinphoneTunnel *tunnel){
- return bcTunnel(tunnel)->isEnabled();
+LinphoneTunnelMode linphone_tunnel_get_mode(const LinphoneTunnel *tunnel){
+ return bcTunnel(tunnel)->getMode();
}
-bool_t linphone_tunnel_connected(LinphoneTunnel *tunnel){
- return bcTunnel(tunnel)->isReady();
+bool_t linphone_tunnel_connected(const LinphoneTunnel *tunnel){
+ return bcTunnel(tunnel)->isConnected();
}
static OrtpLogFunc tunnelOrtpLogHandler=NULL;
@@ -312,27 +322,65 @@ void linphone_tunnel_reconnect(LinphoneTunnel *tunnel){
bcTunnel(tunnel)->reconnect();
}
-void linphone_tunnel_auto_detect(LinphoneTunnel *tunnel){
- tunnel->auto_detect_enabled = TRUE;
- bcTunnel(tunnel)->autoDetect();
+void linphone_tunnel_enable_sip(LinphoneTunnel *tunnel, bool_t enable) {
+ bcTunnel(tunnel)->tunnelizeSipPackets(enable);
+ lp_config_set_int(config(tunnel), "tunnel", "sip", (enable ? TRUE : FALSE));
}
-bool_t linphone_tunnel_auto_detect_enabled(LinphoneTunnel *tunnel) {
- return tunnel->auto_detect_enabled;
+bool_t linphone_tunnel_sip_enabled(const LinphoneTunnel *tunnel) {
+ return bcTunnel(tunnel)->tunnelizeSipPacketsEnabled() ? TRUE : FALSE;
}
static void my_ortp_logv(OrtpLogLevel level, const char *fmt, va_list args){
ortp_logv(level,fmt,args);
}
+static LinphoneTunnelMode _string_to_tunnel_mode(const char *string) {
+ if(string != NULL) {
+ int i;
+ for(i=0; i<3 && strcmp(string, _tunnel_mode_str[i]) != 0; i++);
+ if(i<3) {
+ return (LinphoneTunnelMode)i;
+ } else {
+ ms_error("Invalid tunnel mode '%s'", string);
+ return LinphoneTunnelModeDisable;
+ }
+ } else {
+ return LinphoneTunnelModeDisable;
+ }
+}
+
+static const char *_tunnel_mode_to_string(LinphoneTunnelMode mode) {
+ return _tunnel_mode_str[mode];
+}
+
/**
* Startup tunnel using configuration.
* Called internally from linphonecore at startup.
*/
void linphone_tunnel_configure(LinphoneTunnel *tunnel){
- bool_t enabled=(bool_t)lp_config_get_int(config(tunnel),"tunnel","enabled",FALSE);
+ LinphoneTunnelMode mode = _string_to_tunnel_mode(lp_config_get_string(config(tunnel), "tunnel", "mode", NULL));
+ bool_t tunnelizeSIPPackets = (bool_t)lp_config_get_int(config(tunnel), "tunnel", "sip", TRUE);
linphone_tunnel_enable_logs_with_handler(tunnel,TRUE,my_ortp_logv);
linphone_tunnel_load_config(tunnel);
- linphone_tunnel_enable(tunnel, enabled);
+ linphone_tunnel_enable_sip(tunnel, tunnelizeSIPPackets);
+ linphone_tunnel_set_mode(tunnel, mode);
}
+/* Deprecated functions */
+void linphone_tunnel_enable(LinphoneTunnel *tunnel, bool_t enabled) {
+ if(enabled) linphone_tunnel_set_mode(tunnel, LinphoneTunnelModeEnable);
+ else linphone_tunnel_set_mode(tunnel, LinphoneTunnelModeDisable);
+}
+
+bool_t linphone_tunnel_enabled(const LinphoneTunnel *tunnel) {
+ return linphone_tunnel_get_mode(tunnel) == LinphoneTunnelModeEnable;
+}
+
+void linphone_tunnel_auto_detect(LinphoneTunnel *tunnel) {
+ linphone_tunnel_set_mode(tunnel, LinphoneTunnelModeAuto);
+}
+
+bool_t linphone_tunnel_auto_detect_enabled(LinphoneTunnel *tunnel) {
+ return linphone_tunnel_get_mode(tunnel) == LinphoneTunnelModeAuto;
+}
diff --git a/coreapi/linphone_tunnel.h b/coreapi/linphone_tunnel.h
index 9b33e32f8..3a2c66330 100644
--- a/coreapi/linphone_tunnel.h
+++ b/coreapi/linphone_tunnel.h
@@ -50,10 +50,16 @@ extern "C"
typedef struct _LinphoneTunnelConfig LinphoneTunnelConfig;
+typedef enum _LinphoneTunnelMode {
+ LinphoneTunnelModeDisable,
+ LinphoneTunnelModeEnable,
+ LinphoneTunnelModeAuto
+} LinphoneTunnelMode;
+
/**
* Create a new tunnel configuration
*/
-LINPHONE_PUBLIC LinphoneTunnelConfig *linphone_tunnel_config_new();
+LINPHONE_PUBLIC LinphoneTunnelConfig *linphone_tunnel_config_new(void);
/**
* Set address of server.
@@ -131,51 +137,49 @@ LINPHONE_PUBLIC void linphone_tunnel_config_destroy(LinphoneTunnelConfig *tunnel
LINPHONE_PUBLIC void linphone_tunnel_add_server(LinphoneTunnel *tunnel, LinphoneTunnelConfig *tunnel_config);
/**
- * Remove tunnel server configuration
- *
+ * @brief Remove tunnel server configuration
* @param tunnel object
* @param tunnel_config object
*/
LINPHONE_PUBLIC void linphone_tunnel_remove_server(LinphoneTunnel *tunnel, LinphoneTunnelConfig *tunnel_config);
/**
- * @param tunnel object
- * returns a string of space separated list of host:port of tunnel server addresses
- * */
-LINPHONE_PUBLIC const MSList *linphone_tunnel_get_servers(LinphoneTunnel *tunnel);
+ * @brief Get added servers
+ * @param tunnel A LinphoneTunnel object
+ * @return A list of LinphoneTunnelConfig objects
+ */
+LINPHONE_PUBLIC const MSList *linphone_tunnel_get_servers(const LinphoneTunnel *tunnel);
/**
- * @param tunnel object
- * Removes all tunnel server address previously entered with addServer()
+ * @brief Removes all tunnel server address previously entered with addServer()
+ * @param tunnel A LinphoneTunnel object
**/
LINPHONE_PUBLIC void linphone_tunnel_clean_servers(LinphoneTunnel *tunnel);
/**
- * Sets whether tunneling of SIP and RTP is required.
+ * @brief Set 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 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.
- *
+ * @param mode See #LinphoneTunnelMode
**/
-LINPHONE_PUBLIC void linphone_tunnel_enable(LinphoneTunnel *tunnel, bool_t enabled);
+LINPHONE_PUBLIC void linphone_tunnel_set_mode(LinphoneTunnel *tunnel, LinphoneTunnelMode mode);
/**
- * @param tunnel object
- * Returns a boolean indicating whether tunneled operation is enabled.
+ * @brief Get the tunnel mode
+ * @param tunnel A LinphoneTunnel object
+ * @return Return a #LinphoneTunnelMode enumeration
**/
-LINPHONE_PUBLIC bool_t linphone_tunnel_enabled(LinphoneTunnel *tunnel);
+LINPHONE_PUBLIC LinphoneTunnelMode linphone_tunnel_get_mode(const LinphoneTunnel *tunnel);
/**
- * @param tunnel object
- * Returns a boolean indicating whether tunnel is connected successfully.
+ * @brief Check whether the tunnel is connected
+ * @param tunnel LinphoneTunnel object
+ * @return True if the tunnel is connected
**/
-bool_t linphone_tunnel_connected(LinphoneTunnel *tunnel);
-
-/**
- * @param tunnel object
- * Returns a boolean indicating whether tunnel is connected successfully.
-**/
-bool_t linphone_tunnel_connected(LinphoneTunnel *tunnel);
+LINPHONE_PUBLIC bool_t linphone_tunnel_connected(const LinphoneTunnel *tunnel);
/**
* @param tunnel object
@@ -187,20 +191,18 @@ bool_t linphone_tunnel_connected(LinphoneTunnel *tunnel);
LINPHONE_PUBLIC void linphone_tunnel_reconnect(LinphoneTunnel *tunnel);
/**
- * 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.
- *
Call this method each time to run the auto detection algorithm
+ * @brief Set whether SIP packets must be directly sent to a UA or pass through the tunnel
+ * @param tunnel Tunnel to configure
+ * @param enable If true, SIP packets shall pass through the tunnel
*/
-LINPHONE_PUBLIC void linphone_tunnel_auto_detect(LinphoneTunnel *tunnel);
+LINPHONE_PUBLIC void linphone_tunnel_enable_sip(LinphoneTunnel *tunnel, bool_t enable);
/**
- * Tells whether tunnel auto detection is enabled.
- * @param[in] tunnel LinphoneTunnel object.
- * @return TRUE if auto detection is enabled, FALSE otherwise.
+ * @brief Check whether tunnel is set to transport SIP packets
+ * @param tunnel Tunnel to check
+ * @return True, SIP packets shall pass through through tunnel
*/
-LINPHONE_PUBLIC bool_t linphone_tunnel_auto_detect_enabled(LinphoneTunnel *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.
@@ -222,8 +224,50 @@ LINPHONE_PUBLIC void linphone_tunnel_set_http_proxy(LinphoneTunnel *tunnel, cons
**/
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
+ * @param tunnel LinphoneTunnel object
+ * @param username User name
+ * @param passwd Password
+ */
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
+ * @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.
+ *
+**/
+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
+ * @return Returns a boolean indicating whether tunneled operation is enabled.
+**/
+LINPHONE_PUBLIC bool_t linphone_tunnel_enabled(const LinphoneTunnel *tunnel);
+
+/**
+ * @deprecated Replaced by linphone_tunnel_set_mode(LinphoneTunnelModeAuto)
+ * @brief 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.
+ *
Call this method each time to run the auto detection algorithm
+ */
+LINPHONE_PUBLIC void linphone_tunnel_auto_detect(LinphoneTunnel *tunnel);
+
+/**
+ * @deprecated Replaced by linphone_tunnel_get_mode()
+ * @brief Tells whether tunnel auto detection is enabled.
+ * @param[in] tunnel LinphoneTunnel object.
+ * @return TRUE if auto detection is enabled, FALSE otherwise.
+ */
+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 c208dd249..72693463b 100644
--- a/coreapi/linphone_tunnel_stubs.c
+++ b/coreapi/linphone_tunnel_stubs.c
@@ -29,7 +29,7 @@
#include "lpconfig.h"
-LinphoneTunnel* linphone_core_get_tunnel(LinphoneCore *lc){
+LinphoneTunnel* linphone_core_get_tunnel(const LinphoneCore *lc){
return lc->tunnel;
}
@@ -45,21 +45,21 @@ void linphone_tunnel_add_server(LinphoneTunnel *tunnel, LinphoneTunnelConfig *tu
void linphone_tunnel_remove_server(LinphoneTunnel *tunnel, LinphoneTunnelConfig *tunnel_config){
}
-const MSList *linphone_tunnel_get_servers(LinphoneTunnel *tunnel){
+const MSList *linphone_tunnel_get_servers(const LinphoneTunnel *tunnel){
return NULL;
}
void linphone_tunnel_clean_servers(LinphoneTunnel *tunnel){
}
-void linphone_tunnel_enable(LinphoneTunnel *tunnel, bool_t enabled){
+void linphone_tunnel_set_mode(LinphoneTunnel *tunnel, LinphoneTunnelMode mode) {
}
-bool_t linphone_tunnel_enabled(LinphoneTunnel *tunnel){
- return FALSE;
+LinphoneTunnelMode linphone_tunnel_get_mode(const LinphoneTunnel *tunnel){
+ return LinphoneTunnelModeDisable;
}
-bool_t linphone_tunnel_connected(LinphoneTunnel *tunnel){
+bool_t linphone_tunnel_connected(const LinphoneTunnel *tunnel){
return FALSE;
}
@@ -79,9 +79,14 @@ void linphone_tunnel_get_http_proxy(LinphoneTunnel*tunnel,const char **host, int
void linphone_tunnel_reconnect(LinphoneTunnel *tunnel){
}
-void linphone_tunnel_auto_detect(LinphoneTunnel *tunnel){
-}
-
void linphone_tunnel_configure(LinphoneTunnel *tunnel){
}
+void linphone_tunnel_enable_sip(LinphoneTunnel *tunnel, bool_t enable) {}
+bool_t linphone_tunnel_sip_enabled(const LinphoneTunnel *tunnel) { return FALSE; }
+
+/* Deprecated functions */
+void linphone_tunnel_enable(LinphoneTunnel *tunnel, bool_t enabled) {}
+bool_t linphone_tunnel_enabled(const LinphoneTunnel *tunnel) { return FALSE; }
+void linphone_tunnel_auto_detect(LinphoneTunnel *tunnel) {}
+bool_t linphone_tunnel_auto_detect_enabled(LinphoneTunnel *tunnel) { return FALSE; }
diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c
index 8f82311fd..2517c4a4c 100644
--- a/coreapi/linphonecall.c
+++ b/coreapi/linphonecall.c
@@ -37,6 +37,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "mediastreamer2/mseventqueue.h"
#include "mediastreamer2/mssndcard.h"
+static const char EC_STATE_STORE[] = ".linphone.ecstate";
+
static void linphone_call_stats_uninit(LinphoneCallStats *stats);
#ifdef VIDEO_ENABLED
@@ -151,17 +153,14 @@ static uint16_t linphone_call_get_avpf_rr_interval(const LinphoneCall *call) {
}
static void propagate_encryption_changed(LinphoneCall *call){
- LinphoneCore *lc=call->core;
if (!linphone_call_all_streams_encrypted(call)) {
ms_message("Some streams are not encrypted");
- call->current_params.media_encryption=LinphoneMediaEncryptionNone;
- if (lc->vtable.call_encryption_changed)
- lc->vtable.call_encryption_changed(call->core, call, FALSE, call->auth_token);
+ call->current_params->media_encryption=LinphoneMediaEncryptionNone;
+ linphone_core_notify_call_encryption_changed(call->core, call, FALSE, call->auth_token);
} else {
ms_message("All streams are encrypted");
- call->current_params.media_encryption=LinphoneMediaEncryptionZRTP;
- if (lc->vtable.call_encryption_changed)
- lc->vtable.call_encryption_changed(call->core, call, TRUE, call->auth_token);
+ call->current_params->media_encryption=LinphoneMediaEncryptionZRTP;
+ linphone_core_notify_call_encryption_changed(call->core, call, TRUE, call->auth_token);
}
}
@@ -171,9 +170,9 @@ static void linphone_call_audiostream_encryption_changed(void *data, bool_t encr
call = (LinphoneCall *)data;
- if (encrypted && call->core->vtable.display_status != NULL) {
+ if (encrypted) {
snprintf(status,sizeof(status)-1,_("Authentication token is %s"),call->auth_token);
- call->core->vtable.display_status(call->core, status);
+ linphone_core_notify_display_status(call->core, status);
}
propagate_encryption_changed(call);
@@ -236,6 +235,14 @@ static MSList *make_codec_list(LinphoneCore *lc, const MSList *codecs, int bandw
for(it=codecs;it!=NULL;it=it->next){
PayloadType *pt=(PayloadType*)it->data;
if (pt->flags & PAYLOAD_TYPE_ENABLED){
+ int sample_rate = payload_type_get_rate(pt);
+
+ if( strcasecmp("G722",pt->mime_type) == 0 ){
+ /* G722 spec says 8000 but the codec actually requires 16000 */
+ ms_debug("Correcting sample rate for G722");
+ sample_rate = 16000;
+ }
+
if (bandwidth_limit>0 && !linphone_core_is_payload_type_usable_for_bandwidth(lc,pt,bandwidth_limit)){
ms_message("Codec %s/%i eliminated because of audio bandwidth constraint of %i kbit/s",
pt->mime_type,pt->clock_rate,bandwidth_limit);
@@ -244,7 +251,7 @@ static MSList *make_codec_list(LinphoneCore *lc, const MSList *codecs, int bandw
if (linphone_core_check_payload_type_usability(lc,pt)){
l=ms_list_append(l,payload_type_clone(pt));
nb++;
- if (max_sample_rate && payload_type_get_rate(pt)>*max_sample_rate) *max_sample_rate=payload_type_get_rate(pt);
+ if (max_sample_rate && sample_rate>*max_sample_rate) *max_sample_rate=sample_rate;
}
}
if ((nb_codecs_limit > 0) && (nb >= nb_codecs_limit)) break;
@@ -305,7 +312,7 @@ static void setup_encryption_keys(LinphoneCall *call, SalMediaDescription *md){
for(i=0; inb_streams; i++) {
if (!sal_stream_description_active(&md->streams[i])) continue;
if (sal_stream_description_has_srtp(&md->streams[i]) == TRUE) {
- if (keep_srtp_keys && old_md && sal_stream_description_has_srtp(&old_md->streams[i]) == TRUE){
+ if (keep_srtp_keys && old_md && (sal_stream_description_active(&old_md->streams[i]) == TRUE) && (sal_stream_description_has_srtp(&old_md->streams[i]) == TRUE)) {
int j;
ms_message("Keeping same crypto keys.");
for(j=0;jstreams[i])) continue;
for (pt_it = md->streams[i].payloads; pt_it != NULL; pt_it = pt_it->next) {
pt = (PayloadType *)pt_it->data;
- if (call->params.avpf_enabled == TRUE) {
+ if (call->params->avpf_enabled == TRUE) {
payload_type_set_flag(pt, PAYLOAD_TYPE_RTCP_FEEDBACK_ENABLED);
avpf_params = payload_type_get_avpf_params(pt);
- avpf_params.trr_interval = call->params.avpf_rr_interval;
+ avpf_params.trr_interval = call->params->avpf_rr_interval;
} else {
payload_type_unset_flag(pt, PAYLOAD_TYPE_RTCP_FEEDBACK_ENABLED);
memset(&avpf_params, 0, sizeof(avpf_params));
@@ -348,20 +355,20 @@ static void setup_rtcp_xr(LinphoneCall *call, SalMediaDescription *md) {
LinphoneCore *lc = call->core;
int i;
- md->rtcp_xr.enabled = lp_config_get_int(lc->config, "rtp", "rtcp_xr_enabled", 0);
+ md->rtcp_xr.enabled = lp_config_get_int(lc->config, "rtp", "rtcp_xr_enabled", 1);
if (md->rtcp_xr.enabled == TRUE) {
- const char *rcvr_rtt_mode = lp_config_get_string(lc->config, "rtp", "rtcp_xr_rcvr_rtt_mode", "none");
+ const char *rcvr_rtt_mode = lp_config_get_string(lc->config, "rtp", "rtcp_xr_rcvr_rtt_mode", "all");
if (strcasecmp(rcvr_rtt_mode, "all") == 0) md->rtcp_xr.rcvr_rtt_mode = OrtpRtcpXrRcvrRttAll;
else if (strcasecmp(rcvr_rtt_mode, "sender") == 0) md->rtcp_xr.rcvr_rtt_mode = OrtpRtcpXrRcvrRttSender;
else md->rtcp_xr.rcvr_rtt_mode = OrtpRtcpXrRcvrRttNone;
if (md->rtcp_xr.rcvr_rtt_mode != OrtpRtcpXrRcvrRttNone) {
- md->rtcp_xr.rcvr_rtt_max_size = lp_config_get_int(lc->config, "rtp", "rtcp_xr_rcvr_rtt_max_size", 0);
+ md->rtcp_xr.rcvr_rtt_max_size = lp_config_get_int(lc->config, "rtp", "rtcp_xr_rcvr_rtt_max_size", 10000);
}
- md->rtcp_xr.stat_summary_enabled = lp_config_get_int(lc->config, "rtp", "rtcp_xr_stat_summary_enabled", 0);
+ md->rtcp_xr.stat_summary_enabled = lp_config_get_int(lc->config, "rtp", "rtcp_xr_stat_summary_enabled", 1);
if (md->rtcp_xr.stat_summary_enabled == TRUE) {
md->rtcp_xr.stat_summary_flags = OrtpRtcpXrStatSummaryLoss | OrtpRtcpXrStatSummaryDup | OrtpRtcpXrStatSummaryJitt | OrtpRtcpXrStatSummaryTTL;
}
- md->rtcp_xr.voip_metrics_enabled = lp_config_get_int(lc->config, "rtp", "rtcp_xr_voip_metrics_enabled", 0);
+ md->rtcp_xr.voip_metrics_enabled = lp_config_get_int(lc->config, "rtp", "rtcp_xr_voip_metrics_enabled", 1);
}
for (i = 0; i < md->nb_streams; i++) {
if (!sal_stream_description_active(&md->streams[i])) continue;
@@ -374,13 +381,6 @@ void linphone_call_increment_local_media_description(LinphoneCall *call){
md->session_ver++;
}
-static SalMediaProto get_proto_from_call_params(const LinphoneCallParams *params) {
- if ((params->media_encryption == LinphoneMediaEncryptionSRTP) && params->avpf_enabled) return SalProtoRtpSavpf;
- if (params->media_encryption == LinphoneMediaEncryptionSRTP) return SalProtoRtpSavp;
- if (params->avpf_enabled) return SalProtoRtpAvpf;
- return SalProtoRtpAvp;
-}
-
void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *call){
MSList *l;
PayloadType *pt;
@@ -391,9 +391,9 @@ void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *
SalMediaDescription *md=sal_media_description_new();
LinphoneAddress *addr;
char* local_ip=call->localip;
- const char *subject=linphone_call_params_get_session_name(&call->params);
+ const char *subject=linphone_call_params_get_session_name(call->params);
- linphone_core_adapt_to_network(lc,call->ping_time,&call->params);
+ linphone_core_adapt_to_network(lc,call->ping_time,call->params);
if (call->dest_proxy)
me=linphone_proxy_config_get_identity(call->dest_proxy);
@@ -409,8 +409,8 @@ void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *
strncpy(md->username,linphone_address_get_username(addr),sizeof(md->username));
if (subject) strncpy(md->name,subject,sizeof(md->name));
- if (call->params.down_bw)
- md->bandwidth=call->params.down_bw;
+ if (call->params->down_bw)
+ md->bandwidth=call->params->down_bw;
else md->bandwidth=linphone_core_get_download_bandwidth(lc);
/*set audio capabilities */
@@ -419,19 +419,19 @@ void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *
strncpy(md->streams[0].name,"Audio",sizeof(md->streams[0].name)-1);
md->streams[0].rtp_port=call->media_ports[0].rtp_port;
md->streams[0].rtcp_port=call->media_ports[0].rtcp_port;
- md->streams[0].proto=get_proto_from_call_params(&call->params);
+ md->streams[0].proto=get_proto_from_call_params(call->params);
md->streams[0].type=SalAudio;
- if (call->params.down_ptime)
- md->streams[0].ptime=call->params.down_ptime;
+ if (call->params->down_ptime)
+ md->streams[0].ptime=call->params->down_ptime;
else
md->streams[0].ptime=linphone_core_get_download_ptime(lc);
- l=make_codec_list(lc,lc->codecs_conf.audio_codecs,call->params.audio_bw,&md->streams[0].max_rate,-1);
+ l=make_codec_list(lc,lc->codecs_conf.audio_codecs,call->params->audio_bw,&md->streams[0].max_rate,-1);
pt=payload_type_clone(rtp_profile_get_payload_from_mime(lc->default_profile,"telephone-event"));
l=ms_list_append(l,pt);
md->streams[0].payloads=l;
nb_active_streams++;
- if (call->params.has_video){
+ if (call->params->has_video){
strncpy(md->streams[1].rtp_addr,local_ip,sizeof(md->streams[1].rtp_addr));
strncpy(md->streams[1].rtcp_addr,local_ip,sizeof(md->streams[1].rtcp_addr));
strncpy(md->streams[1].name,"Video",sizeof(md->streams[1].name)-1);
@@ -562,15 +562,13 @@ static void port_config_set(LinphoneCall *call, int stream_index, int min_port,
static void linphone_call_init_common(LinphoneCall *call, LinphoneAddress *from, LinphoneAddress *to){
int min_port, max_port;
ms_message("New LinphoneCall [%p] initialized (LinphoneCore version: %s)",call,linphone_core_get_version());
- call->magic=linphone_call_magic;
- call->refcnt=1;
call->state=LinphoneCallIdle;
call->transfer_state = LinphoneCallIdle;
call->media_start_time=0;
- call->log=linphone_call_log_new(call, from, to);
- call->owns_call_log=TRUE;
+ call->log=linphone_call_log_new(call->dir, from, to);
call->camera_enabled=TRUE;
- call->current_params.media_encryption=LinphoneMediaEncryptionNone;
+ call->current_params = linphone_call_params_new();
+ call->current_params->media_encryption=LinphoneMediaEncryptionNone;
linphone_core_get_audio_port_range(call->core, &min_port, &max_port);
port_config_set(call,0,min_port,max_port);
@@ -612,11 +610,11 @@ void linphone_call_create_op(LinphoneCall *call){
if (call->op) sal_op_release(call->op);
call->op=sal_op_new(call->core->sal);
sal_op_set_user_pointer(call->op,call);
- if (call->params.referer)
- sal_call_set_referer(call->op,call->params.referer->op);
- linphone_configure_op(call->core,call->op,call->log->to,call->params.custom_headers,FALSE);
- if (call->params.privacy != LinphonePrivacyDefault)
- sal_op_set_privacy(call->op,(SalPrivacyMask)call->params.privacy);
+ if (call->params->referer)
+ sal_call_set_referer(call->op,call->params->referer->op);
+ linphone_configure_op(call->core,call->op,call->log->to,call->params->custom_headers,FALSE);
+ if (call->params->privacy != LinphonePrivacyDefault)
+ sal_op_set_privacy(call->op,(SalPrivacyMask)call->params->privacy);
/*else privacy might be set by proxy */
}
@@ -639,21 +637,70 @@ static void linphone_call_outgoing_select_ip_version(LinphoneCall *call, Linphon
}else call->af=AF_INET;
}
+/**
+ * Fill the local ip that routes to the internet according to the destination, or guess it by other special means (upnp).
+ */
+static void linphone_call_get_local_ip(LinphoneCall *call, const LinphoneAddress *remote_addr){
+ const char *ip;
+ int af = call->af;
+ const char *dest = NULL;
+ if (call->dest_proxy == NULL) {
+ struct addrinfo hints;
+ struct addrinfo *res = NULL;
+ int err;
+ const char *domain = linphone_address_get_domain(remote_addr);
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_flags = AI_NUMERICHOST;
+ err = getaddrinfo(domain, NULL, &hints, &res);
+ if (err == 0) {
+ dest = domain;
+ }
+ if (res != NULL) freeaddrinfo(res);
+ }
+ if (_linphone_core_get_firewall_policy(call->core)==LinphonePolicyUseNatAddress
+ && (ip=linphone_core_get_nat_address_resolved(call->core))!=NULL){
+ strncpy(call->localip,ip,LINPHONE_IPADDR_SIZE);
+ return;
+ }
+#ifdef BUILD_UPNP
+ else if (call->core->upnp != NULL && linphone_core_get_firewall_policy(call->core)==LinphonePolicyUseUpnp &&
+ linphone_upnp_context_get_state(call->core->upnp) == LinphoneUpnpStateOk) {
+ ip = linphone_upnp_context_get_external_ipaddress(call->core->upnp);
+ strncpy(call->localip,ip,LINPHONE_IPADDR_SIZE);
+ return;
+ }
+#endif //BUILD_UPNP
+ linphone_core_get_local_ip(call->core, af, dest, call->localip);
+}
+
+static void linphone_call_destroy(LinphoneCall *obj);
+
+BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneCall);
+
+BELLE_SIP_INSTANCIATE_VPTR(LinphoneCall, belle_sip_object_t,
+ (belle_sip_object_destroy_t)linphone_call_destroy,
+ NULL, // clone
+ NULL, // marshal
+ FALSE
+);
+
LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to, const LinphoneCallParams *params, LinphoneProxyConfig *cfg){
- LinphoneCall *call=ms_new0(LinphoneCall,1);
+ LinphoneCall *call = belle_sip_object_new(LinphoneCall);
call->dir=LinphoneCallOutgoing;
call->core=lc;
linphone_call_outgoing_select_ip_version(call,to,cfg);
- linphone_core_get_local_ip(lc,call->af,call->localip);
+ linphone_call_get_local_ip(call, to);
linphone_call_init_common(call,from,to);
- _linphone_call_params_copy(&call->params,params);
+ call->params = linphone_call_params_copy(params);
- if (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) {
+ if (_linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) {
call->ice_session = ice_session_new();
ice_session_set_role(call->ice_session, IR_Controlling);
}
- if (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseStun) {
+ if (_linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseStun) {
call->ping_time=linphone_core_run_stun_tests(call->core,call);
}
#ifdef BUILD_UPNP
@@ -683,25 +730,24 @@ static void linphone_call_incoming_select_ip_version(LinphoneCall *call){
* Fix call parameters on incoming call to eg. enable AVPF if the incoming call propose it and it is not enabled locally.
*/
void linphone_call_set_compatible_incoming_call_parameters(LinphoneCall *call, const SalMediaDescription *md) {
- call->params.has_video &= linphone_core_media_description_contains_video_stream(md);
+ call->params->has_video &= linphone_core_media_description_contains_video_stream(md);
/* Handle AVPF and SRTP. */
- call->params.avpf_enabled = sal_media_description_has_avpf(md);
- if (call->params.avpf_enabled == TRUE) {
+ call->params->avpf_enabled = sal_media_description_has_avpf(md);
+ if (call->params->avpf_enabled == TRUE) {
if (call->dest_proxy != NULL) {
- call->params.avpf_rr_interval = linphone_proxy_config_get_avpf_rr_interval(call->dest_proxy) * 1000;
+ call->params->avpf_rr_interval = linphone_proxy_config_get_avpf_rr_interval(call->dest_proxy) * 1000;
} else {
- call->params.avpf_rr_interval = 5000;
+ call->params->avpf_rr_interval = linphone_core_get_avpf_rr_interval(call->core)*1000;
}
}
if ((sal_media_description_has_srtp(md) == TRUE) && (media_stream_srtp_supported() == TRUE)) {
- call->params.media_encryption = LinphoneMediaEncryptionSRTP;
+ call->params->media_encryption = LinphoneMediaEncryptionSRTP;
}
}
LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to, SalOp *op){
- LinphoneCall *call=ms_new0(LinphoneCall,1);
- char *from_str;
+ LinphoneCall *call = belle_sip_object_new(LinphoneCall);
const SalMediaDescription *md;
LinphoneFirewallPolicy fpol;
@@ -721,36 +767,39 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro
/*the following sends an option request back to the caller so that
we get a chance to discover our nat'd address before answering.*/
call->ping_op=sal_op_new(lc->sal);
- from_str=linphone_address_as_string_uri_only(from);
+
+ linphone_configure_op(lc, call->ping_op, from, NULL, FALSE);
+
sal_op_set_route(call->ping_op,sal_op_get_network_origin(op));
sal_op_set_user_pointer(call->ping_op,call);
- sal_ping(call->ping_op,linphone_core_find_best_identity(lc,from),from_str);
- ms_free(from_str);
+
+ sal_ping(call->ping_op,sal_op_get_from(call->ping_op), sal_op_get_to(call->ping_op));
}
}
linphone_address_clean(from);
- linphone_core_get_local_ip(lc,call->af,call->localip);
+ linphone_call_get_local_ip(call, from);
linphone_call_init_common(call, from, to);
+ call->params = linphone_call_params_new();
call->log->call_id=ms_strdup(sal_op_get_call_id(op)); /*must be known at that time*/
call->dest_proxy = linphone_core_lookup_known_proxy(call->core, to);
- linphone_core_init_default_params(lc, &call->params);
+ linphone_core_init_default_params(lc, call->params);
/*
* Initialize call parameters according to incoming call parameters. This is to avoid to ask later (during reINVITEs) for features that the remote
* end apparently does not support. This features are: privacy, video
*/
/*set privacy*/
- call->current_params.privacy=(LinphonePrivacyMask)sal_op_get_privacy(call->op);
+ call->current_params->privacy=(LinphonePrivacyMask)sal_op_get_privacy(call->op);
/*set video support */
md=sal_call_get_remote_media_description(op);
- call->params.has_video = lc->video_policy.automatically_accept;
+ call->params->has_video = lc->video_policy.automatically_accept;
if (md) {
// It is licit to receive an INVITE without SDP
// In this case WE chose the media parameters according to policy.
linphone_call_set_compatible_incoming_call_parameters(call, md);
}
- fpol=linphone_core_get_firewall_policy(call->core);
+ fpol=_linphone_core_get_firewall_policy(call->core);
/*create the ice session now if ICE is required*/
if (fpol==LinphonePolicyUseIce){
if (md){
@@ -809,7 +858,6 @@ static void linphone_call_set_terminated(LinphoneCall *call){
linphone_core_update_allocated_audio_bandwidth(lc);
linphone_call_stats_uninit(&call->stats[0]);
linphone_call_stats_uninit(&call->stats[1]);
- call->owns_call_log=FALSE;
linphone_call_log_completed(call);
@@ -830,10 +878,10 @@ static void linphone_call_set_terminated(LinphoneCall *call){
}
void linphone_call_fix_call_parameters(LinphoneCall *call){
- call->params.has_video=call->current_params.has_video;
+ call->params->has_video=call->current_params->has_video;
- if (call->params.media_encryption != LinphoneMediaEncryptionZRTP) /*in case of ZRTP call parameter are handle after zrtp negociation*/
- call->params.media_encryption=call->current_params.media_encryption;
+ if (call->params->media_encryption != LinphoneMediaEncryptionZRTP) /*in case of ZRTP call parameter are handle after zrtp negociation*/
+ call->params->media_encryption=call->current_params->media_encryption;
}
const char *linphone_call_state_to_string(LinphoneCallState cs){
@@ -880,7 +928,11 @@ const char *linphone_call_state_to_string(LinphoneCallState cs){
return "undefined state";
}
-void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const char *message){
+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){
LinphoneCore *lc=call->core;
if (call->state!=cstate){
@@ -919,8 +971,8 @@ void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const
call->media_start_time=time(NULL);
}
- if (lc->vtable.call_state_changed)
- lc->vtable.call_state_changed(lc,call,cstate,message);
+ if (!silently)
+ linphone_core_notify_call_state_changed(lc,call,cstate,message);
linphone_reporting_call_state_updated(call);
@@ -982,15 +1034,17 @@ static void linphone_call_destroy(LinphoneCall *obj)
if (obj->transfer_target){
linphone_call_unref(obj->transfer_target);
}
- if (obj->owns_call_log)
- linphone_call_log_destroy(obj->log);
+ if (obj->log)
+ linphone_call_log_unref(obj->log);
if (obj->auth_token) {
ms_free(obj->auth_token);
}
- linphone_call_params_uninit(&obj->params);
- linphone_call_params_uninit(&obj->current_params);
+ 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);
+ }
sal_error_info_reset(&obj->non_op_error);
- ms_free(obj);
}
/**
@@ -998,27 +1052,13 @@ static void linphone_call_destroy(LinphoneCall *obj)
* @{
**/
-/**
- * Increments the call 's reference count.
- * An application that wishes to retain a pointer to call object
- * must use this function to unsure the pointer remains
- * valid. Once the application no more needs this pointer,
- * it must call linphone_call_unref().
-**/
LinphoneCall * linphone_call_ref(LinphoneCall *obj){
- obj->refcnt++;
+ belle_sip_object_ref(obj);
return obj;
}
-/**
- * Decrements the call object reference count.
- * See linphone_call_ref().
-**/
void linphone_call_unref(LinphoneCall *obj){
- obj->refcnt--;
- if (obj->refcnt==0){
- linphone_call_destroy(obj);
- }
+ belle_sip_object_unref(obj);
}
/**
@@ -1028,35 +1068,35 @@ const LinphoneCallParams * linphone_call_get_current_params(LinphoneCall *call){
#ifdef VIDEO_ENABLED
VideoStream *vstream;
#endif
- MS_VIDEO_SIZE_ASSIGN(call->current_params.sent_vsize, UNKNOWN);
- MS_VIDEO_SIZE_ASSIGN(call->current_params.recv_vsize, UNKNOWN);
+ MS_VIDEO_SIZE_ASSIGN(call->current_params->sent_vsize, UNKNOWN);
+ MS_VIDEO_SIZE_ASSIGN(call->current_params->recv_vsize, UNKNOWN);
#ifdef VIDEO_ENABLED
vstream = call->videostream;
if (vstream != NULL) {
- call->current_params.sent_vsize = video_stream_get_sent_video_size(vstream);
- call->current_params.recv_vsize = video_stream_get_received_video_size(vstream);
- call->current_params.sent_fps = video_stream_get_sent_framerate(vstream);
- call->current_params.received_fps = video_stream_get_received_framerate(vstream);
+ call->current_params->sent_vsize = video_stream_get_sent_video_size(vstream);
+ call->current_params->recv_vsize = video_stream_get_received_video_size(vstream);
+ call->current_params->sent_fps = video_stream_get_sent_framerate(vstream);
+ call->current_params->received_fps = video_stream_get_received_framerate(vstream);
}
#endif
if (linphone_call_all_streams_encrypted(call)) {
if (linphone_call_get_authentication_token(call)) {
- call->current_params.media_encryption=LinphoneMediaEncryptionZRTP;
+ call->current_params->media_encryption=LinphoneMediaEncryptionZRTP;
} else {
- call->current_params.media_encryption=LinphoneMediaEncryptionSRTP;
+ call->current_params->media_encryption=LinphoneMediaEncryptionSRTP;
}
} else {
- call->current_params.media_encryption=LinphoneMediaEncryptionNone;
+ call->current_params->media_encryption=LinphoneMediaEncryptionNone;
}
- call->current_params.avpf_enabled = linphone_call_all_streams_avpf_enabled(call);
- if (call->current_params.avpf_enabled == TRUE) {
- call->current_params.avpf_rr_interval = linphone_call_get_avpf_rr_interval(call);
+ call->current_params->avpf_enabled = linphone_call_all_streams_avpf_enabled(call);
+ if (call->current_params->avpf_enabled == TRUE) {
+ call->current_params->avpf_rr_interval = linphone_call_get_avpf_rr_interval(call);
} else {
- call->current_params.avpf_rr_interval = 0;
+ call->current_params->avpf_rr_interval = 0;
}
- return &call->current_params;
+ return call->current_params;
}
/**
@@ -1066,10 +1106,12 @@ const LinphoneCallParams * linphone_call_get_current_params(LinphoneCall *call){
* supports video, encryption or whatever.
**/
const LinphoneCallParams * linphone_call_get_remote_params(LinphoneCall *call){
- LinphoneCallParams *cp=&call->remote_params;
- memset(cp,0,sizeof(*cp));
if (call->op){
- SalMediaDescription *md=sal_call_get_remote_media_description(call->op);
+ LinphoneCallParams *cp;
+ SalMediaDescription *md;
+ if (call->remote_params != NULL) linphone_call_params_unref(call->remote_params);
+ cp = call->remote_params = linphone_call_params_new();
+ md=sal_call_get_remote_media_description(call->op);
if (md) {
SalStreamDescription *sd;
unsigned int i;
@@ -1092,7 +1134,7 @@ const LinphoneCallParams * linphone_call_get_remote_params(LinphoneCall *call){
}
if (md->name[0]!='\0') linphone_call_params_set_session_name(cp,md->name);
}
- cp->custom_headers=(SalCustomHeader*)sal_op_get_recv_custom_header(call->op);
+ cp->custom_headers=sal_custom_header_clone((SalCustomHeader*)sal_op_get_recv_custom_header(call->op));
return cp;
}
return NULL;
@@ -1139,27 +1181,26 @@ const LinphoneErrorInfo *linphone_call_get_error_info(const LinphoneCall *call){
}
/**
- * Get the user_pointer in the LinphoneCall
+ * Get the user pointer associated with the LinphoneCall
*
* @ingroup call_control
- *
- * return user_pointer an opaque user pointer that can be retrieved at any time
+ * @return an opaque user pointer that can be retrieved at any time
**/
-void *linphone_call_get_user_pointer(LinphoneCall *call)
+void *linphone_call_get_user_data(const LinphoneCall *call)
{
- return call->user_pointer;
+ return call->user_data;
}
/**
- * Set the user_pointer in the LinphoneCall
+ * Set the user pointer associated with the LinphoneCall
*
* @ingroup call_control
*
- * the user_pointer is an opaque user pointer that can be retrieved at any time in the LinphoneCall
+ * the user pointer is an opaque user pointer that can be retrieved at any time in the LinphoneCall
**/
-void linphone_call_set_user_pointer(LinphoneCall *call, void *user_pointer)
+void linphone_call_set_user_data(LinphoneCall *call, void *user_pointer)
{
- call->user_pointer = user_pointer;
+ call->user_data = user_pointer;
}
/**
@@ -1303,7 +1344,6 @@ int linphone_call_take_video_snapshot(LinphoneCall *call, const char *file){
return ms_filter_call_method(call->videostream->jpegwriter,MS_JPEG_WRITER_TAKE_SNAPSHOT,(void*)file);
}
ms_warning("Cannot take snapshot: no currently running video stream on this call.");
- return -1;
#endif
return -1;
}
@@ -1313,7 +1353,7 @@ int linphone_call_take_video_snapshot(LinphoneCall *call, const char *file){
* Note that the snapshot is asynchronous, an application shall not assume that the file is created when the function returns.
* @param call a LinphoneCall
* @param file a path where to write the jpeg content.
- * @return 0 if successfull, -1 otherwise (typically if jpeg format is not supported).
+ * @return 0 if successfull, -1 otherwise (typically if jpeg format is not supported).
**/
int linphone_call_take_preview_snapshot(LinphoneCall *call, const char *file){
#ifdef VIDEO_ENABLED
@@ -1333,194 +1373,6 @@ bool_t linphone_call_camera_enabled (const LinphoneCall *call){
return call->camera_enabled;
}
-/**
- * Enable video stream.
-**/
-void linphone_call_params_enable_video(LinphoneCallParams *cp, bool_t enabled){
- cp->has_video=enabled;
-}
-
-/**
- * Returns the audio codec used in the call, described as a PayloadType structure.
-**/
-const PayloadType* linphone_call_params_get_used_audio_codec(const LinphoneCallParams *cp) {
- return cp->audio_codec;
-}
-
-
-/**
- * Returns the video codec used in the call, described as a PayloadType structure.
-**/
-const PayloadType* linphone_call_params_get_used_video_codec(const LinphoneCallParams *cp) {
- return cp->video_codec;
-}
-
-MSVideoSize linphone_call_params_get_sent_video_size(const LinphoneCallParams *cp) {
- return cp->sent_vsize;
-}
-
-MSVideoSize linphone_call_params_get_received_video_size(const LinphoneCallParams *cp) {
- return cp->recv_vsize;
-}
-
-/**
- * Gets the framerate of the video that is sent.
- * @param[in] cp The call parameters.
- * @return the actual sent framerate in frames per seconds, 0 if not available.
- */
-float linphone_call_params_get_sent_framerate(const LinphoneCallParams *cp){
- return cp->sent_fps;
-}
-
-/**
- * Gets the framerate of the video that is received.
- * @param[in] cp The call paramaters for which to get the received framerate.
- * @return the actual received framerate in frames per seconds, 0 if not available.
- */
-float linphone_call_params_get_received_framerate(const LinphoneCallParams *cp){
- return cp->received_fps;
-}
-
-const char * linphone_call_params_get_rtp_profile(const LinphoneCallParams *cp) {
- return sal_media_proto_to_string(get_proto_from_call_params(cp));
-}
-
-/**
- * @ingroup call_control
- * Use to know if this call has been configured in low bandwidth mode.
- * This mode can be automatically discovered thanks to a stun server when activate_edge_workarounds=1 in section [net] of configuration file.
- * An application that would have reliable way to know network capacity may not use activate_edge_workarounds=1 but instead manually configure
- * low bandwidth mode with linphone_call_params_enable_low_bandwidth().
- *
When enabled, this param may transform a call request with video in audio only mode.
- * @return TRUE if low bandwidth has been configured/detected
- */
-bool_t linphone_call_params_low_bandwidth_enabled(const LinphoneCallParams *cp) {
- return cp->low_bandwidth;
-}
-
-/**
- * @ingroup call_control
- * Indicate low bandwith mode.
- * Configuring a call to low bandwidth mode will result in the core to activate several settings for the call in order to ensure that bitrate usage
- * is lowered to the minimum possible. Typically, ptime (packetization time) will be increased, audio codec's output bitrate will be targetted to 20kbit/s provided
- * that it is achievable by the codec selected after SDP handshake. Video is automatically disabled.
- *
-**/
-void linphone_call_params_enable_low_bandwidth(LinphoneCallParams *cp, bool_t enabled){
- cp->low_bandwidth=enabled;
-}
-
-/**
- * Returns whether video is enabled.
-**/
-bool_t linphone_call_params_video_enabled(const LinphoneCallParams *cp){
- return cp->has_video;
-}
-
-/**
- * Returns kind of media encryption selected for the call.
-**/
-LinphoneMediaEncryption linphone_call_params_get_media_encryption(const LinphoneCallParams *cp) {
- return cp->media_encryption;
-}
-
-/**
- * Set requested media encryption for a call.
-**/
-void linphone_call_params_set_media_encryption(LinphoneCallParams *cp, LinphoneMediaEncryption e) {
- cp->media_encryption = e;
-}
-
-
-/**
- * Enable sending of real early media (during outgoing calls).
-**/
-void linphone_call_params_enable_early_media_sending(LinphoneCallParams *cp, bool_t enabled){
- cp->real_early_media=enabled;
-}
-
-/**
- * Indicates whether sending of early media was enabled.
-**/
-bool_t linphone_call_params_early_media_sending_enabled(const LinphoneCallParams *cp){
- return cp->real_early_media;
-}
-
-/**
- * Returns true if the call is part of the locally managed conference.
-**/
-bool_t linphone_call_params_get_local_conference_mode(const LinphoneCallParams *cp){
- return cp->in_conference;
-}
-
-/**
- * Refine bandwidth settings for this call by setting a bandwidth limit for audio streams.
- * As a consequence, codecs whose bitrates are not compatible with this limit won't be used.
-**/
-void linphone_call_params_set_audio_bandwidth_limit(LinphoneCallParams *cp, int bandwidth){
- cp->audio_bw=bandwidth;
-}
-
-void linphone_call_params_add_custom_header(LinphoneCallParams *params, const char *header_name, const char *header_value){
- params->custom_headers=sal_custom_header_append(params->custom_headers,header_name,header_value);
-}
-
-const char *linphone_call_params_get_custom_header(const LinphoneCallParams *params, const char *header_name){
- return sal_custom_header_find(params->custom_headers,header_name);
-}
-
-/**
- * Returns the session name of the media session (ie in SDP). Subject from the SIP message can be retrieved using linphone_call_params_get_custom_header() and is different.
- * @param cp the call parameters.
-**/
-const char *linphone_call_params_get_session_name(const LinphoneCallParams *cp){
- return cp->session_name;
-}
-
-/**
- * Set the session name of the media session (ie in SDP). Subject from the SIP message (which is different) can be set using linphone_call_params_set_custom_header().
- * @param cp the call parameters.
- * @param name the session name
-**/
-void linphone_call_params_set_session_name(LinphoneCallParams *cp, const char *name){
- if (cp->session_name){
- ms_free(cp->session_name);
- cp->session_name=NULL;
- }
- if (name) cp->session_name=ms_strdup(name);
-}
-
-void _linphone_call_params_copy(LinphoneCallParams *ncp, const LinphoneCallParams *cp){
- if (ncp==cp) return;
- memcpy(ncp,cp,sizeof(LinphoneCallParams));
- if (cp->record_file) ncp->record_file=ms_strdup(cp->record_file);
- if (cp->session_name) ncp->session_name=ms_strdup(cp->session_name);
- /*
- * The management of the custom headers is not optimal. We copy everything while ref counting would be more efficient.
- */
- if (cp->custom_headers) ncp->custom_headers=sal_custom_header_clone(cp->custom_headers);
-}
-
-/**
- * @ingroup call_control
- * Set requested level of privacy for the call.
- * \xmlonly javascript \endxmlonly
- * @param params the call parameters to be modified
- * @param privacy LinphonePrivacy to configure privacy
- * */
-void linphone_call_params_set_privacy(LinphoneCallParams *params, LinphonePrivacyMask privacy) {
- params->privacy=privacy;
-}
-
-/**
- * @ingroup call_control
- * Get requested level of privacy for the call.
- * @param params the call parameters
- * @return Privacy mode
- * */
-LinphonePrivacyMask linphone_call_params_get_privacy(const LinphoneCallParams *params) {
- return params->privacy;
-}
/**
* @ingroup call_control
@@ -1538,27 +1390,6 @@ const char* linphone_privacy_to_string(LinphonePrivacy privacy) {
default: return "Unknown privacy mode";
}
}
-/**
- * Copy existing LinphoneCallParams to a new LinphoneCallParams object.
-**/
-LinphoneCallParams * linphone_call_params_copy(const LinphoneCallParams *cp){
- LinphoneCallParams *ncp=ms_new0(LinphoneCallParams,1);
- _linphone_call_params_copy(ncp,cp);
- return ncp;
-}
-
-void linphone_call_params_uninit(LinphoneCallParams *p){
- if (p->record_file) ms_free(p->record_file);
- if (p->custom_headers) sal_custom_header_free(p->custom_headers);
-}
-
-/**
- * Destroy LinphoneCallParams.
-**/
-void linphone_call_params_destroy(LinphoneCallParams *p){
- linphone_call_params_uninit(p);
- ms_free(p);
-}
/**
@@ -1578,16 +1409,22 @@ static void video_stream_event_cb(void *user_pointer, const MSFilter *f, const u
LinphoneCall* call = (LinphoneCall*) user_pointer;
switch (event_id) {
case MS_VIDEO_DECODER_DECODING_ERRORS:
- ms_warning("Case is MS_VIDEO_DECODER_DECODING_ERRORS");
+ ms_warning("MS_VIDEO_DECODER_DECODING_ERRORS");
if (call->videostream && (video_stream_is_decoding_error_to_be_reported(call->videostream, 5000) == TRUE)) {
video_stream_decoding_error_reported(call->videostream);
linphone_call_send_vfu_request(call);
}
break;
+ case MS_VIDEO_DECODER_RECOVERED_FROM_ERRORS:
+ ms_message("MS_VIDEO_DECODER_RECOVERED_FROM_ERRORS");
+ if (call->videostream) {
+ video_stream_decoding_error_recovered(call->videostream);
+ }
+ break;
case MS_VIDEO_DECODER_FIRST_IMAGE_DECODED:
ms_message("First video frame decoded successfully");
if (call->nextVideoFrameDecoded._func != NULL)
- call->nextVideoFrameDecoded._func(call, call->nextVideoFrameDecoded._user_data);
+ call->nextVideoFrameDecoded._func(call, call->nextVideoFrameDecoded._user_data);
break;
case MS_VIDEO_DECODER_SEND_PLI:
case MS_VIDEO_DECODER_SEND_SLI:
@@ -1617,7 +1454,7 @@ static void port_config_set_random_choosed(LinphoneCall *call, int stream_index,
static void _linphone_call_prepare_ice_for_stream(LinphoneCall *call, int stream_index, bool_t create_checklist){
MediaStream *ms=stream_index == 0 ? (MediaStream*)call->audiostream : (MediaStream*)call->videostream;
- if ((linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) && (call->ice_session != NULL)){
+ if ((_linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) && (call->ice_session != NULL)){
IceCheckList *cl;
rtp_session_set_pktinfo(ms->sessions.rtp_session, TRUE);
rtp_session_set_symmetric_rtp(ms->sessions.rtp_session, FALSE);
@@ -1638,11 +1475,11 @@ int linphone_call_prepare_ice(LinphoneCall *call, bool_t incoming_offer){
SalMediaDescription *remote = NULL;
bool_t has_video=FALSE;
- if ((linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) && (call->ice_session != NULL)){
+ if ((_linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) && (call->ice_session != NULL)){
if (incoming_offer){
remote=sal_call_get_remote_media_description(call->op);
- has_video=call->params.has_video && linphone_core_media_description_contains_video_stream(remote);
- }else has_video=call->params.has_video;
+ has_video=call->params->has_video && linphone_core_media_description_contains_video_stream(remote);
+ }else has_video=call->params->has_video;
_linphone_call_prepare_ice_for_stream(call,0,TRUE);
if (has_video) _linphone_call_prepare_ice_for_stream(call,1,TRUE);
@@ -1672,6 +1509,7 @@ int linphone_call_prepare_ice(LinphoneCall *call, bool_t incoming_offer){
void linphone_call_init_audio_stream(LinphoneCall *call){
LinphoneCore *lc=call->core;
AudioStream *audiostream;
+ const char *location;
int dscp;
if (call->audiostream != NULL) return;
@@ -1695,16 +1533,24 @@ void linphone_call_init_audio_stream(LinphoneCall *call){
else if (strcasecmp(type,"full")==0)
audio_stream_enable_echo_limiter(audiostream,ELControlFull);
}
+
+ /* equalizer location in the graph: 'mic' = in input graph, otherwise in output graph.
+ Any other value than mic will default to output graph for compatibility */
+ location = lp_config_get_string(lc->config,"sound","eq_location","hp");
+ audiostream->eq_loc = (strcasecmp(location,"mic") == 0) ? MSEqualizerMic : MSEqualizerHP;
+ ms_message("Equalizer location: %s", location);
+
audio_stream_enable_gain_control(audiostream,TRUE);
if (linphone_core_echo_cancellation_enabled(lc)){
int len,delay,framesize;
- const char *statestr=lp_config_get_string(lc->config,"sound","ec_state",NULL);
+ char *statestr=lp_config_read_relative_file(lc->config, EC_STATE_STORE);
len=lp_config_get_int(lc->config,"sound","ec_tail_len",0);
delay=lp_config_get_int(lc->config,"sound","ec_delay",0);
framesize=lp_config_get_int(lc->config,"sound","ec_framesize",0);
audio_stream_set_echo_canceller_params(audiostream,len,delay,framesize);
if (statestr && audiostream->ec){
ms_filter_call_method(audiostream->ec,MS_ECHO_CANCELLER_SET_STATE_STRING,(void*)statestr);
+ ms_free(statestr);
}
}
audio_stream_enable_automatic_gain_control(audiostream,linphone_core_agc_enabled(lc));
@@ -1718,7 +1564,11 @@ void linphone_call_init_audio_stream(LinphoneCall *call){
if (lc->rtptf){
RtpTransport *artp=lc->rtptf->audio_rtp_func(lc->rtptf->audio_rtp_func_data, call->media_ports[0].rtp_port);
RtpTransport *artcp=lc->rtptf->audio_rtcp_func(lc->rtptf->audio_rtcp_func_data, call->media_ports[0].rtcp_port);
- rtp_session_set_transports(audiostream->ms.sessions.rtp_session,artp,artcp);
+ RtpTransport *meta_rtp;
+ RtpTransport *meta_rtcp;
+ meta_rtp_transport_new(&meta_rtp,TRUE,artp, 0);
+ meta_rtp_transport_new(&meta_rtcp,FALSE,artcp, 0);
+ rtp_session_set_transports(audiostream->ms.sessions.rtp_session,meta_rtp,meta_rtcp);
}
call->audiostream_app_evq = ortp_ev_queue_new();
@@ -1756,9 +1606,13 @@ void linphone_call_init_video_stream(LinphoneCall *call){
if (lc->rtptf){
RtpTransport *vrtp=lc->rtptf->video_rtp_func(lc->rtptf->video_rtp_func_data, call->media_ports[1].rtp_port);
RtpTransport *vrtcp=lc->rtptf->video_rtcp_func(lc->rtptf->video_rtcp_func_data, call->media_ports[1].rtcp_port);
- rtp_session_set_transports(call->videostream->ms.sessions.rtp_session,vrtp,vrtcp);
+ RtpTransport *meta_rtp;
+ RtpTransport *meta_rtcp;
+ meta_rtp_transport_new(&meta_rtp,TRUE,vrtp, 0);
+ meta_rtp_transport_new(&meta_rtcp,FALSE,vrtcp, 0);
+ rtp_session_set_transports(call->videostream->ms.sessions.rtp_session,meta_rtp,meta_rtcp);
}
- call->videostream_app_evq = ortp_ev_queue_new();
+ call->videostream_app_evq = ortp_ev_queue_new();
rtp_session_register_event_queue(call->videostream->ms.sessions.rtp_session,call->videostream_app_evq);
_linphone_call_prepare_ice_for_stream(call,1,FALSE);
#ifdef TEST_EXT_RENDERER
@@ -1783,8 +1637,7 @@ static void linphone_core_dtmf_received(LinphoneCore *lc, int dtmf){
ms_warning("Bad dtmf value %i",dtmf);
return;
}
- if (lc->vtable.dtmf_received != NULL)
- lc->vtable.dtmf_received(lc, linphone_core_get_current_call(lc), dtmf_tab[dtmf]);
+ linphone_core_notify_dtmf_received(lc, linphone_core_get_current_call(lc), dtmf_tab[dtmf]);
}
static void parametrize_equalizer(LinphoneCore *lc, AudioStream *st){
@@ -1871,7 +1724,7 @@ static void post_configure_audio_streams(LinphoneCall*call){
AudioStream *st=call->audiostream;
LinphoneCore *lc=call->core;
_post_configure_audio_stream(st,lc,call->audio_muted);
- if (lc->vtable.dtmf_received!=NULL){
+ if (linphone_core_dtmf_received_has_listener(lc)){
audio_stream_play_received_dtmfs(call->audiostream,FALSE);
}
if (call->record_active)
@@ -1882,7 +1735,7 @@ static int get_ideal_audio_bw(LinphoneCall *call, const SalMediaDescription *md,
int remote_bw=0;
int upload_bw;
int total_upload_bw=linphone_core_get_upload_bandwidth(call->core);
- const LinphoneCallParams *params=&call->params;
+ const LinphoneCallParams *params=call->params;
bool_t will_use_video=linphone_core_media_description_contains_video_stream(md);
bool_t forced=FALSE;
@@ -1929,7 +1782,7 @@ static RtpProfile *make_profile(LinphoneCall *call, const SalMediaDescription *m
bool_t first=TRUE;
LinphoneCore *lc=call->core;
int up_ptime=0;
- const LinphoneCallParams *params=&call->params;
+ const LinphoneCallParams *params=call->params;
*used_pt=-1;
@@ -2037,6 +1890,7 @@ static void configure_rtp_session_for_rtcp_xr(LinphoneCore *lc, LinphoneCall *ca
static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cname, bool_t muted, bool_t send_ringbacktone, bool_t use_arc){
LinphoneCore *lc=call->core;
+ LpConfig* conf;
int used_pt=-1;
char rtcp_tool[128]={0};
const SalStreamDescription *stream;
@@ -2061,7 +1915,7 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cna
call->audio_profile=make_profile(call,call->resultdesc,stream,&used_pt);
if (used_pt!=-1){
- call->current_params.audio_codec = rtp_profile_get_payload(call->audio_profile, used_pt);
+ call->current_params->audio_codec = rtp_profile_get_payload(call->audio_profile, used_pt);
if (playcard==NULL) {
ms_warning("No card defined for playback !");
}
@@ -2081,15 +1935,20 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cna
/*playfile=NULL;*/
}
if (send_ringbacktone){
+ conf = linphone_core_get_config(lc);
captcard=NULL;
playfile=NULL;/* it is setup later*/
+ if( conf && lp_config_get_int(conf,"sound","send_ringback_without_playback", 0) == 1){
+ playcard = NULL;
+ recfile = NULL;
+ }
}
/*if playfile are supplied don't use soundcards*/
if (lc->use_files) {
captcard=NULL;
playcard=NULL;
}
- if (call->params.in_conference){
+ if (call->params->in_conference){
/* first create the graph without soundcard resources*/
captcard=playcard=NULL;
}
@@ -2101,10 +1960,12 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cna
if (playcard && stream->max_rate>0) ms_snd_card_set_preferred_sample_rate(playcard, stream->max_rate);
if (captcard && stream->max_rate>0) ms_snd_card_set_preferred_sample_rate(captcard, stream->max_rate);
audio_stream_enable_adaptive_bitrate_control(call->audiostream,use_arc);
+ media_stream_set_adaptive_bitrate_algorithm(&call->audiostream->ms,
+ ms_qos_analyzer_algorithm_from_string(linphone_core_get_adaptive_rate_algorithm(lc)));
audio_stream_enable_adaptive_jittcomp(call->audiostream, linphone_core_audio_adaptive_jittcomp_enabled(lc));
- if (!call->params.in_conference && call->params.record_file){
- audio_stream_mixed_record_open(call->audiostream,call->params.record_file);
- call->current_params.record_file=ms_strdup(call->params.record_file);
+ if (!call->params->in_conference && call->params->record_file){
+ audio_stream_mixed_record_open(call->audiostream,call->params->record_file);
+ call->current_params->record_file=ms_strdup(call->params->record_file);
}
/* valid local tags are > 0 */
if (sal_stream_description_has_srtp(stream) == TRUE) {
@@ -2147,13 +2008,13 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cna
setup_ring_player(lc,call);
}
- if (call->params.in_conference){
+ if (call->params->in_conference){
/*transform the graph to connect it to the conference filter */
mute=stream->dir==SalStreamRecvOnly;
linphone_call_add_to_conf(call, mute);
}
- call->current_params.in_conference=call->params.in_conference;
- call->current_params.low_bandwidth=call->params.low_bandwidth;
+ call->current_params->in_conference=call->params->in_conference;
+ call->current_params->low_bandwidth=call->params->low_bandwidth;
}else ms_warning("No audio stream accepted ?");
}
}
@@ -2164,12 +2025,17 @@ static void linphone_call_start_video_stream(LinphoneCall *call, const char *cna
int used_pt=-1;
char rtcp_tool[128]={0};
const SalStreamDescription *vstream;
+ MSFilter* source = NULL;
+ bool_t reused_preview = FALSE;
snprintf(rtcp_tool,sizeof(rtcp_tool)-1,"%s-%s",linphone_core_get_user_agent_name(),linphone_core_get_user_agent_version());
/* shutdown preview */
if (lc->previewstream!=NULL) {
- video_preview_stop(lc->previewstream);
+
+ if( lc->video_conf.reuse_preview_source == FALSE) video_preview_stop(lc->previewstream);
+ else source = video_preview_stop_reuse_source(lc->previewstream);
+
lc->previewstream=NULL;
}
@@ -2186,11 +2052,13 @@ static void linphone_call_start_video_stream(LinphoneCall *call, const char *cna
MSWebCam *cam=lc->video_conf.device;
bool_t is_inactive=FALSE;
- call->current_params.video_codec = rtp_profile_get_payload(call->video_profile, used_pt);
- call->current_params.has_video=TRUE;
+ call->current_params->video_codec = rtp_profile_get_payload(call->video_profile, used_pt);
+ call->current_params->has_video=TRUE;
video_stream_enable_adaptive_bitrate_control(call->videostream,
linphone_core_adaptive_rate_control_enabled(lc));
+ media_stream_set_adaptive_bitrate_algorithm(&call->videostream->ms,
+ ms_qos_analyzer_algorithm_from_string(linphone_core_get_adaptive_rate_algorithm(lc)));
video_stream_enable_adaptive_jittcomp(call->videostream, linphone_core_video_adaptive_jittcomp_enabled(lc));
if (lc->video_conf.preview_vsize.width!=0)
video_stream_set_preview_size(call->videostream,lc->video_conf.preview_vsize);
@@ -2242,15 +2110,30 @@ static void linphone_call_start_video_stream(LinphoneCall *call, const char *cna
video_stream_set_device_rotation(call->videostream, lc->device_rotation);
video_stream_set_rtcp_information(call->videostream, cname, rtcp_tool);
video_stream_set_freeze_on_error(call->videostream, lp_config_get_int(lc->config, "video", "freeze_on_error", 0));
- video_stream_start(call->videostream,
- call->video_profile, rtp_addr, vstream->rtp_port,
- rtcp_addr,
- linphone_core_rtcp_enabled(lc) ? (vstream->rtcp_port ? vstream->rtcp_port : vstream->rtp_port+1) : 0,
- used_pt, linphone_core_get_video_jittcomp(lc), cam);
+ if( lc->video_conf.reuse_preview_source && source ){
+ ms_message("video_stream_start_with_source kept: %p", source);
+ video_stream_start_with_source(call->videostream,
+ call->video_profile, rtp_addr, vstream->rtp_port,
+ rtcp_addr,
+ linphone_core_rtcp_enabled(lc) ? (vstream->rtcp_port ? vstream->rtcp_port : vstream->rtp_port+1) : 0,
+ used_pt, linphone_core_get_video_jittcomp(lc), cam, source);
+ reused_preview = TRUE;
+ } else {
+ video_stream_start(call->videostream,
+ call->video_profile, rtp_addr, vstream->rtp_port,
+ rtcp_addr,
+ linphone_core_rtcp_enabled(lc) ? (vstream->rtcp_port ? vstream->rtcp_port : vstream->rtp_port+1) : 0,
+ used_pt, linphone_core_get_video_jittcomp(lc), cam);
+ }
}
}else ms_warning("No video stream accepted.");
}else{
- ms_warning("No valid video stream defined.");
+ ms_message("No valid video stream defined.");
+ }
+ if( reused_preview == FALSE && source != NULL ){
+ /* destroy not-reused source filter */
+ ms_warning("Video preview (%p) not reused: destroying it.", source);
+ ms_filter_destroy(source);
}
#endif
}
@@ -2264,8 +2147,8 @@ void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_mut
const SalStreamDescription *vstream=sal_media_description_find_best_stream(call->resultdesc,SalVideo);
#endif
- call->current_params.audio_codec = NULL;
- call->current_params.video_codec = NULL;
+ call->current_params->audio_codec = NULL;
+ call->current_params->video_codec = NULL;
if ((call->audiostream == NULL) && (call->videostream == NULL)) {
ms_fatal("start_media_stream() called without prior init !");
@@ -2285,7 +2168,7 @@ void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_mut
if (call->audiostream!=NULL) {
linphone_call_start_audio_stream(call,cname,all_inputs_muted,send_ringbacktone,use_arc);
}
- call->current_params.has_video=FALSE;
+ call->current_params->has_video=FALSE;
if (call->videostream!=NULL) {
if (call->audiostream) audio_stream_link_video(call->audiostream,call->videostream);
linphone_call_start_video_stream(call,cname,all_inputs_muted);
@@ -2295,7 +2178,7 @@ void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_mut
call->playing_ringbacktone=send_ringbacktone;
call->up_bw=linphone_core_get_upload_bandwidth(lc);
- if (call->params.media_encryption==LinphoneMediaEncryptionZRTP) {
+ if (call->params->media_encryption==LinphoneMediaEncryptionZRTP) {
OrtpZrtpParams params;
memset(¶ms,0,sizeof(OrtpZrtpParams));
/*call->current_params.media_encryption will be set later when zrtp is activated*/
@@ -2311,7 +2194,7 @@ void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_mut
}
#endif
}else{
- call->current_params.media_encryption=linphone_call_all_streams_encrypted(call) ?
+ call->current_params->media_encryption=linphone_call_all_streams_encrypted(call) ?
LinphoneMediaEncryptionSRTP : LinphoneMediaEncryptionNone;
}
@@ -2424,7 +2307,7 @@ static void linphone_call_stop_audio_stream(LinphoneCall *call) {
ms_filter_call_method(call->audiostream->ec,MS_ECHO_CANCELLER_GET_STATE_STRING,&state_str);
if (state_str){
ms_message("Writing echo canceler state, %i bytes",(int)strlen(state_str));
- lp_config_set_string(call->core->config,"sound","ec_state",state_str);
+ lp_config_write_relative_file(call->core->config, EC_STATE_STORE, state_str);
}
}
audio_stream_get_local_rtp_stats(call->audiostream,&call->log->local_stats);
@@ -2434,7 +2317,7 @@ static void linphone_call_stop_audio_stream(LinphoneCall *call) {
}
audio_stream_stop(call->audiostream);
call->audiostream=NULL;
- call->current_params.audio_codec = NULL;
+ call->current_params->audio_codec = NULL;
}
}
@@ -2450,7 +2333,7 @@ static void linphone_call_stop_video_stream(LinphoneCall *call) {
linphone_call_log_fill_stats(call->log,(MediaStream*)call->videostream);
video_stream_stop(call->videostream);
call->videostream=NULL;
- call->current_params.video_codec = NULL;
+ call->current_params->video_codec = NULL;
}
#endif
}
@@ -2761,26 +2644,39 @@ uint64_t linphone_call_stats_get_late_packets_cumulative_number(const LinphoneCa
}
/**
- * Enable recording of the call (voice-only).
- * This function must be used before the call parameters are assigned to the call.
- * The call recording can be started and paused after the call is established with
- * linphone_call_start_recording() and linphone_call_pause_recording().
- * @param cp the call parameters
- * @param path path and filename of the file where audio is written.
-**/
-void linphone_call_params_set_record_file(LinphoneCallParams *cp, const char *path){
- if (cp->record_file){
- ms_free(cp->record_file);
- cp->record_file=NULL;
- }
- if (path) cp->record_file=ms_strdup(path);
+ * Get the bandwidth measurement of the received stream, expressed in kbit/s, including IP/UDP/RTP headers.
+ * @param[in] stats LinphoneCallStats object
+ * @return The bandwidth measurement of the received stream in kbit/s.
+ */
+float linphone_call_stats_get_download_bandwidth(const LinphoneCallStats *stats) {
+ return stats->download_bandwidth;
}
/**
- * Retrieves the path for the audio recoding of the call.
-**/
-const char *linphone_call_params_get_record_file(const LinphoneCallParams *cp){
- return cp->record_file;
+ * Get the bandwidth measurement of the sent stream, expressed in kbit/s, including IP/UDP/RTP headers.
+ * @param[in] stats LinphoneCallStats object
+ * @return The bandwidth measurement of the sent stream in kbit/s.
+ */
+float linphone_call_stats_get_upload_bandwidth(const LinphoneCallStats *stats) {
+ return stats->upload_bandwidth;
+}
+
+/**
+ * Get the state of ICE processing.
+ * @param[in] stats LinphoneCallStats object
+ * @return The state of ICE processing.
+ */
+LinphoneIceState linphone_call_stats_get_ice_state(const LinphoneCallStats *stats) {
+ return stats->ice_state;
+}
+
+/**
+ * Get the state of uPnP processing.
+ * @param[in] stats LinphoneCallStats object
+ * @return The state of uPnP processing.
+ */
+LinphoneUpnpState linphone_call_stats_get_upnp_state(const LinphoneCallStats *stats) {
+ return stats->upnp_state;
}
/**
@@ -2788,11 +2684,11 @@ const char *linphone_call_params_get_record_file(const LinphoneCallParams *cp){
* The output file where audio is recorded must be previously specified with linphone_call_params_set_record_file().
**/
void linphone_call_start_recording(LinphoneCall *call){
- if (!call->params.record_file){
+ if (!call->params->record_file){
ms_error("linphone_call_start_recording(): no output file specified. Use linphone_call_params_set_record_file().");
return;
}
- if (call->audiostream && !call->params.in_conference){
+ if (call->audiostream && !call->params->in_conference){
audio_stream_mixed_record_start(call->audiostream);
}
call->record_active=TRUE;
@@ -2802,7 +2698,7 @@ void linphone_call_start_recording(LinphoneCall *call){
* Stop call recording.
**/
void linphone_call_stop_recording(LinphoneCall *call){
- if (call->audiostream && !call->params.in_conference){
+ if (call->audiostream && !call->params->in_conference){
audio_stream_mixed_record_stop(call->audiostream);
}
call->record_active=FALSE;
@@ -2835,8 +2731,7 @@ static void linphone_core_disconnected(LinphoneCore *lc, LinphoneCall *call){
if (from) ms_free(from);
ms_message("On call [%p]: %s",call,temp);
- if (lc->vtable.display_warning!=NULL)
- lc->vtable.display_warning(lc,temp);
+ linphone_core_notify_display_warning(lc,temp);
linphone_core_terminate_call(lc,call);
linphone_core_play_named_tone(lc,LinphoneToneCallLost);
}
@@ -2847,17 +2742,16 @@ static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){
int ping_time;
if (evt == ORTP_EVENT_ICE_SESSION_PROCESSING_FINISHED) {
- LinphoneCallParams params;
- _linphone_call_params_copy(¶ms,&call->current_params);
- if (call->params.media_encryption == LinphoneMediaEncryptionZRTP) {
+ LinphoneCallParams *params = linphone_call_params_copy(call->current_params);
+ if (call->params->media_encryption == LinphoneMediaEncryptionZRTP) {
/* preserve media encryption param because at that time ZRTP negociation may still be ongoing*/
- params.media_encryption=call->params.media_encryption;
+ params->media_encryption=call->params->media_encryption;
}
switch (ice_session_state(call->ice_session)) {
case IS_Completed:
ice_session_select_candidates(call->ice_session);
if (ice_session_role(call->ice_session) == IR_Controlling) {
- linphone_core_update_call(call->core, call, ¶ms);
+ linphone_core_update_call(call->core, call, params);
}
break;
case IS_Failed:
@@ -2865,7 +2759,7 @@ static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){
ice_session_select_candidates(call->ice_session);
if (ice_session_role(call->ice_session) == IR_Controlling) {
/* At least one ICE session has succeeded, so perform a call update. */
- linphone_core_update_call(call->core, call, ¶ms);
+ linphone_core_update_call(call->core, call, params);
}
}
break;
@@ -2873,6 +2767,7 @@ static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){
break;
}
linphone_core_update_ice_state_in_call_stats(call);
+ linphone_call_params_unref(params);
} else if (evt == ORTP_EVENT_ICE_GATHERING_FINISHED) {
if (evd->info.ice_processing_successful==TRUE) {
@@ -2892,7 +2787,7 @@ static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){
linphone_core_start_update_call(call->core, call);
break;
case LinphoneCallUpdatedByRemote:
- linphone_core_start_accept_call_update(call->core, call);
+ linphone_core_start_accept_call_update(call->core, call,call->prevstate,linphone_call_state_to_string(call->prevstate));
break;
case LinphoneCallOutgoingInit:
linphone_call_stop_media_streams_for_ice_gathering(call);
@@ -2907,13 +2802,13 @@ static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){
}
} else if (evt == ORTP_EVENT_ICE_LOSING_PAIRS_COMPLETED) {
if (call->state==LinphoneCallUpdatedByRemote){
- linphone_core_start_accept_call_update(call->core, call);
+ linphone_core_start_accept_call_update(call->core, call,call->prevstate,linphone_call_state_to_string(call->prevstate));
linphone_core_update_ice_state_in_call_stats(call);
}
} else if (evt == ORTP_EVENT_ICE_RESTART_NEEDED) {
ice_session_restart(call->ice_session);
ice_session_set_role(call->ice_session, IR_Controlling);
- linphone_core_update_call(call->core, call, &call->current_params);
+ linphone_core_update_call(call->core, call, call->current_params);
}
}
@@ -2958,8 +2853,7 @@ void linphone_call_notify_stats_updated(LinphoneCall *call, int stream_index){
LinphoneCore *lc=call->core;
if (stats->updated){
linphone_reporting_on_rtcp_update(call, stream_index);
- if (lc->vtable.call_stats_updated)
- lc->vtable.call_stats_updated(lc, call, stats);
+ linphone_core_notify_call_stats_updated(lc, call, stats);
stats->updated = 0;
}
}
@@ -3054,11 +2948,10 @@ void linphone_call_log_completed(LinphoneCall *call){
info=ortp_strdup_printf(ngettext("You have missed %i call.",
"You have missed %i calls.", lc->missed_calls),
lc->missed_calls);
- if (lc->vtable.display_status!=NULL)
- lc->vtable.display_status(lc,info);
+ linphone_core_notify_display_status(lc,info);
ms_free(info);
}
- lc->call_logs=ms_list_prepend(lc->call_logs,(void *)call->log);
+ lc->call_logs=ms_list_prepend(lc->call_logs,linphone_call_log_ref(call->log));
if (ms_list_size(lc->call_logs)>lc->max_call_logs){
MSList *elem,*prevelem=NULL;
/*find the last element*/
@@ -3066,12 +2959,10 @@ void linphone_call_log_completed(LinphoneCall *call){
prevelem=elem;
}
elem=prevelem;
- linphone_call_log_destroy((LinphoneCallLog*)elem->data);
+ linphone_call_log_unref((LinphoneCallLog*)elem->data);
lc->call_logs=ms_list_remove_link(lc->call_logs,elem);
}
- if (lc->vtable.call_log_updated!=NULL){
- lc->vtable.call_log_updated(lc,call->log);
- }
+ linphone_core_notify_call_log_updated(lc,call->log);
call_logs_write_to_config_file(lc);
}
@@ -3090,13 +2981,12 @@ void linphone_call_set_transfer_state(LinphoneCall* call, LinphoneCallState stat
,linphone_call_state_to_string(call->transfer_state)
,linphone_call_state_to_string(state));
call->transfer_state = state;
- if (lc->vtable.transfer_state_changed)
- lc->vtable.transfer_state_changed(lc, call, state);
+ linphone_core_notify_transfer_state_changed(lc, call, state);
}
}
bool_t linphone_call_is_in_conference(const LinphoneCall *call) {
- return call->params.in_conference;
+ return call->params->in_conference;
}
/**
@@ -3130,7 +3020,7 @@ void linphone_call_zoom_video(LinphoneCall* call, float zoom_factor, float* cx,
zoom[0] = zoom_factor;
zoom[1] = *cx;
zoom[2] = *cy;
- ms_filter_call_method(vstream->output, MS_VIDEO_DISPLAY_ZOOM, &zoom);
+ ms_filter_call_method(vstream->output, MS_VIDEO_DISPLAY_ZOOM, &zoom);
}else ms_warning("Could not apply zoom: video output wasn't activated.");
}
@@ -3140,7 +3030,7 @@ static LinphoneAddress *get_fixed_contact(LinphoneCore *lc, LinphoneCall *call ,
const char *localip=call->localip;
/* first use user's supplied ip address if asked*/
- if (linphone_core_get_firewall_policy(lc)==LinphonePolicyUseNatAddress){
+ if (_linphone_core_get_firewall_policy(lc)==LinphonePolicyUseNatAddress){
ctt=linphone_core_get_primary_contact_parsed(lc);
linphone_address_set_domain(ctt,linphone_core_get_nat_address_resolved(lc));
ret=ctt;
@@ -3186,3 +3076,16 @@ void linphone_call_set_contact_op(LinphoneCall* call) {
linphone_address_destroy(contact);
}
}
+
+LinphonePlayer *linphone_call_get_player(LinphoneCall *call){
+ if (call->player==NULL)
+ call->player=linphone_call_build_player(call);
+ return call->player;
+}
+
+void linphone_call_set_new_params(LinphoneCall *call, const LinphoneCallParams *params){
+ LinphoneCallParams *cp=NULL;
+ if (params) cp=linphone_call_params_copy(params);
+ if (call->params) linphone_call_params_unref(call->params);
+ call->params=cp;
+}
diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c
index 8e5e06172..1cb00d513 100644
--- a/coreapi/linphonecore.c
+++ b/coreapi/linphonecore.c
@@ -17,8 +17,6 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-#define _GNU_SOURCE
-
#include "linphonecore.h"
#include "sipsetup.h"
#include "lpconfig.h"
@@ -42,7 +40,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifdef HAVE_CONFIG_H
#include "config.h"
-#include "liblinphone_gitversion.h"
+#ifndef ANDROID /*on Android LIBLINPHONE version is passed from root Makefile*/
+ #include "liblinphone_gitversion.h"
+#endif
#else
#ifndef LIBLINPHONE_GIT_VERSION
#define LIBLINPHONE_GIT_VERSION "unknown"
@@ -64,6 +64,7 @@ static const char *liblinphone_version=
LIBLINPHONE_VERSION
#endif
;
+static bool_t liblinphone_serialize_logs = FALSE;
static void set_network_reachable(LinphoneCore* lc,bool_t isReachable, time_t curtime);
static void linphone_core_run_hooks(LinphoneCore *lc);
static void linphone_core_free_hooks(LinphoneCore *lc);
@@ -75,10 +76,10 @@ static void linphone_core_free_hooks(LinphoneCore *lc);
const char *linphone_core_get_nat_address_resolved(LinphoneCore *lc);
static void toggle_video_preview(LinphoneCore *lc, bool_t val);
-#ifdef WINAPI_FAMILY_PHONE_APP
-#define SOUNDS_PREFIX "Assets/Sounds/"
-#else
+#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
#define SOUNDS_PREFIX
+#else
+#define SOUNDS_PREFIX "Assets/Sounds/"
#endif
/* relative path where is stored local ring*/
#define LOCAL_RING SOUNDS_PREFIX "rings/oldphone.wav"
@@ -101,305 +102,6 @@ int lc_callback_obj_invoke(LCCallbackObj *obj, LinphoneCore *lc){
}
-/*prevent a gcc bug with %c*/
-static size_t my_strftime(char *s, size_t max, const char *fmt, const struct tm *tm){
- return strftime(s, max, fmt, tm);
-}
-
-static void set_call_log_date(LinphoneCallLog *cl, time_t start_time){
- struct tm loctime;
-#ifdef WIN32
-#if !defined(_WIN32_WCE)
- loctime=*localtime(&start_time);
- /*FIXME*/
-#endif /*_WIN32_WCE*/
-#else
- localtime_r(&start_time,&loctime);
-#endif
- my_strftime(cl->start_date,sizeof(cl->start_date),"%c",&loctime);
-}
-
-LinphoneCallLog * linphone_call_log_new(LinphoneCall *call, LinphoneAddress *from, LinphoneAddress *to){
- LinphoneCallLog *cl=ms_new0(LinphoneCallLog,1);
- cl->dir=call->dir;
- cl->start_date_time=time(NULL);
- set_call_log_date(cl,cl->start_date_time);
- cl->from=from;
- cl->to=to;
- cl->status=LinphoneCallAborted; /*default status*/
- cl->quality=-1;
-
- cl->reporting.reports[LINPHONE_CALL_STATS_AUDIO]=linphone_reporting_new();
- cl->reporting.reports[LINPHONE_CALL_STATS_VIDEO]=linphone_reporting_new();
- return cl;
-}
-
-void call_logs_write_to_config_file(LinphoneCore *lc){
- MSList *elem;
- char logsection[32];
- int i;
- char *tmp;
- LpConfig *cfg=lc->config;
-
- if (linphone_core_get_global_state (lc)==LinphoneGlobalStartup) return;
-
- for(i=0,elem=lc->call_logs;elem!=NULL;elem=elem->next,++i){
- LinphoneCallLog *cl=(LinphoneCallLog*)elem->data;
- snprintf(logsection,sizeof(logsection),"call_log_%i",i);
- lp_config_clean_section(cfg,logsection);
- lp_config_set_int(cfg,logsection,"dir",cl->dir);
- lp_config_set_int(cfg,logsection,"status",cl->status);
- tmp=linphone_address_as_string(cl->from);
- lp_config_set_string(cfg,logsection,"from",tmp);
- ms_free(tmp);
- tmp=linphone_address_as_string(cl->to);
- lp_config_set_string(cfg,logsection,"to",tmp);
- ms_free(tmp);
- if (cl->start_date_time)
- lp_config_set_int64(cfg,logsection,"start_date_time",(int64_t)cl->start_date_time);
- else lp_config_set_string(cfg,logsection,"start_date",cl->start_date);
- lp_config_set_int(cfg,logsection,"duration",cl->duration);
- if (cl->refkey) lp_config_set_string(cfg,logsection,"refkey",cl->refkey);
- lp_config_set_float(cfg,logsection,"quality",cl->quality);
- lp_config_set_int(cfg,logsection,"video_enabled", cl->video_enabled);
- lp_config_set_string(cfg,logsection,"call_id",cl->call_id);
- }
- for(;imax_call_logs;++i){
- snprintf(logsection,sizeof(logsection),"call_log_%i",i);
- lp_config_clean_section(cfg,logsection);
- }
-}
-
-static time_t string_to_time(const char *date){
-#ifndef WIN32
- struct tm tmtime={0};
- strptime(date,"%c",&tmtime);
- return mktime(&tmtime);
-#else
- return 0;
-#endif
-}
-
-static void call_logs_read_from_config_file(LinphoneCore *lc){
- char logsection[32];
- int i;
- const char *tmp;
- uint64_t sec;
- LpConfig *cfg=lc->config;
- for(i=0;;++i){
- snprintf(logsection,sizeof(logsection),"call_log_%i",i);
- if (lp_config_has_section(cfg,logsection)){
- LinphoneCallLog *cl=ms_new0(LinphoneCallLog,1);
- cl->dir=lp_config_get_int(cfg,logsection,"dir",0);
- cl->status=lp_config_get_int(cfg,logsection,"status",0);
- tmp=lp_config_get_string(cfg,logsection,"from",NULL);
- if (tmp) cl->from=linphone_address_new(tmp);
- tmp=lp_config_get_string(cfg,logsection,"to",NULL);
- if (tmp) cl->to=linphone_address_new(tmp);
- sec=lp_config_get_int64(cfg,logsection,"start_date_time",0);
- if (sec) {
- /*new call log format with date expressed in seconds */
- cl->start_date_time=(time_t)sec;
- set_call_log_date(cl,cl->start_date_time);
- }else{
- tmp=lp_config_get_string(cfg,logsection,"start_date",NULL);
- if (tmp) {
- strncpy(cl->start_date,tmp,sizeof(cl->start_date));
- cl->start_date_time=string_to_time(cl->start_date);
- }
- }
- cl->duration=lp_config_get_int(cfg,logsection,"duration",0);
- tmp=lp_config_get_string(cfg,logsection,"refkey",NULL);
- if (tmp) cl->refkey=ms_strdup(tmp);
- cl->quality=lp_config_get_float(cfg,logsection,"quality",-1);
- cl->video_enabled=lp_config_get_int(cfg,logsection,"video_enabled",0);
- tmp=lp_config_get_string(cfg,logsection,"call_id",NULL);
- if (tmp) cl->call_id=ms_strdup(tmp);
- lc->call_logs=ms_list_append(lc->call_logs,cl);
- }else break;
- }
-}
-
-
-
-/**
- * @addtogroup call_logs
- * @{
-**/
-
-/**
- * Returns a human readable string describing the call.
- *
- * @note: the returned char* must be freed by the application (use ms_free()).
-**/
-char * linphone_call_log_to_str(LinphoneCallLog *cl){
- char *status;
- char *tmp;
- char *from=linphone_address_as_string (cl->from);
- char *to=linphone_address_as_string (cl->to);
- switch(cl->status){
- case LinphoneCallAborted:
- status=_("aborted");
- break;
- case LinphoneCallSuccess:
- status=_("completed");
- break;
- case LinphoneCallMissed:
- status=_("missed");
- break;
- default:
- status="unknown";
- }
- tmp=ortp_strdup_printf(_("%s at %s\nFrom: %s\nTo: %s\nStatus: %s\nDuration: %i mn %i sec\n"),
- (cl->dir==LinphoneCallIncoming) ? _("Incoming call") : _("Outgoing call"),
- cl->start_date,
- from,
- to,
- status,
- cl->duration/60,
- cl->duration%60);
- ms_free(from);
- ms_free(to);
- return tmp;
-}
-
-/**
- * Returns RTP statistics computed locally regarding the call.
- *
-**/
-const rtp_stats_t *linphone_call_log_get_local_stats(const LinphoneCallLog *cl){
- return &cl->local_stats;
-}
-
-/**
- * Returns RTP statistics computed by remote end and sent back via RTCP.
- *
- * @note Not implemented yet.
-**/
-const rtp_stats_t *linphone_call_log_get_remote_stats(const LinphoneCallLog *cl){
- return &cl->remote_stats;
-}
-
-const char *linphone_call_log_get_call_id(const LinphoneCallLog *cl){
- return cl->call_id;
-}
-
-/**
- * Assign a user pointer to the call log.
-**/
-void linphone_call_log_set_user_pointer(LinphoneCallLog *cl, void *up){
- cl->user_pointer=up;
-}
-
-/**
- * Returns the user pointer associated with the call log.
-**/
-void *linphone_call_log_get_user_pointer(const LinphoneCallLog *cl){
- return cl->user_pointer;
-}
-
-
-
-/**
- * Associate a persistent reference key to the call log.
- *
- * The reference key can be for example an id to an external database.
- * It is stored in the config file, thus can survive to process exits/restarts.
- *
-**/
-void linphone_call_log_set_ref_key(LinphoneCallLog *cl, const char *refkey){
- if (cl->refkey!=NULL){
- ms_free(cl->refkey);
- cl->refkey=NULL;
- }
- if (refkey) cl->refkey=ms_strdup(refkey);
-}
-
-/**
- * Get the persistent reference key associated to the call log.
- *
- * The reference key can be for example an id to an external database.
- * It is stored in the config file, thus can survive to process exits/restarts.
- *
-**/
-const char *linphone_call_log_get_ref_key(const LinphoneCallLog *cl){
- return cl->refkey;
-}
-
-/**
- * Returns origin (ie from) address of the call.
-**/
-LinphoneAddress *linphone_call_log_get_from(LinphoneCallLog *cl){
- return cl->from;
-}
-
-/**
- * Returns destination address (ie to) of the call.
-**/
-LinphoneAddress *linphone_call_log_get_to(LinphoneCallLog *cl){
- return cl->to;
-}
-
-/**
- * Returns remote address (that is from or to depending on call direction).
-**/
-LinphoneAddress *linphone_call_log_get_remote_address(LinphoneCallLog *cl){
- return (cl->dir == LinphoneCallIncoming) ? cl->from : cl->to;
-}
-
-/**
- * Returns the direction of the call.
-**/
-LinphoneCallDir linphone_call_log_get_dir(LinphoneCallLog *cl){
- return cl->dir;
-}
-
-/**
- * Returns the status of the call.
-**/
-LinphoneCallStatus linphone_call_log_get_status(LinphoneCallLog *cl){
- return cl->status;
-}
-
-/**
- * Returns the start date of the call, expressed as a POSIX time_t.
-**/
-time_t linphone_call_log_get_start_date(LinphoneCallLog *cl){
- return cl->start_date_time;
-}
-
-/**
- * Returns duration of the call.
-**/
-int linphone_call_log_get_duration(LinphoneCallLog *cl){
- return cl->duration;
-}
-
-/**
- * Returns overall quality indication of the call.
-**/
-float linphone_call_log_get_quality(LinphoneCallLog *cl){
- return cl->quality;
-}
-/**
- * return true if video was enabled at the end of the call
- */
-bool_t linphone_call_log_video_enabled(LinphoneCallLog *cl) {
- return cl->video_enabled;
-}
-/** @} */
-
-void linphone_call_log_destroy(LinphoneCallLog *cl){
- if (cl->from!=NULL) linphone_address_destroy(cl->from);
- if (cl->to!=NULL) linphone_address_destroy(cl->to);
- if (cl->refkey!=NULL) ms_free(cl->refkey);
- if (cl->call_id) ms_free(cl->call_id);
- if (cl->reporting.reports[LINPHONE_CALL_STATS_AUDIO]!=NULL) linphone_reporting_destroy(cl->reporting.reports[LINPHONE_CALL_STATS_AUDIO]);
- if (cl->reporting.reports[LINPHONE_CALL_STATS_VIDEO]!=NULL) linphone_reporting_destroy(cl->reporting.reports[LINPHONE_CALL_STATS_VIDEO]);
-
- ms_free(cl);
-}
-
/**
* Returns TRUE if the LinphoneCall asked to autoanswer
*
@@ -480,11 +182,15 @@ void linphone_core_enable_logs_with_cb(OrtpLogFunc logfunc){
* @ingroup misc
* @deprecated Use #linphone_core_set_log_level instead.
**/
-void linphone_core_disable_logs(){
+void linphone_core_disable_logs(void){
ortp_set_log_level_mask(ORTP_ERROR|ORTP_FATAL);
sal_disable_logs();
}
+void linphone_core_serialize_logs(void) {
+ liblinphone_serialize_logs = TRUE;
+}
+
static void net_config_read (LinphoneCore *lc)
{
@@ -722,6 +428,7 @@ static void sip_config_read(LinphoneCore *lc)
LinphoneProxyConfig *cfg=linphone_proxy_config_new_from_config_file(lc,i);
if (cfg!=NULL){
linphone_core_add_proxy_config(lc,cfg);
+ linphone_proxy_config_unref(cfg);
}else{
break;
}
@@ -759,6 +466,7 @@ static void sip_config_read(LinphoneCore *lc)
sal_enable_sip_update_method(lc->sal,lp_config_get_int(lc->config,"sip","sip_update",1));
lc->sip_conf.vfu_with_info=lp_config_get_int(lc->config,"sip","vfu_with_info",1);
linphone_core_set_sip_transport_timeout(lc, lp_config_get_int(lc->config, "sip", "transport_timeout", 63000));
+ sal_set_supported_tags(lc->sal,lp_config_get_string(lc->config,"sip","supported","replaces, outbound"));
}
static void rtp_config_read(LinphoneCore *lc)
@@ -801,6 +509,7 @@ static void rtp_config_read(LinphoneCore *lc)
adaptive_jitt_comp_enabled = lp_config_get_int(lc->config, "rtp", "video_adaptive_jitt_comp_enabled", TRUE);
linphone_core_enable_video_adaptive_jittcomp(lc, adaptive_jitt_comp_enabled);
lc->rtp_conf.disable_upnp = lp_config_get_int(lc->config, "rtp", "disable_upnp", FALSE);
+ linphone_core_set_avpf_mode(lc,lp_config_get_int(lc->config,"rtp","avpf",0));
}
static PayloadType * find_payload(RtpProfile *prof, const char *mime_type, int clock_rate, int channels, const char *recv_fmtp){
@@ -897,7 +606,7 @@ static int codec_compare(const PayloadType *a, const PayloadType *b){
rb=find_codec_rank(b->mime_type,b->clock_rate);
if (ra>rb) return 1;
if (raconfig,"video","size","cif"));
-
+
linphone_core_set_preview_video_size_by_name(lc,
lp_config_get_string(lc->config,"video","preview_size",NULL));
-
+
linphone_core_set_preferred_framerate(lc,lp_config_get_float(lc->config,"video","framerate",0));
#ifdef VIDEO_ENABLED
@@ -1014,12 +723,14 @@ static void video_config_read(LinphoneCore *lc){
capture=lp_config_get_int(lc->config,"video","capture",1);
display=lp_config_get_int(lc->config,"video","display",1);
self_view=lp_config_get_int(lc->config,"video","self_view",1);
+ reuse_source=lp_config_get_int(lc->config,"video","reuse_source",0);
vpol.automatically_initiate=lp_config_get_int(lc->config,"video","automatically_initiate",automatic_video);
vpol.automatically_accept=lp_config_get_int(lc->config,"video","automatically_accept",automatic_video);
linphone_core_enable_video_capture(lc, capture);
linphone_core_enable_video_display(lc, display);
linphone_core_enable_video_preview(lc,lp_config_get_int(lc->config,"video","show_local",0));
linphone_core_enable_self_view(lc,self_view);
+ linphone_core_enable_video_source_reuse(lc, reuse_source);
linphone_core_set_video_policy(lc,&vpol);
#endif
}
@@ -1080,6 +791,28 @@ bool_t linphone_core_adaptive_rate_control_enabled(const LinphoneCore *lc){
return lp_config_get_int(lc->config,"net","adaptive_rate_control",TRUE);
}
+/**
+ * Sets adaptive rate algorithm. It will be used for each new calls starting from
+ * now. Calls already started will not be updated.
+ *
+ * @ingroup media_parameters
+ *
+**/
+void linphone_core_set_adaptive_rate_algorithm(LinphoneCore *lc, const char* algorithm){
+ lp_config_set_string(lc->config,"net","adaptive_rate_algorithm",algorithm);
+}
+
+/**
+ * Returns which adaptive rate algorithm is currently configured for future calls.
+ *
+ * @ingroup media_parameters
+ *
+ * See linphone_core_set_adaptive_rate_algorithm().
+**/
+const char * linphone_core_get_adaptive_rate_algorithm(const LinphoneCore *lc){
+ return lp_config_get_string(lc->config, "net", "adaptive_rate_algorithm", "Simple");
+}
+
bool_t linphone_core_rtcp_enabled(const LinphoneCore *lc){
return lp_config_get_int(lc->config,"rtp","rtcp_enabled",TRUE);
}
@@ -1264,9 +997,7 @@ static void linphone_core_free_payload_types(LinphoneCore *lc){
void linphone_core_set_state(LinphoneCore *lc, LinphoneGlobalState gstate, const char *message){
lc->state=gstate;
- if (lc->vtable.global_state_changed){
- lc->vtable.global_state_changed(lc,gstate,message);
- }
+ linphone_core_notify_global_state_changed(lc,gstate,message);
}
static void misc_config_read(LinphoneCore *lc) {
@@ -1299,18 +1030,18 @@ static void linphone_core_start(LinphoneCore * lc) {
ui_config_read(lc);
#ifdef TUNNEL_ENABLED
lc->tunnel=linphone_core_tunnel_new(lc);
- if (lc->tunnel) linphone_tunnel_configure(lc->tunnel);
+ if (lc->tunnel) {
+ linphone_tunnel_configure(lc->tunnel);
+ }
#endif
- if (lc->vtable.display_status)
- lc->vtable.display_status(lc,_("Ready"));
+ linphone_core_notify_display_status(lc,_("Ready"));
lc->auto_net_state_mon=lc->sip_conf.auto_net_state_mon;
linphone_core_set_state(lc,LinphoneGlobalOn,"Ready");
}
void linphone_configuring_terminated(LinphoneCore *lc, LinphoneConfiguringState state, const char *message) {
- if (lc->vtable.configuring_status)
- lc->vtable.configuring_status(lc, state, message);
+ linphone_core_notify_configuring_status(lc, state, message);
if (state == LinphoneConfiguringSuccessful) {
if (linphone_core_is_provisioning_transient(lc) == TRUE)
@@ -1323,16 +1054,21 @@ 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;
+ LinphoneCoreVTable* local_vtable= linphone_vtable_new();
ms_message("Initializing LinphoneCore %s", linphone_core_get_version());
memset (lc, 0, sizeof (LinphoneCore));
lc->config=lp_config_ref(config);
lc->data=userdata;
lc->ringstream_autorelease=TRUE;
- memcpy(&lc->vtable,vtable,sizeof(LinphoneCoreVTable));
+ memcpy(local_vtable,vtable,sizeof(LinphoneCoreVTable));
+ lc->vtables=ms_list_append(lc->vtables,local_vtable);
linphone_core_set_state(lc,LinphoneGlobalStartup,"Starting up");
ortp_init();
+ if (liblinphone_serialize_logs == TRUE) {
+ ortp_set_log_thread_id(ortp_thread_self());
+ }
lc->dyn_pt=96;
lc->default_profile=rtp_profile_new("default profile");
linphone_core_assign_payload_type(lc,&payload_type_pcmu8000,0,NULL);
@@ -1419,7 +1155,7 @@ static void linphone_core_init(LinphoneCore * lc, const LinphoneCoreVTable *vtab
remote_provisioning_uri = linphone_core_get_provisioning_uri(lc);
if (remote_provisioning_uri == NULL) {
linphone_configuring_terminated(lc, LinphoneConfiguringSkipped, NULL);
- } // else linphone_core_start will be called after the remote provisioining (see linphone_core_iterate)
+ } // else linphone_core_start will be called after the remote provisioning (see linphone_core_iterate)
}
/**
@@ -1460,6 +1196,8 @@ LinphoneCore *linphone_core_new_with_config(const LinphoneCoreVTable *vtable, st
/**
* Returns the list of available audio codecs.
+ * @param[in] lc The LinphoneCore object
+ * @return \mslist{PayloadType}
*
* This list is unmodifiable. The ->data field of the MSList points a PayloadType
* structure holding the codec information.
@@ -1474,6 +1212,8 @@ const MSList *linphone_core_get_audio_codecs(const LinphoneCore *lc)
/**
* Returns the list of available video codecs.
+ * @param[in] lc The LinphoneCore object
+ * @return \mslist{PayloadType}
*
* This list is unmodifiable. The ->data field of the MSList points a PayloadType
* structure holding the codec information.
@@ -1512,44 +1252,6 @@ int linphone_core_set_primary_contact(LinphoneCore *lc, const char *contact)
}
-/*Returns the local ip that routes to the internet, or guessed by other special means (upnp)*/
-/*result must be an array of chars at least LINPHONE_IPADDR_SIZE */
-void linphone_core_get_local_ip(LinphoneCore *lc, int af, char *result){
- const char *ip;
- if (linphone_core_get_firewall_policy(lc)==LinphonePolicyUseNatAddress
- && (ip=linphone_core_get_nat_address_resolved(lc))!=NULL){
- strncpy(result,ip,LINPHONE_IPADDR_SIZE);
- return;
- }
-#ifdef BUILD_UPNP
- else if (lc->upnp != NULL && linphone_core_get_firewall_policy(lc)==LinphonePolicyUseUpnp &&
- linphone_upnp_context_get_state(lc->upnp) == LinphoneUpnpStateOk) {
- ip = linphone_upnp_context_get_external_ipaddress(lc->upnp);
- strncpy(result,ip,LINPHONE_IPADDR_SIZE);
- return;
- }
-#endif //BUILD_UPNP
- if (af==AF_UNSPEC){
- if (linphone_core_ipv6_enabled(lc)){
- bool_t has_ipv6;
- has_ipv6=linphone_core_get_local_ip_for(AF_INET6,NULL,result)==0;
- if (strcmp(result,"::1")!=0)
- return; /*this machine has real ipv6 connectivity*/
- if (linphone_core_get_local_ip_for(AF_INET,NULL,result)==0 && strcmp(result,"127.0.0.1")!=0)
- return; /*this machine has only ipv4 connectivity*/
- if (has_ipv6){
- /*this machine has only local loopback for both ipv4 and ipv6, so prefer ipv6*/
- strncpy(result,"::1",LINPHONE_IPADDR_SIZE);
- return;
- }
- }
- /*in all other cases use IPv4*/
- af=AF_INET;
- }
- if (linphone_core_get_local_ip_for(af,NULL,result)==0)
- return;
-}
-
static void update_primary_contact(LinphoneCore *lc){
char *guessed=NULL;
char tmp[LINPHONE_IPADDR_SIZE];
@@ -1564,7 +1266,7 @@ static void update_primary_contact(LinphoneCore *lc){
ms_error("Could not parse identity contact !");
url=linphone_address_new("sip:unknown@unkwownhost");
}
- linphone_core_get_local_ip(lc, AF_UNSPEC, tmp);
+ linphone_core_get_local_ip(lc, AF_UNSPEC, NULL, tmp);
if (strcmp(tmp,"127.0.0.1")==0 || strcmp(tmp,"::1")==0 ){
ms_warning("Local loopback network only !");
lc->sip_conf.loopback_only=TRUE;
@@ -1634,6 +1336,9 @@ LinphoneAddress *linphone_core_get_primary_contact_parsed(LinphoneCore *lc){
/**
* Sets the list of audio codecs.
+ * @param[in] lc The LinphoneCore object
+ * @param[in] codecs \mslist{PayloadType}
+ * @return 0
*
* @ingroup media_parameters
* The list is taken by the LinphoneCore thus the application should not free it.
@@ -1649,6 +1354,9 @@ int linphone_core_set_audio_codecs(LinphoneCore *lc, MSList *codecs)
/**
* Sets the list of video codecs.
+ * @param[in] lc The LinphoneCore object
+ * @param[in] codecs \mslist{PayloadType}
+ * @return 0
*
* @ingroup media_parameters
* The list is taken by the LinphoneCore thus the application should not free it.
@@ -1766,24 +1474,53 @@ bool_t linphone_core_get_rtp_no_xmit_on_audio_mute(const LinphoneCore *lc){
return lc->rtp_conf.rtp_no_xmit_on_audio_mute;
}
+static void apply_jitter_value(LinphoneCore *lc, int value, MSFormatType stype){
+ LinphoneCall *call;
+ MSList *it;
+ for (it=lc->calls;it!=NULL;it=it->next){
+ MediaStream *ms;
+ call=(LinphoneCall*)it->data;
+ ms = stype==MSAudio ? (MediaStream*)call->audiostream : (MediaStream*)call->videostream;
+ if (ms){
+ RtpSession *s=ms->sessions.rtp_session;
+ if (s){
+ if (value>0){
+ ms_message("Jitter buffer size set to [%i] ms on call [%p]",value,call);
+ rtp_session_set_jitter_compensation(s,value);
+ rtp_session_enable_jitter_buffer(s,TRUE);
+ }else if (value==0){
+ ms_warning("Jitter buffer is disabled per application request on call [%p]",call);
+ rtp_session_enable_jitter_buffer(s,FALSE);
+ }
+ }
+ }
+ }
+}
+
/**
* Sets the nominal audio jitter buffer size in milliseconds.
+ * The value takes effect immediately for all running and pending calls, if any.
+ * A value of 0 disables the jitter buffer.
*
* @ingroup media_parameters
**/
void linphone_core_set_audio_jittcomp(LinphoneCore *lc, int value)
{
lc->rtp_conf.audio_jitt_comp=value;
+ apply_jitter_value(lc, value, MSAudio);
}
/**
* Sets the nominal video jitter buffer size in milliseconds.
+ * The value takes effect immediately for all running and pending calls, if any.
+ * A value of 0 disables the jitter buffer.
*
* @ingroup media_parameters
**/
void linphone_core_set_video_jittcomp(LinphoneCore *lc, int value)
{
lc->rtp_conf.video_jitt_comp=value;
+ apply_jitter_value(lc, value, MSVideo);
}
void linphone_core_set_rtp_no_xmit_on_audio_mute(LinphoneCore *lc,bool_t rtp_no_xmit_on_audio_mute){
@@ -1900,28 +1637,8 @@ int linphone_core_get_sip_port(LinphoneCore *lc)
return tr.udp_port>0 ? tr.udp_port : (tr.tcp_port > 0 ? tr.tcp_port : tr.tls_port);
}
-#if !USE_BELLE_SIP
static char _ua_name[64]="Linphone";
-static char _ua_version[64]=LINPHONE_VERSION;
-#endif
-
-#if HAVE_EXOSIP_GET_VERSION && !USE_BELLESIP
-extern const char *eXosip_get_version();
-#endif
-
-static void apply_user_agent(LinphoneCore *lc){
-#if !USE_BELLESIP /*default user agent is handled at sal level*/
- char ua_string[256];
- snprintf(ua_string,sizeof(ua_string)-1,"%s/%s (eXosip2/%s)",_ua_name,_ua_version,
-#if HAVE_EXOSIP_GET_VERSION
- eXosip_get_version()
-#else
- "unknown"
-#endif
- );
- if (lc->sal) sal_set_user_agent(lc->sal,ua_string);
-#endif
-}
+static char _ua_version[64]=LIBLINPHONE_VERSION;
/**
* Sets the user agent string used in SIP messages.
@@ -1929,27 +1646,15 @@ static void apply_user_agent(LinphoneCore *lc){
* @ingroup misc
**/
void linphone_core_set_user_agent(LinphoneCore *lc, const char *name, const char *ver){
-#if USE_BELLESIP
char ua_string[256];
snprintf(ua_string, sizeof(ua_string) - 1, "%s/%s", name?name:"", ver?ver:"");
if (lc->sal) {
sal_set_user_agent(lc->sal, ua_string);
sal_append_stack_string_to_user_agent(lc->sal);
}
-#else
- strncpy(_ua_name,name,sizeof(_ua_name)-1);
- strncpy(_ua_version,ver,sizeof(_ua_version));
- apply_user_agent(lc);
-#endif
}
const char *linphone_core_get_user_agent(LinphoneCore *lc){
-#if USE_BELLESIP
return sal_get_user_agent(lc->sal);
-#else
- static char ua_buffer[255] = {0};
- snprintf(ua_buffer, "%s/%s", _ua_name, _ua_version, 254);
- return ua_buffer;
-#endif
}
const char *linphone_core_get_user_agent_name(void){
@@ -1963,8 +1668,7 @@ const char *linphone_core_get_user_agent_version(void){
static void transport_error(LinphoneCore *lc, const char* transport, int port){
char *msg=ortp_strdup_printf("Could not start %s transport on port %i, maybe this port is already used.",transport,port);
ms_warning("%s",msg);
- if (lc->vtable.display_warning)
- lc->vtable.display_warning(lc,msg);
+ linphone_core_notify_display_warning(lc,msg);
ms_free(msg);
}
@@ -2007,7 +1711,6 @@ static int apply_transports(LinphoneCore *lc){
}
}
}
- apply_user_agent(lc);
return 0;
}
@@ -2134,7 +1837,7 @@ static void monitor_network_state(LinphoneCore *lc, time_t curtime){
/* only do the network up checking every five seconds */
if (lc->network_last_check==0 || (curtime-lc->network_last_check)>=5){
- linphone_core_get_local_ip(lc,AF_UNSPEC,newip);
+ linphone_core_get_local_ip(lc,AF_UNSPEC,NULL,newip);
if (strcmp(newip,"::1")!=0 && strcmp(newip,"127.0.0.1")!=0){
new_status=TRUE;
}else new_status=FALSE; /*no network*/
@@ -2164,10 +1867,11 @@ static void proxy_update(LinphoneCore *lc){
for(elem=lc->sip_conf.deleted_proxies;elem!=NULL;elem=next){
LinphoneProxyConfig* cfg = (LinphoneProxyConfig*)elem->data;
next=elem->next;
- if (ms_time(NULL) - cfg->deletion_date > 5) {
+ if (ms_time(NULL) - cfg->deletion_date > 32) {
lc->sip_conf.deleted_proxies =ms_list_remove_link(lc->sip_conf.deleted_proxies,elem);
- ms_message("clearing proxy config for [%s]",linphone_proxy_config_get_addr(cfg));
- linphone_proxy_config_destroy(cfg);
+ ms_message("Proxy config for [%s] is definitely removed from core.",linphone_proxy_config_get_addr(cfg));
+ _linphone_proxy_config_release_ops(cfg);
+ linphone_proxy_config_unref(cfg);
}
}
}
@@ -2177,8 +1881,7 @@ static void assign_buddy_info(LinphoneCore *lc, BuddyInfo *info){
if (lf!=NULL){
lf->info=info;
ms_message("%s has a BuddyInfo assigned with image %p",info->sip_uri, info->image_data);
- if (lc->vtable.buddy_info_updated)
- lc->vtable.buddy_info_updated(lc,lf);
+ linphone_core_notify_buddy_info_updated(lc,lf);
}else{
ms_warning("Could not any friend with uri %s",info->sip_uri);
}
@@ -2264,7 +1967,10 @@ void linphone_core_iterate(LinphoneCore *lc){
int elapsed;
bool_t one_second_elapsed=FALSE;
const char *remote_provisioning_uri = NULL;
-
+ if (lc->network_reachable_to_be_notified) {
+ lc->network_reachable_to_be_notified=FALSE;
+ linphone_core_notify_network_reachable(lc,lc->network_reachable);
+ }
if (linphone_core_get_global_state(lc) == LinphoneGlobalStartup) {
if (sal_get_root_ca(lc->sal)) {
belle_tls_verify_policy_t *tls_policy = belle_tls_verify_policy_new();
@@ -2272,8 +1978,7 @@ void linphone_core_iterate(LinphoneCore *lc){
belle_http_provider_set_tls_verify_policy(lc->http_provider, tls_policy);
}
- if (lc->vtable.display_status)
- lc->vtable.display_status(lc, _("Configuring"));
+ linphone_core_notify_display_status(lc, _("Configuring"));
linphone_core_set_state(lc, LinphoneGlobalConfiguring, "Configuring");
remote_provisioning_uri = linphone_core_get_provisioning_uri(lc);
@@ -2362,7 +2067,7 @@ void linphone_core_iterate(LinphoneCore *lc){
#endif //BUILD_UPNP
linphone_core_start_invite(lc,call, NULL);
}
- if (call->state==LinphoneCallIncomingReceived){
+ if (call->state==LinphoneCallIncomingReceived || call->state==LinphoneCallIncomingEarlyMedia){
if (one_second_elapsed) ms_message("incoming call ringing for %i seconds",elapsed);
if (elapsed>lc->sip_conf.inc_timeout){
LinphoneReason decline_reason;
@@ -2406,6 +2111,10 @@ void linphone_core_iterate(LinphoneCore *lc){
lp_config_sync(lc->config);
}
}
+
+ if (liblinphone_serialize_logs == TRUE) {
+ ortp_logv_flush();
+ }
}
/**
@@ -2434,11 +2143,9 @@ LinphoneAddress * linphone_core_interpret_url(LinphoneCore *lc, const char *url)
if (*url=='\0') return NULL;
if (is_enum(url,&enum_domain)){
- if (lc->vtable.display_status!=NULL)
- lc->vtable.display_status(lc,_("Looking for telephone number destination..."));
+ linphone_core_notify_display_status(lc,_("Looking for telephone number destination..."));
if (enum_lookup(enum_domain,&enumres)<0){
- if (lc->vtable.display_status!=NULL)
- lc->vtable.display_status(lc,_("Could not resolve this number."));
+ linphone_core_notify_display_status(lc,_("Could not resolve this number."));
ms_free(enum_domain);
return NULL;
}
@@ -2535,7 +2242,7 @@ LinphoneCall * linphone_core_start_refered_call(LinphoneCore *lc, LinphoneCall *
}
if (!params){
- cp->has_video = call->current_params.has_video; /*start the call to refer-target with video enabled if original call had video*/
+ cp->has_video = call->current_params->has_video; /*start the call to refer-target with video enabled if original call had video*/
}
cp->referer=call;
ms_message("Starting new call to refered address %s",call->refer_to);
@@ -2721,13 +2428,11 @@ int linphone_core_start_invite(LinphoneCore *lc, LinphoneCall *call, const Linph
call->log->call_id=ms_strdup(sal_op_get_call_id(call->op)); /*must be known at that time*/
barmsg=ortp_strdup_printf("%s %s", _("Contacting"), real_url);
- if (lc->vtable.display_status!=NULL)
- lc->vtable.display_status(lc,barmsg);
+ linphone_core_notify_display_status(lc,barmsg);
ms_free(barmsg);
if (err<0){
- if (lc->vtable.display_status!=NULL)
- lc->vtable.display_status(lc,_("Could not call"));
+ linphone_core_notify_display_status(lc,_("Could not call"));
linphone_call_stop_media_streams(call);
linphone_call_set_state(call,LinphoneCallError,"Call failed");
}else {
@@ -2835,6 +2540,7 @@ void linphone_configure_op(LinphoneCore *lc, SalOp *op, const LinphoneAddress *d
sal_op_set_to_address(op,dest);
sal_op_set_from(op,identity);
sal_op_set_sent_custom_header(op,headers);
+ sal_op_set_realm(op,linphone_proxy_config_get_realm(proxy));
if (with_contact && proxy && proxy->op){
const SalAddress *contact;
if ((contact=sal_op_get_contact_address(proxy->op))){
@@ -2876,8 +2582,7 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const
linphone_core_preempt_sound_resources(lc);
if(!linphone_core_can_we_add_call(lc)){
- if (lc->vtable.display_warning)
- lc->vtable.display_warning(lc,_("Sorry, we have reached the maximum number of simultaneous calls"));
+ linphone_core_notify_display_warning(lc,_("Sorry, we have reached the maximum number of simultaneous calls"));
return NULL;
}
@@ -2888,6 +2593,9 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const
from=linphone_proxy_config_get_identity(proxy);
cp->avpf_enabled = linphone_proxy_config_avpf_enabled(proxy);
cp->avpf_rr_interval = linphone_proxy_config_get_avpf_rr_interval(proxy) * 1000;
+ }else{
+ cp->avpf_enabled=linphone_core_get_avpf_mode(lc)==LinphoneAVPFEnabled;
+ if (cp->avpf_enabled) cp->avpf_rr_interval=linphone_core_get_avpf_rr_interval(lc) * 1000;
}
/* if no proxy or no identity defined for this proxy, default to primary contact*/
@@ -2908,15 +2616,15 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const
/* this call becomes now the current one*/
lc->current_call=call;
linphone_call_set_state (call,LinphoneCallOutgoingInit,"Starting outgoing call");
- call->log->start_date_time=time(NULL);
+ call->log->start_date_time=ms_time(NULL);
linphone_call_init_media_streams(call);
- if (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) {
+ if (_linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) {
/* Defer the start of the call after the ICE gathering process. */
if (linphone_call_prepare_ice(call,FALSE)==1)
defer=TRUE;
}
- else if (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseUpnp) {
+ else if (_linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseUpnp) {
#ifdef BUILD_UPNP
if (linphone_core_update_upnp(lc,call)<0) {
/* uPnP port mappings failed, proceed with the call anyway. */
@@ -3007,7 +2715,7 @@ int linphone_core_transfer_call_to_another(LinphoneCore *lc, LinphoneCall *call,
return result;
}
-bool_t linphone_core_inc_invite_pending(LinphoneCore*lc){
+bool_t linphone_core_is_incoming_invite_pending(LinphoneCore*lc){
LinphoneCall *call = linphone_core_get_current_call(lc);
if(call != NULL)
{
@@ -3036,8 +2744,7 @@ void linphone_core_notify_incoming_call(LinphoneCore *lc, LinphoneCall *call){
if (md){
if (sal_media_description_empty(md) || linphone_core_incompatible_security(lc,md)){
sal_call_decline(call->op,SalReasonNotAcceptable,NULL);
- linphone_call_stop_media_streams(call);
- linphone_core_del_call(lc,call);
+ linphone_call_set_state_base(call, LinphoneCallError, NULL,TRUE);
linphone_call_unref(call);
return;
}
@@ -3049,9 +2756,8 @@ void linphone_core_notify_incoming_call(LinphoneCore *lc, LinphoneCall *call){
linphone_address_destroy(from_parsed);
barmesg=ortp_strdup_printf("%s %s%s",tmp,_("is contacting you"),
(sal_call_autoanswer_asked(call->op)) ?_(" and asked autoanswer."):_("."));
- if (lc->vtable.show) lc->vtable.show(lc);
- if (lc->vtable.display_status)
- lc->vtable.display_status(lc,barmesg);
+ linphone_core_notify_show_interface(lc);
+ linphone_core_notify_display_status(lc,barmesg);
/* play the ring if this is the only call*/
if (ms_list_size(lc->calls)==1){
@@ -3117,7 +2823,7 @@ int linphone_core_accept_early_media_with_params(LinphoneCore* lc, LinphoneCall*
// if parameters are passed, update the media description
if ( params ) {
- _linphone_call_params_copy ( &call->params,params );
+ linphone_call_set_new_params(call,params);
linphone_call_make_local_media_description ( lc,call );
sal_call_set_local_media_description ( call->op,call->localdesc );
sal_op_set_sent_custom_header ( call->op,params->custom_headers );
@@ -3151,26 +2857,28 @@ int linphone_core_accept_early_media(LinphoneCore* lc, LinphoneCall* call){
int linphone_core_start_update_call(LinphoneCore *lc, LinphoneCall *call){
const char *subject;
+ bool_t no_user_consent=call->params->no_user_consent;
- linphone_call_make_local_media_description(lc,call);
+ if (!no_user_consent) linphone_call_make_local_media_description(lc,call);
#ifdef BUILD_UPNP
if(call->upnp_session != NULL) {
linphone_core_update_local_media_description_from_upnp(call->localdesc, call->upnp_session);
}
#endif //BUILD_UPNP
- if (call->params.in_conference){
+ if (call->params->in_conference){
subject="Conference";
- }else{
+ }else if (!no_user_consent){
subject="Media change";
+ }else{
+ subject="Refreshing";
}
- if (lc->vtable.display_status)
- lc->vtable.display_status(lc,_("Modifying call parameters..."));
+ linphone_core_notify_display_status(lc,_("Modifying call parameters..."));
sal_call_set_local_media_description (call->op,call->localdesc);
if (call->dest_proxy && call->dest_proxy->op){
/*give a chance to update the contact address if connectivity has changed*/
sal_op_set_contact_address(call->op,sal_op_get_contact_address(call->dest_proxy->op));
}else sal_op_set_contact_address(call->op,NULL);
- return sal_call_update(call->op,subject);
+ return sal_call_update(call->op,subject,no_user_consent);
}
/**
@@ -3207,7 +2915,7 @@ int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const Linpho
if (params!=NULL){
linphone_call_set_state(call,LinphoneCallUpdating,"Updating call");
#if defined(VIDEO_ENABLED) && defined(BUILD_UPNP)
- has_video = call->params.has_video;
+ has_video = call->params->has_video;
// Video removing
if((call->videostream != NULL) && !params->has_video) {
@@ -3220,8 +2928,7 @@ int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const Linpho
}
#endif /* defined(VIDEO_ENABLED) && defined(BUILD_UPNP) */
-
- _linphone_call_params_copy(&call->params,params);
+ linphone_call_set_new_params(call,params);
err=linphone_call_prepare_ice(call,FALSE);
if (err==1) {
ms_message("Defer call update to gather ICE candidates");
@@ -3230,7 +2937,7 @@ int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const Linpho
#if defined(VIDEO_ENABLED) && defined(BUILD_UPNP)
// Video adding
- if (!has_video && call->params.has_video) {
+ if (!has_video && call->params->has_video) {
if(call->upnp_session != NULL) {
ms_message("Defer call update to add uPnP port mappings");
video_stream_prepare_video(call->videostream);
@@ -3248,6 +2955,7 @@ int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const Linpho
#ifdef VIDEO_ENABLED
if ((call->videostream != NULL) && (call->state == LinphoneCallStreamsRunning)) {
video_stream_set_sent_video_size(call->videostream,linphone_core_get_preferred_video_size(lc));
+ video_stream_set_fps(call->videostream, linphone_core_get_preferred_framerate(lc));
if (call->camera_enabled && call->videostream->cam!=lc->video_conf.device){
video_stream_change_camera(call->videostream,lc->video_conf.device);
}else video_stream_update_video_params(call->videostream);
@@ -3281,7 +2989,7 @@ int linphone_core_defer_call_update(LinphoneCore *lc, LinphoneCall *call){
return -1;
}
-int linphone_core_start_accept_call_update(LinphoneCore *lc, LinphoneCall *call){
+int linphone_core_start_accept_call_update(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState next_state, const char *state_info){
SalMediaDescription *md;
if (call->ice_session != NULL) {
if (ice_session_nb_losing_pairs(call->ice_session) > 0) {
@@ -3299,8 +3007,7 @@ int linphone_core_start_accept_call_update(LinphoneCore *lc, LinphoneCall *call)
linphone_core_update_streams (lc,call,md);
linphone_call_fix_call_parameters(call);
}
- if (call->state != LinphoneCallOutgoingEarlyMedia) /*don't change the state in case of outgoing early (SIP UPDATE)*/
- linphone_call_set_state(call,LinphoneCallStreamsRunning,"Connected (streams running)");
+ linphone_call_set_state(call,next_state,state_info);
return 0;
}
@@ -3329,14 +3036,14 @@ int linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, const
linphone_call_state_to_string(call->state));
return -1;
}
- return _linphone_core_accept_call_update(lc, call, params);
+ return _linphone_core_accept_call_update(lc, call, params, call->prevstate, linphone_call_state_to_string(call->prevstate));
}
-int _linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params){
+int _linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params, LinphoneCallState next_state, const char *state_info){
SalMediaDescription *remote_desc;
bool_t keep_sdp_version;
#if defined(VIDEO_ENABLED) && defined(BUILD_UPNP)
- bool_t old_has_video = call->params.has_video;
+ bool_t old_has_video = call->params->has_video;
#endif
remote_desc = sal_call_get_remote_media_description(call->op);
@@ -3345,23 +3052,23 @@ int _linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, cons
/* Remote has sent an INVITE with the same SDP as before, so send a 200 OK with the same SDP as before. */
ms_warning("SDP version has not changed, send same SDP as before.");
sal_call_accept(call->op);
- linphone_call_set_state(call,LinphoneCallStreamsRunning,"Connected (streams running)");
+ linphone_call_set_state(call,next_state,state_info);
return 0;
}
if (params==NULL){
- call->params.has_video=lc->video_policy.automatically_accept || call->current_params.has_video;
+ call->params->has_video=lc->video_policy.automatically_accept || call->current_params->has_video;
}else
- _linphone_call_params_copy(&call->params,params);
+ linphone_call_set_new_params(call,params);
- if (call->params.has_video && !linphone_core_video_enabled(lc)){
+ if (call->params->has_video && !linphone_core_video_enabled(lc)){
ms_warning("linphone_core_accept_call_update(): requested video but video support is globally disabled. Refusing video.");
- call->params.has_video=FALSE;
+ call->params->has_video=FALSE;
}
- if (call->current_params.in_conference) {
+ if (call->current_params->in_conference) {
ms_warning("Video isn't supported in conference");
- call->params.has_video = FALSE;
+ call->params->has_video = FALSE;
}
- call->params.has_video &= linphone_core_media_description_contains_video_stream(remote_desc);
+ call->params->has_video &= linphone_core_media_description_contains_video_stream(remote_desc);
linphone_call_init_media_streams(call); /*so that video stream is initialized if necessary*/
if (call->ice_session != NULL) {
if (linphone_call_prepare_ice(call,TRUE)==1)
@@ -3372,7 +3079,7 @@ int _linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, cons
if(call->upnp_session != NULL) {
linphone_core_update_upnp_from_remote_media_description(call, sal_call_get_remote_media_description(call->op));
#ifdef VIDEO_ENABLED
- if ((call->params.has_video) && (call->params.has_video != old_has_video)) {
+ if ((call->params->has_video) && (call->params->has_video != old_has_video)) {
video_stream_prepare_video(call->videostream);
if (linphone_core_update_upnp(lc, call)<0) {
/* uPnP update failed, proceed with the call anyway. */
@@ -3383,7 +3090,7 @@ int _linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, cons
}
#endif //BUILD_UPNP
- linphone_core_start_accept_call_update(lc, call);
+ linphone_core_start_accept_call_update(lc, call, next_state, state_info);
return 0;
}
@@ -3466,7 +3173,7 @@ int linphone_core_accept_call_with_params(LinphoneCore *lc, LinphoneCall *call,
linphone_call_set_contact_op(call);
if (params){
const SalMediaDescription *md = sal_call_get_remote_media_description(call->op);
- _linphone_call_params_copy(&call->params,params);
+ linphone_call_set_new_params(call,params);
// There might not be a md if the INVITE was lacking an SDP
// In this case we use the parameters as is.
if (md) {
@@ -3493,8 +3200,7 @@ int linphone_core_accept_call_with_params(LinphoneCore *lc, LinphoneCall *call,
linphone_call_update_remote_session_id_and_ver(call);
sal_call_accept(call->op);
- if (lc->vtable.display_status!=NULL)
- lc->vtable.display_status(lc,_("Connected."));
+ linphone_core_notify_display_status(lc,_("Connected."));
lc->current_call=call;
linphone_call_set_state(call,LinphoneCallConnected,"Connected");
new_md=sal_call_get_final_media_description(call->op);
@@ -3519,8 +3225,7 @@ int linphone_core_abort_call(LinphoneCore *lc, LinphoneCall *call, const char *e
linphone_call_delete_upnp_session(call);
#endif //BUILD_UPNP
- if (lc->vtable.display_status!=NULL)
- lc->vtable.display_status(lc,_("Call aborted") );
+ linphone_core_notify_display_status(lc,_("Call aborted") );
linphone_call_set_state(call,LinphoneCallError,error);
return 0;
}
@@ -3539,8 +3244,7 @@ static void terminate_call(LinphoneCore *lc, LinphoneCall *call){
linphone_call_delete_upnp_session(call);
#endif //BUILD_UPNP
- if (lc->vtable.display_status!=NULL)
- lc->vtable.display_status(lc,_("Call ended") );
+ linphone_core_notify_display_status(lc,_("Call ended") );
linphone_call_set_state(call,LinphoneCallEnd,"Call terminated");
}
@@ -3640,6 +3344,8 @@ int linphone_core_terminate_all_calls(LinphoneCore *lc){
/**
* Returns the current list of calls.
+ * @param[in] lc The LinphoneCore object
+ * @return \mslist{LinphoneCall}
*
* Note that this list is read-only and might be changed by the core after a function call to linphone_core_iterate().
* Similarly the LinphoneCall objects inside it might be destroyed without prior notice.
@@ -3708,14 +3414,12 @@ int _linphone_core_pause_call(LinphoneCore *lc, LinphoneCall *call)
return -1;
}
sal_call_set_local_media_description(call->op,call->localdesc);
- if (sal_call_update(call->op,subject) != 0){
- if (lc->vtable.display_warning)
- lc->vtable.display_warning(lc,_("Could not pause the call"));
+ if (sal_call_update(call->op,subject,FALSE) != 0){
+ linphone_core_notify_display_warning(lc,_("Could not pause the call"));
}
lc->current_call=NULL;
linphone_call_set_state(call,LinphoneCallPausing,"Pausing call");
- if (lc->vtable.display_status)
- lc->vtable.display_status(lc,_("Pausing the current call..."));
+ linphone_core_notify_display_status(lc,_("Pausing the current call..."));
if (call->audiostream || call->videostream)
linphone_call_stop_media_streams (call);
call->paused_by_app=FALSE;
@@ -3769,7 +3473,7 @@ int linphone_core_resume_call(LinphoneCore *lc, LinphoneCall *call){
ms_warning("we cannot resume a call that has not been established and paused before");
return -1;
}
- if (call->params.in_conference==FALSE){
+ if (call->params->in_conference==FALSE){
if (linphone_core_sound_resources_locked(lc)){
ms_warning("Cannot resume call %p because another call is locking the sound resources.",call);
return -1;
@@ -3792,16 +3496,15 @@ int linphone_core_resume_call(LinphoneCore *lc, LinphoneCall *call){
#endif //BUILD_UPNP
sal_call_set_local_media_description(call->op,call->localdesc);
sal_media_description_set_dir(call->localdesc,SalStreamSendRecv);
- if (call->params.in_conference && !call->current_params.in_conference) subject="Conference";
- if(sal_call_update(call->op,subject) != 0){
+ if (call->params->in_conference && !call->current_params->in_conference) subject="Conference";
+ if ( sal_call_update(call->op,subject,FALSE) != 0){
return -1;
}
linphone_call_set_state(call,LinphoneCallResuming,"Resuming");
- if (call->params.in_conference==FALSE)
+ if (call->params->in_conference==FALSE)
lc->current_call=call;
snprintf(temp,sizeof(temp)-1,"Resuming the call with %s",linphone_call_get_remote_address_as_string(call));
- if (lc->vtable.display_status)
- lc->vtable.display_status(lc,temp);
+ linphone_core_notify_display_status(lc,temp);
return 0;
}
@@ -3821,6 +3524,7 @@ static int remote_address_compare(LinphoneCall *call, const LinphoneAddress *rad
LinphoneCall *linphone_core_get_call_by_remote_address(LinphoneCore *lc, const char *remote_address){
LinphoneAddress *raddr=linphone_address_new(remote_address);
MSList *elem=ms_list_find_custom(lc->calls,(int (*)(const void*,const void *))remote_address_compare,raddr);
+ linphone_address_unref(raddr);
if (elem) return (LinphoneCall*) elem->data;
return NULL;
}
@@ -4475,7 +4179,7 @@ void linphone_core_set_ringback(LinphoneCore *lc, const char *path){
if (lc->sound_conf.remote_ring!=0){
ms_free(lc->sound_conf.remote_ring);
}
- lc->sound_conf.remote_ring=ms_strdup(path);
+ lc->sound_conf.remote_ring=path?ms_strdup(path):NULL;
}
/**
@@ -4763,9 +4467,23 @@ void linphone_core_set_firewall_policy(LinphoneCore *lc, LinphoneFirewallPolicy
lp_config_set_string(lc->config,"net","firewall_policy",policy);
}
-LinphoneFirewallPolicy linphone_core_get_firewall_policy(const LinphoneCore *lc){
- const char *policy = lp_config_get_string(lc->config, "net", "firewall_policy", NULL);
+inline LinphoneFirewallPolicy linphone_core_get_firewall_policy(const LinphoneCore *lc) {
+ return _linphone_core_get_firewall_policy_with_lie(lc, FALSE);
+}
+inline LinphoneFirewallPolicy _linphone_core_get_firewall_policy(const LinphoneCore *lc) {
+ return _linphone_core_get_firewall_policy_with_lie(lc, TRUE);
+}
+
+LinphoneFirewallPolicy _linphone_core_get_firewall_policy_with_lie(const LinphoneCore *lc, bool_t lie){
+ const char *policy;
+ if(lie) {
+ LinphoneTunnel *tunnel = linphone_core_get_tunnel(lc);
+ if(tunnel != NULL && linphone_tunnel_get_mode(tunnel)) {
+ return LinphonePolicyNoFirewall;
+ }
+ }
+ policy = lp_config_get_string(lc->config, "net", "firewall_policy", NULL);
if ((policy == NULL) || (strcmp(policy, "0") == 0))
return LinphonePolicyNoFirewall;
else if ((strcmp(policy, "nat_address") == 0) || (strcmp(policy, "1") == 0))
@@ -4780,23 +4498,19 @@ LinphoneFirewallPolicy linphone_core_get_firewall_policy(const LinphoneCore *lc)
return LinphonePolicyNoFirewall;
}
-/**
- * Get the list of call logs (past calls).
- *
- * @ingroup call_logs
-**/
+
+
+/*******************************************************************************
+ * Call log related functions *
+ ******************************************************************************/
+
const MSList * linphone_core_get_call_logs(LinphoneCore *lc){
return lc->call_logs;
}
-/**
- * Erase the call log.
- *
- * @ingroup call_logs
-**/
void linphone_core_clear_call_logs(LinphoneCore *lc){
lc->missed_calls=0;
- ms_list_for_each(lc->call_logs,(void (*)(void*))linphone_call_log_destroy);
+ ms_list_for_each(lc->call_logs,(void (*)(void*))linphone_call_log_unref);
lc->call_logs=ms_list_free(lc->call_logs);
call_logs_write_to_config_file(lc);
}
@@ -4812,9 +4526,12 @@ void linphone_core_reset_missed_calls_count(LinphoneCore *lc) {
void linphone_core_remove_call_log(LinphoneCore *lc, LinphoneCallLog *cl){
lc->call_logs = ms_list_remove(lc->call_logs, cl);
call_logs_write_to_config_file(lc);
- linphone_call_log_destroy(cl);
+ linphone_call_log_unref(cl);
}
+
+
+
static void toggle_video_preview(LinphoneCore *lc, bool_t val){
#ifdef VIDEO_ENABLED
if (val){
@@ -4889,6 +4606,18 @@ void linphone_core_enable_video_display(LinphoneCore *lc, bool_t enable) {
reapply_network_bandwidth_settings(lc);
}
+void linphone_core_enable_video_source_reuse(LinphoneCore* lc, bool_t enable){
+#ifndef VIDEO_ENABLED
+ if (enable == TRUE) {
+ ms_warning("Cannot enable video display, this version of linphone was built without video support.");
+ }
+#endif
+ lc->video_conf.reuse_preview_source = enable;
+ if( linphone_core_ready(lc) ){
+ lp_config_set_int(lc->config, "video", "reuse_source", lc->video_conf.reuse_preview_source);
+ }
+}
+
bool_t linphone_core_video_capture_enabled(LinphoneCore *lc) {
return lc->video_conf.capture;
}
@@ -5357,11 +5086,13 @@ static void update_preview_size(LinphoneCore *lc, MSVideoSize oldvsize, MSVideoS
void linphone_core_set_preferred_video_size(LinphoneCore *lc, MSVideoSize vsize){
if (video_size_supported(vsize)){
MSVideoSize oldvsize=lc->video_conf.preview_vsize;
+
if (oldvsize.width==0){
oldvsize=lc->video_conf.vsize;
- update_preview_size(lc,oldvsize,vsize);
}
lc->video_conf.vsize=vsize;
+ update_preview_size(lc,oldvsize,vsize);
+
if (linphone_core_ready(lc))
lp_config_set_string(lc->config,"video","size",video_size_get_name(vsize));
}
@@ -5447,6 +5178,7 @@ void linphone_core_set_preferred_framerate(LinphoneCore *lc, float fps){
}
/**
* Returns the preferred video framerate, previously set by linphone_core_set_preferred_framerate().
+ * @ingroup media_parameters
* @param lc the linphone core
* @return frame rate in number of frames per seconds.
**/
@@ -5457,16 +5189,22 @@ float linphone_core_get_preferred_framerate(LinphoneCore *lc){
/**
* Ask the core to stream audio from and to files, instead of using the soundcard.
+ * @ingroup media_parameters
+ * @param[in] lc LinphoneCore object
+ * @param[in] yesno A boolean value asking to stream audio from and to files or not.
**/
-void linphone_core_use_files(LinphoneCore *lc, bool_t yesno){
+void linphone_core_set_use_files(LinphoneCore *lc, bool_t yesno){
lc->use_files=yesno;
}
/**
* Sets a wav file to be played when putting somebody on hold,
- * or when files are used instead of soundcards (see linphone_core_use_files()).
+ * or when files are used instead of soundcards (see linphone_core_set_use_files()).
*
* The file must be a 16 bit linear wav file.
+ * @ingroup media_parameters
+ * @param[in] lc LinphoneCore object
+ * @param[in] file The path to the file to be played when putting somebody on hold.
**/
void linphone_core_set_play_file(LinphoneCore *lc, const char *file){
LinphoneCall *call=linphone_core_get_current_call(lc);
@@ -5484,10 +5222,13 @@ void linphone_core_set_play_file(LinphoneCore *lc, const char *file){
/**
* Sets a wav file where incoming stream is to be recorded,
- * when files are used instead of soundcards (see linphone_core_use_files()).
+ * when files are used instead of soundcards (see linphone_core_set_use_files()).
*
* This feature is different from call recording (linphone_call_params_set_record_file())
* The file will be a 16 bit linear wav file.
+ * @ingroup media_parameters
+ * @param[in] lc LinphoneCore object
+ * @param[in] file The path to the file where incoming stream is to be recorded.
**/
void linphone_core_set_record_file(LinphoneCore *lc, const char *file){
LinphoneCall *call=linphone_core_get_current_call(lc);
@@ -5659,7 +5400,7 @@ void linphone_core_stop_dtmf(LinphoneCore *lc){
*
* @ingroup initializing
**/
-void *linphone_core_get_user_data(LinphoneCore *lc){
+void *linphone_core_get_user_data(const LinphoneCore *lc){
return lc->data;
}
@@ -5805,15 +5546,11 @@ void sip_config_uninit(LinphoneCore *lc)
}
if (i>=20) ms_warning("Cannot complete unregistration, giving up");
}
- ms_list_for_each(config->proxies,(void (*)(void*)) linphone_proxy_config_destroy);
- ms_list_free(config->proxies);
- config->proxies=NULL;
+ config->proxies=ms_list_free_with_data(config->proxies,(void (*)(void*)) _linphone_proxy_config_release);
/*no longuer need to write proxy config if not changedlinphone_proxy_config_write_to_config_file(lc->config,NULL,i);*/ /*mark the end */
- ms_list_for_each(lc->auth_info,(void (*)(void*))linphone_auth_info_destroy);
- ms_list_free(lc->auth_info);
- lc->auth_info=NULL;
+ lc->auth_info=ms_list_free_with_data(lc->auth_info,(void (*)(void*))linphone_auth_info_destroy);
/*now that we are unregisted, we no longer need the tunnel.*/
#ifdef TUNNEL_ENABLED
@@ -6006,20 +5743,14 @@ static void linphone_core_uninit(LinphoneCore *lc)
}
#endif //BUILD_UPNP
- if (lc->chatrooms){
- MSList *cr=ms_list_copy(lc->chatrooms);
- MSList *elem;
- for(elem=cr;elem!=NULL;elem=elem->next){
- linphone_chat_room_destroy((LinphoneChatRoom*)elem->data);
- }
- ms_list_free(cr);
- }
+ ms_list_for_each(lc->chatrooms, (MSIterateFunc)linphone_chat_room_release);
+ lc->chatrooms = ms_list_free(lc->chatrooms);
if (lp_config_needs_commit(lc->config)) lp_config_sync(lc->config);
lp_config_destroy(lc->config);
lc->config = NULL; /* Mark the config as NULL to block further calls */
- ms_list_for_each(lc->call_logs,(void (*)(void*))linphone_call_log_destroy);
+ ms_list_for_each(lc->call_logs,(void (*)(void*))linphone_call_log_unref);
lc->call_logs=ms_list_free(lc->call_logs);
ms_list_for_each(lc->last_recv_msg_ids,ms_free);
@@ -6045,6 +5776,10 @@ static void linphone_core_uninit(LinphoneCore *lc)
linphone_core_message_storage_close(lc);
ms_exit();
linphone_core_set_state(lc,LinphoneGlobalOff,"Off");
+ if (liblinphone_serialize_logs == TRUE) {
+ ortp_set_log_thread_id(0);
+ }
+ ms_list_free_with_data(lc->vtables,(void (*)(void *))linphone_vtable_destroy);
}
static void set_network_reachable(LinphoneCore* lc,bool_t isReachable, time_t curtime){
@@ -6052,7 +5787,7 @@ static void set_network_reachable(LinphoneCore* lc,bool_t isReachable, time_t cu
const MSList *elem=linphone_core_get_proxy_config_list(lc);
if (lc->network_reachable==isReachable) return; // no change, ignore.
-
+ lc->network_reachable_to_be_notified=TRUE;
ms_message("Network state is now [%s]",isReachable?"UP":"DOWN");
for(;elem!=NULL;elem=elem->next){
LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)elem->data;
@@ -6223,8 +5958,8 @@ static PayloadType* find_payload_type_from_list(const char* type, int rate, int
}
-PayloadType* linphone_core_find_payload_type(LinphoneCore* lc, const char* type, int rate, int channels) {
- PayloadType* result = find_payload_type_from_list(type, rate, channels, linphone_core_get_audio_codecs(lc));
+LinphonePayloadType* linphone_core_find_payload_type(LinphoneCore* lc, const char* type, int rate, int channels) {
+ LinphonePayloadType* result = find_payload_type_from_list(type, rate, channels, linphone_core_get_audio_codecs(lc));
if (result) {
return result;
} else {
@@ -6262,11 +5997,24 @@ LinphoneGlobalState linphone_core_get_global_state(const LinphoneCore *lc){
}
LinphoneCallParams *linphone_core_create_default_call_parameters(LinphoneCore *lc){
- LinphoneCallParams *p=ms_new0(LinphoneCallParams,1);
+ LinphoneCallParams *p=linphone_call_params_new();
linphone_core_init_default_params(lc, p);
return p;
}
+/**
+ * Create a LinphoneCallParams suitable for linphone_core_invite_with_params(), linphone_core_accept_call_with_params(), linphone_core_accept_early_media_with_params(),
+ * linphone_core_accept_call_update().
+ * The parameters are initialized according to the current LinphoneCore configuration and the current state of the LinphoneCall.
+ * @param lc the LinphoneCore
+ * @param call the call for which the parameters are to be build, or NULL in the case where the parameters are to be used for a new outgoing call.
+ * @return a new LinphoneCallParams
+ */
+LinphoneCallParams *linphone_core_create_call_params(LinphoneCore *lc, LinphoneCall *call){
+ if (!call) return linphone_core_create_default_call_parameters(lc);
+ return linphone_call_params_copy(call->params);
+}
+
const char *linphone_reason_to_string(LinphoneReason err){
switch(err){
case LinphoneReasonNone:
@@ -6677,3 +6425,208 @@ bool_t linphone_core_sdp_200_ack_enabled(const LinphoneCore *lc) {
void linphone_core_set_file_transfer_server(LinphoneCore *core, const char * server_url) {
core->file_transfer_server=ms_strdup(server_url);
}
+
+const char * linphone_core_get_file_transfer_server(LinphoneCore *core) {
+ return core->file_transfer_server;
+}
+
+/**
+ * This function controls signaling features supported by the core.
+ * They are typically included in a SIP Supported header.
+ * @param lc the LinphoneCore
+ * @param tag the feature tag name
+ * @ingroup initializing
+**/
+void linphone_core_add_supported_tag(LinphoneCore *lc, const char *tag){
+ sal_add_supported_tag(lc->sal,tag);
+ lp_config_set_string(lc->config,"sip","supported",sal_get_supported_tags(lc->sal));
+}
+
+/**
+ * Remove a supported tag. @see linphone_core_add_supported_tag()
+ * @param lc the LinphoneCore
+ * @param tag the tag to remove
+ * @ingroup initializing
+**/
+void linphone_core_remove_supported_tag(LinphoneCore *lc, const char *tag){
+ sal_remove_supported_tag(lc->sal,tag);
+ lp_config_set_string(lc->config,"sip","supported",sal_get_supported_tags(lc->sal));
+}
+
+/**
+ * Enable RTCP feedback (also known as RTP/AVPF profile).
+ * Setting LinphoneAVPFDefault is equivalent to LinphoneAVPFDisabled.
+ * This setting can be overriden per LinphoneProxyConfig with linphone_proxy_config_set_avpf_mode().
+ * The value set here is used for calls placed or received out of any proxy configured, or if the proxy config is configured with LinphoneAVPFDefault.
+ * @param lc the LinphoneCore
+ * @param mode the mode.
+**/
+void linphone_core_set_avpf_mode(LinphoneCore *lc, LinphoneAVPFMode mode){
+ if (mode==LinphoneAVPFDefault) mode=LinphoneAVPFDisabled;
+ lc->rtp_conf.avpf_mode=mode;
+ if (linphone_core_ready(lc)) lp_config_set_int(lc->config,"rtp","avpf",mode);
+}
+
+/**
+ * Return AVPF enablement. See linphone_core_set_avpf_mode() .
+ * @param lc the core
+ * @return the avpf enablement mode.
+**/
+LinphoneAVPFMode linphone_core_get_avpf_mode(const LinphoneCore *lc){
+ return lc->rtp_conf.avpf_mode;
+}
+
+/**
+ * Return the avpf report interval in seconds.
+ * @param lc the LinphoneCore
+ * @return the avpf report interval in seconds.
+**/
+int linphone_core_get_avpf_rr_interval(const LinphoneCore *lc){
+ return lp_config_get_int(lc->config,"rtp","avpf_rr_interval",5);
+}
+
+/**
+ * Set the avpf report interval in seconds.
+ * This value can be overriden by the proxy config using linphone_proxy_config_set_avpf_rr_interval().
+ * @param lc the core
+ * @param interval interval in seconds.
+**/
+void linphone_core_set_avpf_rr_interval(LinphoneCore *lc, int interval){
+ return lp_config_set_int(lc->config,"rtp","avpf_rr_interval",interval);
+}
+
+int linphone_payload_type_get_type(const LinphonePayloadType *pt) {
+ return pt->type;
+}
+
+int linphone_payload_type_get_normal_bitrate(const LinphonePayloadType *pt) {
+ return pt->normal_bitrate;
+}
+
+char * linphone_payload_type_get_mime_type(const LinphonePayloadType *pt) {
+ return pt->mime_type;
+}
+
+int linphone_payload_type_get_channels(const LinphonePayloadType *pt) {
+ return pt->channels;
+}
+
+LinphoneCoreVTable *linphone_vtable_new() {
+ return ms_new0(LinphoneCoreVTable,1);
+}
+
+void linphone_vtable_destroy(LinphoneCoreVTable* table) {
+ ms_free(table);
+}
+#define NOTIFY_IF_EXIST(function_name) \
+ MSList* iterator; \
+ ms_message ("Linphone core [%p] notifying [%s]",lc,#function_name);\
+ for (iterator=lc->vtables; iterator!=NULL; iterator=iterator->next) \
+ if (((LinphoneCoreVTable*)(iterator->data))->function_name)\
+ ((LinphoneCoreVTable*)(iterator->data))->function_name
+
+void linphone_core_notify_global_state_changed(LinphoneCore *lc, LinphoneGlobalState gstate, const char *message) {
+ NOTIFY_IF_EXIST(global_state_changed)(lc,gstate,message);
+}
+void linphone_core_notify_call_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cstate, const char *message){
+ NOTIFY_IF_EXIST(call_state_changed)(lc,call,cstate,message);
+}
+void linphone_core_notify_call_encryption_changed(LinphoneCore *lc, LinphoneCall *call, bool_t on, const char *authentication_token) {
+ NOTIFY_IF_EXIST(call_encryption_changed)(lc,call,on,authentication_token);
+}
+void linphone_core_notify_registration_state_changed(LinphoneCore *lc, LinphoneProxyConfig *cfg, LinphoneRegistrationState cstate, const char *message){
+ NOTIFY_IF_EXIST(registration_state_changed)(lc,cfg,cstate,message);
+}
+void linphone_core_notify_show_interface(LinphoneCore *lc){
+ NOTIFY_IF_EXIST(show)(lc);
+}
+void linphone_core_notify_display_status(LinphoneCore *lc, const char *message) {
+ NOTIFY_IF_EXIST(display_status)(lc,message);
+}
+void linphone_core_notify_display_message(LinphoneCore *lc, const char *message){
+ NOTIFY_IF_EXIST(display_message)(lc,message);
+}
+void linphone_core_notify_display_warning(LinphoneCore *lc, const char *message){
+ NOTIFY_IF_EXIST(display_warning)(lc,message);
+}
+void linphone_core_notify_display_url(LinphoneCore *lc, const char *message, const char *url){
+ NOTIFY_IF_EXIST(display_url)(lc,message,url);
+}
+void linphone_core_notify_notify_presence_received(LinphoneCore *lc, LinphoneFriend * lf){
+ NOTIFY_IF_EXIST(notify_presence_received)(lc,lf);
+}
+void linphone_core_notify_new_subscription_requested(LinphoneCore *lc, LinphoneFriend *lf, const char *url){
+ NOTIFY_IF_EXIST(new_subscription_requested)(lc,lf,url);
+}
+void linphone_core_notify_auth_info_requested(LinphoneCore *lc, const char *realm, const char *username, const char *domain){
+ NOTIFY_IF_EXIST(auth_info_requested)(lc,realm,username,domain);
+}
+void linphone_core_notify_call_log_updated(LinphoneCore *lc, LinphoneCallLog *newcl){
+ NOTIFY_IF_EXIST(call_log_updated)(lc,newcl);
+}
+void linphone_core_notify_text_message_received(LinphoneCore *lc, LinphoneChatRoom *room, const LinphoneAddress *from, const char *message){
+ NOTIFY_IF_EXIST(text_received)(lc,room,from,message);
+}
+void linphone_core_notify_message_received(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMessage *message){
+ NOTIFY_IF_EXIST(message_received)(lc,room,message);
+}
+void linphone_core_notify_file_transfer_recv(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, const char* buff, size_t size) {
+ NOTIFY_IF_EXIST(file_transfer_recv)(lc,message,content,buff,size);
+}
+void linphone_core_notify_file_transfer_send(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, char* buff, size_t* size) {
+ NOTIFY_IF_EXIST(file_transfer_send)(lc,message,content,buff,size);
+}
+void linphone_core_notify_file_transfer_progress_indication(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, size_t progress) {
+ NOTIFY_IF_EXIST(file_transfer_progress_indication)(lc,message,content,progress);
+}
+void linphone_core_notify_is_composing_received(LinphoneCore *lc, LinphoneChatRoom *room) {
+ NOTIFY_IF_EXIST(is_composing_received)(lc,room);
+}
+void linphone_core_notify_dtmf_received(LinphoneCore* lc, LinphoneCall *call, int dtmf) {
+ NOTIFY_IF_EXIST(dtmf_received)(lc,call,dtmf);
+}
+bool_t linphone_core_dtmf_received_has_listener(const LinphoneCore* lc) {
+ MSList* iterator;
+ for (iterator=lc->vtables; iterator!=NULL; iterator=iterator->next)
+ if (((LinphoneCoreVTable*)(iterator->data))->dtmf_received)
+ return TRUE;
+ return FALSE;
+}
+void linphone_core_notify_refer_received(LinphoneCore *lc, const char *refer_to) {
+ NOTIFY_IF_EXIST(refer_received)(lc,refer_to);
+}
+void linphone_core_notify_buddy_info_updated(LinphoneCore *lc, LinphoneFriend *lf) {
+ NOTIFY_IF_EXIST(buddy_info_updated)(lc,lf);
+}
+void linphone_core_notify_transfer_state_changed(LinphoneCore *lc, LinphoneCall *transfered, LinphoneCallState new_call_state) {
+ NOTIFY_IF_EXIST(transfer_state_changed)(lc,transfered,new_call_state);
+}
+void linphone_core_notify_call_stats_updated(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallStats *stats) {
+ NOTIFY_IF_EXIST(call_stats_updated)(lc,call,stats);
+}
+void linphone_core_notify_info_received(LinphoneCore *lc, LinphoneCall *call, const LinphoneInfoMessage *msg) {
+ NOTIFY_IF_EXIST(info_received)(lc,call,msg);
+}
+void linphone_core_notify_configuring_status(LinphoneCore *lc, LinphoneConfiguringState status, const char *message) {
+ NOTIFY_IF_EXIST(configuring_status)(lc,status,message);
+}
+void linphone_core_notify_network_reachable(LinphoneCore *lc, bool_t reachable) {
+ NOTIFY_IF_EXIST(network_reachable)(lc,reachable);
+}
+void linphone_core_notify_notify_received(LinphoneCore *lc, LinphoneEvent *lev, const char *notified_event, const LinphoneContent *body) {
+ NOTIFY_IF_EXIST(notify_received)(lc,lev,notified_event,body);
+}
+void linphone_core_notify_subscription_state_changed(LinphoneCore *lc, LinphoneEvent *lev, LinphoneSubscriptionState state) {
+ NOTIFY_IF_EXIST(subscription_state_changed)(lc,lev,state);
+}
+void linphone_core_notify_publish_state_changed(LinphoneCore *lc, LinphoneEvent *lev, LinphonePublishState state) {
+ NOTIFY_IF_EXIST(publish_state_changed)(lc,lev,state);
+}
+void linphone_core_add_listener(LinphoneCore *lc, LinphoneCoreVTable *vtable) {
+ ms_message("Vtable [%p] registered on core [%p]",lc,vtable);
+ lc->vtables=ms_list_append(lc->vtables,vtable);
+}
+void linphone_core_remove_listener(LinphoneCore *lc, const LinphoneCoreVTable *vtable) {
+ ms_message("Vtable [%p] unregistered on core [%p]",lc,vtable);
+ lc->vtables=ms_list_remove(lc->vtables,(void*)vtable);
+}
diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h
index 157c15073..9ded4edaa 100644
--- a/coreapi/linphonecore.h
+++ b/coreapi/linphonecore.h
@@ -24,6 +24,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "mediastreamer2/mscommon.h"
#include "mediastreamer2/msvideo.h"
#include "mediastreamer2/mediastream.h"
+#include "mediastreamer2/bitratecontrol.h"
#ifdef IN_LINPHONE
#include "sipsetup.h"
@@ -249,86 +250,61 @@ LinphoneDictionary* lp_config_section_to_dict( const LpConfig* lpconfig, const c
void lp_config_load_dict_to_section( LpConfig* lpconfig, const char* section, const LinphoneDictionary* dict);
-#ifdef IN_LINPHONE
-#include "linphonefriend.h"
-#include "event.h"
-#else
-#include "linphone/linphonefriend.h"
-#include "linphone/event.h"
-#endif
-
-LINPHONE_PUBLIC LinphoneAddress * linphone_address_new(const char *addr);
-LINPHONE_PUBLIC LinphoneAddress * linphone_address_clone(const LinphoneAddress *addr);
-LINPHONE_PUBLIC LinphoneAddress * linphone_address_ref(LinphoneAddress *addr);
-LINPHONE_PUBLIC void linphone_address_unref(LinphoneAddress *addr);
-LINPHONE_PUBLIC const char *linphone_address_get_scheme(const LinphoneAddress *u);
-LINPHONE_PUBLIC const char *linphone_address_get_display_name(const LinphoneAddress* u);
-LINPHONE_PUBLIC const char *linphone_address_get_username(const LinphoneAddress *u);
-LINPHONE_PUBLIC const char *linphone_address_get_domain(const LinphoneAddress *u);
-LINPHONE_PUBLIC int linphone_address_get_port(const LinphoneAddress *u);
-LINPHONE_PUBLIC void linphone_address_set_display_name(LinphoneAddress *u, const char *display_name);
-LINPHONE_PUBLIC void linphone_address_set_username(LinphoneAddress *uri, const char *username);
-LINPHONE_PUBLIC void linphone_address_set_domain(LinphoneAddress *uri, const char *host);
-LINPHONE_PUBLIC void linphone_address_set_port(LinphoneAddress *uri, int port);
-/*remove tags, params etc... so that it is displayable to the user*/
-LINPHONE_PUBLIC void linphone_address_clean(LinphoneAddress *uri);
-LINPHONE_PUBLIC bool_t linphone_address_is_secure(const LinphoneAddress *uri);
-LINPHONE_PUBLIC LinphoneTransportType linphone_address_get_transport(const LinphoneAddress *uri);
-LINPHONE_PUBLIC void linphone_address_set_transport(LinphoneAddress *uri,LinphoneTransportType type);
-LINPHONE_PUBLIC char *linphone_address_as_string(const LinphoneAddress *u);
-LINPHONE_PUBLIC char *linphone_address_as_string_uri_only(const LinphoneAddress *u);
-LINPHONE_PUBLIC bool_t linphone_address_weak_equal(const LinphoneAddress *a1, const LinphoneAddress *a2);
-LINPHONE_PUBLIC void linphone_address_destroy(LinphoneAddress *u);
-
/**
- * Create a #LinphoneAddress object by parsing the user supplied address, given as a string.
- * @param[in] lc #LinphoneCore object
- * @param[in] address String containing the user supplied address
- * @return The create #LinphoneAddress object
- * @ingroup linphone_address
- */
-LINPHONE_PUBLIC LinphoneAddress * linphone_core_create_address(LinphoneCore *lc, const char *address);
-
-struct _SipSetupContext;
-
-
-/**
- * Enum representing the direction of a call.
- * @ingroup call_logs
+ * @addtogroup media_parameters
+ * @{
**/
-enum _LinphoneCallDir {
- LinphoneCallOutgoing, /**< outgoing calls*/
- LinphoneCallIncoming /**< incoming calls*/
+
+/**
+ * Object representing an RTP payload type.
+ */
+typedef PayloadType LinphonePayloadType;
+
+/**
+ * Get the type of payload.
+ * @param[in] pt LinphonePayloadType object
+ * @return The type of payload.
+ */
+LINPHONE_PUBLIC int linphone_payload_type_get_type(const LinphonePayloadType *pt);
+
+/**
+ * Get the normal bitrate in bits/s.
+ * @param[in] pt LinphonePayloadType object
+ * @return The normal bitrate in bits/s.
+ */
+LINPHONE_PUBLIC int linphone_payload_type_get_normal_bitrate(const LinphonePayloadType *pt);
+
+/**
+ * Get the mime type.
+ * @param[in] pt LinphonePayloadType object
+ * @return The mime type.
+ */
+LINPHONE_PUBLIC char * linphone_payload_type_get_mime_type(const LinphonePayloadType *pt);
+
+/**
+ * Get the number of channels.
+ * @param[in] pt LinphonePayloadType object
+ * @return The number of channels.
+ */
+LINPHONE_PUBLIC int linphone_payload_type_get_channels(const LinphonePayloadType *pt);
+
+
+/**
+ * Enum describing RTP AVPF activation modes.
+**/
+enum _LinphoneAVPFMode{
+ LinphoneAVPFDefault=-1, /**