Merge remote-tracking branch 'linphone/master' into daemon

Conflicts:
	.gitignore
	configure.ac
This commit is contained in:
Simon Morlat 2015-12-07 10:52:33 +01:00
commit 52d6aa101f
412 changed files with 57343 additions and 34013 deletions

64
.clang-format Normal file
View file

@ -0,0 +1,64 @@
---
# BasedOnStyle: LLVM
AccessModifierOffset: -2
AlignAfterOpenBracket: true
AlignEscapedNewlinesLeft: false
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: false
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: false
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: false
BinPackArguments: true
BinPackParameters: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
ColumnLimit: 120
CommentPragmas: '^ IWYU pragma:'
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
IndentCaseLabels: false
IndentFunctionDeclarationAfterType: false
IndentWidth: 4
IndentWrappedFunctionNames: false
KeepEmptyLinesAtTheStartOfBlocks: true
Language: Cpp
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right
SpaceAfterCStyleCast: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Cpp11
TabWidth: 4
UseTab: Always
...

51
.git-pre-commit Executable file
View file

@ -0,0 +1,51 @@
#!/bin/bash
# This hook purpose is to keep coding style consistent between all developers
# It is automatically installed in .git/hooks folder by cmake on first run.
# From https://github.com/tatsuhiro-t/nghttp2/blob/master/pre-commit
function invalid-format-detected {
cat git-clang-format.diff
echo "*****************"
echo "$0: Invalid coding style detected (see git-clang-format.diff for issues). Please correct it using one of the following:"
echo "1) Apply patch located at git-clang-format.diff using:"
echo " cd $(git rev-parse --show-toplevel) && $1"
echo "2) Use clang-format to correctly format source code using:"
echo " $2"
echo "3) Reformat these lines manually."
echo "*** Aborting commit.***"
exit 1
}
function git-clang-format-diffing {
format_diff=$(which git-clang-format)
format_diff_options="--style=file"
#only diffing commited files, ignored staged one
$format_diff $format_diff_options --diff $(git --no-pager diff --cached --name-status | grep -v '^D' | cut -f2) > git-clang-format.diff
if ! grep -q -E '(no modified files to format|clang-format did not modify any files)' git-clang-format.diff; then
invalid-format-detected "git apply git-clang-format.diff" "clang-format $format_diff_options -i <some_file.c>"
fi
}
function clang-format-diff-diffing {
format_diff=$(find /usr/bin/ -name 'clang-format-diff*' -type f | tail -n1)
format_diff_options="-style file"
git diff-index --cached --diff-filter=ACMR -p HEAD -- | $format_diff $format_diff_options -p1 > git-clang-format.diff
if [ -s git-clang-format.diff ]; then
invalid-format-detected "patch -p0 < git-clang-format.diff" "${format_diff/-diff/} $format_diff_options -i <some_file.cpp>"
fi
}
set -e
if which git-clang-format &>/dev/null; then
git-clang-format-diffing $@
elif [ ! -z "$(find /usr/bin/ /usr/local/bin/ /opt/bin/ -name 'clang-format-diff*' -type f 2>/dev/null)" ]; then
# Warning! We need at least version 1.6...
clang-format-diff-diffing $@
else
echo "$0: Please install clang-format (coding style checker) - could not find git-clang-format nor clang-format-diff in PATH. Skipping code verification..."
exit 0
fi

12
.gitignore vendored
View file

@ -50,6 +50,8 @@ coreapi/help/chatroom
coreapi/help/doc/
coreapi/help/helloworld
coreapi/help/registration
coreapi/help/realtimetext_receiver
coreapi/help/realtimetext_sender
coreapi/test_ecc
coreapi/test_lsd
gtk/version_date.h
@ -68,6 +70,9 @@ specs.c
*.swp
.deps
.libs
tools/test_ecc
tools/test_lsd
tools/test_numbers
coreapi/help/notify
share/fresh-rootca.pem
tester/liblinphone_tester
@ -89,7 +94,12 @@ tester/linphone_log.gz.txt
tools/auto_answer
tools/lp-autoanswer
build/macos/pkg-distribution.xml
tester/record_for_lc_*.wav
record_for_lc_*.wav
tester/record-call_with_file_player.wav
tester/ZIDCache*.xml
tester/stereo-record.wav
.dirstamp
git-clang-format.diff
*.log
.bc_tester_utils.tmp

View file

@ -25,12 +25,12 @@ project(LINPHONE C CXX)
set(LINPHONE_MAJOR_VERSION "3")
set(LINPHONE_MINOR_VERSION "8")
set(LINPHONE_MICRO_VERSION "2")
set(LINPHONE_MINOR_VERSION "9")
set(LINPHONE_MICRO_VERSION "1")
set(LINPHONE_VERSION "${LINPHONE_MAJOR_VERSION}.${LINPHONE_MINOR_VERSION}.${LINPHONE_MICRO_VERSION}")
set(LINPHONE_SO_VERSION "7")
set(LINPHONE_SO_VERSION "8")
file(GLOB LINPHONE_PO_FILES RELATIVE "${CMAKE_SOURCE_DIR}/po" "${CMAKE_SOURCE_DIR}/po/*.po")
file(GLOB LINPHONE_PO_FILES RELATIVE "${CMAKE_CURRENT_LIST_DIR}/po" "${CMAKE_CURRENT_LIST_DIR}/po/*.po")
string(REGEX REPLACE "([a-zA-Z_]+)\\.po" "\\1" LINPHONE_ALL_LANGS_LIST "${LINPHONE_PO_FILES}")
string(REPLACE ";" " " LINPHONE_ALL_LANGS "${LINPHONE_ALL_LANGS_LIST}")
@ -42,9 +42,11 @@ option(ENABLE_DATE "Use build date in internal version number." NO)
option(ENABLE_DOC "Enable documentation generation with Doxygen." YES)
option(ENABLE_GTK_UI "Turn on or off compilation of gtk interface." YES)
option(ENABLE_LDAP "Enable LDAP support." NO)
option(ENABLE_LIME "Enable Instant Messaging Encryption." NO)
option(ENABLE_MSG_STORAGE "Turn on compilation of message storage." YES)
cmake_dependent_option(ENABLE_NOTIFY "Enable libnotify support." YES "ENABLE_GTK_UI" NO)
option(ENABLE_RELATIVE_PREFIX "Find resources relatively to the installation directory." NO)
option(ENABLE_STRICT "Build with strict compile options." YES)
option(ENABLE_TOOLS "Turn on or off compilation of tools." YES)
option(ENABLE_TUNNEL "Turn on compilation of tunnel support." NO)
option(ENABLE_TUTORIALS "Enable compilation of tutorials." YES)
@ -52,6 +54,25 @@ 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)
option(ENABLE_DEBUG_LOGS "Turn on or off debug level logs." NO)
option(ENABLE_NLS "Build with internationalisation support" YES)
option(ENABLE_CALL_LOGS_STORAGE "Turn on compilation of call logs storage." YES)
macro(apply_compile_flags SOURCE_FILES)
if(${SOURCE_FILES})
set(options "")
foreach(a ${ARGV})
if(STRICT_OPTIONS_${a})
string(REPLACE ";" " " options_${a} "${STRICT_OPTIONS_${a}}")
set(options "${options} ${options_${a}}")
endif()
endforeach()
if(options)
set_source_files_properties(${${SOURCE_FILES}} PROPERTIES COMPILE_FLAGS "${options}")
endif()
endif()
endmacro()
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
@ -62,39 +83,18 @@ include(CMakePushCheckState)
set(MSVC_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/include/MSVC")
if(MSVC)
list(APPEND CMAKE_REQUIRED_INCLUDES "${MSVC_INCLUDE_DIR}")
if(ENABLE_GTK_UI)
if(NOT EXISTS "${CMAKE_CURRENT_BINARY_DIR}/intltool_win32.zip")
message(STATUS "Installing intltool")
file(DOWNLOAD http://ftp.acc.umu.se/pub/GNOME/binaries/win32/intltool/0.40/intltool_0.40.4-1_win32.zip "${CMAKE_CURRENT_BINARY_DIR}/intltool_win32.zip" SHOW_PROGRESS)
execute_process(
COMMAND "${CMAKE_COMMAND}" "-E" "tar" "x" "${CMAKE_CURRENT_BINARY_DIR}/intltool_win32.zip"
WORKING_DIRECTORY "${CMAKE_INSTALL_PREFIX}"
)
endif()
if(NOT EXISTS "${CMAKE_CURRENT_BINARY_DIR}/gtk+-bundle_win32.zip")
message(STATUS "Installing GTK")
file(DOWNLOAD http://ftp.gnome.org/pub/gnome/binaries/win32/gtk+/2.24/gtk+-bundle_2.24.10-20120208_win32.zip "${CMAKE_CURRENT_BINARY_DIR}/gtk+-bundle_win32.zip" SHOW_PROGRESS)
execute_process(
COMMAND "${CMAKE_COMMAND}" "-E" "tar" "x" "${CMAKE_CURRENT_BINARY_DIR}/gtk+-bundle_win32.zip"
WORKING_DIRECTORY "${CMAKE_INSTALL_PREFIX}"
)
endif()
endif()
if(ENABLE_ASSISTANT)
if(NOT EXISTS "${CMAKE_CURRENT_BINARY_DIR}/libsoup.zip")
message(STATUS "Installing libsoup")
file(DOWNLOAD http://www.linphone.org/files/libsoup_2.24.0-1_win32.zip "${CMAKE_CURRENT_BINARY_DIR}/libsoup.zip" SHOW_PROGRESS)
execute_process(
COMMAND "${CMAKE_COMMAND}" "-E" "tar" "x" "${CMAKE_CURRENT_BINARY_DIR}/libsoup.zip"
WORKING_DIRECTORY "${CMAKE_INSTALL_PREFIX}"
)
endif()
endif()
endif()
find_package(BelleSIP REQUIRED)
find_package(Mediastreamer2 REQUIRED)
# find_package should be invoked here to check for libraries - however do NOT
# call include_directories here (see below)
if(LINPHONE_BUILDER_GROUP_EXTERNAL_SOURCE_PATH_BUILDERS)
include("${EP_bellesip_CONFIG_DIR}/BelleSIPConfig.cmake")
include("${EP_ms2_CONFIG_DIR}/Mediastreamer2Config.cmake")
else()
find_package(BelleSIP REQUIRED)
find_package(Mediastreamer2 REQUIRED)
endif()
find_package(XML2 REQUIRED)
find_package(Zlib)
if(ENABLE_UNIT_TESTS)
@ -112,7 +112,11 @@ if(ENABLE_UNIT_TESTS)
endif()
endif()
if(ENABLE_TUNNEL)
find_package(Tunnel)
if(LINPHONE_BUILDER_GROUP_EXTERNAL_SOURCE_PATH_BUILDERS)
include("${EP_tunnel_CONFIG_DIR}/TunnelConfig.cmake")
else()
find_package(Tunnel)
endif()
if(NOT TUNNEL_FOUND)
message(WARNING "Could not find the tunnel library!")
set(ENABLE_TUNNEL OFF CACHE BOOL "Enable tunnel support." FORCE)
@ -130,18 +134,46 @@ if(ENABLE_NOTIFY)
set(ENABLE_NOTIFY OFF CACHE BOOL "Enable libnotify support." FORCE)
endif()
endif()
if(ENABLE_ASSISTANT)
find_package(Soup)
if(SOUP_FOUND)
set(BUILD_WIZARD 1)
else()
message(WARNING "Could not find the soup library!")
if(ENABLE_GTK_UI)
if(WIN32)
set(GTK2_ADDITIONAL_SUFFIXES "../lib/glib-2.0/include" "../lib/gtk-2.0/include")
endif()
find_package(GTK2 2.18 REQUIRED gtk)
if(ENABLE_ASSISTANT AND GTK2_VERSION VERSION_LESS 2.22)
message(WARNING "You need at least GTK 2.22 to enable the assistant")
set(ENABLE_ASSISTANT OFF CACHE BOOL "Turn on assistant compiling." FORCE)
endif()
if(APPLE)
find_package(GtkMacIntegration)
if(GTKMACINTEGRATION_FOUND)
set(HAVE_GTK_OSX 1)
add_definitions("${GTKMACINTEGRATION_CPPFLAGS}")
else()
message(WARNING "gtk-mac-integration not found. Please install gtk-osx-application package.")
endif()
endif()
endif()
if(ENABLE_ASSISTANT)
set(BUILD_WIZARD 1)
endif()
if(ENABLE_NLS)
find_package(Gettext REQUIRED)
find_package(Intl REQUIRED)
endif()
if(ENABLE_CALL_LOGS_STORAGE)
find_package(Sqlite3 REQUIRED)
endif()
if(ENABLE_LIME)
set(HAVE_LIME 1)
endif()
find_package(Gettext)
if(UNIX AND NOT APPLE)
include(CheckIncludeFiles)
check_include_files(libudev.h HAVE_LIBUDEV_H)
endif()
# include_directories must be called only UNDER THIS LINE in order to use our
# projects submodules first (we do NOT want to have system headers in first position)
include_directories(
include/
coreapi/
@ -149,45 +181,60 @@ include_directories(
${CMAKE_CURRENT_BINARY_DIR}/coreapi/
${BELLESIP_INCLUDE_DIRS}
${MEDIASTREAMER2_INCLUDE_DIRS}
${XML2_INCLUDE_DIRS}
)
if(ENABLE_TUNNEL)
include_directories(${TUNNEL_INCLUDE_DIRS})
endif()
include_directories(${XML2_INCLUDE_DIRS})
if(ZLIB_FOUND)
include_directories(${ZLIB_INCLUDE_DIRS})
set(HAVE_ZLIB 1)
endif()
if(SQLITE3_FOUND)
include_directories(${SQLITE3_INCLUDE_DIRS})
add_definitions("-DMSG_STORAGE_ENABLED")
if(ENABLE_MSG_STORAGE)
add_definitions("-DMSG_STORAGE_ENABLED")
endif()
if(ENABLE_CALL_LOGS_STORAGE)
add_definitions("-DCALL_LOGS_STORAGE_ENABLED")
endif()
endif()
if(ENABLE_TUNNEL)
include_directories(${TUNNEL_INCLUDE_DIRS})
endif()
if(ENABLE_ASSISTANT)
include_directories(${SOUP_INCLUDE_DIRS})
if(INTL_FOUND)
set(HAVE_INTL 1)
include_directories(${INTL_INCLUDE_DIRS})
endif()
if(MSVC)
include_directories(${MSVC_INCLUDE_DIR})
endif()
add_definitions("-DIN_LINPHONE")
if(ENABLE_DEBUG_LOGS)
add_definitions("-DDEBUG")
endif()
if(MSVC)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W3")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W3")
else()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wuninitialized -Wdeclaration-after-statement -fno-strict-aliasing -Werror")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wuninitialized -Werror")
set(STRICT_OPTIONS_CPP )
set(STRICT_OPTIONS_C )
set(STRICT_OPTIONS_OBJC )
if(NOT MSVC)
list(APPEND STRICT_OPTIONS_CPP "-Wall" "-Wuninitialized" "-Wno-error=deprecated-declarations")
list(APPEND STRICT_OPTIONS_C "-Wdeclaration-after-statement" "-Wstrict-prototypes" "-Wno-error=strict-prototypes")
if(CMAKE_C_COMPILER_ID STREQUAL "Clang")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Qunused-arguments -Wno-array-bounds")
endif()
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Qunused-arguments -Wno-array-bounds")
list(APPEND STRICT_OPTIONS_CPP "-Qunused-arguments" "-Wno-array-bounds")
endif()
if(APPLE)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-error=unknown-warning-option -Wno-tautological-compare -Wno-unused-function")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error=unknown-warning-option -Wno-tautological-compare -Wno-unused-function")
list(APPEND STRICT_OPTIONS_CPP "-Wno-error=unknown-warning-option" "-Qunused-arguments" "-Wno-tautological-compare" "-Wno-unused-function" "-Wno-array-bounds")
endif()
if(ENABLE_STRICT)
list(APPEND STRICT_OPTIONS_CPP "-Werror" "-fno-strict-aliasing")
endif()
endif()
if(STRICT_OPTIONS_CPP)
list(REMOVE_DUPLICATES STRICT_OPTIONS_CPP)
endif()
if(STRICT_OPTIONS_C)
list(REMOVE_DUPLICATES STRICT_OPTIONS_C)
endif()
@ -216,6 +263,13 @@ if(ENABLE_VIDEO)
endif()
if(LINPHONE_BUILDER_GROUP_EXTERNAL_SOURCE_PATH_BUILDERS)
set(EXPORT_TARGETS_NAME "LinphoneBuilder")
else()
set(EXPORT_TARGETS_NAME "Linphone")
endif()
add_subdirectory(coreapi)
add_subdirectory(share)
if(ENABLE_CONSOLE_UI)
@ -240,9 +294,8 @@ write_basic_package_version_file(
VERSION ${LINPHONE_VERSION}
COMPATIBILITY AnyNewerVersion
)
export(EXPORT LinphoneTargets
export(EXPORT ${EXPORT_TARGETS_NAME}Targets
FILE "${CMAKE_CURRENT_BINARY_DIR}/LinphoneTargets.cmake"
NAMESPACE BelledonneCommunications::
)
configure_file(cmake/LinphoneConfig.cmake.in
"${CMAKE_CURRENT_BINARY_DIR}/LinphoneConfig.cmake"
@ -250,9 +303,8 @@ configure_file(cmake/LinphoneConfig.cmake.in
)
set(ConfigPackageLocation lib/cmake/Linphone)
install(EXPORT LinphoneTargets
install(EXPORT ${EXPORT_TARGETS_NAME}Targets
FILE LinphoneTargets.cmake
NAMESPACE BelledonneCommunications::
DESTINATION ${ConfigPackageLocation}
)
install(FILES

View file

@ -225,11 +225,7 @@ Linphone.app:
MS2_PLUGINS_INSTALL_PREFIX=$(prefix) \
LINPHONE_ADDITIONAL_DEPENDENCIES_PREFIX=$(LINPHONE_ADDITIONAL_DEPENDENCIES_PREFIX) \
gtk-mac-bundler $(PACKAGE_BUNDLE_FILE)
printf "[Pango]\nModuleFiles=./etc/pango/pango.modules\n" \
> $(BUNDLEDIR)/Contents/Resources/etc/pango/pangorc
cp -f $(BUNDLEDIR)/Contents/Resources/etc/pango/pango.modules $(BUNDLEDIR)/Contents/Resources/etc/pango/pango.modules.orig
sed -e 's:@executable_path.*/::g' $(BUNDLEDIR)/Contents/Resources/etc/pango/pango.modules.orig > $(BUNDLEDIR)/Contents/Resources/etc/pango/pango.modules
patch -R ${BUNDLEDIR}/Contents/Resources/share/themes/Quartz/gtk-2.0/gtkrc ${srcdir}/build/macos/quartz-theme-gtkrc.patch
patch ${BUNDLEDIR}/Contents/Resources/share/themes/Quartz/gtk-2.0/gtkrc ${srcdir}/build/macos/quartz-theme-gtkrc.patch
rm -f ${BUNDLEDIR}/Contents/Resources/lib/libopenh264*
bundle: $(MACAPPNAME)

47
NEWS
View file

@ -1,9 +1,40 @@
linphone-3.9.1 -- November 16th, 2015
* Fix crash when recording video calls with the VP8 codec
* Fix H.264 codec support in Mac OS X package
* Fix translation of account assistant
* Bug fixes
linphone-3.9.0 -- November 2nd, 2015
* Video recording of calls in MKV format
* Clickable URLs in chat view
* Add buttons to change the record and playback volumes during a call
* Add button to start chatting without having to create a contact first
* Some icon changes
* Call logs now stored in database
* Bug fixes
linphone-3.8.5 -- June 30th, 2015
* Fix bug about status icon on MacOSX. Attention request worked only once
* Fix crash at the end of the audio assistant
* Fix crash when configuring a remote provisioning
* Fix regression in the codec view. Codec which are not usable because
bandwidth limits are to low were not greyed anymore
* Fix language selection on Windows and MacOSX
* Add translation for 'Arabic' and 'Turkish' items in the language selection
list
linphone-3.8.4 -- June 9th, 2015
* Add a built-in XMLRPC client. Linphone does not depend on libsoup anymore
linphone-3.8.3 -- June 4th, 2015
* Fix status icons on all platforms (Windows, MacOS, non-KDE Linux desktop environment)
linphone-3.8.2 -- May 7th, 2015
Application level improvements:
* add support of the StatusNotifierItem standard to display a status icon on KDE5
* auto-answering can be set through the preferences panel
* bug fixes
Liblinphone level improvements:
* fix audio bug with opus codec
* fix ICE corner case not properly handled and resulting bad final ice status
@ -51,14 +82,14 @@ linphone-3.7.0 -- February 20th, 2014
* Keyboard can be used for DTMF input
* Faster and higly responsive UI thanks to fully asynchronous operation of the liblinphone.
* Addon of opus codec
* Possibility to specify a remote provisionning http URI for configuration
* Possibility to specify a remote provisioning http URI for configuration
* LDAP search integration for Linux and MacOSX
* is-composing notification in chat area
* is-composing notification in chat area
Liblinphone level improvements thanks to new "belle-sip" SIP stack:
* multiple SIP transports simultaneously now allowed
* IP dual stack: can use IPv6 and IPv4 simultaneously
* fully asynchronous behavior: no more lengthly DNS or connections
* fully asynchronous behavior: no more lengthly DNS or connections
* +sip.instance parameter (RFC5626)
* alias parameter (RFC5923)
* better management of network disconnections
@ -76,7 +107,7 @@ linphone-3.7.0 -- February 20th, 2014
linphone-3.6.1 -- June 17, 2013
* fix memory leak with some video cameras on windows.
Requires: mediastreamer2 = 2.9.1 and ortp = 0.22.0
linphone-3.6.0 -- May 27, 2013
@ -141,9 +172,9 @@ linphone-3.4.1 -- February 17th, 2011
Requires mediastreamer-2.7.1
linphone-3.4.0 -- February 7th, 2011
* implement multiple calls feature:
* implement multiple calls feature:
- call hold (with possibility to play a music file)
- call resume
- call resume
- acceptance of 2nd call while putting the others on hold
- creation of another outgoing call while already in call
- blind call transfer
@ -314,7 +345,7 @@ linphone-1.4.1 -- September 18, 2006
* do not change mixer settings at startup
linphone-1.4.0 -- September 11, 2006
* no more glib dependency at all
* no more glib dependency at all
* new mediastreamer2 framework for audio/video streaming
* stable video support with H.263-1998
* echo cancelation

3
README
View file

@ -26,7 +26,6 @@ This is Linphone, a free (GPL) video softphone based on the SIP protocol.
- theora (optional)
+ gsm codec (gsm source package or libgsm-dev or gsm-devel) (optional)
+ libreadline (optional: for convenient command line in linphonec)
+ libsoup (optional: for wizard - account creation assistant)
+ libsqlite3 (optional : for a local history of chat messages)
+ if you want uPnP support (optional):
- libupnp (version 1.6 branch (not patched with 18-url-upnpstrings.patch))
@ -39,7 +38,7 @@ 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 libsrtp-dev
libsqlite3-dev libupnp4-dev libsrtp-dev
+ Install zrtp (optional), for unbreakable call encryption
$ git clone git://git.linphone.org:bzrtp

View file

@ -24,24 +24,23 @@ In order to enable generation of bundle for older MacOS version, it is recommend
##### Linphone library (liblinphone)
sudo port install automake autoconf libtool pkgconfig intltool wget cunit \
antlr3 speex libvpx readline sqlite3 openldap libupnp \
antlr3 speex readline sqlite3 openldap libupnp \
ffmpeg-devel -gpl2
##### Linphone UI (GTK version)
Install `GTK`. It is recommended to use the `quartz` backend for better integration.
sudo port install gtk2 +quartz +no_x11 libsoup
sudo port install gtk-osx-application +no_python
sudo port install gtk2 +quartz +no_x11
sudo port install gtk-osx-application-gtk2 +no_python
sudo port install hicolor-icon-theme
#### Using HomeBrew
##### Linphone library (liblinphone)
brew tap Gui13/linphone
brew install intltool libtool wget pkg-config automake libantlr3.4c \
antlr3.2 gettext speex ffmpeg readline libvpx opus
homebrew/versions/antlr3 gettext speex ffmpeg readline libvpx opus
ln -s /usr/local/bin/glibtoolize /usr/local/bin/libtoolize
brew link --force gettext
#readline is required from linphonec.c otherwise compilation will fail
@ -51,7 +50,7 @@ Install `GTK`. It is recommended to use the `quartz` backend for better integrat
brew install cairo --without-x11
brew install gtk+ --without-x11
brew install gtk-mac-integration libsoup hicolor-icon-theme
brew install gtk-mac-integration hicolor-icon-theme
### Building Linphone
@ -77,6 +76,27 @@ The next pieces need to be compiled manually.
./autogen.sh && ./configure --prefix=/opt/local && make
sudo make install
* Install libvpx (Must be manualy build because the macport recipe does not support 'macosx_deployment_target')
git clone https://chromium.googlesource.com/webm/libvpx -b v1.4.0
cd libvpx
./configure --prefix=/opt/local \
--target=x86_64-darwin10-gcc \
--enable-error-concealment \
--enable-multithread \
--enable-realtime-only \
--enable-spatial-resampling \
--enable-vp8 \
--disable-vp9 \
--enable-libs \
--disable-install-docs \
--disable-debug-libs \
--disable-examples \
--disable-unit-tests \
--as=yasm
make
sudo make install
* Install belle-sip (sip stack)
git clone git://git.linphone.org/belle-sip.git
@ -123,15 +143,12 @@ The next pieces need to be compiled manually.
### Generate portable bundle
If you want to generate a portable bundle, then install `gtk-mac-bundler`:
If you want to generate a portable bundle, then install `gtk-mac-bundler` linphone fork:
git clone https://github.com/jralls/gtk-mac-bundler.git
cd gtk-mac-bundler
git checkout 6e2ed855aaeae43c29436c342ae83568573b5636
git clone git://git.linphone.org/gtk-mac-bundler.git
cd gtk-mac-bundler
make install
export PATH=$PATH:~/.local/bin
# make this dummy charset.alias file for the bundler to be happy:
sudo touch /opt/local/lib/charset.alias
export PATH=$PATH:~/.local/bin
# set writing right for owner on the libssl and libcrypto libraries in order gtk-mac-bundler
# be able to rewrite their rpath
sudo chmod u+w /opt/local/lib/libssl.1.0.0.dylib /opt/local/lib/libcrypto.1.0.0.dylib
@ -160,11 +177,11 @@ The resulting bundle is located in Linphone build directory, together with a zip
* For a better appearance, you can install `gtk-quartz-engine` (a GTK theme) that makes GTK application more similar to other Mac applications (but not perfect).
sudo port install gnome-common
git clone https://github.com/jralls/gtk-quartz-engine.git
cd gtk-quartz-engine
./autogen.sh
./configure --prefix=/opt/local CFLAGS="$CFLAGS -Wno-error" && make
sudo make install
git clone https://github.com/jralls/gtk-quartz-engine.git
cd gtk-quartz-engine
./autogen.sh
./configure --prefix=/opt/local CFLAGS="$CFLAGS -Wno-error" && make
sudo make install
Generate a new bundle to have it included.

View file

@ -16,19 +16,25 @@ else
AUTOMAKE=automake-${AM_VERSION}
fi
if test -f /opt/local/bin/glibtoolize ; then
# darwin
LIBTOOLIZE=/opt/local/bin/glibtoolize
else
LIBTOOLIZE=libtoolize
fi
LIBTOOLIZE="libtoolize"
for lt in glibtoolize libtoolize15 libtoolize14 libtoolize13 ; do
if test -x /usr/bin/$lt ; then
LIBTOOLIZE=$lt ; break
fi
if test -x /usr/local/bin/$lt ; then
LIBTOOLIZE=$lt ; break
fi
if test -x /opt/local/bin/$lt ; then
LIBTOOLIZE=$lt ; break
fi
done
if test -d /opt/local/share/aclocal ; then
ACLOCAL_ARGS="-I /opt/local/share/aclocal"
ACLOCAL_ARGS="-I /opt/local/share/aclocal"
fi
if test -d /share/aclocal ; then
ACLOCAL_ARGS="$ACLOCAL_ARGS -I /share/aclocal"
ACLOCAL_ARGS="$ACLOCAL_ARGS -I /share/aclocal"
fi
INTLTOOLIZE=$(which intltoolize)
@ -49,6 +55,13 @@ $AUTOMAKE --force-missing --add-missing --copy
autoconf
set +x
#install git pre-commit hooks if possible
if [ -d .git/hooks ] && [ ! -f .git/hooks/pre-commit ]; then
cp .git-pre-commit .git/hooks/pre-commit
chmod +x .git/hooks/pre-commit
fi
if [ "$srcdir" = "." ]; then
if [ -x oRTP/autogen.sh ]; then
echo "Generating build scripts in oRTP..."

View file

@ -26,6 +26,7 @@ include $(CLEAR_VARS)
LOCAL_CPP_EXTENSION := .cc
LOCAL_SRC_FILES := \
account_creator.c \
address.c \
authentication.c \
bellesip_sal/sal_address_impl.c \
@ -45,6 +46,7 @@ LOCAL_SRC_FILES := \
call_log.c \
call_params.c \
chat.c \
chat_file_transfer.c \
conference.c \
content.c \
ec-calibrator.c \
@ -73,6 +75,7 @@ LOCAL_SRC_FILES := \
sipsetup.c \
xml2lpc.c \
xml.c \
xmlrpc.c \
vtables.c
ifndef LIBLINPHONE_VERSION
@ -80,6 +83,7 @@ LIBLINPHONE_VERSION = "Devel"
endif
LOCAL_CFLAGS += \
-Wno-error=deprecated-declarations \
-D_BYTE_ORDER=_LITTLE_ENDIAN \
-DORTP_INET6 \
-DINET6 \
@ -116,6 +120,7 @@ LOCAL_C_INCLUDES += \
$(LOCAL_PATH)/../build/android \
$(LOCAL_PATH)/../oRTP/include \
$(LOCAL_PATH)/../mediastreamer2/include \
$(LOCAL_PATH)/../mediastreamer2/src/audiofilters/ \
$(LOCAL_PATH)/../../belle-sip/include \
$(LOCAL_PATH)/../../../gen \
$(LOCAL_PATH)/../../externals/libxml2/include \
@ -170,6 +175,11 @@ LOCAL_CFLAGS += -DHAVE_SILK
LOCAL_STATIC_LIBRARIES += libmssilk
endif
ifeq ($(BUILD_CODEC2),1)
LOCAL_CFLAGS += -DHAVE_CODEC2
LOCAL_STATIC_LIBRARIES += libcodec2 libmscodec2
endif
ifneq ($(BUILD_WEBRTC_AECM)$(BUILD_WEBRTC_ISAC),00)
LOCAL_CFLAGS += -DHAVE_WEBRTC
LOCAL_STATIC_LIBRARIES += libmswebrtc
@ -250,7 +260,7 @@ ifeq ($(BUILD_SRTP),1)
endif
ifeq ($(BUILD_SQLITE),1)
LOCAL_CFLAGS += -DMSG_STORAGE_ENABLED
LOCAL_CFLAGS += -DMSG_STORAGE_ENABLED -DCALL_LOGS_STORAGE_ENABLED
LOCAL_STATIC_LIBRARIES += liblinsqlite
LOCAL_C_INCLUDES += \
$(LOCAL_PATH)/../../externals/sqlite3/
@ -274,6 +284,7 @@ include $(BUILD_SHARED_LIBRARY)
LOCAL_CPPFLAGS=$(LOCAL_CFLAGS)
LOCAL_CFLAGS += -Wdeclaration-after-statement
LOCAL_LDFLAGS := -Wl,-soname,$(LOCAL_MODULE_FILENAME).so
$(call import-module,android/cpufeatures)

View file

@ -10,9 +10,6 @@
/* Define if wizard enabled */
/* #undef BUILD_WIZARD */
/* Tells whether localisation is possible */
/* #undef ENABLE_NLS */
/* Defined when using gsm at nonstandard rates */
/* #undef ENABLE_NONSTANDARD_GSM */
@ -60,7 +57,7 @@
/* #undef HAVE_GETIFADDRS */
/* Tells wheter localisation is possible */
/* #undef HAVE_GETTEXT */
/* #undef HAVE_INTL */
/* Define to 1 if you have the `get_current_dir_name' function. */
#define HAVE_GET_CURRENT_DIR_NAME 1
@ -153,7 +150,7 @@
/* #undef LINPHONE_CONFIG_DIR */
/* path of liblinphone plugins, not mediastreamer2 plugins */
/* #undef LINPHONE_PLUGINS_DIR */
/* #undef LINPHONE_PLUGINS_DIR */
/* Linphone's version number */
/* #undef LINPHONE_VERSION */
@ -205,11 +202,14 @@
/* #undef VERSION */
/* defined if video support is available */
/* #undef VIDEO_ENABLED */
/* #undef VIDEO_ENABLED */
/* Tell whether RSVP support should be compiled. */
/* #undef VINCENT_MAURY_RSVP */
/* Defined when LIME support is compiled */
#define HAVE_LIME 1
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel). */
#if defined AC_APPLE_UNIVERSAL_BUILD

View file

@ -2,27 +2,28 @@ LOCAL_PATH := $(call my-dir)/../../tester
common_SRC_FILES := \
common/bc_tester_utils.c \
call_tester.c \
liblinphone_tester.c \
message_tester.c \
presence_tester.c \
register_tester.c \
setup_tester.c \
upnp_tester.c \
eventapi_tester.c \
stun_tester.c \
flexisip_tester.c \
tester.c \
remote_provisioning_tester.c \
quality_reporting_tester.c \
log_collection_tester.c \
transport_tester.c \
player_tester.c \
dtmf_tester.c \
accountmanager.c \
call_tester.c \
dtmf_tester.c \
eventapi_tester.c \
flexisip_tester.c \
liblinphone_tester.c \
log_collection_tester.c \
message_tester.c \
multi_call_tester.c \
offeranswer_tester.c \
player_tester.c \
presence_tester.c \
proxy_config_tester.c \
quality_reporting_tester.c \
register_tester.c \
remote_provisioning_tester.c \
setup_tester.c \
stun_tester.c \
tester.c \
tunnel_tester.c \
upnp_tester.c \
multicast_call_tester.c \
multi_call.c \
common_C_INCLUDES += \
$(LOCAL_PATH) \

View file

@ -3,6 +3,7 @@ export LINPHONE_WORKDIR="$bundle_res"
export GIO_EXTRA_MODULES="$bundle_lib/gio/modules"
export PANGO_LIBDIR="$bundle_lib"
export PANGO_SYSCONFDIR="$bundle_etc"
export GDK_PIXBUF_MODULE_FILE="$bundle_lib/gdk-pixbuf-2.0/2.10.0/loaders.cache"
#this is very important not to force a shared library path so that native frameworks can find their dependencies by themselves,
#and not be forced to use the few libraries we have in the bundle that have the same name as native libs (ex: libiconv)
@ -23,4 +24,4 @@ esac
export LANG
echo "LANG is $LANG"
echo "LANG is $LANG"

View file

@ -17,6 +17,7 @@
<prefix name="ms2plugins">${env:MS2_PLUGINS_INSTALL_PREFIX}</prefix>
<!-- This prefix definition is necessary if some dependencies are to be taken from /usr/local/lib -->
<prefix name="local">${env:LINPHONE_ADDITIONAL_DEPENDENCIES_PREFIX}</prefix>
<!-- The project directory is the default location of the created
app. If you leave out the path, the current directory is
used. Note the usage of an environment variable here again.
@ -71,19 +72,11 @@
${prefix}/lib/${gtkdir}/modules/*.so
</binary>
<binary>
${prefix}/lib/gdk-pixbuf-2.0
</binary>
<data>
${prefix}/share/mime/globs
${prefix}/share/mime/mime.cache
</data>
<binary>
${prefix}/lib/pango/${pkg:pango:pango_module_version}/modules/*.so
</binary>
<!-- Copy in GTK+ theme engines. Note the use of the
<!-- Copy in GTK+ theme engines and print backends. Note the use of the
"${pkg:module:variable}" macro, which evaluates to a pkg-config
variable in the specified module. Note that any libraries that
binaries link to are also copied in automatically. Note also
@ -93,30 +86,58 @@
${prefix}/lib/${gtkdir}/${pkg:${gtk}:gtk_binary_version}/engines/*.so
</binary>
<binary>
${prefix}/lib/${gtkdir}/${pkg:${gtk}:gtk_binary_version}/immodules/*.so
</binary>
<!-- Copy GIO modules, required for https access for wizard-->
<binary>
${prefix}/lib/gio/modules/libgiognutls.so
${prefix}/lib/${gtkdir}/${pkg:${gtk}:gtk_binary_version}/printbackends/*.so
</binary>
<!-- Translation filenames, one for each program or library that you
<!-- Starting with 2.24, gdk-pixbuf installs into its own directory. Do
not install the svg pixbuf loader as it does not work. -->
<binary>
${prefix}/lib/gdk-pixbuf-2.0/${pkg:${gtk}:gtk_binary_version}/loaders/libpixbufloader-bmp.so
</binary>
<binary>
${prefix}/lib/gdk-pixbuf-2.0/${pkg:${gtk}:gtk_binary_version}/loaders/libpixbufloader-gif.so
</binary>
<binary>
${prefix}/lib/gdk-pixbuf-2.0/${pkg:${gtk}:gtk_binary_version}/loaders/libpixbufloader-icns.so
</binary>
<binary>
${prefix}/lib/gdk-pixbuf-2.0/${pkg:${gtk}:gtk_binary_version}/loaders/libpixbufloader-ico.so
</binary>
<binary>
${prefix}/lib/gdk-pixbuf-2.0/${pkg:${gtk}:gtk_binary_version}/loaders/libpixbufloader-jpeg.so
</binary>
<binary>
${prefix}/lib/gdk-pixbuf-2.0/${pkg:${gtk}:gtk_binary_version}/loaders/libpixbufloader-png.so
</binary>
<!--binary>
${prefix}/lib/pango/${pkg:pango:pango_module_version}/modules/
</binary-->
<!--data>
${prefix}/etc/pango/
</data-->
<!-- Translation filenames, one for each program or library that you
want to copy in to the bundle. The "dest" attribute is
optional, as usual. Bundler will find all translations of that
library/program under the indicated directory and copy them.-->
<data name="linphone">
${prefix:linphone}/share/locale
</data>
<translations name="gdk-pixbuf">
${prefix}/share/locale
</translations>
<translations name="glib20">
${prefix}/share/locale
</translations>
<translations name="gtk20">
${prefix}/share/locale
</translations>
<data name="linphone">
${prefix:linphone}/share/locale
</data>
<translations name="gdk-pixbuf">
${prefix}/share/locale
</translations>
<translations name="glib20">
${prefix}/share/locale
</translations>
<!-- Data to copy in, usually Glade/UI files, images, sounds files
etc. The destination inside the bundle can be specified if the
@ -136,6 +157,9 @@
${prefix:linphone}/share/images
</data>
<data>
${prefix:linphone}/share/icons
</data>
<!-- Copy in the themes data. You may want to trim this to save space
in your bundle. -->
@ -151,7 +175,6 @@
${project}/../../pixmaps/linphone.icns
</data>
<data dest="${bundle}/Contents/Resources">
${project}/environment.sh
</data>
@ -168,10 +191,14 @@
${prefix:linphone}/share/sounds/linphone/rings/oldphone.wav
</data>
<data dest="${bundle}/Contents/Resources/share/sounds/linphone/rings/toy-mono.wav">
${prefix:linphone}/share/sounds/linphone/rings/toy-mono.wav
</data>
<data dest="${bundle}/Contents/Resources/share/sounds/linphone/ringback.wav">
${prefix:linphone}/share/sounds/linphone/ringback.wav
</data>
<data dest="${bundle}/Contents/Resources/share/sounds/linphone/incoming_chat.wav">
${prefix:linphone}/share/sounds/linphone/incoming_chat.wav
</data>

View file

@ -1,4 +1,20 @@
85c85
< buttontype = "textured"
---
> buttontype = "aqua"
--- /opt/local/share/themes/Quartz/gtk-2.0/gtkrc 2015-03-25 15:29:53.000000000 +0100
+++ gtkrc 2015-10-29 13:43:15.000000000 +0100
@@ -12,7 +12,7 @@
gtk-menu-images = 0
gtk-toolbar-style = 0
gtk-enable-mnemonics = 0
-gtk-icon-sizes = "gtk-small-toolbar=16,16:gtk-large-toolbar=22,22"
+gtk-icon-sizes = "gtk-menu=12,12:gtk-button=16,16:gtk-small-toolbar=16,16:gtk-large-toolbar=22,22"
gtk-toolbar-icon-size = large-toolbar
gtk-error-bell = 0
gtk-show-input-method-menu = 0
@@ -82,7 +82,7 @@
engine "quartz"
{
- buttontype = "aqua"
+ buttontype = "textured"
}
}

View file

@ -0,0 +1,16 @@
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:liblinphone_tester"
xmlns:model="using:liblinphone_tester.DataModel" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"
x:Class="liblinphone_tester.App"
RequestedTheme="Light">
<Application.Resources>
<ResourceDictionary>
<model:UnitTestCaseStateToSymbolConverter x:Key="UnitTestCaseStateToSymbol"/>
<model:UnitTestCaseStateToSymbolColorConverter x:Key="UnitTestCaseStateToSymbolColor"/>
<model:OutputTraceLevelToColorConverter x:Key="OutputTraceLevelToColor"/>
</ResourceDictionary>
</Application.Resources>
</Application>

View file

@ -0,0 +1,132 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.ApplicationModel;
using Windows.ApplicationModel.Activation;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
// The Blank Application template is documented at http://go.microsoft.com/fwlink/?LinkId=402347&clcid=0x409
namespace liblinphone_tester
{
/// <summary>
/// Provides application-specific behavior to supplement the default Application class.
/// </summary>
sealed partial class App : Application
{
/// <summary>
/// Allows tracking page views, exceptions and other telemetry through the Microsoft Application Insights service.
/// </summary>
public static Microsoft.ApplicationInsights.TelemetryClient TelemetryClient;
/// <summary>
/// Initializes the singleton application object. This is the first line of authored code
/// executed, and as such is the logical equivalent of main() or WinMain().
/// </summary>
public App()
{
TelemetryClient = new Microsoft.ApplicationInsights.TelemetryClient();
this.InitializeComponent();
this.Suspending += OnSuspending;
}
/// <summary>
/// Invoked when the application is launched normally by the end user. Other entry points
/// will be used such as when the application is launched to open a specific file.
/// </summary>
/// <param name="e">Details about the launch request and process.</param>
protected override void OnLaunched(LaunchActivatedEventArgs e)
{
#if DEBUG
if (System.Diagnostics.Debugger.IsAttached)
{
this.DebugSettings.EnableFrameRateCounter = true;
}
#endif
Frame rootFrame = Window.Current.Content as Frame;
// Do not repeat app initialization when the Window already has content,
// just ensure that the window is active
if (rootFrame == null)
{
// Create a Frame to act as the navigation context and navigate to the first page
rootFrame = new Frame();
rootFrame.NavigationFailed += OnNavigationFailed;
if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
{
//TODO: Load state from previously suspended application
}
// Place the frame in the current Window
Window.Current.Content = rootFrame;
}
if (rootFrame.Content == null)
{
// When the navigation stack isn't restored navigate to the first page,
// configuring the new page by passing required information as a navigation
// parameter
rootFrame.Navigate(typeof(MainPage), e.Arguments);
}
// Ensure the current window is active
Window.Current.Activate();
}
/// <summary>
/// Invoked when Navigation to a certain page fails
/// </summary>
/// <param name="sender">The Frame which failed navigation</param>
/// <param name="e">Details about the navigation failure</param>
void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
{
throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
}
/// <summary>
/// Invoked when application execution is being suspended. Application state is saved
/// without knowing whether the application will be terminated or resumed with the contents
/// of memory still intact.
/// </summary>
/// <param name="sender">The source of the suspend request.</param>
/// <param name="e">Details about the suspend request.</param>
private void OnSuspending(object sender, SuspendingEventArgs e)
{
var deferral = e.SuspendingOperation.GetDeferral();
//TODO: Save application state and stop any background activity
deferral.Complete();
}
protected override void OnActivated(IActivatedEventArgs args)
{
if (args.Kind == ActivationKind.Protocol)
{
var protocolArgs = (ProtocolActivatedEventArgs)args;
var uri = protocolArgs.Uri;
Frame rootFrame = Window.Current.Content as Frame;
if (rootFrame == null)
rootFrame = new Frame();
rootFrame.NavigationFailed += OnNavigationFailed;
rootFrame.Navigate(typeof(MainPage), uri);
Window.Current.Content = rootFrame;
Window.Current.Activate();
}
base.OnActivated(args);
}
}
}

View file

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<ApplicationInsights xmlns="http://schemas.microsoft.com/ApplicationInsights/2013/Settings">
<!--
Learn more about Application Insights configuration with ApplicationInsights.config here:
http://go.microsoft.com/fwlink/?LinkID=513840
Note: If not present, please add <InstrumentationKey>Your Key</InstrumentationKey> to the top of this file.
-->
<TelemetryModules>
<Add Type="Microsoft.ApplicationInsights.Extensibility.Implementation.Tracing.DiagnosticsTelemetryModule, Microsoft.ApplicationInsights"/>
<Add Type="Microsoft.ApplicationInsights.Extensibility.Windows.SessionTelemetryModule, Microsoft.ApplicationInsights.Extensibility.Windows"/>
<Add Type="Microsoft.ApplicationInsights.Extensibility.Windows.PageViewTelemetryModule, Microsoft.ApplicationInsights.Extensibility.Windows"/>
<Add Type="Microsoft.ApplicationInsights.Extensibility.Windows.UnhandledExceptionTelemetryModule, Microsoft.ApplicationInsights.Extensibility.Windows"/>
</TelemetryModules>
<TelemetryChannel Type="Microsoft.ApplicationInsights.Channel.PersistenceChannel, Microsoft.ApplicationInsights.PersistenceChannel"/>
<ContextInitializers>
<Add Type="Microsoft.ApplicationInsights.Extensibility.ComponentContextInitializer, Microsoft.ApplicationInsights"/>
<Add Type="Microsoft.ApplicationInsights.Extensibility.DeviceContextInitializer, Microsoft.ApplicationInsights"/>
</ContextInitializers>
<TelemetryInitializers>
<Add Type="Microsoft.ApplicationInsights.Extensibility.Windows.UserContextInitializer, Microsoft.ApplicationInsights.Extensibility.Windows"/>
</TelemetryInitializers>
</ApplicationInsights>

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View file

@ -0,0 +1,251 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using liblinphone_tester_runtime_component;
using System.Collections.ObjectModel;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Media;
using System.ComponentModel;
using Windows.UI;
using Windows.UI.Xaml.Documents;
using Windows.UI.Core;
namespace liblinphone_tester.DataModel
{
public class OutputTrace
{
public OutputTrace(String lev, String msg)
{
Level = lev;
Msg = msg;
}
public String Level { get; private set; }
public String Msg { get; private set; }
}
public class UnitTestSuite
{
public UnitTestSuite(string name)
{
Name = name;
Cases = new ObservableCollection<UnitTestCase>();
Selected = false;
}
public string Name { get; private set; }
public bool Selected
{
get { return Cases.All(x => x.Selected); }
set
{
foreach (UnitTestCase c in Cases)
{
c.Selected = value;
}
}
}
public ObservableCollection<UnitTestCase> Cases { get; private set; }
}
public enum UnitTestCaseState
{
NotRun,
Success,
Failure
}
public class UnitTestCase : INotifyPropertyChanged
{
public UnitTestCase(UnitTestSuite suite, string name)
{
_suite = new WeakReference(suite);
Name = name;
Selected = false;
State = UnitTestCaseState.NotRun;
Traces = new ObservableCollection<OutputTrace>();
}
public UnitTestSuite Suite
{
get { return _suite.Target as UnitTestSuite; }
}
public string Name { get; private set; }
public bool Selected
{
get { return _selected; }
set
{
_selected = value;
RaisePropertyChanged("Selected");
}
}
public UnitTestCaseState State
{
get { return _state; }
set
{
_state = value;
RaisePropertyChanged("State");
}
}
public ObservableCollection<OutputTrace> Traces
{
get { return _traces; }
set
{
_traces = value;
RaisePropertyChanged("Traces");
}
}
public CoreDispatcher Dispatcher { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged(string name)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
private WeakReference _suite;
private bool _selected;
private UnitTestCaseState _state;
private ObservableCollection<OutputTrace> _traces;
}
public sealed class UnitTestDataSource
{
private static UnitTestDataSource _unitTestDataSource = new UnitTestDataSource();
private ObservableCollection<UnitTestSuite> _suites = new ObservableCollection<UnitTestSuite>();
public ObservableCollection<UnitTestSuite> Suites
{
get { return this._suites; }
}
public static IEnumerable<UnitTestSuite> GetSuites(LibLinphoneTester tester)
{
return _unitTestDataSource.FillSuites(tester);
}
private IEnumerable<UnitTestSuite> FillSuites(LibLinphoneTester tester)
{
if (this.Suites.Count != 0) return this.Suites;
for (int i = 0; i < tester.nbTestSuites(); i++)
{
UnitTestSuite suite = new UnitTestSuite(tester.testSuiteName(i));
for (int j = 0; j < tester.nbTests(suite.Name); j++)
{
suite.Cases.Add(new UnitTestCase(suite, tester.testName(suite.Name, j)));
}
this.Suites.Add(suite);
}
return this.Suites;
}
}
public sealed class UnitTestCaseStateToSymbolConverter : IValueConverter
{
object IValueConverter.Convert(object value, Type targetType, object parametr, string language)
{
if (!value.GetType().Equals(typeof(UnitTestCaseState)))
{
throw new ArgumentException("Only UnitTestCaseState is supported");
}
if (targetType.Equals(typeof(Symbol)))
{
switch ((UnitTestCaseState)value)
{
case UnitTestCaseState.Success:
return Symbol.Like;
case UnitTestCaseState.Failure:
return Symbol.Dislike;
case UnitTestCaseState.NotRun:
default:
return Symbol.Help;
}
}
else
{
throw new ArgumentException(string.Format("Unsupported type {0}", targetType.FullName));
}
}
object IValueConverter.ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
public sealed class UnitTestCaseStateToSymbolColorConverter : IValueConverter
{
object IValueConverter.Convert(object value, Type targetType, object parameter, string language)
{
if (!value.GetType().Equals(typeof(UnitTestCaseState)))
{
throw new ArgumentException("Only UnitTestCaseState is supported");
}
if (targetType.Equals(typeof(Brush)))
{
switch ((UnitTestCaseState)value)
{
case UnitTestCaseState.Success:
return new SolidColorBrush(Colors.ForestGreen);
case UnitTestCaseState.Failure:
return new SolidColorBrush(Colors.IndianRed);
case UnitTestCaseState.NotRun:
default:
return new SolidColorBrush(Colors.LightGray);
}
}
else
{
throw new ArgumentException(string.Format("Unsupported format {0}", targetType.FullName));
}
}
object IValueConverter.ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
public sealed class OutputTraceLevelToColorConverter : IValueConverter
{
object IValueConverter.Convert(object value, Type targetType, object parameter, string language)
{
if (!value.GetType().Equals(typeof(String)))
{
throw new ArgumentException("Only String is supported");
}
if (targetType.Equals(typeof(Brush)))
{
if ((String)value == "Error")
{
return new SolidColorBrush(Colors.IndianRed);
}
else if ((String)value == "Warning")
{
return new SolidColorBrush(Colors.Orange);
}
return new SolidColorBrush(Colors.Black);
}
else
{
throw new ArgumentException(string.Format("Unsupported format {0}", targetType.FullName));
}
}
object IValueConverter.ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
}

View file

@ -0,0 +1,128 @@
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:liblinphone_tester"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:model="using:liblinphone_tester.DataModel"
xmlns:uixdata="using:Windows.UI.Xaml.Data" x:Name="page"
x:Class="liblinphone_tester.MainPage">
<Page.Resources>
<CollectionViewSource x:Name="UnitTestCVS"
Source="{x:Bind Suites}"
ItemsPath="Cases"
IsSourceGrouped="True"/>
<DataTemplate x:Key="ZoomedInTemplate" x:DataType="model:UnitTestCase">
<Grid Width="320">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<CheckBox Grid.Column="0"
Content="{x:Bind Name}"
IsChecked="{Binding Selected, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
<SymbolIcon Grid.Column="1"
Symbol="{Binding State, Mode=OneWay, Converter={StaticResource UnitTestCaseStateToSymbol}, UpdateSourceTrigger=PropertyChanged}"
Foreground="{Binding State, Mode=OneWay, Converter={StaticResource UnitTestCaseStateToSymbolColor}, UpdateSourceTrigger=PropertyChanged}" Margin="16,0,32,0"/>
</Grid>
</DataTemplate>
<DataTemplate x:Key="ZoomedInGroupHeaderTemplate" x:DataType="model:UnitTestSuite">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{x:Bind Name}" Foreground="{ThemeResource ApplicationForegroundThemeBrush}" Style="{StaticResource SubtitleTextBlockStyle}"/>
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="ZoomedOutTemplate" x:DataType="uixdata:ICollectionViewGroup">
<TextBlock Text="{x:Bind Group.(model:UnitTestSuite.Name)}" Style="{StaticResource SubtitleTextBlockStyle}" TextWrapping="Wrap"/>
</DataTemplate>
<DataTemplate x:Key="TraceTemplate">
<TextBlock FontFamily="Courier New">
<Run Text="{Binding Msg}" Foreground="{Binding Level, Converter={StaticResource OutputTraceLevelToColor}}"/>
</TextBlock>
</DataTemplate>
</Page.Resources>
<Page.BottomAppBar>
<CommandBar x:Name="CommandBar">
<AppBarButton x:Name="Run" Icon="Play" Label="Run" Click="RunSelected_Click"/>
<AppBarButton x:Name="SelectAll" Icon="SelectAll" Label="Select all" Click="SelectAll_Click"/>
<AppBarToggleButton x:Name="Verbose" Icon="Comment" IsChecked="True" Label="Verbose"/>
</CommandBar>
</Page.BottomAppBar>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<SplitView x:Name="splitView" Grid.Row="0" IsPaneOpen="True" DisplayMode="Inline">
<SplitView.Pane>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="Test selection" Style="{StaticResource HeaderTextBlockStyle}" Margin="12,0,0,0"/>
<SemanticZoom x:Name="SemanticZoom" Grid.Row="1">
<SemanticZoom.ZoomedInView>
<ListView ItemsSource="{x:Bind UnitTestCVS.View}"
ScrollViewer.IsHorizontalScrollChainingEnabled="False"
SelectionMode="None"
ItemTemplate="{StaticResource ZoomedInTemplate}"
IsItemClickEnabled="True"
ItemClick="UnitTestCase_Click">
<ListView.GroupStyle>
<GroupStyle HeaderTemplate="{StaticResource ZoomedInGroupHeaderTemplate}" />
</ListView.GroupStyle>
</ListView>
</SemanticZoom.ZoomedInView>
<SemanticZoom.ZoomedOutView>
<ListView ItemsSource="{x:Bind UnitTestCVS.View.CollectionGroups}"
SelectionMode="None"
ItemTemplate="{StaticResource ZoomedOutTemplate}">
</ListView>
</SemanticZoom.ZoomedOutView>
</SemanticZoom>
</Grid>
</SplitView.Pane>
<Grid x:Name="TestResultPage">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="Test result" Style="{StaticResource HeaderTextBlockStyle}" Margin="12,0,0,0"/>
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Style="{StaticResource SubheaderTextBlockStyle}" Margin="16,0,0,0" Text="{Binding Name, Mode=OneWay}"/>
<SymbolIcon Grid.Column="1" x:Name="TestResultState"
Visibility="Collapsed"
Symbol="{Binding State, Mode=OneWay, Converter={StaticResource UnitTestCaseStateToSymbol}, UpdateSourceTrigger=PropertyChanged}"
Foreground="{Binding State, Mode=OneWay, Converter={StaticResource UnitTestCaseStateToSymbolColor}, UpdateSourceTrigger=PropertyChanged}" Margin="16,0,32,0"/>
<AppBarButton Grid.Column="2" x:Name="TestResultRun"
Icon="Play" Label="Run"
IsEnabled="{Binding IsEnabled, ElementName=CommandBar}"
Click="RunSingle_Click" Visibility="Collapsed"/>
</Grid>
<ScrollViewer Grid.Row="2">
<ItemsControl ItemsSource="{Binding Traces}" ItemTemplate="{StaticResource TraceTemplate}" Margin="20,12,0,0"/>
</ScrollViewer>
</Grid>
</SplitView>
<ProgressBar x:Name="ProgressIndicator" Grid.Row="1"
Width="{Binding ActualWidth, ElementName=CommandBar, Mode=OneWay}" Margin="16,0,0,0"/>
</Grid>
</Page>

View file

@ -0,0 +1,200 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using liblinphone_tester.DataModel;
using liblinphone_tester_runtime_component;
using System.Threading.Tasks;
using Windows.UI.Core;
using Windows.UI.Xaml.Documents;
using Windows.Storage;
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409
namespace liblinphone_tester
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page, OutputTraceListener
{
public MainPage()
{
this.InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
if ((e.Parameter is Uri) && (e.Parameter.ToString().Equals("liblinphone-tester:autolaunch")))
{
AutoLaunch();
}
else
{
LibLinphoneTester.Instance.initialize(ApplicationData.Current.LocalFolder, true);
_suites = UnitTestDataSource.GetSuites(LibLinphoneTester.Instance);
}
}
public IEnumerable<UnitTestSuite> Suites
{
get { return _suites; }
}
private IEnumerable<UnitTestSuite> _suites;
private void SelectAll_Click(object sender, RoutedEventArgs e)
{
bool allSelected = Suites.All(x => x.Selected);
foreach (UnitTestSuite suite in Suites)
{
suite.Selected = !allSelected;
}
}
private void RunSelected_Click(object sender, RoutedEventArgs e)
{
int nbCases = 0;
foreach (UnitTestSuite suite in Suites)
{
foreach (UnitTestCase c in suite.Cases)
{
if (c.Selected) nbCases++;
}
}
if (nbCases == 0) return;
PrepareRun(nbCases);
var tup = new Tuple<IEnumerable<UnitTestSuite>, bool?>(Suites, Verbose.IsChecked);
var t = Task.Factory.StartNew(async (object parameters) =>
{
var p = parameters as Tuple<IEnumerable<UnitTestSuite>, bool?>;
IEnumerable<UnitTestSuite> suites = p.Item1;
bool verbose = p.Item2 != null ? (bool)p.Item2 : false;
foreach (UnitTestSuite suite in suites)
{
foreach (UnitTestCase c in suite.Cases)
{
if (c.Selected)
{
await RunUnitTestCase(c, verbose);
}
}
}
}, tup);
}
private void RunSingle_Click(object sender, RoutedEventArgs e)
{
PrepareRun(1);
var tup = new Tuple<UnitTestCase, bool?>(DisplayedTestCase, Verbose.IsChecked);
var t = Task.Factory.StartNew(async (object parameters) =>
{
var p = parameters as Tuple<UnitTestCase, bool?>;
UnitTestCase c = p.Item1;
bool verbose = p.Item2 != null ? (bool)p.Item2 : false;
await RunUnitTestCase(c, verbose);
}, tup);
}
private void PrepareRun(int nbCases)
{
CommandBar.IsEnabled = false;
ProgressIndicator.IsEnabled = true;
ProgressIndicator.Minimum = 0;
ProgressIndicator.Maximum = nbCases;
ProgressIndicator.Value = 0;
LibLinphoneTester.Instance.setOutputTraceListener(this);
}
private async Task RunUnitTestCase(UnitTestCase c, bool verbose)
{
UnitTestCaseState newState = UnitTestCaseState.NotRun;
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
RunningTestCase = c;
});
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
c.Traces.Clear();
});
c.Dispatcher = Dispatcher;
if (LibLinphoneTester.Instance.run(c.Suite.Name, c.Name, verbose))
{
newState = UnitTestCaseState.Failure;
}
else
{
newState = UnitTestCaseState.Success;
}
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
c.State = newState;
ProgressIndicator.Value += 1;
if (ProgressIndicator.Value == ProgressIndicator.Maximum)
{
UnprepareRun();
}
});
}
private void UnprepareRun()
{
LibLinphoneTester.Instance.setOutputTraceListener(null);
RunningTestCase = null;
ProgressIndicator.IsEnabled = false;
CommandBar.IsEnabled = true;
}
private void UnitTestCase_Click(object sender, ItemClickEventArgs e)
{
DisplayedTestCase = (e.ClickedItem as UnitTestCase);
TestResultPage.DataContext = DisplayedTestCase;
TestResultState.Visibility = Visibility.Visible;
TestResultRun.Visibility = Visibility.Visible;
}
public async void outputTrace(String lev, String msg)
{
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
if (RunningTestCase != null)
{
RunningTestCase.Traces.Add(new OutputTrace(lev, msg));
}
});
}
private void AutoLaunch()
{
CommandBar.IsEnabled = false;
ProgressIndicator.IsIndeterminate = true;
ProgressIndicator.IsEnabled = true;
LibLinphoneTester.Instance.initialize(ApplicationData.Current.LocalFolder, false);
LibLinphoneTester.Instance.runAllToXml();
if (LibLinphoneTester.Instance.AsyncAction != null)
{
LibLinphoneTester.Instance.AsyncAction.Completed += (asyncInfo, asyncStatus) => {
App.Current.Exit();
};
}
}
private UnitTestCase RunningTestCase;
private UnitTestCase DisplayedTestCase;
}
}

View file

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" IgnorableNamespaces="uap mp">
<Identity Name="BelledonneCommunications.LibLinphoneTester" Publisher="CN=belledonne communications, O=belledonne communications, L=Grenoble, C=FR" Version="1.0.0.0" />
<mp:PhoneIdentity PhoneProductId="7fdbb4f3-13d7-4ca5-a0b9-c7fe297c78f1" PhonePublisherId="00000000-0000-0000-0000-000000000000" />
<Properties>
<DisplayName>liblinphone-tester</DisplayName>
<PublisherDisplayName>Belledonne Communications</PublisherDisplayName>
<Logo>Assets\StoreLogo.png</Logo>
</Properties>
<Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.10069.0" MaxVersionTested="10.0.10069.0" />
</Dependencies>
<Resources>
<Resource Language="x-generate" />
</Resources>
<Applications>
<Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="liblinphone_tester.App">
<uap:VisualElements DisplayName="liblinphone-tester" Square150x150Logo="Assets\Logo.png" Square44x44Logo="Assets\SmallLogo.png" Description="liblinphone-tester" BackgroundColor="#ffffff">
<uap:DefaultTile Wide310x150Logo="Assets\WideLogo.png">
<uap:ShowNameOnTiles>
<uap:ShowOn Tile="wide310x150Logo" />
</uap:ShowNameOnTiles>
</uap:DefaultTile>
<uap:SplashScreen Image="Assets\SplashScreen.png" />
</uap:VisualElements>
<Extensions>
<uap:Extension Category="windows.protocol">
<uap:Protocol Name="liblinphone-tester" />
</uap:Extension>
</Extensions>
</Application>
</Applications>
<Capabilities>
<Capability Name="internetClient" />
<DeviceCapability Name="microphone" />
</Capabilities>
</Package>

View file

@ -0,0 +1,29 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("liblinphone-tester")]
[assembly: AssemblyDescription("LibLinphone tester for Windows 10")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Belledonne Communications")]
[assembly: AssemblyProduct("liblinphone-tester-windows10")]
[assembly: AssemblyCopyright("Copyright © 2015 Belledonne Communications")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: ComVisible(false)]

View file

@ -0,0 +1,31 @@
<!--
This file contains Runtime Directives used by .NET Native. The defaults here are suitable for most
developers. However, you can modify these parameters to modify the behavior of the .NET Native
optimizer.
Runtime Directives are documented at http://go.microsoft.com/fwlink/?LinkID=391919
To fully enable reflection for App1.MyClass and all of its public/private members
<Type Name="App1.MyClass" Dynamic="Required All"/>
To enable dynamic creation of the specific instantiation of AppClass<T> over System.Int32
<TypeInstantiation Name="App1.AppClass" Arguments="System.Int32" Activate="Required Public" />
Using the Namespace directive to apply reflection policy to all the types in a particular namespace
<Namespace Name="DataClasses.ViewModels" Seralize="All" />
-->
<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
<Application>
<!--
An Assembly element with Name="*Application*" applies to all assemblies in
the application package. The asterisks are not wildcards.
-->
<Assembly Name="*Application*" Dynamic="Required All" />
<!-- Add your application specific runtime directives here. -->
</Application>
</Directives>

View file

@ -0,0 +1,142 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|ARM">
<Configuration>Debug</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|ARM">
<Configuration>Release</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\..\..\tester\liblinphone_tester_windows.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\..\tester\liblinphone_tester_windows.h" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\..\bcg729\build\windows10\libmsbcg729\libmsbcg729.vcxproj">
<Project>{acf5ea95-d647-4d0c-8f97-2cd9aae8a2e0}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\..\..\build\sqlite\sqlite.vcxproj">
<Project>{74cad9d0-d8ae-4896-b71b-b2d9b48f30aa}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\..\..\msamr\build\windows10\libmsamr\libmsamr.vcxproj">
<Project>{8c1bc968-c5c8-4d4b-9ef3-d6a065fc7c97}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\..\..\msilbc\build\windows10\libmsilbc\libmsilbc.vcxproj">
<Project>{6a18bbb9-08d1-41a8-be57-17fc992cc36f}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\..\..\msopenh264\build\windows10\libmsopenh264\libmsopenh264.vcxproj">
<Project>{bb8ebb21-f22c-4a68-99cb-67fa36c495e3}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\..\..\mssilk\build\windows10\libmssilk\libmssilk.vcxproj">
<Project>{b84d5c3b-6de5-49c8-b3dd-5eb67b01a527}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\..\..\mswasapi\windows10\libmswasapi\libmswasapi.vcxproj">
<Project>{266b769a-c04e-424c-9033-7209f0425bc0}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\..\..\mswebrtc\build\windows10\libmswebrtc\libmswebrtc.vcxproj">
<Project>{878cf9d3-9761-479e-a715-a1de9f99cb78}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\..\..\mswinrtvid\windows10\libmswinrtvid\libmswinrtvid.vcxproj">
<Project>{2d0e44c4-e51d-4911-b876-345d1e5e5209}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\..\..\zlib\build\windows10\zlib\zlib.vcxproj">
<Project>{a34f450d-392d-4660-9618-810bd695b3b0}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\..\mediastreamer2\build\windows10\mswinrtjpeg2yuv\mswinrtjpeg2yuv.vcxproj">
<Project>{545f846d-7f19-4d6d-a50b-172a7c9b61e7}</Project>
</ProjectReference>
<ProjectReference Include="..\liblinphone-tester-static\liblinphone-tester-static.vcxproj">
<Project>{9eb3fe8d-2d91-4d29-a3bb-98ddb51d45b7}</Project>
</ProjectReference>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{1ce10f06-8fad-437f-b3d7-3b7a8909a190}</ProjectGuid>
<Keyword>WindowsRuntimeComponent</Keyword>
<ProjectName>liblinphone-tester-runtime-component</ProjectName>
<RootNamespace>liblinphone_tester_runtime_component</RootNamespace>
<DefaultLanguage>en-US</DefaultLanguage>
<MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
<AppContainerApplication>true</AppContainerApplication>
<ApplicationType>Windows Store</ApplicationType>
<ApplicationTypeRevision>10</ApplicationTypeRevision>
<WindowsTargetPlatformVersion>10.0.10240.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformMinVersion>10.0.10069.0</WindowsTargetPlatformMinVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<GenerateManifest>false</GenerateManifest>
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<PreprocessorDefinitions>IN_LINPHONE;_WINRT_DLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalUsingDirectories>$(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)</AdditionalUsingDirectories>
<AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
<DisableSpecificWarnings>28204</DisableSpecificWarnings>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\..\..\coreapi;$(ProjectDir)..\..\..\..\tester\common;$(ProjectDir)..\..\..\..\mediastreamer2\include;$(ProjectDir)..\..\..\..\oRTP\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<PreprocessorDefinitions>IN_LINPHONE;_WINRT_DLL;NDEBUG;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalUsingDirectories>$(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)</AdditionalUsingDirectories>
<AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
<DisableSpecificWarnings>28204</DisableSpecificWarnings>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\..\..\coreapi;$(ProjectDir)..\..\..\..\tester\common;$(ProjectDir)..\..\..\..\mediastreamer2\include;$(ProjectDir)..\..\..\..\oRTP\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View file

@ -0,0 +1,130 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|ARM">
<Configuration>Debug</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|ARM">
<Configuration>Release</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\..\..\tester\accountmanager.c" />
<ClCompile Include="..\..\..\..\tester\call_tester.c" />
<ClCompile Include="..\..\..\..\tester\common\bc_tester_utils.c" />
<ClCompile Include="..\..\..\..\tester\dtmf_tester.c" />
<ClCompile Include="..\..\..\..\tester\eventapi_tester.c" />
<ClCompile Include="..\..\..\..\tester\flexisip_tester.c" />
<ClCompile Include="..\..\..\..\tester\liblinphone_tester.c" />
<ClCompile Include="..\..\..\..\tester\log_collection_tester.c" />
<ClCompile Include="..\..\..\..\tester\message_tester.c" />
<ClCompile Include="..\..\..\..\tester\multicast_call_tester.c" />
<ClCompile Include="..\..\..\..\tester\multi_call_tester.c" />
<ClCompile Include="..\..\..\..\tester\offeranswer_tester.c" />
<ClCompile Include="..\..\..\..\tester\player_tester.c" />
<ClCompile Include="..\..\..\..\tester\presence_tester.c" />
<ClCompile Include="..\..\..\..\tester\proxy_config_tester.c" />
<ClCompile Include="..\..\..\..\tester\quality_reporting_tester.c" />
<ClCompile Include="..\..\..\..\tester\register_tester.c" />
<ClCompile Include="..\..\..\..\tester\remote_provisioning_tester.c" />
<ClCompile Include="..\..\..\..\tester\setup_tester.c" />
<ClCompile Include="..\..\..\..\tester\stun_tester.c" />
<ClCompile Include="..\..\..\..\tester\tester.c" />
<ClCompile Include="..\..\..\..\tester\tunnel_tester.c" />
<ClCompile Include="..\..\..\..\tester\upnp_tester.c" />
<ClCompile Include="..\..\..\..\tester\video_tester.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\..\tester\common\bc_tester_utils.h" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\..\belle-sip\build\windows10\belle-sip\belle-sip.vcxproj">
<Project>{b6cdf482-7da3-43d4-9b12-70150106c191}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\..\..\cunit\build\windows10\cunit\cunit.vcxproj">
<Project>{025e28a8-9dfb-4015-ad56-19896aa6cc9b}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\..\mediastreamer2\build\windows10\mediastreamer2\mediastreamer2.vcxproj">
<Project>{88e3c241-eb6f-4c84-80dc-89b8961daf80}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\..\oRTP\build\windows10\ortp\ortp.vcxproj">
<Project>{2e56b851-9d8d-40e5-84bb-e4ee63b71d25}</Project>
</ProjectReference>
<ProjectReference Include="..\..\liblinphone\liblinphone.vcxproj">
<Project>{c7139899-d8bc-48a3-a437-6844a8baabef}</Project>
</ProjectReference>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{9eb3fe8d-2d91-4d29-a3bb-98ddb51d45b7}</ProjectGuid>
<Keyword>StaticLibrary</Keyword>
<ProjectName>liblinphone-tester-static</ProjectName>
<RootNamespace>liblinphone_tester_static</RootNamespace>
<DefaultLanguage>en-US</DefaultLanguage>
<MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
<AppContainerApplication>true</AppContainerApplication>
<ApplicationType>Windows Store</ApplicationType>
<ApplicationTypeRevision>10</ApplicationTypeRevision>
<WindowsTargetPlatformVersion>10.0.10240.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformMinVersion>10.0.10069.0</WindowsTargetPlatformMinVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<GenerateManifest>false</GenerateManifest>
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<CompileAsWinRT>false</CompileAsWinRT>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>$(SolutionDir)$(Platform)\$(Configuration)\include;$(ProjectDir)..\..\..\..\tester;$(ProjectDir)..\..\..\..\tester\common;$(ProjectDir)..\..\liblinphone;$(ProjectDir)..\..\..\..\coreapi;$(ProjectDir)..\..\..\..\include;$(ProjectDir)..\..\..\..\mediastreamer2\include;$(ProjectDir)..\..\..\..\oRTP\include;$(ProjectDir)..\..\..\..\..\belle-sip\include;$(ProjectDir)..\..\..\..\..\sqlite;$(ProjectDir)..\..\..\..\..\zlib;$(ProjectDir)..\..\..\..\..\cunit\build\windows10\cunit\$(Platform)\$(Configuration);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>BC_CONFIG_FILE="config.h";IN_LINPHONE;MSG_STORAGE_ENABLED;VIDEO_ENABLED;HAVE_CU_GET_SUITE;HAVE_ZLIB;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View file

@ -0,0 +1,321 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProjectGuid>{EC78E1D3-6FD8-4CAF-8D3F-6F4F97093BE5}</ProjectGuid>
<OutputType>AppContainerExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>liblinphone_tester</RootNamespace>
<AssemblyName>liblinphone-tester</AssemblyName>
<DefaultLanguage>en-US</DefaultLanguage>
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
<TargetPlatformVersion>10.0.10240.0</TargetPlatformVersion>
<TargetPlatformMinVersion>10.0.10069.0</TargetPlatformMinVersion>
<MinimumVisualStudioVersion>14</MinimumVisualStudioVersion>
<EnableDotNetNativeCompatibleProfile>true</EnableDotNetNativeCompatibleProfile>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<PackageCertificateKeyFile>liblinphone-tester_TemporaryKey.pfx</PackageCertificateKeyFile>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\ARM\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>ARM</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM'">
<OutputPath>bin\ARM\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>ARM</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
</PropertyGroup>
<ItemGroup>
<!-- A reference to the entire .Net Framework and Windows SDK are automatically included -->
<Content Include="ApplicationInsights.config">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\messages.db">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\rcfiles\marie_remote_localfile_win10_rc">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<None Include="project.json" />
</ItemGroup>
<ItemGroup>
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
</Compile>
<Compile Include="DataModel\UnitTestDataSource.cs" />
<Compile Include="MainPage.xaml.cs">
<DependentUpon>MainPage.xaml</DependentUpon>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<AppxManifest Include="Package.appxmanifest">
<SubType>Designer</SubType>
</AppxManifest>
<None Include="liblinphone-tester_TemporaryKey.pfx" />
</ItemGroup>
<ItemGroup>
<Content Include="Assets\sounds\sintel_trailer_opus_h264.mkv" />
<Content Include="Assets\sounds\sintel_trailer_opus_vp8.mkv" />
<Content Include="Assets\sounds\sintel_trailer_pcmu_h264.mkv" />
<Content Include="Assets\StoreLogo.png" />
<Content Include="Assets\WideLogo.png" />
<Content Include="Properties\Default.rd.xml" />
<Content Include="Assets\images\nowebcamCIF.jpg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\rcfiles\empty_rc">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\rcfiles\laure_rc">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\rcfiles\marie_early_rc">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\rcfiles\marie_h264_rc">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\rcfiles\marie_quality_reporting_rc">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\rcfiles\marie_rc">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\rcfiles\marie_rc_rtcp_xr">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\rcfiles\marie_remote_404_rc">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\rcfiles\marie_remote_default_values_rc">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\rcfiles\marie_remote_https_rc">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\rcfiles\marie_remote_invalid_rc">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\rcfiles\marie_remote_invalid_uri_rc">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\rcfiles\marie_remote_localfile2_rc">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\rcfiles\marie_remote_localfile_android_rc">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\rcfiles\marie_remote_localfile_rc">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\rcfiles\marie_remote_rc">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\rcfiles\marie_sips_rc">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\rcfiles\marie_transient_remote_rc">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\rcfiles\marie_zrtp_aes256_rc">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\rcfiles\marie_zrtp_b256_rc">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\rcfiles\marie_zrtp_srtpsuite_aes256_rc">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\rcfiles\multi_account_rc">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\rcfiles\pauline_alt_rc">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\rcfiles\pauline_h264_rc">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\rcfiles\pauline_rc">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\rcfiles\pauline_rc_rtcp_xr">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\rcfiles\pauline_sips_rc">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\rcfiles\pauline_tcp_rc">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\rcfiles\pauline_wild_rc">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\rcfiles\pauline_zrtp_aes256_rc">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\rcfiles\pauline_zrtp_b256_rc">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\rcfiles\pauline_zrtp_srtpsuite_aes256_rc">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\rcfiles\remote_zero_length_params_rc">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\rcfiles\stun_rc">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\rcfiles\upnp_rc">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\rcfiles\zero_length_params_rc">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\sounds\ahbahouaismaisbon.wav">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\sounds\hello8000.mkv">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\sounds\hello8000.wav">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\sounds\hello8000_mkv_ref.wav">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\sounds\oldphone.wav">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\sounds\ringback.wav">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\sounds\vrroom.wav">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\tester_hosts">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\certificates\altname\agent.pem">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\certificates\altname\cafile.pem">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\certificates\altname\openssl-altname.cnf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\certificates\cn\agent.pem">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\certificates\cn\cafile.pem">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\certificates\cn\openssl-cn.cnf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\Logo.png" />
<Content Include="Assets\SmallLogo.png" />
<Content Include="Assets\SplashScreen.png" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Page Include="MainPage.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="liblinphone-tester-runtime-component\liblinphone-tester-runtime-component.vcxproj">
<Project>{1ce10f06-8fad-437f-b3d7-3b7a8909a190}</Project>
<Name>liblinphone-tester-runtime-component</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup />
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '14.0' ">
<VisualStudioVersion>14.0</VisualStudioVersion>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
<PropertyGroup>
<PreBuildEvent>XCopy /I /Y $(ProjectDir)..\..\..\tester\messages.db $(ProjectDir)Assets\
XCopy /I /Y $(ProjectDir)..\..\..\tester\tester_hosts $(ProjectDir)Assets\
XCopy /I /Y $(ProjectDir)..\..\..\tester\certificates\altname $(ProjectDir)Assets\certificates\altname
XCopy /I /Y $(ProjectDir)..\..\..\tester\certificates\cn $(ProjectDir)Assets\certificates\cn
XCopy /I /Y $(ProjectDir)..\..\..\tester\images $(ProjectDir)Assets\images
XCopy /I /Y $(ProjectDir)..\..\..\tester\rcfiles $(ProjectDir)Assets\rcfiles
XCopy /I /Y $(ProjectDir)..\..\..\tester\sounds $(ProjectDir)Assets\sounds</PreBuildEvent>
</PropertyGroup>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View file

@ -0,0 +1,488 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.23107.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "liblinphone-tester", "liblinphone-tester.csproj", "{EC78E1D3-6FD8-4CAF-8D3F-6F4F97093BE5}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "liblinphone-tester-static", "liblinphone-tester-static\liblinphone-tester-static.vcxproj", "{9EB3FE8D-2D91-4D29-A3BB-98DDB51D45B7}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "liblinphone", "..\liblinphone\liblinphone.vcxproj", "{C7139899-D8BC-48A3-A437-6844A8BAABEF}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mediastreamer2", "..\..\..\mediastreamer2\build\windows10\mediastreamer2\mediastreamer2.vcxproj", "{88E3C241-EB6F-4C84-80DC-89B8961DAF80}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ortp", "..\..\..\oRTP\build\windows10\ortp\ortp.vcxproj", "{2E56B851-9D8D-40E5-84BB-E4EE63B71D25}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "srtp", "..\..\..\..\srtp\build\windows10\srtp\srtp.vcxproj", "{59104E4F-A087-442E-ABD4-BCD2A1F0B0FE}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xml2", "..\..\..\..\build\xml2\xml2.vcxproj", "{2B04DE79-4D33-4405-AC01-C89E0593A71D}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "polarssl", "..\..\..\..\polarssl\build\windows10\polarssl\polarssl.vcxproj", "{88768DD9-5110-4AC8-8B0E-41CD7713E1A2}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "speex", "..\..\..\..\speex\build\windows10\speex\speex.vcxproj", "{971DD379-1C2D-44D2-9285-FDA556C48176}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "speexdsp", "..\..\..\..\speex\build\windows10\speexdsp\speexdsp.vcxproj", "{104BF91B-8314-4328-A996-90B8DF6052AF}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "opus", "..\..\..\..\opus\build\windows10\opus\opus.vcxproj", "{81AF1025-E0EE-4AD6-988D-2EF162778693}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bzrtp", "..\..\..\..\bzrtp\build\windows10\bzrtp\bzrtp.vcxproj", "{45C7723D-3107-4906-9633-F43ABE8A7147}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gsm", "..\..\..\..\gsm\build\windows10\gsm\gsm.vcxproj", "{EF1103C7-8AAC-464B-BA31-86B87246FA72}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "belle-sip", "..\..\..\..\belle-sip\build\windows10\belle-sip\belle-sip.vcxproj", "{B6CDF482-7DA3-43D4-9B12-70150106C191}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "antlr3c", "..\..\..\..\antlr3\runtime\C\build\windows10\antlr3c\antlr3c.vcxproj", "{01CCCCC9-CA0C-4528-92BC-5B8BE1D02D6D}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib", "..\..\..\..\zlib\build\windows10\zlib\zlib.vcxproj", "{A34F450D-392D-4660-9618-810BD695B3B0}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sqlite", "..\..\..\..\build\sqlite\sqlite.vcxproj", "{74CAD9D0-D8AE-4896-B71B-B2D9B48F30AA}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "liblinphone-tester-runtime-component", "liblinphone-tester-runtime-component\liblinphone-tester-runtime-component.vcxproj", "{1CE10F06-8FAD-437F-B3D7-3B7A8909A190}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cunit", "..\..\..\..\cunit\build\windows10\cunit\cunit.vcxproj", "{025E28A8-9DFB-4015-AD56-19896AA6CC9B}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libmsamr", "..\..\..\..\msamr\build\windows10\libmsamr\libmsamr.vcxproj", "{8C1BC968-C5C8-4D4B-9EF3-D6A065FC7C97}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libmsilbc", "..\..\..\..\msilbc\build\windows10\libmsilbc\libmsilbc.vcxproj", "{6A18BBB9-08D1-41A8-BE57-17FC992CC36F}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libmssilk", "..\..\..\..\mssilk\build\windows10\libmssilk\libmssilk.vcxproj", "{B84D5C3B-6DE5-49C8-B3DD-5EB67B01A527}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libmswasapi", "..\..\..\..\mswasapi\windows10\libmswasapi\libmswasapi.vcxproj", "{266B769A-C04E-424C-9033-7209F0425BC0}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libmswebrtc", "..\..\..\..\mswebrtc\build\windows10\libmswebrtc\libmswebrtc.vcxproj", "{878CF9D3-9761-479E-A715-A1DE9F99CB78}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ilbc", "..\..\..\..\libilbc-rfc3951\build\windows10\ilbc\ilbc.vcxproj", "{995B01AF-C568-453E-9E5F-8AE81FB79B4B}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "opencore_amrnb", "..\..\..\..\msamr\build\windows10\opencore_amrnb\opencore_amrnb.vcxproj", "{71A5F1C8-F76D-4297-95AA-75E1C967DC79}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "opencore_amrwb", "..\..\..\..\msamr\build\windows10\opencore_amrwb\opencore_amrwb.vcxproj", "{3CC91899-3E98-49FD-BED5-FA290A9A5C8E}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vo-amrwbenc", "..\..\..\..\msamr\build\windows10\vo-amrwbenc\vo-amrwbenc.vcxproj", "{D829672F-3775-4718-A991-1ABC42CBA67C}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "webrtc", "..\..\..\..\mswebrtc\webrtc\build\windows10\webrtc\webrtc.vcxproj", "{C5895B75-BDCF-406C-B803-9CB954E90F0C}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libmsbcg729", "..\..\..\..\bcg729\build\windows10\libmsbcg729\libmsbcg729.vcxproj", "{ACF5EA95-D647-4D0C-8F97-2CD9AAE8A2E0}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libmsopenh264", "..\..\..\..\msopenh264\build\windows10\libmsopenh264\libmsopenh264.vcxproj", "{BB8EBB21-F22C-4A68-99CB-67FA36C495E3}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libmswinrtvid", "..\..\..\..\mswinrtvid\windows10\libmswinrtvid\libmswinrtvid.vcxproj", "{2D0E44C4-E51D-4911-B876-345D1E5E5209}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mswinrtjpeg2yuv", "..\..\..\mediastreamer2\build\windows10\mswinrtjpeg2yuv\mswinrtjpeg2yuv.vcxproj", "{545F846D-7F19-4D6D-A50B-172A7C9B61E7}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|ARM = Debug|ARM
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|ARM = Release|ARM
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{EC78E1D3-6FD8-4CAF-8D3F-6F4F97093BE5}.Debug|ARM.ActiveCfg = Debug|ARM
{EC78E1D3-6FD8-4CAF-8D3F-6F4F97093BE5}.Debug|ARM.Build.0 = Debug|ARM
{EC78E1D3-6FD8-4CAF-8D3F-6F4F97093BE5}.Debug|ARM.Deploy.0 = Debug|ARM
{EC78E1D3-6FD8-4CAF-8D3F-6F4F97093BE5}.Debug|x64.ActiveCfg = Debug|x64
{EC78E1D3-6FD8-4CAF-8D3F-6F4F97093BE5}.Debug|x64.Build.0 = Debug|x64
{EC78E1D3-6FD8-4CAF-8D3F-6F4F97093BE5}.Debug|x64.Deploy.0 = Debug|x64
{EC78E1D3-6FD8-4CAF-8D3F-6F4F97093BE5}.Debug|x86.ActiveCfg = Debug|x86
{EC78E1D3-6FD8-4CAF-8D3F-6F4F97093BE5}.Debug|x86.Build.0 = Debug|x86
{EC78E1D3-6FD8-4CAF-8D3F-6F4F97093BE5}.Debug|x86.Deploy.0 = Debug|x86
{EC78E1D3-6FD8-4CAF-8D3F-6F4F97093BE5}.Release|ARM.ActiveCfg = Release|ARM
{EC78E1D3-6FD8-4CAF-8D3F-6F4F97093BE5}.Release|ARM.Build.0 = Release|ARM
{EC78E1D3-6FD8-4CAF-8D3F-6F4F97093BE5}.Release|ARM.Deploy.0 = Release|ARM
{EC78E1D3-6FD8-4CAF-8D3F-6F4F97093BE5}.Release|x64.ActiveCfg = Release|x64
{EC78E1D3-6FD8-4CAF-8D3F-6F4F97093BE5}.Release|x64.Build.0 = Release|x64
{EC78E1D3-6FD8-4CAF-8D3F-6F4F97093BE5}.Release|x64.Deploy.0 = Release|x64
{EC78E1D3-6FD8-4CAF-8D3F-6F4F97093BE5}.Release|x86.ActiveCfg = Release|x86
{EC78E1D3-6FD8-4CAF-8D3F-6F4F97093BE5}.Release|x86.Build.0 = Release|x86
{EC78E1D3-6FD8-4CAF-8D3F-6F4F97093BE5}.Release|x86.Deploy.0 = Release|x86
{9EB3FE8D-2D91-4D29-A3BB-98DDB51D45B7}.Debug|ARM.ActiveCfg = Debug|ARM
{9EB3FE8D-2D91-4D29-A3BB-98DDB51D45B7}.Debug|ARM.Build.0 = Debug|ARM
{9EB3FE8D-2D91-4D29-A3BB-98DDB51D45B7}.Debug|x64.ActiveCfg = Debug|x64
{9EB3FE8D-2D91-4D29-A3BB-98DDB51D45B7}.Debug|x64.Build.0 = Debug|x64
{9EB3FE8D-2D91-4D29-A3BB-98DDB51D45B7}.Debug|x86.ActiveCfg = Debug|Win32
{9EB3FE8D-2D91-4D29-A3BB-98DDB51D45B7}.Debug|x86.Build.0 = Debug|Win32
{9EB3FE8D-2D91-4D29-A3BB-98DDB51D45B7}.Release|ARM.ActiveCfg = Release|ARM
{9EB3FE8D-2D91-4D29-A3BB-98DDB51D45B7}.Release|ARM.Build.0 = Release|ARM
{9EB3FE8D-2D91-4D29-A3BB-98DDB51D45B7}.Release|x64.ActiveCfg = Release|x64
{9EB3FE8D-2D91-4D29-A3BB-98DDB51D45B7}.Release|x64.Build.0 = Release|x64
{9EB3FE8D-2D91-4D29-A3BB-98DDB51D45B7}.Release|x86.ActiveCfg = Release|Win32
{9EB3FE8D-2D91-4D29-A3BB-98DDB51D45B7}.Release|x86.Build.0 = Release|Win32
{C7139899-D8BC-48A3-A437-6844A8BAABEF}.Debug|ARM.ActiveCfg = Debug|ARM
{C7139899-D8BC-48A3-A437-6844A8BAABEF}.Debug|ARM.Build.0 = Debug|ARM
{C7139899-D8BC-48A3-A437-6844A8BAABEF}.Debug|x64.ActiveCfg = Debug|x64
{C7139899-D8BC-48A3-A437-6844A8BAABEF}.Debug|x64.Build.0 = Debug|x64
{C7139899-D8BC-48A3-A437-6844A8BAABEF}.Debug|x86.ActiveCfg = Debug|Win32
{C7139899-D8BC-48A3-A437-6844A8BAABEF}.Debug|x86.Build.0 = Debug|Win32
{C7139899-D8BC-48A3-A437-6844A8BAABEF}.Release|ARM.ActiveCfg = Release|ARM
{C7139899-D8BC-48A3-A437-6844A8BAABEF}.Release|ARM.Build.0 = Release|ARM
{C7139899-D8BC-48A3-A437-6844A8BAABEF}.Release|x64.ActiveCfg = Release|x64
{C7139899-D8BC-48A3-A437-6844A8BAABEF}.Release|x64.Build.0 = Release|x64
{C7139899-D8BC-48A3-A437-6844A8BAABEF}.Release|x86.ActiveCfg = Release|Win32
{C7139899-D8BC-48A3-A437-6844A8BAABEF}.Release|x86.Build.0 = Release|Win32
{88E3C241-EB6F-4C84-80DC-89B8961DAF80}.Debug|ARM.ActiveCfg = Debug|ARM
{88E3C241-EB6F-4C84-80DC-89B8961DAF80}.Debug|ARM.Build.0 = Debug|ARM
{88E3C241-EB6F-4C84-80DC-89B8961DAF80}.Debug|x64.ActiveCfg = Debug|x64
{88E3C241-EB6F-4C84-80DC-89B8961DAF80}.Debug|x64.Build.0 = Debug|x64
{88E3C241-EB6F-4C84-80DC-89B8961DAF80}.Debug|x86.ActiveCfg = Debug|Win32
{88E3C241-EB6F-4C84-80DC-89B8961DAF80}.Debug|x86.Build.0 = Debug|Win32
{88E3C241-EB6F-4C84-80DC-89B8961DAF80}.Release|ARM.ActiveCfg = Release|ARM
{88E3C241-EB6F-4C84-80DC-89B8961DAF80}.Release|ARM.Build.0 = Release|ARM
{88E3C241-EB6F-4C84-80DC-89B8961DAF80}.Release|x64.ActiveCfg = Release|x64
{88E3C241-EB6F-4C84-80DC-89B8961DAF80}.Release|x64.Build.0 = Release|x64
{88E3C241-EB6F-4C84-80DC-89B8961DAF80}.Release|x86.ActiveCfg = Release|Win32
{88E3C241-EB6F-4C84-80DC-89B8961DAF80}.Release|x86.Build.0 = Release|Win32
{2E56B851-9D8D-40E5-84BB-E4EE63B71D25}.Debug|ARM.ActiveCfg = Debug|ARM
{2E56B851-9D8D-40E5-84BB-E4EE63B71D25}.Debug|ARM.Build.0 = Debug|ARM
{2E56B851-9D8D-40E5-84BB-E4EE63B71D25}.Debug|x64.ActiveCfg = Debug|x64
{2E56B851-9D8D-40E5-84BB-E4EE63B71D25}.Debug|x64.Build.0 = Debug|x64
{2E56B851-9D8D-40E5-84BB-E4EE63B71D25}.Debug|x86.ActiveCfg = Debug|Win32
{2E56B851-9D8D-40E5-84BB-E4EE63B71D25}.Debug|x86.Build.0 = Debug|Win32
{2E56B851-9D8D-40E5-84BB-E4EE63B71D25}.Release|ARM.ActiveCfg = Release|ARM
{2E56B851-9D8D-40E5-84BB-E4EE63B71D25}.Release|ARM.Build.0 = Release|ARM
{2E56B851-9D8D-40E5-84BB-E4EE63B71D25}.Release|x64.ActiveCfg = Release|x64
{2E56B851-9D8D-40E5-84BB-E4EE63B71D25}.Release|x64.Build.0 = Release|x64
{2E56B851-9D8D-40E5-84BB-E4EE63B71D25}.Release|x86.ActiveCfg = Release|Win32
{2E56B851-9D8D-40E5-84BB-E4EE63B71D25}.Release|x86.Build.0 = Release|Win32
{59104E4F-A087-442E-ABD4-BCD2A1F0B0FE}.Debug|ARM.ActiveCfg = Debug|ARM
{59104E4F-A087-442E-ABD4-BCD2A1F0B0FE}.Debug|ARM.Build.0 = Debug|ARM
{59104E4F-A087-442E-ABD4-BCD2A1F0B0FE}.Debug|x64.ActiveCfg = Debug|x64
{59104E4F-A087-442E-ABD4-BCD2A1F0B0FE}.Debug|x64.Build.0 = Debug|x64
{59104E4F-A087-442E-ABD4-BCD2A1F0B0FE}.Debug|x86.ActiveCfg = Debug|Win32
{59104E4F-A087-442E-ABD4-BCD2A1F0B0FE}.Debug|x86.Build.0 = Debug|Win32
{59104E4F-A087-442E-ABD4-BCD2A1F0B0FE}.Release|ARM.ActiveCfg = Release|ARM
{59104E4F-A087-442E-ABD4-BCD2A1F0B0FE}.Release|ARM.Build.0 = Release|ARM
{59104E4F-A087-442E-ABD4-BCD2A1F0B0FE}.Release|x64.ActiveCfg = Release|x64
{59104E4F-A087-442E-ABD4-BCD2A1F0B0FE}.Release|x64.Build.0 = Release|x64
{59104E4F-A087-442E-ABD4-BCD2A1F0B0FE}.Release|x86.ActiveCfg = Release|Win32
{59104E4F-A087-442E-ABD4-BCD2A1F0B0FE}.Release|x86.Build.0 = Release|Win32
{2B04DE79-4D33-4405-AC01-C89E0593A71D}.Debug|ARM.ActiveCfg = Debug|ARM
{2B04DE79-4D33-4405-AC01-C89E0593A71D}.Debug|ARM.Build.0 = Debug|ARM
{2B04DE79-4D33-4405-AC01-C89E0593A71D}.Debug|x64.ActiveCfg = Debug|x64
{2B04DE79-4D33-4405-AC01-C89E0593A71D}.Debug|x64.Build.0 = Debug|x64
{2B04DE79-4D33-4405-AC01-C89E0593A71D}.Debug|x86.ActiveCfg = Debug|Win32
{2B04DE79-4D33-4405-AC01-C89E0593A71D}.Debug|x86.Build.0 = Debug|Win32
{2B04DE79-4D33-4405-AC01-C89E0593A71D}.Release|ARM.ActiveCfg = Release|ARM
{2B04DE79-4D33-4405-AC01-C89E0593A71D}.Release|ARM.Build.0 = Release|ARM
{2B04DE79-4D33-4405-AC01-C89E0593A71D}.Release|x64.ActiveCfg = Release|x64
{2B04DE79-4D33-4405-AC01-C89E0593A71D}.Release|x64.Build.0 = Release|x64
{2B04DE79-4D33-4405-AC01-C89E0593A71D}.Release|x86.ActiveCfg = Release|Win32
{2B04DE79-4D33-4405-AC01-C89E0593A71D}.Release|x86.Build.0 = Release|Win32
{88768DD9-5110-4AC8-8B0E-41CD7713E1A2}.Debug|ARM.ActiveCfg = Debug|ARM
{88768DD9-5110-4AC8-8B0E-41CD7713E1A2}.Debug|ARM.Build.0 = Debug|ARM
{88768DD9-5110-4AC8-8B0E-41CD7713E1A2}.Debug|x64.ActiveCfg = Debug|x64
{88768DD9-5110-4AC8-8B0E-41CD7713E1A2}.Debug|x64.Build.0 = Debug|x64
{88768DD9-5110-4AC8-8B0E-41CD7713E1A2}.Debug|x86.ActiveCfg = Debug|Win32
{88768DD9-5110-4AC8-8B0E-41CD7713E1A2}.Debug|x86.Build.0 = Debug|Win32
{88768DD9-5110-4AC8-8B0E-41CD7713E1A2}.Release|ARM.ActiveCfg = Release|ARM
{88768DD9-5110-4AC8-8B0E-41CD7713E1A2}.Release|ARM.Build.0 = Release|ARM
{88768DD9-5110-4AC8-8B0E-41CD7713E1A2}.Release|x64.ActiveCfg = Release|x64
{88768DD9-5110-4AC8-8B0E-41CD7713E1A2}.Release|x64.Build.0 = Release|x64
{88768DD9-5110-4AC8-8B0E-41CD7713E1A2}.Release|x86.ActiveCfg = Release|Win32
{88768DD9-5110-4AC8-8B0E-41CD7713E1A2}.Release|x86.Build.0 = Release|Win32
{971DD379-1C2D-44D2-9285-FDA556C48176}.Debug|ARM.ActiveCfg = Debug|ARM
{971DD379-1C2D-44D2-9285-FDA556C48176}.Debug|ARM.Build.0 = Debug|ARM
{971DD379-1C2D-44D2-9285-FDA556C48176}.Debug|x64.ActiveCfg = Debug|x64
{971DD379-1C2D-44D2-9285-FDA556C48176}.Debug|x64.Build.0 = Debug|x64
{971DD379-1C2D-44D2-9285-FDA556C48176}.Debug|x86.ActiveCfg = Debug|Win32
{971DD379-1C2D-44D2-9285-FDA556C48176}.Debug|x86.Build.0 = Debug|Win32
{971DD379-1C2D-44D2-9285-FDA556C48176}.Release|ARM.ActiveCfg = Release|ARM
{971DD379-1C2D-44D2-9285-FDA556C48176}.Release|ARM.Build.0 = Release|ARM
{971DD379-1C2D-44D2-9285-FDA556C48176}.Release|x64.ActiveCfg = Release|x64
{971DD379-1C2D-44D2-9285-FDA556C48176}.Release|x64.Build.0 = Release|x64
{971DD379-1C2D-44D2-9285-FDA556C48176}.Release|x86.ActiveCfg = Release|Win32
{971DD379-1C2D-44D2-9285-FDA556C48176}.Release|x86.Build.0 = Release|Win32
{104BF91B-8314-4328-A996-90B8DF6052AF}.Debug|ARM.ActiveCfg = Debug|ARM
{104BF91B-8314-4328-A996-90B8DF6052AF}.Debug|ARM.Build.0 = Debug|ARM
{104BF91B-8314-4328-A996-90B8DF6052AF}.Debug|x64.ActiveCfg = Debug|x64
{104BF91B-8314-4328-A996-90B8DF6052AF}.Debug|x64.Build.0 = Debug|x64
{104BF91B-8314-4328-A996-90B8DF6052AF}.Debug|x86.ActiveCfg = Debug|Win32
{104BF91B-8314-4328-A996-90B8DF6052AF}.Debug|x86.Build.0 = Debug|Win32
{104BF91B-8314-4328-A996-90B8DF6052AF}.Release|ARM.ActiveCfg = Release|ARM
{104BF91B-8314-4328-A996-90B8DF6052AF}.Release|ARM.Build.0 = Release|ARM
{104BF91B-8314-4328-A996-90B8DF6052AF}.Release|x64.ActiveCfg = Release|x64
{104BF91B-8314-4328-A996-90B8DF6052AF}.Release|x64.Build.0 = Release|x64
{104BF91B-8314-4328-A996-90B8DF6052AF}.Release|x86.ActiveCfg = Release|Win32
{104BF91B-8314-4328-A996-90B8DF6052AF}.Release|x86.Build.0 = Release|Win32
{81AF1025-E0EE-4AD6-988D-2EF162778693}.Debug|ARM.ActiveCfg = Debug|ARM
{81AF1025-E0EE-4AD6-988D-2EF162778693}.Debug|ARM.Build.0 = Debug|ARM
{81AF1025-E0EE-4AD6-988D-2EF162778693}.Debug|x64.ActiveCfg = Debug|x64
{81AF1025-E0EE-4AD6-988D-2EF162778693}.Debug|x64.Build.0 = Debug|x64
{81AF1025-E0EE-4AD6-988D-2EF162778693}.Debug|x86.ActiveCfg = Debug|Win32
{81AF1025-E0EE-4AD6-988D-2EF162778693}.Debug|x86.Build.0 = Debug|Win32
{81AF1025-E0EE-4AD6-988D-2EF162778693}.Release|ARM.ActiveCfg = Release|ARM
{81AF1025-E0EE-4AD6-988D-2EF162778693}.Release|ARM.Build.0 = Release|ARM
{81AF1025-E0EE-4AD6-988D-2EF162778693}.Release|x64.ActiveCfg = Release|x64
{81AF1025-E0EE-4AD6-988D-2EF162778693}.Release|x64.Build.0 = Release|x64
{81AF1025-E0EE-4AD6-988D-2EF162778693}.Release|x86.ActiveCfg = Release|Win32
{81AF1025-E0EE-4AD6-988D-2EF162778693}.Release|x86.Build.0 = Release|Win32
{45C7723D-3107-4906-9633-F43ABE8A7147}.Debug|ARM.ActiveCfg = Debug|ARM
{45C7723D-3107-4906-9633-F43ABE8A7147}.Debug|ARM.Build.0 = Debug|ARM
{45C7723D-3107-4906-9633-F43ABE8A7147}.Debug|x64.ActiveCfg = Debug|x64
{45C7723D-3107-4906-9633-F43ABE8A7147}.Debug|x64.Build.0 = Debug|x64
{45C7723D-3107-4906-9633-F43ABE8A7147}.Debug|x86.ActiveCfg = Debug|Win32
{45C7723D-3107-4906-9633-F43ABE8A7147}.Debug|x86.Build.0 = Debug|Win32
{45C7723D-3107-4906-9633-F43ABE8A7147}.Release|ARM.ActiveCfg = Release|ARM
{45C7723D-3107-4906-9633-F43ABE8A7147}.Release|ARM.Build.0 = Release|ARM
{45C7723D-3107-4906-9633-F43ABE8A7147}.Release|x64.ActiveCfg = Release|x64
{45C7723D-3107-4906-9633-F43ABE8A7147}.Release|x64.Build.0 = Release|x64
{45C7723D-3107-4906-9633-F43ABE8A7147}.Release|x86.ActiveCfg = Release|Win32
{45C7723D-3107-4906-9633-F43ABE8A7147}.Release|x86.Build.0 = Release|Win32
{EF1103C7-8AAC-464B-BA31-86B87246FA72}.Debug|ARM.ActiveCfg = Debug|ARM
{EF1103C7-8AAC-464B-BA31-86B87246FA72}.Debug|ARM.Build.0 = Debug|ARM
{EF1103C7-8AAC-464B-BA31-86B87246FA72}.Debug|x64.ActiveCfg = Debug|x64
{EF1103C7-8AAC-464B-BA31-86B87246FA72}.Debug|x64.Build.0 = Debug|x64
{EF1103C7-8AAC-464B-BA31-86B87246FA72}.Debug|x86.ActiveCfg = Debug|Win32
{EF1103C7-8AAC-464B-BA31-86B87246FA72}.Debug|x86.Build.0 = Debug|Win32
{EF1103C7-8AAC-464B-BA31-86B87246FA72}.Release|ARM.ActiveCfg = Release|ARM
{EF1103C7-8AAC-464B-BA31-86B87246FA72}.Release|ARM.Build.0 = Release|ARM
{EF1103C7-8AAC-464B-BA31-86B87246FA72}.Release|x64.ActiveCfg = Release|x64
{EF1103C7-8AAC-464B-BA31-86B87246FA72}.Release|x64.Build.0 = Release|x64
{EF1103C7-8AAC-464B-BA31-86B87246FA72}.Release|x86.ActiveCfg = Release|Win32
{EF1103C7-8AAC-464B-BA31-86B87246FA72}.Release|x86.Build.0 = Release|Win32
{B6CDF482-7DA3-43D4-9B12-70150106C191}.Debug|ARM.ActiveCfg = Debug|ARM
{B6CDF482-7DA3-43D4-9B12-70150106C191}.Debug|ARM.Build.0 = Debug|ARM
{B6CDF482-7DA3-43D4-9B12-70150106C191}.Debug|x64.ActiveCfg = Debug|x64
{B6CDF482-7DA3-43D4-9B12-70150106C191}.Debug|x64.Build.0 = Debug|x64
{B6CDF482-7DA3-43D4-9B12-70150106C191}.Debug|x86.ActiveCfg = Debug|Win32
{B6CDF482-7DA3-43D4-9B12-70150106C191}.Debug|x86.Build.0 = Debug|Win32
{B6CDF482-7DA3-43D4-9B12-70150106C191}.Release|ARM.ActiveCfg = Release|ARM
{B6CDF482-7DA3-43D4-9B12-70150106C191}.Release|ARM.Build.0 = Release|ARM
{B6CDF482-7DA3-43D4-9B12-70150106C191}.Release|x64.ActiveCfg = Release|x64
{B6CDF482-7DA3-43D4-9B12-70150106C191}.Release|x64.Build.0 = Release|x64
{B6CDF482-7DA3-43D4-9B12-70150106C191}.Release|x86.ActiveCfg = Release|Win32
{B6CDF482-7DA3-43D4-9B12-70150106C191}.Release|x86.Build.0 = Release|Win32
{01CCCCC9-CA0C-4528-92BC-5B8BE1D02D6D}.Debug|ARM.ActiveCfg = Debug|ARM
{01CCCCC9-CA0C-4528-92BC-5B8BE1D02D6D}.Debug|ARM.Build.0 = Debug|ARM
{01CCCCC9-CA0C-4528-92BC-5B8BE1D02D6D}.Debug|x64.ActiveCfg = Debug|x64
{01CCCCC9-CA0C-4528-92BC-5B8BE1D02D6D}.Debug|x64.Build.0 = Debug|x64
{01CCCCC9-CA0C-4528-92BC-5B8BE1D02D6D}.Debug|x86.ActiveCfg = Debug|Win32
{01CCCCC9-CA0C-4528-92BC-5B8BE1D02D6D}.Debug|x86.Build.0 = Debug|Win32
{01CCCCC9-CA0C-4528-92BC-5B8BE1D02D6D}.Release|ARM.ActiveCfg = Release|ARM
{01CCCCC9-CA0C-4528-92BC-5B8BE1D02D6D}.Release|ARM.Build.0 = Release|ARM
{01CCCCC9-CA0C-4528-92BC-5B8BE1D02D6D}.Release|x64.ActiveCfg = Release|x64
{01CCCCC9-CA0C-4528-92BC-5B8BE1D02D6D}.Release|x64.Build.0 = Release|x64
{01CCCCC9-CA0C-4528-92BC-5B8BE1D02D6D}.Release|x86.ActiveCfg = Release|Win32
{01CCCCC9-CA0C-4528-92BC-5B8BE1D02D6D}.Release|x86.Build.0 = Release|Win32
{A34F450D-392D-4660-9618-810BD695B3B0}.Debug|ARM.ActiveCfg = Debug|ARM
{A34F450D-392D-4660-9618-810BD695B3B0}.Debug|ARM.Build.0 = Debug|ARM
{A34F450D-392D-4660-9618-810BD695B3B0}.Debug|x64.ActiveCfg = Debug|x64
{A34F450D-392D-4660-9618-810BD695B3B0}.Debug|x64.Build.0 = Debug|x64
{A34F450D-392D-4660-9618-810BD695B3B0}.Debug|x86.ActiveCfg = Debug|Win32
{A34F450D-392D-4660-9618-810BD695B3B0}.Debug|x86.Build.0 = Debug|Win32
{A34F450D-392D-4660-9618-810BD695B3B0}.Release|ARM.ActiveCfg = Release|ARM
{A34F450D-392D-4660-9618-810BD695B3B0}.Release|ARM.Build.0 = Release|ARM
{A34F450D-392D-4660-9618-810BD695B3B0}.Release|x64.ActiveCfg = Release|x64
{A34F450D-392D-4660-9618-810BD695B3B0}.Release|x64.Build.0 = Release|x64
{A34F450D-392D-4660-9618-810BD695B3B0}.Release|x86.ActiveCfg = Release|Win32
{A34F450D-392D-4660-9618-810BD695B3B0}.Release|x86.Build.0 = Release|Win32
{74CAD9D0-D8AE-4896-B71B-B2D9B48F30AA}.Debug|ARM.ActiveCfg = Debug|ARM
{74CAD9D0-D8AE-4896-B71B-B2D9B48F30AA}.Debug|ARM.Build.0 = Debug|ARM
{74CAD9D0-D8AE-4896-B71B-B2D9B48F30AA}.Debug|x64.ActiveCfg = Debug|x64
{74CAD9D0-D8AE-4896-B71B-B2D9B48F30AA}.Debug|x64.Build.0 = Debug|x64
{74CAD9D0-D8AE-4896-B71B-B2D9B48F30AA}.Debug|x86.ActiveCfg = Debug|Win32
{74CAD9D0-D8AE-4896-B71B-B2D9B48F30AA}.Debug|x86.Build.0 = Debug|Win32
{74CAD9D0-D8AE-4896-B71B-B2D9B48F30AA}.Release|ARM.ActiveCfg = Release|ARM
{74CAD9D0-D8AE-4896-B71B-B2D9B48F30AA}.Release|ARM.Build.0 = Release|ARM
{74CAD9D0-D8AE-4896-B71B-B2D9B48F30AA}.Release|x64.ActiveCfg = Release|x64
{74CAD9D0-D8AE-4896-B71B-B2D9B48F30AA}.Release|x64.Build.0 = Release|x64
{74CAD9D0-D8AE-4896-B71B-B2D9B48F30AA}.Release|x86.ActiveCfg = Release|Win32
{74CAD9D0-D8AE-4896-B71B-B2D9B48F30AA}.Release|x86.Build.0 = Release|Win32
{1CE10F06-8FAD-437F-B3D7-3B7A8909A190}.Debug|ARM.ActiveCfg = Debug|ARM
{1CE10F06-8FAD-437F-B3D7-3B7A8909A190}.Debug|ARM.Build.0 = Debug|ARM
{1CE10F06-8FAD-437F-B3D7-3B7A8909A190}.Debug|x64.ActiveCfg = Debug|x64
{1CE10F06-8FAD-437F-B3D7-3B7A8909A190}.Debug|x64.Build.0 = Debug|x64
{1CE10F06-8FAD-437F-B3D7-3B7A8909A190}.Debug|x86.ActiveCfg = Debug|Win32
{1CE10F06-8FAD-437F-B3D7-3B7A8909A190}.Debug|x86.Build.0 = Debug|Win32
{1CE10F06-8FAD-437F-B3D7-3B7A8909A190}.Release|ARM.ActiveCfg = Release|ARM
{1CE10F06-8FAD-437F-B3D7-3B7A8909A190}.Release|ARM.Build.0 = Release|ARM
{1CE10F06-8FAD-437F-B3D7-3B7A8909A190}.Release|x64.ActiveCfg = Release|x64
{1CE10F06-8FAD-437F-B3D7-3B7A8909A190}.Release|x64.Build.0 = Release|x64
{1CE10F06-8FAD-437F-B3D7-3B7A8909A190}.Release|x86.ActiveCfg = Release|Win32
{1CE10F06-8FAD-437F-B3D7-3B7A8909A190}.Release|x86.Build.0 = Release|Win32
{025E28A8-9DFB-4015-AD56-19896AA6CC9B}.Debug|ARM.ActiveCfg = Debug|ARM
{025E28A8-9DFB-4015-AD56-19896AA6CC9B}.Debug|ARM.Build.0 = Debug|ARM
{025E28A8-9DFB-4015-AD56-19896AA6CC9B}.Debug|x64.ActiveCfg = Debug|x64
{025E28A8-9DFB-4015-AD56-19896AA6CC9B}.Debug|x64.Build.0 = Debug|x64
{025E28A8-9DFB-4015-AD56-19896AA6CC9B}.Debug|x86.ActiveCfg = Debug|Win32
{025E28A8-9DFB-4015-AD56-19896AA6CC9B}.Debug|x86.Build.0 = Debug|Win32
{025E28A8-9DFB-4015-AD56-19896AA6CC9B}.Release|ARM.ActiveCfg = Release|ARM
{025E28A8-9DFB-4015-AD56-19896AA6CC9B}.Release|ARM.Build.0 = Release|ARM
{025E28A8-9DFB-4015-AD56-19896AA6CC9B}.Release|x64.ActiveCfg = Release|x64
{025E28A8-9DFB-4015-AD56-19896AA6CC9B}.Release|x64.Build.0 = Release|x64
{025E28A8-9DFB-4015-AD56-19896AA6CC9B}.Release|x86.ActiveCfg = Release|Win32
{025E28A8-9DFB-4015-AD56-19896AA6CC9B}.Release|x86.Build.0 = Release|Win32
{8C1BC968-C5C8-4D4B-9EF3-D6A065FC7C97}.Debug|ARM.ActiveCfg = Debug|ARM
{8C1BC968-C5C8-4D4B-9EF3-D6A065FC7C97}.Debug|ARM.Build.0 = Debug|ARM
{8C1BC968-C5C8-4D4B-9EF3-D6A065FC7C97}.Debug|x64.ActiveCfg = Debug|x64
{8C1BC968-C5C8-4D4B-9EF3-D6A065FC7C97}.Debug|x64.Build.0 = Debug|x64
{8C1BC968-C5C8-4D4B-9EF3-D6A065FC7C97}.Debug|x86.ActiveCfg = Debug|Win32
{8C1BC968-C5C8-4D4B-9EF3-D6A065FC7C97}.Debug|x86.Build.0 = Debug|Win32
{8C1BC968-C5C8-4D4B-9EF3-D6A065FC7C97}.Release|ARM.ActiveCfg = Release|ARM
{8C1BC968-C5C8-4D4B-9EF3-D6A065FC7C97}.Release|ARM.Build.0 = Release|ARM
{8C1BC968-C5C8-4D4B-9EF3-D6A065FC7C97}.Release|x64.ActiveCfg = Release|x64
{8C1BC968-C5C8-4D4B-9EF3-D6A065FC7C97}.Release|x64.Build.0 = Release|x64
{8C1BC968-C5C8-4D4B-9EF3-D6A065FC7C97}.Release|x86.ActiveCfg = Release|Win32
{8C1BC968-C5C8-4D4B-9EF3-D6A065FC7C97}.Release|x86.Build.0 = Release|Win32
{6A18BBB9-08D1-41A8-BE57-17FC992CC36F}.Debug|ARM.ActiveCfg = Debug|ARM
{6A18BBB9-08D1-41A8-BE57-17FC992CC36F}.Debug|ARM.Build.0 = Debug|ARM
{6A18BBB9-08D1-41A8-BE57-17FC992CC36F}.Debug|x64.ActiveCfg = Debug|x64
{6A18BBB9-08D1-41A8-BE57-17FC992CC36F}.Debug|x64.Build.0 = Debug|x64
{6A18BBB9-08D1-41A8-BE57-17FC992CC36F}.Debug|x86.ActiveCfg = Debug|Win32
{6A18BBB9-08D1-41A8-BE57-17FC992CC36F}.Debug|x86.Build.0 = Debug|Win32
{6A18BBB9-08D1-41A8-BE57-17FC992CC36F}.Release|ARM.ActiveCfg = Release|ARM
{6A18BBB9-08D1-41A8-BE57-17FC992CC36F}.Release|ARM.Build.0 = Release|ARM
{6A18BBB9-08D1-41A8-BE57-17FC992CC36F}.Release|x64.ActiveCfg = Release|x64
{6A18BBB9-08D1-41A8-BE57-17FC992CC36F}.Release|x64.Build.0 = Release|x64
{6A18BBB9-08D1-41A8-BE57-17FC992CC36F}.Release|x86.ActiveCfg = Release|Win32
{6A18BBB9-08D1-41A8-BE57-17FC992CC36F}.Release|x86.Build.0 = Release|Win32
{B84D5C3B-6DE5-49C8-B3DD-5EB67B01A527}.Debug|ARM.ActiveCfg = Debug|ARM
{B84D5C3B-6DE5-49C8-B3DD-5EB67B01A527}.Debug|ARM.Build.0 = Debug|ARM
{B84D5C3B-6DE5-49C8-B3DD-5EB67B01A527}.Debug|x64.ActiveCfg = Debug|x64
{B84D5C3B-6DE5-49C8-B3DD-5EB67B01A527}.Debug|x64.Build.0 = Debug|x64
{B84D5C3B-6DE5-49C8-B3DD-5EB67B01A527}.Debug|x86.ActiveCfg = Debug|Win32
{B84D5C3B-6DE5-49C8-B3DD-5EB67B01A527}.Debug|x86.Build.0 = Debug|Win32
{B84D5C3B-6DE5-49C8-B3DD-5EB67B01A527}.Release|ARM.ActiveCfg = Release|ARM
{B84D5C3B-6DE5-49C8-B3DD-5EB67B01A527}.Release|ARM.Build.0 = Release|ARM
{B84D5C3B-6DE5-49C8-B3DD-5EB67B01A527}.Release|x64.ActiveCfg = Release|x64
{B84D5C3B-6DE5-49C8-B3DD-5EB67B01A527}.Release|x64.Build.0 = Release|x64
{B84D5C3B-6DE5-49C8-B3DD-5EB67B01A527}.Release|x86.ActiveCfg = Release|Win32
{B84D5C3B-6DE5-49C8-B3DD-5EB67B01A527}.Release|x86.Build.0 = Release|Win32
{266B769A-C04E-424C-9033-7209F0425BC0}.Debug|ARM.ActiveCfg = Debug|ARM
{266B769A-C04E-424C-9033-7209F0425BC0}.Debug|ARM.Build.0 = Debug|ARM
{266B769A-C04E-424C-9033-7209F0425BC0}.Debug|x64.ActiveCfg = Debug|x64
{266B769A-C04E-424C-9033-7209F0425BC0}.Debug|x64.Build.0 = Debug|x64
{266B769A-C04E-424C-9033-7209F0425BC0}.Debug|x86.ActiveCfg = Debug|Win32
{266B769A-C04E-424C-9033-7209F0425BC0}.Debug|x86.Build.0 = Debug|Win32
{266B769A-C04E-424C-9033-7209F0425BC0}.Release|ARM.ActiveCfg = Release|ARM
{266B769A-C04E-424C-9033-7209F0425BC0}.Release|ARM.Build.0 = Release|ARM
{266B769A-C04E-424C-9033-7209F0425BC0}.Release|x64.ActiveCfg = Release|x64
{266B769A-C04E-424C-9033-7209F0425BC0}.Release|x64.Build.0 = Release|x64
{266B769A-C04E-424C-9033-7209F0425BC0}.Release|x86.ActiveCfg = Release|Win32
{266B769A-C04E-424C-9033-7209F0425BC0}.Release|x86.Build.0 = Release|Win32
{878CF9D3-9761-479E-A715-A1DE9F99CB78}.Debug|ARM.ActiveCfg = Debug|ARM
{878CF9D3-9761-479E-A715-A1DE9F99CB78}.Debug|ARM.Build.0 = Debug|ARM
{878CF9D3-9761-479E-A715-A1DE9F99CB78}.Debug|x64.ActiveCfg = Debug|x64
{878CF9D3-9761-479E-A715-A1DE9F99CB78}.Debug|x64.Build.0 = Debug|x64
{878CF9D3-9761-479E-A715-A1DE9F99CB78}.Debug|x86.ActiveCfg = Debug|Win32
{878CF9D3-9761-479E-A715-A1DE9F99CB78}.Debug|x86.Build.0 = Debug|Win32
{878CF9D3-9761-479E-A715-A1DE9F99CB78}.Release|ARM.ActiveCfg = Release|ARM
{878CF9D3-9761-479E-A715-A1DE9F99CB78}.Release|ARM.Build.0 = Release|ARM
{878CF9D3-9761-479E-A715-A1DE9F99CB78}.Release|x64.ActiveCfg = Release|x64
{878CF9D3-9761-479E-A715-A1DE9F99CB78}.Release|x64.Build.0 = Release|x64
{878CF9D3-9761-479E-A715-A1DE9F99CB78}.Release|x86.ActiveCfg = Release|Win32
{878CF9D3-9761-479E-A715-A1DE9F99CB78}.Release|x86.Build.0 = Release|Win32
{995B01AF-C568-453E-9E5F-8AE81FB79B4B}.Debug|ARM.ActiveCfg = Debug|ARM
{995B01AF-C568-453E-9E5F-8AE81FB79B4B}.Debug|ARM.Build.0 = Debug|ARM
{995B01AF-C568-453E-9E5F-8AE81FB79B4B}.Debug|x64.ActiveCfg = Debug|x64
{995B01AF-C568-453E-9E5F-8AE81FB79B4B}.Debug|x64.Build.0 = Debug|x64
{995B01AF-C568-453E-9E5F-8AE81FB79B4B}.Debug|x86.ActiveCfg = Debug|Win32
{995B01AF-C568-453E-9E5F-8AE81FB79B4B}.Debug|x86.Build.0 = Debug|Win32
{995B01AF-C568-453E-9E5F-8AE81FB79B4B}.Release|ARM.ActiveCfg = Release|ARM
{995B01AF-C568-453E-9E5F-8AE81FB79B4B}.Release|ARM.Build.0 = Release|ARM
{995B01AF-C568-453E-9E5F-8AE81FB79B4B}.Release|x64.ActiveCfg = Release|x64
{995B01AF-C568-453E-9E5F-8AE81FB79B4B}.Release|x64.Build.0 = Release|x64
{995B01AF-C568-453E-9E5F-8AE81FB79B4B}.Release|x86.ActiveCfg = Release|Win32
{995B01AF-C568-453E-9E5F-8AE81FB79B4B}.Release|x86.Build.0 = Release|Win32
{71A5F1C8-F76D-4297-95AA-75E1C967DC79}.Debug|ARM.ActiveCfg = Debug|ARM
{71A5F1C8-F76D-4297-95AA-75E1C967DC79}.Debug|ARM.Build.0 = Debug|ARM
{71A5F1C8-F76D-4297-95AA-75E1C967DC79}.Debug|x64.ActiveCfg = Debug|x64
{71A5F1C8-F76D-4297-95AA-75E1C967DC79}.Debug|x64.Build.0 = Debug|x64
{71A5F1C8-F76D-4297-95AA-75E1C967DC79}.Debug|x86.ActiveCfg = Debug|Win32
{71A5F1C8-F76D-4297-95AA-75E1C967DC79}.Debug|x86.Build.0 = Debug|Win32
{71A5F1C8-F76D-4297-95AA-75E1C967DC79}.Release|ARM.ActiveCfg = Release|ARM
{71A5F1C8-F76D-4297-95AA-75E1C967DC79}.Release|ARM.Build.0 = Release|ARM
{71A5F1C8-F76D-4297-95AA-75E1C967DC79}.Release|x64.ActiveCfg = Release|x64
{71A5F1C8-F76D-4297-95AA-75E1C967DC79}.Release|x64.Build.0 = Release|x64
{71A5F1C8-F76D-4297-95AA-75E1C967DC79}.Release|x86.ActiveCfg = Release|Win32
{71A5F1C8-F76D-4297-95AA-75E1C967DC79}.Release|x86.Build.0 = Release|Win32
{3CC91899-3E98-49FD-BED5-FA290A9A5C8E}.Debug|ARM.ActiveCfg = Debug|ARM
{3CC91899-3E98-49FD-BED5-FA290A9A5C8E}.Debug|ARM.Build.0 = Debug|ARM
{3CC91899-3E98-49FD-BED5-FA290A9A5C8E}.Debug|x64.ActiveCfg = Debug|x64
{3CC91899-3E98-49FD-BED5-FA290A9A5C8E}.Debug|x64.Build.0 = Debug|x64
{3CC91899-3E98-49FD-BED5-FA290A9A5C8E}.Debug|x86.ActiveCfg = Debug|Win32
{3CC91899-3E98-49FD-BED5-FA290A9A5C8E}.Debug|x86.Build.0 = Debug|Win32
{3CC91899-3E98-49FD-BED5-FA290A9A5C8E}.Release|ARM.ActiveCfg = Release|ARM
{3CC91899-3E98-49FD-BED5-FA290A9A5C8E}.Release|ARM.Build.0 = Release|ARM
{3CC91899-3E98-49FD-BED5-FA290A9A5C8E}.Release|x64.ActiveCfg = Release|x64
{3CC91899-3E98-49FD-BED5-FA290A9A5C8E}.Release|x64.Build.0 = Release|x64
{3CC91899-3E98-49FD-BED5-FA290A9A5C8E}.Release|x86.ActiveCfg = Release|Win32
{3CC91899-3E98-49FD-BED5-FA290A9A5C8E}.Release|x86.Build.0 = Release|Win32
{D829672F-3775-4718-A991-1ABC42CBA67C}.Debug|ARM.ActiveCfg = Debug|ARM
{D829672F-3775-4718-A991-1ABC42CBA67C}.Debug|ARM.Build.0 = Debug|ARM
{D829672F-3775-4718-A991-1ABC42CBA67C}.Debug|x64.ActiveCfg = Debug|x64
{D829672F-3775-4718-A991-1ABC42CBA67C}.Debug|x64.Build.0 = Debug|x64
{D829672F-3775-4718-A991-1ABC42CBA67C}.Debug|x86.ActiveCfg = Debug|Win32
{D829672F-3775-4718-A991-1ABC42CBA67C}.Debug|x86.Build.0 = Debug|Win32
{D829672F-3775-4718-A991-1ABC42CBA67C}.Release|ARM.ActiveCfg = Release|ARM
{D829672F-3775-4718-A991-1ABC42CBA67C}.Release|ARM.Build.0 = Release|ARM
{D829672F-3775-4718-A991-1ABC42CBA67C}.Release|x64.ActiveCfg = Release|x64
{D829672F-3775-4718-A991-1ABC42CBA67C}.Release|x64.Build.0 = Release|x64
{D829672F-3775-4718-A991-1ABC42CBA67C}.Release|x86.ActiveCfg = Release|Win32
{D829672F-3775-4718-A991-1ABC42CBA67C}.Release|x86.Build.0 = Release|Win32
{C5895B75-BDCF-406C-B803-9CB954E90F0C}.Debug|ARM.ActiveCfg = Debug|ARM
{C5895B75-BDCF-406C-B803-9CB954E90F0C}.Debug|ARM.Build.0 = Debug|ARM
{C5895B75-BDCF-406C-B803-9CB954E90F0C}.Debug|x64.ActiveCfg = Debug|x64
{C5895B75-BDCF-406C-B803-9CB954E90F0C}.Debug|x64.Build.0 = Debug|x64
{C5895B75-BDCF-406C-B803-9CB954E90F0C}.Debug|x86.ActiveCfg = Debug|Win32
{C5895B75-BDCF-406C-B803-9CB954E90F0C}.Debug|x86.Build.0 = Debug|Win32
{C5895B75-BDCF-406C-B803-9CB954E90F0C}.Release|ARM.ActiveCfg = Release|ARM
{C5895B75-BDCF-406C-B803-9CB954E90F0C}.Release|ARM.Build.0 = Release|ARM
{C5895B75-BDCF-406C-B803-9CB954E90F0C}.Release|x64.ActiveCfg = Release|x64
{C5895B75-BDCF-406C-B803-9CB954E90F0C}.Release|x64.Build.0 = Release|x64
{C5895B75-BDCF-406C-B803-9CB954E90F0C}.Release|x86.ActiveCfg = Release|Win32
{C5895B75-BDCF-406C-B803-9CB954E90F0C}.Release|x86.Build.0 = Release|Win32
{ACF5EA95-D647-4D0C-8F97-2CD9AAE8A2E0}.Debug|ARM.ActiveCfg = Debug|ARM
{ACF5EA95-D647-4D0C-8F97-2CD9AAE8A2E0}.Debug|ARM.Build.0 = Debug|ARM
{ACF5EA95-D647-4D0C-8F97-2CD9AAE8A2E0}.Debug|x64.ActiveCfg = Debug|x64
{ACF5EA95-D647-4D0C-8F97-2CD9AAE8A2E0}.Debug|x64.Build.0 = Debug|x64
{ACF5EA95-D647-4D0C-8F97-2CD9AAE8A2E0}.Debug|x86.ActiveCfg = Debug|Win32
{ACF5EA95-D647-4D0C-8F97-2CD9AAE8A2E0}.Debug|x86.Build.0 = Debug|Win32
{ACF5EA95-D647-4D0C-8F97-2CD9AAE8A2E0}.Release|ARM.ActiveCfg = Release|ARM
{ACF5EA95-D647-4D0C-8F97-2CD9AAE8A2E0}.Release|ARM.Build.0 = Release|ARM
{ACF5EA95-D647-4D0C-8F97-2CD9AAE8A2E0}.Release|x64.ActiveCfg = Release|x64
{ACF5EA95-D647-4D0C-8F97-2CD9AAE8A2E0}.Release|x64.Build.0 = Release|x64
{ACF5EA95-D647-4D0C-8F97-2CD9AAE8A2E0}.Release|x86.ActiveCfg = Release|Win32
{ACF5EA95-D647-4D0C-8F97-2CD9AAE8A2E0}.Release|x86.Build.0 = Release|Win32
{BB8EBB21-F22C-4A68-99CB-67FA36C495E3}.Debug|ARM.ActiveCfg = Debug|ARM
{BB8EBB21-F22C-4A68-99CB-67FA36C495E3}.Debug|ARM.Build.0 = Debug|ARM
{BB8EBB21-F22C-4A68-99CB-67FA36C495E3}.Debug|x64.ActiveCfg = Debug|x64
{BB8EBB21-F22C-4A68-99CB-67FA36C495E3}.Debug|x64.Build.0 = Debug|x64
{BB8EBB21-F22C-4A68-99CB-67FA36C495E3}.Debug|x86.ActiveCfg = Debug|Win32
{BB8EBB21-F22C-4A68-99CB-67FA36C495E3}.Debug|x86.Build.0 = Debug|Win32
{BB8EBB21-F22C-4A68-99CB-67FA36C495E3}.Release|ARM.ActiveCfg = Release|ARM
{BB8EBB21-F22C-4A68-99CB-67FA36C495E3}.Release|ARM.Build.0 = Release|ARM
{BB8EBB21-F22C-4A68-99CB-67FA36C495E3}.Release|x64.ActiveCfg = Release|x64
{BB8EBB21-F22C-4A68-99CB-67FA36C495E3}.Release|x64.Build.0 = Release|x64
{BB8EBB21-F22C-4A68-99CB-67FA36C495E3}.Release|x86.ActiveCfg = Release|Win32
{BB8EBB21-F22C-4A68-99CB-67FA36C495E3}.Release|x86.Build.0 = Release|Win32
{2D0E44C4-E51D-4911-B876-345D1E5E5209}.Debug|ARM.ActiveCfg = Debug|ARM
{2D0E44C4-E51D-4911-B876-345D1E5E5209}.Debug|ARM.Build.0 = Debug|ARM
{2D0E44C4-E51D-4911-B876-345D1E5E5209}.Debug|x64.ActiveCfg = Debug|x64
{2D0E44C4-E51D-4911-B876-345D1E5E5209}.Debug|x64.Build.0 = Debug|x64
{2D0E44C4-E51D-4911-B876-345D1E5E5209}.Debug|x86.ActiveCfg = Debug|Win32
{2D0E44C4-E51D-4911-B876-345D1E5E5209}.Debug|x86.Build.0 = Debug|Win32
{2D0E44C4-E51D-4911-B876-345D1E5E5209}.Release|ARM.ActiveCfg = Release|ARM
{2D0E44C4-E51D-4911-B876-345D1E5E5209}.Release|ARM.Build.0 = Release|ARM
{2D0E44C4-E51D-4911-B876-345D1E5E5209}.Release|x64.ActiveCfg = Release|x64
{2D0E44C4-E51D-4911-B876-345D1E5E5209}.Release|x64.Build.0 = Release|x64
{2D0E44C4-E51D-4911-B876-345D1E5E5209}.Release|x86.ActiveCfg = Release|Win32
{2D0E44C4-E51D-4911-B876-345D1E5E5209}.Release|x86.Build.0 = Release|Win32
{545F846D-7F19-4D6D-A50B-172A7C9B61E7}.Debug|ARM.ActiveCfg = Debug|ARM
{545F846D-7F19-4D6D-A50B-172A7C9B61E7}.Debug|ARM.Build.0 = Debug|ARM
{545F846D-7F19-4D6D-A50B-172A7C9B61E7}.Debug|x64.ActiveCfg = Debug|x64
{545F846D-7F19-4D6D-A50B-172A7C9B61E7}.Debug|x64.Build.0 = Debug|x64
{545F846D-7F19-4D6D-A50B-172A7C9B61E7}.Debug|x86.ActiveCfg = Debug|Win32
{545F846D-7F19-4D6D-A50B-172A7C9B61E7}.Debug|x86.Build.0 = Debug|Win32
{545F846D-7F19-4D6D-A50B-172A7C9B61E7}.Release|ARM.ActiveCfg = Release|ARM
{545F846D-7F19-4D6D-A50B-172A7C9B61E7}.Release|ARM.Build.0 = Release|ARM
{545F846D-7F19-4D6D-A50B-172A7C9B61E7}.Release|x64.ActiveCfg = Release|x64
{545F846D-7F19-4D6D-A50B-172A7C9B61E7}.Release|x64.Build.0 = Release|x64
{545F846D-7F19-4D6D-A50B-172A7C9B61E7}.Release|x86.ActiveCfg = Release|Win32
{545F846D-7F19-4D6D-A50B-172A7C9B61E7}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View file

@ -0,0 +1,19 @@
{
"dependencies": {
"Microsoft.ApplicationInsights": "1.0.0",
"Microsoft.ApplicationInsights.PersistenceChannel": "1.0.0",
"Microsoft.ApplicationInsights.WindowsApps": "1.0.0",
"Microsoft.NETCore.UniversalWindowsPlatform": "5.0.0"
},
"frameworks": {
"uap10.0": {}
},
"runtimes": {
"win10-arm": {},
"win10-arm-aot": {},
"win10-x86": {},
"win10-x86-aot": {},
"win10-x64": {},
"win10-x64-aot": {}
}
}

View file

@ -0,0 +1,230 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.22823.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "liblinphone", "liblinphone.vcxproj", "{C7139899-D8BC-48A3-A437-6844A8BAABEF}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mediastreamer2", "..\..\..\mediastreamer2\build\windows10\mediastreamer2\mediastreamer2.vcxproj", "{88E3C241-EB6F-4C84-80DC-89B8961DAF80}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ortp", "..\..\..\oRTP\build\windows10\ortp\ortp.vcxproj", "{2E56B851-9D8D-40E5-84BB-E4EE63B71D25}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "srtp", "..\..\..\..\srtp\build\windows10\srtp\srtp.vcxproj", "{59104E4F-A087-442E-ABD4-BCD2A1F0B0FE}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xml2", "..\..\..\..\build\xml2\xml2.vcxproj", "{2B04DE79-4D33-4405-AC01-C89E0593A71D}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "polarssl", "..\..\..\..\polarssl\build\windows10\polarssl\polarssl.vcxproj", "{88768DD9-5110-4AC8-8B0E-41CD7713E1A2}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "speex", "..\..\..\..\speex\build\windows10\speex\speex.vcxproj", "{971DD379-1C2D-44D2-9285-FDA556C48176}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "speexdsp", "..\..\..\..\speex\build\windows10\speexdsp\speexdsp.vcxproj", "{104BF91B-8314-4328-A996-90B8DF6052AF}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "opus", "..\..\..\..\opus\build\windows10\opus\opus.vcxproj", "{81AF1025-E0EE-4AD6-988D-2EF162778693}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bzrtp", "..\..\..\..\bzrtp\build\windows10\bzrtp\bzrtp.vcxproj", "{45C7723D-3107-4906-9633-F43ABE8A7147}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gsm", "..\..\..\..\gsm\build\windows10\gsm\gsm.vcxproj", "{EF1103C7-8AAC-464B-BA31-86B87246FA72}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "belle-sip", "..\..\..\..\belle-sip\build\windows10\belle-sip\belle-sip.vcxproj", "{B6CDF482-7DA3-43D4-9B12-70150106C191}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "antlr3c", "..\..\..\..\antlr3\runtime\C\build\windows10\antlr3c\antlr3c.vcxproj", "{01CCCCC9-CA0C-4528-92BC-5B8BE1D02D6D}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib", "..\..\..\..\zlib\build\windows10\zlib\zlib.vcxproj", "{A34F450D-392D-4660-9618-810BD695B3B0}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sqlite", "..\..\..\..\build\sqlite\sqlite.vcxproj", "{74CAD9D0-D8AE-4896-B71B-B2D9B48F30AA}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|ARM = Debug|ARM
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|ARM = Release|ARM
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{C7139899-D8BC-48A3-A437-6844A8BAABEF}.Debug|ARM.ActiveCfg = Debug|ARM
{C7139899-D8BC-48A3-A437-6844A8BAABEF}.Debug|ARM.Build.0 = Debug|ARM
{C7139899-D8BC-48A3-A437-6844A8BAABEF}.Debug|x64.ActiveCfg = Debug|x64
{C7139899-D8BC-48A3-A437-6844A8BAABEF}.Debug|x64.Build.0 = Debug|x64
{C7139899-D8BC-48A3-A437-6844A8BAABEF}.Debug|x86.ActiveCfg = Debug|Win32
{C7139899-D8BC-48A3-A437-6844A8BAABEF}.Debug|x86.Build.0 = Debug|Win32
{C7139899-D8BC-48A3-A437-6844A8BAABEF}.Release|ARM.ActiveCfg = Release|ARM
{C7139899-D8BC-48A3-A437-6844A8BAABEF}.Release|ARM.Build.0 = Release|ARM
{C7139899-D8BC-48A3-A437-6844A8BAABEF}.Release|x64.ActiveCfg = Release|x64
{C7139899-D8BC-48A3-A437-6844A8BAABEF}.Release|x64.Build.0 = Release|x64
{C7139899-D8BC-48A3-A437-6844A8BAABEF}.Release|x86.ActiveCfg = Release|Win32
{C7139899-D8BC-48A3-A437-6844A8BAABEF}.Release|x86.Build.0 = Release|Win32
{88E3C241-EB6F-4C84-80DC-89B8961DAF80}.Debug|ARM.ActiveCfg = Debug|ARM
{88E3C241-EB6F-4C84-80DC-89B8961DAF80}.Debug|ARM.Build.0 = Debug|ARM
{88E3C241-EB6F-4C84-80DC-89B8961DAF80}.Debug|x64.ActiveCfg = Debug|x64
{88E3C241-EB6F-4C84-80DC-89B8961DAF80}.Debug|x64.Build.0 = Debug|x64
{88E3C241-EB6F-4C84-80DC-89B8961DAF80}.Debug|x86.ActiveCfg = Debug|Win32
{88E3C241-EB6F-4C84-80DC-89B8961DAF80}.Debug|x86.Build.0 = Debug|Win32
{88E3C241-EB6F-4C84-80DC-89B8961DAF80}.Release|ARM.ActiveCfg = Release|ARM
{88E3C241-EB6F-4C84-80DC-89B8961DAF80}.Release|ARM.Build.0 = Release|ARM
{88E3C241-EB6F-4C84-80DC-89B8961DAF80}.Release|x64.ActiveCfg = Release|x64
{88E3C241-EB6F-4C84-80DC-89B8961DAF80}.Release|x64.Build.0 = Release|x64
{88E3C241-EB6F-4C84-80DC-89B8961DAF80}.Release|x86.ActiveCfg = Release|Win32
{88E3C241-EB6F-4C84-80DC-89B8961DAF80}.Release|x86.Build.0 = Release|Win32
{2E56B851-9D8D-40E5-84BB-E4EE63B71D25}.Debug|ARM.ActiveCfg = Debug|ARM
{2E56B851-9D8D-40E5-84BB-E4EE63B71D25}.Debug|ARM.Build.0 = Debug|ARM
{2E56B851-9D8D-40E5-84BB-E4EE63B71D25}.Debug|x64.ActiveCfg = Debug|x64
{2E56B851-9D8D-40E5-84BB-E4EE63B71D25}.Debug|x64.Build.0 = Debug|x64
{2E56B851-9D8D-40E5-84BB-E4EE63B71D25}.Debug|x86.ActiveCfg = Debug|Win32
{2E56B851-9D8D-40E5-84BB-E4EE63B71D25}.Debug|x86.Build.0 = Debug|Win32
{2E56B851-9D8D-40E5-84BB-E4EE63B71D25}.Release|ARM.ActiveCfg = Release|ARM
{2E56B851-9D8D-40E5-84BB-E4EE63B71D25}.Release|ARM.Build.0 = Release|ARM
{2E56B851-9D8D-40E5-84BB-E4EE63B71D25}.Release|x64.ActiveCfg = Release|x64
{2E56B851-9D8D-40E5-84BB-E4EE63B71D25}.Release|x64.Build.0 = Release|x64
{2E56B851-9D8D-40E5-84BB-E4EE63B71D25}.Release|x86.ActiveCfg = Release|Win32
{2E56B851-9D8D-40E5-84BB-E4EE63B71D25}.Release|x86.Build.0 = Release|Win32
{59104E4F-A087-442E-ABD4-BCD2A1F0B0FE}.Debug|ARM.ActiveCfg = Debug|ARM
{59104E4F-A087-442E-ABD4-BCD2A1F0B0FE}.Debug|ARM.Build.0 = Debug|ARM
{59104E4F-A087-442E-ABD4-BCD2A1F0B0FE}.Debug|x64.ActiveCfg = Debug|x64
{59104E4F-A087-442E-ABD4-BCD2A1F0B0FE}.Debug|x64.Build.0 = Debug|x64
{59104E4F-A087-442E-ABD4-BCD2A1F0B0FE}.Debug|x86.ActiveCfg = Debug|Win32
{59104E4F-A087-442E-ABD4-BCD2A1F0B0FE}.Debug|x86.Build.0 = Debug|Win32
{59104E4F-A087-442E-ABD4-BCD2A1F0B0FE}.Release|ARM.ActiveCfg = Release|ARM
{59104E4F-A087-442E-ABD4-BCD2A1F0B0FE}.Release|ARM.Build.0 = Release|ARM
{59104E4F-A087-442E-ABD4-BCD2A1F0B0FE}.Release|x64.ActiveCfg = Release|x64
{59104E4F-A087-442E-ABD4-BCD2A1F0B0FE}.Release|x64.Build.0 = Release|x64
{59104E4F-A087-442E-ABD4-BCD2A1F0B0FE}.Release|x86.ActiveCfg = Release|Win32
{59104E4F-A087-442E-ABD4-BCD2A1F0B0FE}.Release|x86.Build.0 = Release|Win32
{2B04DE79-4D33-4405-AC01-C89E0593A71D}.Debug|ARM.ActiveCfg = Debug|ARM
{2B04DE79-4D33-4405-AC01-C89E0593A71D}.Debug|ARM.Build.0 = Debug|ARM
{2B04DE79-4D33-4405-AC01-C89E0593A71D}.Debug|x64.ActiveCfg = Debug|x64
{2B04DE79-4D33-4405-AC01-C89E0593A71D}.Debug|x64.Build.0 = Debug|x64
{2B04DE79-4D33-4405-AC01-C89E0593A71D}.Debug|x86.ActiveCfg = Debug|Win32
{2B04DE79-4D33-4405-AC01-C89E0593A71D}.Debug|x86.Build.0 = Debug|Win32
{2B04DE79-4D33-4405-AC01-C89E0593A71D}.Release|ARM.ActiveCfg = Release|ARM
{2B04DE79-4D33-4405-AC01-C89E0593A71D}.Release|ARM.Build.0 = Release|ARM
{2B04DE79-4D33-4405-AC01-C89E0593A71D}.Release|x64.ActiveCfg = Release|x64
{2B04DE79-4D33-4405-AC01-C89E0593A71D}.Release|x64.Build.0 = Release|x64
{2B04DE79-4D33-4405-AC01-C89E0593A71D}.Release|x86.ActiveCfg = Release|Win32
{2B04DE79-4D33-4405-AC01-C89E0593A71D}.Release|x86.Build.0 = Release|Win32
{88768DD9-5110-4AC8-8B0E-41CD7713E1A2}.Debug|ARM.ActiveCfg = Debug|ARM
{88768DD9-5110-4AC8-8B0E-41CD7713E1A2}.Debug|ARM.Build.0 = Debug|ARM
{88768DD9-5110-4AC8-8B0E-41CD7713E1A2}.Debug|x64.ActiveCfg = Debug|x64
{88768DD9-5110-4AC8-8B0E-41CD7713E1A2}.Debug|x64.Build.0 = Debug|x64
{88768DD9-5110-4AC8-8B0E-41CD7713E1A2}.Debug|x86.ActiveCfg = Debug|Win32
{88768DD9-5110-4AC8-8B0E-41CD7713E1A2}.Debug|x86.Build.0 = Debug|Win32
{88768DD9-5110-4AC8-8B0E-41CD7713E1A2}.Release|ARM.ActiveCfg = Release|ARM
{88768DD9-5110-4AC8-8B0E-41CD7713E1A2}.Release|ARM.Build.0 = Release|ARM
{88768DD9-5110-4AC8-8B0E-41CD7713E1A2}.Release|x64.ActiveCfg = Release|x64
{88768DD9-5110-4AC8-8B0E-41CD7713E1A2}.Release|x64.Build.0 = Release|x64
{88768DD9-5110-4AC8-8B0E-41CD7713E1A2}.Release|x86.ActiveCfg = Release|Win32
{88768DD9-5110-4AC8-8B0E-41CD7713E1A2}.Release|x86.Build.0 = Release|Win32
{971DD379-1C2D-44D2-9285-FDA556C48176}.Debug|ARM.ActiveCfg = Debug|ARM
{971DD379-1C2D-44D2-9285-FDA556C48176}.Debug|ARM.Build.0 = Debug|ARM
{971DD379-1C2D-44D2-9285-FDA556C48176}.Debug|x64.ActiveCfg = Debug|x64
{971DD379-1C2D-44D2-9285-FDA556C48176}.Debug|x64.Build.0 = Debug|x64
{971DD379-1C2D-44D2-9285-FDA556C48176}.Debug|x86.ActiveCfg = Debug|Win32
{971DD379-1C2D-44D2-9285-FDA556C48176}.Debug|x86.Build.0 = Debug|Win32
{971DD379-1C2D-44D2-9285-FDA556C48176}.Release|ARM.ActiveCfg = Release|ARM
{971DD379-1C2D-44D2-9285-FDA556C48176}.Release|ARM.Build.0 = Release|ARM
{971DD379-1C2D-44D2-9285-FDA556C48176}.Release|x64.ActiveCfg = Release|x64
{971DD379-1C2D-44D2-9285-FDA556C48176}.Release|x64.Build.0 = Release|x64
{971DD379-1C2D-44D2-9285-FDA556C48176}.Release|x86.ActiveCfg = Release|Win32
{971DD379-1C2D-44D2-9285-FDA556C48176}.Release|x86.Build.0 = Release|Win32
{104BF91B-8314-4328-A996-90B8DF6052AF}.Debug|ARM.ActiveCfg = Debug|ARM
{104BF91B-8314-4328-A996-90B8DF6052AF}.Debug|ARM.Build.0 = Debug|ARM
{104BF91B-8314-4328-A996-90B8DF6052AF}.Debug|x64.ActiveCfg = Debug|x64
{104BF91B-8314-4328-A996-90B8DF6052AF}.Debug|x64.Build.0 = Debug|x64
{104BF91B-8314-4328-A996-90B8DF6052AF}.Debug|x86.ActiveCfg = Debug|Win32
{104BF91B-8314-4328-A996-90B8DF6052AF}.Debug|x86.Build.0 = Debug|Win32
{104BF91B-8314-4328-A996-90B8DF6052AF}.Release|ARM.ActiveCfg = Release|ARM
{104BF91B-8314-4328-A996-90B8DF6052AF}.Release|ARM.Build.0 = Release|ARM
{104BF91B-8314-4328-A996-90B8DF6052AF}.Release|x64.ActiveCfg = Release|x64
{104BF91B-8314-4328-A996-90B8DF6052AF}.Release|x64.Build.0 = Release|x64
{104BF91B-8314-4328-A996-90B8DF6052AF}.Release|x86.ActiveCfg = Release|Win32
{104BF91B-8314-4328-A996-90B8DF6052AF}.Release|x86.Build.0 = Release|Win32
{81AF1025-E0EE-4AD6-988D-2EF162778693}.Debug|ARM.ActiveCfg = Debug|ARM
{81AF1025-E0EE-4AD6-988D-2EF162778693}.Debug|ARM.Build.0 = Debug|ARM
{81AF1025-E0EE-4AD6-988D-2EF162778693}.Debug|x64.ActiveCfg = Debug|x64
{81AF1025-E0EE-4AD6-988D-2EF162778693}.Debug|x64.Build.0 = Debug|x64
{81AF1025-E0EE-4AD6-988D-2EF162778693}.Debug|x86.ActiveCfg = Debug|Win32
{81AF1025-E0EE-4AD6-988D-2EF162778693}.Debug|x86.Build.0 = Debug|Win32
{81AF1025-E0EE-4AD6-988D-2EF162778693}.Release|ARM.ActiveCfg = Release|ARM
{81AF1025-E0EE-4AD6-988D-2EF162778693}.Release|ARM.Build.0 = Release|ARM
{81AF1025-E0EE-4AD6-988D-2EF162778693}.Release|x64.ActiveCfg = Release|x64
{81AF1025-E0EE-4AD6-988D-2EF162778693}.Release|x64.Build.0 = Release|x64
{81AF1025-E0EE-4AD6-988D-2EF162778693}.Release|x86.ActiveCfg = Release|Win32
{81AF1025-E0EE-4AD6-988D-2EF162778693}.Release|x86.Build.0 = Release|Win32
{45C7723D-3107-4906-9633-F43ABE8A7147}.Debug|ARM.ActiveCfg = Debug|ARM
{45C7723D-3107-4906-9633-F43ABE8A7147}.Debug|ARM.Build.0 = Debug|ARM
{45C7723D-3107-4906-9633-F43ABE8A7147}.Debug|x64.ActiveCfg = Debug|x64
{45C7723D-3107-4906-9633-F43ABE8A7147}.Debug|x64.Build.0 = Debug|x64
{45C7723D-3107-4906-9633-F43ABE8A7147}.Debug|x86.ActiveCfg = Debug|Win32
{45C7723D-3107-4906-9633-F43ABE8A7147}.Debug|x86.Build.0 = Debug|Win32
{45C7723D-3107-4906-9633-F43ABE8A7147}.Release|ARM.ActiveCfg = Release|ARM
{45C7723D-3107-4906-9633-F43ABE8A7147}.Release|ARM.Build.0 = Release|ARM
{45C7723D-3107-4906-9633-F43ABE8A7147}.Release|x64.ActiveCfg = Release|x64
{45C7723D-3107-4906-9633-F43ABE8A7147}.Release|x64.Build.0 = Release|x64
{45C7723D-3107-4906-9633-F43ABE8A7147}.Release|x86.ActiveCfg = Release|Win32
{45C7723D-3107-4906-9633-F43ABE8A7147}.Release|x86.Build.0 = Release|Win32
{EF1103C7-8AAC-464B-BA31-86B87246FA72}.Debug|ARM.ActiveCfg = Debug|ARM
{EF1103C7-8AAC-464B-BA31-86B87246FA72}.Debug|ARM.Build.0 = Debug|ARM
{EF1103C7-8AAC-464B-BA31-86B87246FA72}.Debug|x64.ActiveCfg = Debug|x64
{EF1103C7-8AAC-464B-BA31-86B87246FA72}.Debug|x64.Build.0 = Debug|x64
{EF1103C7-8AAC-464B-BA31-86B87246FA72}.Debug|x86.ActiveCfg = Debug|Win32
{EF1103C7-8AAC-464B-BA31-86B87246FA72}.Debug|x86.Build.0 = Debug|Win32
{EF1103C7-8AAC-464B-BA31-86B87246FA72}.Release|ARM.ActiveCfg = Release|ARM
{EF1103C7-8AAC-464B-BA31-86B87246FA72}.Release|ARM.Build.0 = Release|ARM
{EF1103C7-8AAC-464B-BA31-86B87246FA72}.Release|x64.ActiveCfg = Release|x64
{EF1103C7-8AAC-464B-BA31-86B87246FA72}.Release|x64.Build.0 = Release|x64
{EF1103C7-8AAC-464B-BA31-86B87246FA72}.Release|x86.ActiveCfg = Release|Win32
{EF1103C7-8AAC-464B-BA31-86B87246FA72}.Release|x86.Build.0 = Release|Win32
{B6CDF482-7DA3-43D4-9B12-70150106C191}.Debug|ARM.ActiveCfg = Debug|ARM
{B6CDF482-7DA3-43D4-9B12-70150106C191}.Debug|ARM.Build.0 = Debug|ARM
{B6CDF482-7DA3-43D4-9B12-70150106C191}.Debug|x64.ActiveCfg = Debug|x64
{B6CDF482-7DA3-43D4-9B12-70150106C191}.Debug|x64.Build.0 = Debug|x64
{B6CDF482-7DA3-43D4-9B12-70150106C191}.Debug|x86.ActiveCfg = Debug|Win32
{B6CDF482-7DA3-43D4-9B12-70150106C191}.Debug|x86.Build.0 = Debug|Win32
{B6CDF482-7DA3-43D4-9B12-70150106C191}.Release|ARM.ActiveCfg = Release|ARM
{B6CDF482-7DA3-43D4-9B12-70150106C191}.Release|ARM.Build.0 = Release|ARM
{B6CDF482-7DA3-43D4-9B12-70150106C191}.Release|x64.ActiveCfg = Release|x64
{B6CDF482-7DA3-43D4-9B12-70150106C191}.Release|x64.Build.0 = Release|x64
{B6CDF482-7DA3-43D4-9B12-70150106C191}.Release|x86.ActiveCfg = Release|Win32
{B6CDF482-7DA3-43D4-9B12-70150106C191}.Release|x86.Build.0 = Release|Win32
{01CCCCC9-CA0C-4528-92BC-5B8BE1D02D6D}.Debug|ARM.ActiveCfg = Debug|ARM
{01CCCCC9-CA0C-4528-92BC-5B8BE1D02D6D}.Debug|ARM.Build.0 = Debug|ARM
{01CCCCC9-CA0C-4528-92BC-5B8BE1D02D6D}.Debug|x64.ActiveCfg = Debug|x64
{01CCCCC9-CA0C-4528-92BC-5B8BE1D02D6D}.Debug|x64.Build.0 = Debug|x64
{01CCCCC9-CA0C-4528-92BC-5B8BE1D02D6D}.Debug|x86.ActiveCfg = Debug|Win32
{01CCCCC9-CA0C-4528-92BC-5B8BE1D02D6D}.Debug|x86.Build.0 = Debug|Win32
{01CCCCC9-CA0C-4528-92BC-5B8BE1D02D6D}.Release|ARM.ActiveCfg = Release|ARM
{01CCCCC9-CA0C-4528-92BC-5B8BE1D02D6D}.Release|ARM.Build.0 = Release|ARM
{01CCCCC9-CA0C-4528-92BC-5B8BE1D02D6D}.Release|x64.ActiveCfg = Release|x64
{01CCCCC9-CA0C-4528-92BC-5B8BE1D02D6D}.Release|x64.Build.0 = Release|x64
{01CCCCC9-CA0C-4528-92BC-5B8BE1D02D6D}.Release|x86.ActiveCfg = Release|Win32
{01CCCCC9-CA0C-4528-92BC-5B8BE1D02D6D}.Release|x86.Build.0 = Release|Win32
{A34F450D-392D-4660-9618-810BD695B3B0}.Debug|ARM.ActiveCfg = Debug|ARM
{A34F450D-392D-4660-9618-810BD695B3B0}.Debug|ARM.Build.0 = Debug|ARM
{A34F450D-392D-4660-9618-810BD695B3B0}.Debug|x64.ActiveCfg = Debug|x64
{A34F450D-392D-4660-9618-810BD695B3B0}.Debug|x64.Build.0 = Debug|x64
{A34F450D-392D-4660-9618-810BD695B3B0}.Debug|x86.ActiveCfg = Debug|Win32
{A34F450D-392D-4660-9618-810BD695B3B0}.Debug|x86.Build.0 = Debug|Win32
{A34F450D-392D-4660-9618-810BD695B3B0}.Release|ARM.ActiveCfg = Release|ARM
{A34F450D-392D-4660-9618-810BD695B3B0}.Release|ARM.Build.0 = Release|ARM
{A34F450D-392D-4660-9618-810BD695B3B0}.Release|x64.ActiveCfg = Release|x64
{A34F450D-392D-4660-9618-810BD695B3B0}.Release|x64.Build.0 = Release|x64
{A34F450D-392D-4660-9618-810BD695B3B0}.Release|x86.ActiveCfg = Release|Win32
{A34F450D-392D-4660-9618-810BD695B3B0}.Release|x86.Build.0 = Release|Win32
{74CAD9D0-D8AE-4896-B71B-B2D9B48F30AA}.Debug|ARM.ActiveCfg = Debug|ARM
{74CAD9D0-D8AE-4896-B71B-B2D9B48F30AA}.Debug|ARM.Build.0 = Debug|ARM
{74CAD9D0-D8AE-4896-B71B-B2D9B48F30AA}.Debug|x64.ActiveCfg = Debug|x64
{74CAD9D0-D8AE-4896-B71B-B2D9B48F30AA}.Debug|x64.Build.0 = Debug|x64
{74CAD9D0-D8AE-4896-B71B-B2D9B48F30AA}.Debug|x86.ActiveCfg = Debug|Win32
{74CAD9D0-D8AE-4896-B71B-B2D9B48F30AA}.Debug|x86.Build.0 = Debug|Win32
{74CAD9D0-D8AE-4896-B71B-B2D9B48F30AA}.Release|ARM.ActiveCfg = Release|ARM
{74CAD9D0-D8AE-4896-B71B-B2D9B48F30AA}.Release|ARM.Build.0 = Release|ARM
{74CAD9D0-D8AE-4896-B71B-B2D9B48F30AA}.Release|x64.ActiveCfg = Release|x64
{74CAD9D0-D8AE-4896-B71B-B2D9B48F30AA}.Release|x64.Build.0 = Release|x64
{74CAD9D0-D8AE-4896-B71B-B2D9B48F30AA}.Release|x86.ActiveCfg = Release|Win32
{74CAD9D0-D8AE-4896-B71B-B2D9B48F30AA}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View file

@ -0,0 +1,192 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|ARM">
<Configuration>Debug</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|ARM">
<Configuration>Release</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\..\coreapi\account_creator.c" />
<ClCompile Include="..\..\..\coreapi\address.c" />
<ClCompile Include="..\..\..\coreapi\authentication.c" />
<ClCompile Include="..\..\..\coreapi\bellesip_sal\sal_address_impl.c" />
<ClCompile Include="..\..\..\coreapi\bellesip_sal\sal_impl.c" />
<ClCompile Include="..\..\..\coreapi\bellesip_sal\sal_op_call.c" />
<ClCompile Include="..\..\..\coreapi\bellesip_sal\sal_op_call_transfer.c" />
<ClCompile Include="..\..\..\coreapi\bellesip_sal\sal_op_events.c" />
<ClCompile Include="..\..\..\coreapi\bellesip_sal\sal_op_impl.c" />
<ClCompile Include="..\..\..\coreapi\bellesip_sal\sal_op_info.c" />
<ClCompile Include="..\..\..\coreapi\bellesip_sal\sal_op_message.c" />
<ClCompile Include="..\..\..\coreapi\bellesip_sal\sal_op_presence.c" />
<ClCompile Include="..\..\..\coreapi\bellesip_sal\sal_op_publish.c" />
<ClCompile Include="..\..\..\coreapi\bellesip_sal\sal_op_registration.c" />
<ClCompile Include="..\..\..\coreapi\bellesip_sal\sal_sdp.c" />
<ClCompile Include="..\..\..\coreapi\buffer.c" />
<ClCompile Include="..\..\..\coreapi\callbacks.c" />
<ClCompile Include="..\..\..\coreapi\call_log.c" />
<ClCompile Include="..\..\..\coreapi\call_params.c" />
<ClCompile Include="..\..\..\coreapi\chat.c" />
<ClCompile Include="..\..\..\coreapi\chat_file_transfer.c" />
<ClCompile Include="..\..\..\coreapi\conference.c" />
<ClCompile Include="..\..\..\coreapi\content.c" />
<ClCompile Include="..\..\..\coreapi\dict.c" />
<ClCompile Include="..\..\..\coreapi\ec-calibrator.c" />
<ClCompile Include="..\..\..\coreapi\enum.c" />
<ClCompile Include="..\..\..\coreapi\event.c" />
<ClCompile Include="..\..\..\coreapi\friend.c" />
<ClCompile Include="..\..\..\coreapi\info.c" />
<ClCompile Include="..\..\..\coreapi\lime.c" />
<ClCompile Include="..\..\..\coreapi\linphonecall.c" />
<ClCompile Include="..\..\..\coreapi\linphonecore.c" />
<ClCompile Include="..\..\..\coreapi\linphone_tunnel_config.c" />
<ClCompile Include="..\..\..\coreapi\linphone_tunnel_stubs.c" />
<ClCompile Include="..\..\..\coreapi\localplayer.c" />
<ClCompile Include="..\..\..\coreapi\lpc2xml.c" />
<ClCompile Include="..\..\..\coreapi\lpconfig.c" />
<ClCompile Include="..\..\..\coreapi\lsd.c" />
<ClCompile Include="..\..\..\coreapi\message_storage.c" />
<ClCompile Include="..\..\..\coreapi\misc.c" />
<ClCompile Include="..\..\..\coreapi\offeranswer.c" />
<ClCompile Include="..\..\..\coreapi\player.c" />
<ClCompile Include="..\..\..\coreapi\presence.c" />
<ClCompile Include="..\..\..\coreapi\proxy.c" />
<ClCompile Include="..\..\..\coreapi\quality_reporting.c" />
<ClCompile Include="..\..\..\coreapi\remote_provisioning.c" />
<ClCompile Include="..\..\..\coreapi\sal.c" />
<ClCompile Include="..\..\..\coreapi\siplogin.c" />
<ClCompile Include="..\..\..\coreapi\sipsetup.c" />
<ClCompile Include="..\..\..\coreapi\vtables.c" />
<ClCompile Include="..\..\..\coreapi\xml.c" />
<ClCompile Include="..\..\..\coreapi\xml2lpc.c" />
<ClCompile Include="..\..\..\coreapi\xmlrpc.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\coreapi\account_creator.h" />
<ClInclude Include="..\..\..\coreapi\bellesip_sal\sal_impl.h" />
<ClInclude Include="..\..\..\coreapi\buffer.h" />
<ClInclude Include="..\..\..\coreapi\call_log.h" />
<ClInclude Include="..\..\..\coreapi\call_params.h" />
<ClInclude Include="..\..\..\coreapi\content.h" />
<ClInclude Include="..\..\..\coreapi\enum.h" />
<ClInclude Include="..\..\..\coreapi\event.h" />
<ClInclude Include="..\..\..\coreapi\lime.h" />
<ClInclude Include="..\..\..\coreapi\linphonecore.h" />
<ClInclude Include="..\..\..\coreapi\linphonecore_utils.h" />
<ClInclude Include="..\..\..\coreapi\linphonefriend.h" />
<ClInclude Include="..\..\..\coreapi\linphonepresence.h" />
<ClInclude Include="..\..\..\coreapi\linphone_tunnel.h" />
<ClInclude Include="..\..\..\coreapi\lpc2xml.h" />
<ClInclude Include="..\..\..\coreapi\lpconfig.h" />
<ClInclude Include="..\..\..\coreapi\offeranswer.h" />
<ClInclude Include="..\..\..\coreapi\private.h" />
<ClInclude Include="..\..\..\coreapi\quality_reporting.h" />
<ClInclude Include="..\..\..\coreapi\sipsetup.h" />
<ClInclude Include="..\..\..\coreapi\xml2lpc.h" />
<ClInclude Include="..\..\..\coreapi\xmlrpc.h" />
<ClInclude Include="config.h" />
<ClInclude Include="liblinphone_gitversion.h" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\belle-sip\build\windows10\belle-sip\belle-sip.vcxproj">
<Project>{b6cdf482-7da3-43d4-9b12-70150106c191}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\..\build\sqlite\sqlite.vcxproj">
<Project>{74cad9d0-d8ae-4896-b71b-b2d9b48f30aa}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\..\build\xml2\xml2.vcxproj">
<Project>{2b04de79-4d33-4405-ac01-c89e0593a71d}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\..\zlib\build\windows10\zlib\zlib.vcxproj">
<Project>{a34f450d-392d-4660-9618-810bd695b3b0}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\mediastreamer2\build\windows10\mediastreamer2\mediastreamer2.vcxproj">
<Project>{88e3c241-eb6f-4c84-80dc-89b8961daf80}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\oRTP\build\windows10\ortp\ortp.vcxproj">
<Project>{2e56b851-9d8d-40e5-84bb-e4ee63b71d25}</Project>
</ProjectReference>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{c7139899-d8bc-48a3-a437-6844a8baabef}</ProjectGuid>
<Keyword>DynamicLibrary</Keyword>
<ProjectName>liblinphone</ProjectName>
<RootNamespace>liblinphone</RootNamespace>
<DefaultLanguage>en-US</DefaultLanguage>
<MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
<AppContainerApplication>true</AppContainerApplication>
<ApplicationType>Windows Store</ApplicationType>
<ApplicationTypeRevision>10</ApplicationTypeRevision>
<WindowsTargetPlatformVersion>10.0.10240.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformMinVersion>10.0.10069.0</WindowsTargetPlatformMinVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<GenerateManifest>false</GenerateManifest>
<IgnoreImportLibrary>false</IgnoreImportLibrary>
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<CompileAsWinRT>false</CompileAsWinRT>
<AdditionalIncludeDirectories>$(SolutionDir)$(Platform)\$(Configuration)\include;$(ProjectDir)..\..\..\include;$(ProjectDir)..\..\..\coreapi;$(ProjectDir)..\..\..\mediastreamer2\include;$(ProjectDir)..\..\..\..\belle-sip\include;$(ProjectDir)..\..\..\oRTP\include;$(ProjectDir)..\..\..\..\sqlite;$(ProjectDir)..\..\..\..\zlib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>HAVE_CONFIG_H;HAVE_ZLIB;MSG_STORAGE_ENABLED;VIDEO_ENABLED;IN_LINPHONE;LINPHONE_PLUGINS_DIR="\\linphone\\plugins";_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<DisableSpecificWarnings>4996</DisableSpecificWarnings>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
</Link>
<PreBuildEvent>
<Command>version.bat</Command>
</PreBuildEvent>
<PreBuildEvent>
<Message>Batch script to get the git version</Message>
</PreBuildEvent>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View file

@ -0,0 +1,22 @@
@ECHO off
SET gitlog=
FOR /f "delims=" %%a IN ('git log -1 "--pretty=format:%%H" ../../../configure.ac') DO SET gitlog=%%a
IF [%gitlog%] == [] GOTO UnknownGitVersion
FOR /f "delims=" %%a IN ('git describe --always') DO SET gitdescribe=%%a
GOTO End
:UnknownGitVersion
SET gitdescribe=unknown
:End
ECHO #define LIBLINPHONE_GIT_VERSION "%gitdescribe%" > liblinphone_gitversion.h
FOR /F "delims=" %%a IN ('findstr /B AC_INIT ..\..\..\configure.ac') DO (
FOR /F "tokens=1,2,3 delims=[,]" %%1 IN ("%%a") DO (
ECHO #define LIBLINPHONE_VERSION "%%3" > config.h
)
)

View file

@ -96,6 +96,7 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\coreapi\account_creator.c" />
<ClCompile Include="..\..\coreapi\address.c" />
<ClCompile Include="..\..\coreapi\authentication.c" />
<ClCompile Include="..\..\coreapi\bellesip_sal\sal_address_impl.c" />
@ -144,6 +145,7 @@
<ClCompile Include="..\..\coreapi\TunnelManager.cc" />
<ClCompile Include="..\..\coreapi\vtables.c" />
<ClCompile Include="..\..\coreapi\xml.c" />
<ClCompile Include="..\..\coreapi\xmlrpc.c" />
<ClCompile Include="..\..\coreapi\xml2lpc.c" />
</ItemGroup>
<ItemGroup>

View file

@ -0,0 +1,54 @@
############################################################################
# FindGtkMacIntegration.txt
# Copyright (C) 2015 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 libgtkmacintegration include file and library
#
# GTKMACINTEGRATION_FOUND - system has libgtkmacintegration
# GTKMACINTEGRATION_INCLUDE_DIRS - the libgtkmacintegration include directory
# GTKMACINTEGRATION_LIBRARIES - The libraries needed to use libgtkmacintegration
# GTKMACINTEGRATION_CPPFLAGS - The cflags needed to use libgtkmacintegration
set(_GTKMACINTEGRATION_ROOT_PATHS
${CMAKE_INSTALL_PREFIX}
)
find_path(GTKMACINTEGRATION_INCLUDE_DIRS
NAMES gtkosxapplication.h
HINTS _GTKMACINTEGRATION_ROOT_PATHS
PATH_SUFFIXES include/gtkmacintegration-gtk2 include/gtkmacintegration
)
find_library(GTKMACINTEGRATION_LIBRARIES
NAMES gtkmacintegration-gtk2 gtkmacintegration
HINTS ${_GTKMACINTEGRATION_ROOT_PATHS}
PATH_SUFFIXES bin lib
)
set(GTKMACINTEGRATION_CPPFLAGS "-DMAC_INTEGRATION")
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(GTKMACINTEGRATION
DEFAULT_MSG
GTKMACINTEGRATION_INCLUDE_DIRS GTKMACINTEGRATION_LIBRARIES GTKMACINTEGRATION_CPPFLAGS
)
mark_as_advanced(GTKMACINTEGRATION_INCLUDE_DIRS GTKMACINTEGRATION_LIBRARIES GTKMACINTEGRATION_CPPFLAGS)

View file

@ -1,65 +0,0 @@
############################################################################
# FindSoup.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.
#
############################################################################
#
# - Find the soup include file and library
#
# SOUP_FOUND - system has libsoup
# SOUP_INCLUDE_DIRS - the libsoup include directory
# SOUP_LIBRARIES - The libraries needed to use libsoup
if(WIN32)
set(GTK2_ADDITIONAL_SUFFIXES "../lib/glib-2.0/include" "../lib/gtk-2.0/include")
endif()
find_package(GTK2 2.18 REQUIRED gtk)
set(_SOUP_ROOT_PATHS
${CMAKE_INSTALL_PREFIX}
)
find_path(SOUP_INCLUDE_DIRS
NAMES libsoup/soup.h
HINTS _SOUP_ROOT_PATHS
PATH_SUFFIXES include/libsoup-2.4
)
if(SOUP_INCLUDE_DIRS)
set(HAVE_LIBSOUP_SOUP_H 1)
list(APPEND SOUP_INCLUDE_DIRS ${GTK2_INCLUDE_DIRS})
endif()
find_library(SOUP_LIBRARIES
NAMES soup-2.4
HINTS ${_SOUP_ROOT_PATHS}
PATH_SUFFIXES bin lib
)
if(SOUP_LIBRARIES)
list(APPEND SOUP_LIBRARIES ${GTK2_LIBRARIES})
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Soup
DEFAULT_MSG
SOUP_INCLUDE_DIRS SOUP_LIBRARIES HAVE_LIBSOUP_SOUP_H
)
mark_as_advanced(SOUP_INCLUDE_DIRS SOUP_LIBRARIES HAVE_LIBSOUP_SOUP_H)

View file

@ -41,8 +41,13 @@ if(ZLIB_INCLUDE_DIRS)
endif()
if(ENABLE_STATIC)
if(IOS OR QNX)
set(_ZLIB_STATIC_NAMES z)
else()
set(_ZLIB_STATIC_NAMES zstatic zlibstatic zlibstaticd)
endif()
find_library(ZLIB_LIBRARIES
NAMES zstatic zlibstatic zlibstaticd
NAMES ${_ZLIB_STATIC_NAMES}
HINTS ${_ZLIB_ROOT_PATHS}
PATH_SUFFIXES bin lib
)

View file

@ -29,7 +29,10 @@
# LINPHONE_CPPFLAGS - The compilation flags needed to use linphone
# LINPHONE_LDFLAGS - The linking flags needed to use linphone
include("${CMAKE_CURRENT_LIST_DIR}/LinphoneTargets.cmake")
if(NOT LINPHONE_BUILDER_GROUP_EXTERNAL_SOURCE_PATH_BUILDERS)
include("${CMAKE_CURRENT_LIST_DIR}/LinphoneTargets.cmake")
endif()
find_package(Mediastreamer2 REQUIRED)
find_package(BelleSIP REQUIRED)
if(@ENABLE_TUNNEL@)
@ -38,7 +41,7 @@ endif()
get_filename_component(LINPHONE_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
set(LINPHONE_INCLUDE_DIRS "${LINPHONE_CMAKE_DIR}/../../../include")
set(LINPHONE_LIBRARIES BelledonneCommunications::linphone)
set(LINPHONE_LIBRARIES linphone)
set(LINPHONE_LDFLAGS @LINK_FLAGS@)
list(APPEND LINPHONE_INCLUDE_DIRS ${MEDIASTREAMER2_INCLUDE_DIRS} ${BELLESIP_INCLUDE_DIRS})
list(APPEND LINPHONE_LIBRARIES ${MEDIASTREAMER2_LIBRARIES} ${BELLESIP_LIBRARIES})

View file

@ -38,7 +38,11 @@
#define PACKAGE_SOUND_DIR "${PACKAGE_SOUND_DIR}"
#cmakedefine BUILD_WIZARD
#cmakedefine HAVE_GTK_OSX 1
#cmakedefine HAVE_NOTIFY4
#cmakedefine HAVE_ZLIB 1
#cmakedefine HAVE_CU_GET_SUITE 1
#cmakedefine HAVE_CU_CURSES 1
#cmakedefine HAVE_LIBUDEV_H 0
#cmakedefine HAVE_LIME
#cmakedefine ENABLE_NLS 1

View file

@ -1,6 +1,6 @@
dnl Process this file with autoconf to produce a configure script.
AC_INIT([linphone],[3.8.2-linphone-daemon],[linphone-developers@nongnu.org])
AC_INIT([linphone],[3.9.1-linphone-daemon],[linphone-developers@nongnu.org])
AC_CANONICAL_SYSTEM
AC_CONFIG_SRCDIR([coreapi/linphonecore.c])
@ -17,7 +17,7 @@ if test "$LINPHONE_EXTRA_VERSION" != "" ;then
LINPHONE_VERSION=$LINPHONE_VERSION.${LINPHONE_EXTRA_VERSION}
fi
LIBLINPHONE_SO_CURRENT=7 dnl increment this number when you add/change/remove an interface
LIBLINPHONE_SO_CURRENT=8 dnl increment this number when you add/change/remove an interface
LIBLINPHONE_SO_REVISION=0 dnl increment this number when you change source code, without changing interfaces; set to 0 when incrementing CURRENT
LIBLINPHONE_SO_AGE=0 dnl increment this number when you add an interface, set to 0 if you remove an interface
@ -132,7 +132,7 @@ AC_CONFIG_COMMANDS([libtool-hacking],
dnl Add the languages which your application supports here.
PKG_PROG_PKG_CONFIG
ALL_LINGUAS=$(cd po && echo *.po | sed 's/\.po//g')
ALL_LINGUAS=$(cd $srcdir/po && echo *.po | sed 's/\.po//g')
AC_SUBST(ALL_LINGUAS)
AC_DEFINE_UNQUOTED(LINPHONE_ALL_LANGS, "$ALL_LINGUAS", [All supported languages])
@ -147,8 +147,7 @@ if test "$mingw_found" != "yes" ; then
LIBS="$LIBS $LIBINTL"
else
if test "$USE_NLS" = "yes" ; then
AC_DEFINE(ENABLE_NLS,1,[Tells whether localisation is possible])
AC_DEFINE(HAVE_GETTEXT,1,[Tells wheter localisation is possible])
AC_DEFINE(HAVE_INTL,1,[Tells wheter localisation is possible])
LIBS="$LIBS -lintl"
fi
fi
@ -633,7 +632,7 @@ AC_ARG_ENABLE(zrtp,
dnl this options are just for passing to mediastreamer2 subproject
AC_ARG_ENABLE(dtls,
[AS_HELP_STRING([--enable-dtls], [Turn on dtls support - requires polarssl > 1.4])],
[AS_HELP_STRING([--enable-dtls], [Turn on srtp-dtls support - requires polarssl > 1.4])],
[case "${enableval}" in
yes) dtls=true ;;
no) dtls=false ;;
@ -739,16 +738,6 @@ AC_ARG_ENABLE(assistant,
[build_wizard=check]
)
dnl check libsoup (needed for wizard)
if test "$build_wizard" != "false" ; then
PKG_CHECK_MODULES(LIBSOUP, [libsoup-2.4 >= 2.26],[],
[if test "$build_wizard" = "true" ; then
AC_MSG_ERROR([Could not found libsoup, assistant cannot be compiled.])
else
build_wizard=false
fi]
)
fi
if test "$build_wizard" != "false" ; then
PKG_CHECK_MODULES(LIBGTKWIZARD, [gtk+-2.0 >= 2.22.0],[],
[if test "$build_wizard" = "true" ; then
@ -758,8 +747,6 @@ if test "$build_wizard" != "false" ; then
fi]
)
fi
AC_SUBST(LIBSOUP_CFLAGS)
AC_SUBST(LIBSOUP_LIBS)
AM_CONDITIONAL(BUILD_WIZARD, test x$build_wizard != xfalse)
if test "$build_wizard" != "false" ; then
build_wizard=true
@ -781,7 +768,7 @@ AC_ARG_ENABLE(strict,
)
STRICT_OPTIONS="-Wall -Wuninitialized"
STRICT_OPTIONS_CC="-Wdeclaration-after-statement "
STRICT_OPTIONS_CC="-Wdeclaration-after-statement -Wstrict-prototypes"
STRICT_OPTIONS_CXX=""
#for clang
@ -804,7 +791,7 @@ case "$target_os" in
;;
esac
if test "$strictness" = "yes" ; then
STRICT_OPTIONS="$STRICT_OPTIONS -Werror"
STRICT_OPTIONS="$STRICT_OPTIONS -Werror -Wno-error=deprecated-declarations -Wno-error=strict-prototypes"
CFLAGS="$CFLAGS -fno-strict-aliasing"
fi
@ -907,7 +894,7 @@ if test x$enable_msg_storage != xfalse; then
AC_CHECK_LIB(sqlite3, sqlite3_open, [SQLITE3_LIBS+=" -lsqlite3 "; found_sqlite=yes], [foo=bar])
fi
if test "$found_sqlite" = "yes"; then
SQLITE3_CFLAGS+="-DMSG_STORAGE_ENABLED"
SQLITE3_CFLAGS+=" -DMSG_STORAGE_ENABLED"
if test "$build_macos" = "yes" -o "$ios_found" = "yes"; then
SQLITE3_LIBS+=" -liconv"
fi
@ -925,6 +912,41 @@ fi
AM_CONDITIONAL(BUILD_MSG_STORAGE, test x$enable_msg_storage = xtrue)
AC_ARG_ENABLE(call-logs-storage,
[AS_HELP_STRING([--enable-call-logs-storage=[yes/no]], [Turn on compilation of call logs storage (default=auto)])],
[case "${enableval}" in
yes) enable_call_logs_storage=true ;;
no) enable_call_logs_storage=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-call-logs-storage) ;;
esac],
[enable_call_logs_storage=auto]
)
if test x$enable_call_logs_storage != xfalse; then
PKG_CHECK_MODULES(SQLITE3,[sqlite3 >= 3.6.0],[found_sqlite=yes],[found_sqlite=no])
if test "$found_sqlite" = "no"; then
dnl Check the lib presence in case the PKG-CONFIG version is not found
AC_CHECK_LIB(sqlite3, sqlite3_open, [SQLITE3_LIBS+=" -lsqlite3 "; found_sqlite=yes], [foo=bar])
fi
if test "$found_sqlite" = "yes"; then
SQLITE3_CFLAGS+=" -DCALL_LOGS_STORAGE_ENABLED"
if test "$build_macos" = "yes" -o "$ios_found" = "yes"; then
SQLITE3_LIBS+=" -liconv"
fi
enable_call_logs_storage=true
else
if test x$enable_call_logs_storage = xtrue; then
AC_MSG_ERROR([sqlite3, required for call logs storage, not found])
fi
enable_call_logs_storage=false
fi
AC_SUBST(SQLITE3_CFLAGS)
AC_SUBST(SQLITE3_LIBS)
fi
AM_CONDITIONAL(BUILD_CALL_LOGS_STORAGE, test x$enable_call_logs_storage = xtrue)
PKG_CHECK_MODULES(BELLESIP, [belle-sip >= 1.4.0])
SIPSTACK_CFLAGS="$BELLESIP_CFLAGS"
@ -1019,12 +1041,12 @@ dnl ##################################################
dnl # Check for doxygen
dnl ##################################################
AC_ARG_ENABLE(doxygen,
[AS_HELP_STRING([--disable-documentation], [Disable documentation generation using doxygen (default=no)])],
AC_ARG_ENABLE(documentation,
[AS_HELP_STRING([--enable-documentation], [Documentation generation using doxygen (default=yes)])],
[case "${enableval}" in
yes) documentation_enabled=yes;;
no) documentation_enabled=no;;
*) AC_MSG_ERROR("Bad value for --disable-documentation");;
*) AC_MSG_ERROR("Bad value for --enable-documentation");;
esac],
[documentation_enabled=yes]
)
@ -1035,6 +1057,11 @@ else
fi
AM_CONDITIONAL(HAVE_DOXYGEN, test "$DOXYGEN" != "false")
AC_PATH_PROG([SIPP],[sipp],[false])
if test "x$SIPP" != "xfalse" ; then
AC_DEFINE(HAVE_SIPP,1,[defined when SIPP is available])
AC_DEFINE_UNQUOTED(SIPP_COMMAND,"$SIPP",[defined when SIPP is available])
fi
AC_CONFIG_FILES([
Makefile
@ -1077,12 +1104,14 @@ printf "* %-30s %s\n" "Video support" $video
printf "* %-30s %s\n" "GTK interface" $gtk_ui
printf "* %-30s %s\n" "Account assistant" $build_wizard
printf "* %-30s %s\n" "Console interface" $console_ui
printf "* %-30s %s\n" "Tools" $build_tools
printf "* %-30s %s\n" "Tools" $build_tools
printf "* %-30s %s\n" "Message storage" $enable_msg_storage
printf "* %-30s %s\n" "Call logs storage" $enable_call_logs_storage
printf "* %-30s %s\n" "IM encryption" $lime
printf "* %-30s %s\n" "uPnP support" $build_upnp
printf "* %-30s %s\n" "LDAP support" $enable_ldap
printf "* %-30s %s\n" "ZLIB support" $found_zlib
printf "* %-30s %s\n" "Documentation" $documentation_enabled
if test "$enable_tunnel" = "true" ; then
printf "* %-30s %s\n" "Tunnel support" "true"

View file

@ -29,6 +29,7 @@ set(LINPHONECSH_SOURCE_FILES
shell.c
)
apply_compile_flags(LINPHONEC_SOURCE_FILES "CPP" "C")
add_executable(linphonec ${LINPHONEC_SOURCE_FILES})
target_link_libraries(linphonec linphone)

View file

@ -564,7 +564,7 @@ lpc_cmd_call(LinphoneCore *lc, char *args)
}
{
LinphoneCall *call;
LinphoneCallParams *cp=linphone_core_create_default_call_parameters (lc);
LinphoneCallParams *cp=linphone_core_create_call_params (lc, NULL);
char *opt1,*opt2;
if ( linphone_core_in_call(lc) )
{
@ -633,16 +633,16 @@ lpc_cmd_chat(LinphoneCore *lc, char *args)
/* missing one parameter */
return 0;
}
cr = linphone_core_create_chat_room(lc,arg1);
cr = linphone_core_get_chat_room_from_uri(lc,arg1);
linphone_chat_room_send_message(cr,arg2);
return 1;
}
const char *linphonec_get_callee(){
const char *linphonec_get_callee(void){
return callee_name;
}
const char *linphonec_get_caller(){
const char *linphonec_get_caller(void){
return caller_name;
}
@ -2376,12 +2376,12 @@ static int lpc_cmd_rtp_no_xmit_on_audio_mute(LinphoneCore *lc, char *args)
#ifdef VIDEO_ENABLED
static int _lpc_cmd_video_window(LinphoneCore *lc, char *args, bool_t is_preview){
char subcommand[64];
int a,b;
long a,b;
int err;
VideoParams *params=is_preview ? &lpc_preview_params : &lpc_video_params;
if (!args) return 0;
err=sscanf(args,"%63s %i %i",subcommand,&a,&b);
err=sscanf(args,"%63s %ld %ld",subcommand,&a,&b);
if (err>=1){
if (strcmp(subcommand,"pos")==0){
if (err<3) return 0;
@ -2403,15 +2403,15 @@ static int _lpc_cmd_video_window(LinphoneCore *lc, char *args, bool_t is_preview
if (is_preview) linphone_core_enable_video_preview (lc,FALSE);
}else if (strcmp(subcommand,"id")==0){
if (err == 1){
linphonec_out("vwindow id: 0x%x\n",is_preview ? linphone_core_get_native_preview_window_id (lc) :
linphonec_out("vwindow id: 0x%p\n",is_preview ? linphone_core_get_native_preview_window_id (lc) :
linphone_core_get_native_video_window_id (lc));
return 1;
} else if (err != 2) return 0;
params->wid=a;
params->wid=(void *)a;
if (is_preview)
linphone_core_set_native_preview_window_id (lc,a);
linphone_core_set_native_preview_window_id(lc, (void *)a);
else
linphone_core_set_native_video_window_id(lc,a);
linphone_core_set_native_video_window_id(lc, (void *)a);
}else if (is_preview==TRUE){
if (strcmp(subcommand,"integrated")==0){
linphone_core_use_preview_window (lc,FALSE);

View file

@ -65,15 +65,6 @@
#endif /*_WIN32_WCE*/
#ifdef HAVE_GETTEXT
#include <libintl.h>
#ifndef _
#define _(String) gettext(String)
#endif
#else
#define _(something) (something)
#endif
#ifndef PACKAGE_DIR
#define PACKAGE_DIR ""
#endif
@ -164,7 +155,7 @@ static char zrtpsecrets[PATH_MAX];
static char usr_certificates_path[PATH_MAX];
static const char *factory_configfile_name=NULL;
static char *sip_addr_to_call = NULL; /* for autocall */
static int window_id = 0; /* 0=standalone window, or window id for embedding video */
static void *window_id = NULL; /* NULL=standalone window, or window id for embedding video */
#if !defined(_WIN32_WCE)
static ortp_pipe_t client_sock=ORTP_PIPE_INVALID;
#endif /*_WIN32_WCE*/
@ -368,7 +359,7 @@ static void linphonec_call_state_changed(LinphoneCore *lc, LinphoneCall *call, L
if ( auto_answer) {
answer_call=TRUE;
} else if (real_early_media_sending) {
LinphoneCallParams* callparams = linphone_core_create_default_call_parameters(lc);
LinphoneCallParams* callparams = linphone_core_create_call_params(lc, call);
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);
@ -602,7 +593,7 @@ void linphonec_set_autoanswer(bool_t enabled){
auto_answer=enabled;
}
bool_t linphonec_get_autoanswer(){
bool_t linphonec_get_autoanswer(void){
return auto_answer;
}
@ -714,16 +705,6 @@ linphonec_init(int argc, char **argv)
default:
break;
}
#ifdef ENABLE_NLS
if (NULL == bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR))
perror ("bindtextdomain failed");
#ifndef __ARM__
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
#endif
textdomain (GETTEXT_PACKAGE);
#else
printf ("NLS disabled.\n");
#endif
linphonec_parse_cmdline(argc, argv);
@ -759,9 +740,9 @@ linphonec_init(int argc, char **argv)
linphone_core_set_user_certificates_path(linphonec,usr_certificates_path);
linphone_core_enable_video_capture(linphonec, vcap_enabled);
linphone_core_enable_video_display(linphonec, display_enabled);
if (display_enabled && window_id != 0)
if (display_enabled && (window_id != NULL))
{
printf("Setting window_id: 0x%x\n", window_id);
printf("Setting window_id: 0x%p\n", window_id);
linphone_core_set_native_video_window_id(linphonec,window_id);
}
@ -984,29 +965,30 @@ static void x11_apply_video_params(VideoParams *params, Window window){
#endif
static void lpc_apply_video_params(){
static unsigned long old_wid=0,old_pwid=0;
unsigned long wid=linphone_core_get_native_video_window_id (linphonec);
unsigned long pwid=linphone_core_get_native_preview_window_id (linphonec);
static void lpc_apply_video_params(void){
static void *old_wid=NULL;
static void *old_pwid=NULL;
void *wid=linphone_core_get_native_video_window_id(linphonec);
void *pwid=linphone_core_get_native_preview_window_id(linphonec);
if (wid!=0 && (lpc_video_params.refresh || old_wid!=wid)){
if (wid!=NULL && (lpc_video_params.refresh || old_wid!=wid)){
lpc_video_params.refresh=FALSE;
#ifdef HAVE_X11_XLIB_H
if (lpc_video_params.wid==0){ // do not manage window if embedded
x11_apply_video_params(&lpc_video_params,wid);
x11_apply_video_params(&lpc_video_params,(Window)wid);
} else {
linphone_core_show_video(linphonec, lpc_video_params.show);
}
#endif
}
old_wid=wid;
if (pwid!=0 && (lpc_preview_params.refresh || old_pwid!=pwid)){
if (pwid!=NULL && (lpc_preview_params.refresh || old_pwid!=pwid)){
lpc_preview_params.refresh=FALSE;
#ifdef HAVE_X11_XLIB_H
/*printf("wid=%lu pwid=%lu\n",wid,pwid);*/
if (lpc_preview_params.wid==0){ // do not manage window if embedded
/*printf("wid=%p pwid=%p\n",wid,pwid);*/
if (lpc_preview_params.wid==NULL){ // do not manage window if embedded
printf("Refreshing\n");
x11_apply_video_params(&lpc_preview_params,pwid);
x11_apply_video_params(&lpc_preview_params,(Window)pwid);
}
#endif
}
@ -1303,7 +1285,7 @@ linphonec_parse_cmdline(int argc, char **argv)
arg_num++;
if (arg_num < argc) {
char *tmp;
window_id = strtol( argv[arg_num], &tmp, 0 );
window_id = (void *)strtol( argv[arg_num], &tmp, 0 );
lpc_video_params.wid = window_id;
}
}

View file

@ -99,7 +99,7 @@ typedef struct {
typedef struct {
int x,y,w,h;
unsigned long wid;
void *wid;
bool_t show;
bool_t refresh;
} VideoParams;
@ -116,11 +116,11 @@ extern VideoParams lpc_preview_params;
extern int linphonec_parse_command_line(LinphoneCore *lc, char *cl);
extern char *linphonec_command_generator(const char *text, int state);
void linphonec_main_loop_exit();
void linphonec_main_loop_exit(void);
extern void linphonec_finish(int exit_status);
extern char *linphonec_readline(char *prompt);
void linphonec_set_autoanswer(bool_t enabled);
bool_t linphonec_get_autoanswer();
bool_t linphonec_get_autoanswer(void);
void linphonec_command_finished(void);
void linphonec_set_caller(const char *caller);
LinphoneCall *linphonec_get_call(long id);

View file

@ -20,17 +20,38 @@
#
############################################################################
if(MSVC AND NOT "${CMAKE_SYSTEM_NAME}" STREQUAL "WindowsPhone")
if(MSVC AND NOT CMAKE_SYSTEM_NAME STREQUAL "WindowsPhone")
find_library(LIBGCC NAMES gcc)
find_library(LIBMINGWEX NAMES mingwex)
endif()
if(NOT WIN32)
find_package(Iconv)
find_package(Iconv QUIET)
endif()
set(SOURCE_FILES
set(LINPHONE_HEADER_FILES
account_creator.h
buffer.h
call_log.h
call_params.h
content.h
event.h
linphonecore.h
linphonecore_utils.h
linphonefriend.h
linphonepresence.h
linphone_proxy_config.h
linphone_tunnel.h
lpc2xml.h
lpconfig.h
sipsetup.h
xml2lpc.h
xmlrpc.h
)
set(LINPHONE_SOURCE_FILES_C
account_creator.c
address.c
authentication.c
bellesip_sal/sal_address_impl.c
@ -51,6 +72,7 @@ set(SOURCE_FILES
call_log.c
call_params.c
chat.c
chat_file_transfer.c
conference.c
contactprovider.c
content.c
@ -59,19 +81,15 @@ set(SOURCE_FILES
enum.c
enum.h
event.c
event.h
friend.c
info.c
ldap/ldapprovider.c
lime.c
linphonecall.c
linphonecore.c
linphonecore.h
linphonecore_utils.h
linphonefriend.h
linphone_tunnel_config.c
linphone_tunnel.h
localplayer.c
lpc2xml.c
lpconfig.c
lpconfig.h
lsd.c
@ -88,38 +106,37 @@ set(SOURCE_FILES
sal.c
siplogin.c
sipsetup.c
sipsetup.h
xml2lpc.c
xml2lpc.h
xml.c
xmlrpc.c
vtables.c
)
set(LINPHONE_SOURCE_FILES_CXX )
if(ENABLE_TUNNEL)
list(APPEND SOURCE_FILES
list(APPEND LINPHONE_SOURCE_FILES_CXX
linphone_tunnel.cc
TunnelManager.cc
)
add_definitions(-DTUNNEL_ENABLED)
else()
list(APPEND SOURCE_FILES linphone_tunnel_stubs.c)
endif()
if(ENABLE_ASSISTANT)
list(APPEND SOURCE_FILES sipwizard.c)
list(APPEND LINPHONE_SOURCE_FILES_C linphone_tunnel_stubs.c)
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_custom_target(liblinphone-git-version
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
BYPRODUCTS "${CMAKE_CURRENT_BINARY_DIR}/liblinphone_gitversion.h"
)
add_definitions(
-DUSE_BELLESIP
-DLIBLINPHONE_EXPORTS
)
apply_compile_flags(LINPHONE_SOURCE_FILES_C "CPP" "C")
apply_compile_flags(LINPHONE_SOURCE_FILES_CXX "CPP" "CXX")
set(LIBS
${BELLESIP_LIBRARIES}
${MEDIASTREAMER2_LIBRARIES}
@ -137,21 +154,21 @@ endif()
if(ENABLE_TUNNEL)
list(APPEND LIBS ${TUNNEL_LIBRARIES})
endif()
if(ENABLE_ASSISTANT)
list(APPEND LIBS ${SOUP_LIBRARIES})
endif()
if(MSVC AND NOT "${CMAKE_SYSTEM_NAME}" STREQUAL "WindowsPhone")
if(MSVC AND NOT CMAKE_SYSTEM_NAME STREQUAL "WindowsPhone")
list(APPEND LIBS ${LIBGCC} ${LIBMINGWEX})
endif()
if(WIN32 AND NOT "${CMAKE_SYSTEM_NAME}" STREQUAL "WindowsPhone")
if(WIN32 AND NOT CMAKE_SYSTEM_NAME STREQUAL "WindowsPhone")
list(APPEND LIBS shlwapi)
endif()
if(INTL_FOUND)
list(APPEND LIBS ${INTL_LIBRARIES})
endif()
if(ENABLE_STATIC)
add_library(linphone STATIC ${SOURCE_FILES} ${GENERATED_SOURCE_FILES})
add_library(linphone STATIC ${LINPHONE_HEADER_FILES} ${LINPHONE_SOURCE_FILES_C} ${LINPHONE_SOURCE_FILES_CXX})
target_link_libraries(linphone ${LIBS})
else()
add_library(linphone SHARED ${SOURCE_FILES} ${GENERATED_SOURCE_FILES})
add_library(linphone SHARED ${LINPHONE_HEADER_FILES} ${LINPHONE_SOURCE_FILES_C} ${LINPHONE_SOURCE_FILES_CXX})
set_target_properties(linphone PROPERTIES VERSION ${LINPHONE_SO_VERSION} LINKER_LANGUAGE CXX)
target_link_libraries(linphone ${LIBS})
if(MSVC)
@ -163,7 +180,8 @@ else()
endif()
endif()
endif()
if(WIN32 AND "${CMAKE_SYSTEM_NAME}" STREQUAL "WindowsPhone")
add_dependencies(linphone liblinphone-git-version)
if(WIN32 AND CMAKE_SYSTEM_NAME STREQUAL "WindowsPhone")
set_target_properties(linphone PROPERTIES PREFIX "lib")
endif()
if(ICONV_FOUND)
@ -175,32 +193,14 @@ if(ICONV_FOUND)
endif()
endif()
install(TARGETS linphone EXPORT LinphoneTargets
install(TARGETS linphone EXPORT ${EXPORT_TARGETS_NAME}Targets
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
)
set(HEADER_FILES
buffer.h
call_log.h
call_params.h
content.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}
install(FILES ${LINPHONE_HEADER_FILES}
DESTINATION include/linphone
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
)

View file

@ -25,6 +25,7 @@ CLEANFILES=$(GITVERSION_FILE)
linphone_includedir=$(includedir)/linphone
linphone_include_HEADERS=\
account_creator.h \
buffer.h \
call_log.h \
call_params.h \
@ -34,15 +35,18 @@ linphone_include_HEADERS=\
linphonecore_utils.h \
linphonefriend.h \
linphonepresence.h \
linphone_proxy_config.h \
linphone_tunnel.h \
lpc2xml.h \
lpconfig.h \
sipsetup.h \
xml2lpc.h
xml2lpc.h \
xmlrpc.h
lib_LTLIBRARIES=liblinphone.la
liblinphone_la_SOURCES=\
account_creator.c \
address.c \
authentication.c \
buffer.c \
@ -50,23 +54,23 @@ liblinphone_la_SOURCES=\
call_log.c \
call_params.c \
chat.c \
chat_file_transfer.c \
conference.c \
contactprovider.c contactprovider.h contact_providers_priv.h \
content.c \
dict.c \
ec-calibrator.c \
enum.c enum.h \
event.c event.h \
event.c \
friend.c \
info.c \
ldap/ldapprovider.c ldap/ldapprovider.h \
linphonecall.c \
linphonecore.c linphonecore.h \
linphonecore_utils.h \
linphonecore.c \
localplayer.c \
lpc2xml.c \
lime.c lime.h\
lpconfig.c lpconfig.h \
lpconfig.c \
lsd.c \
message_storage.c \
misc.c \
@ -79,9 +83,10 @@ liblinphone_la_SOURCES=\
remote_provisioning.c \
sal.c \
siplogin.c \
sipsetup.c sipsetup.h \
sipsetup.c \
xml2lpc.c \
xml.c \
xmlrpc.c \
vtables.c \
$(GITVERSION_FILE)
@ -102,10 +107,6 @@ liblinphone_la_SOURCES+= bellesip_sal/sal_address_impl.c \
bellesip_sal/sal_op_info.c \
bellesip_sal/sal_op_events.c
if BUILD_WIZARD
liblinphone_la_SOURCES+=sipwizard.c
endif
liblinphone_la_SOURCES+=linphone_tunnel_config.c
if BUILD_TUNNEL
liblinphone_la_SOURCES+=linphone_tunnel.cc TunnelManager.cc TunnelManager.hh linphone_tunnel.h
@ -137,7 +138,6 @@ liblinphone_la_LIBADD= \
$(ORTP_LIBS) \
$(SIPSTACK_LIBS) \
$(TUNNEL_LIBS) \
$(LIBSOUP_LIBS) \
$(SQLITE3_LIBS) \
$(LIBXML2_LIBS) \
$(LDAP_LIBS) \
@ -145,22 +145,6 @@ liblinphone_la_LIBADD= \
$(ZLIB_LIBS)
if ENABLE_TESTS
noinst_PROGRAMS=test_lsd test_ecc test_numbers
test_lsd_SOURCES=test_lsd.c
test_lsd_LDADD=liblinphone.la $(liblinphone_la_LIBADD)
test_ecc_SOURCES=test_ecc.c
test_ecc_LDADD=liblinphone.la $(liblinphone_la_LIBADD)
test_numbers_SOURCES=test_numbers.c
test_numbers_LDADD=liblinphone.la $(liblinphone_la_LIBADD)
endif
AM_CPPFLAGS=\
-I$(top_srcdir) -I$(top_srcdir)/include -I$(builddir) \
$(ORTP_CFLAGS) \
@ -170,7 +154,6 @@ COMMON_CFLAGS=\
$(STRICT_OPTIONS) \
-DIN_LINPHONE \
$(SIPSTACK_CFLAGS) \
$(LIBSOUP_CFLAGS) \
-DENABLE_TRACE \
-DLOG_DOMAIN=\"LinphoneCore\" \
$(IPV6_CFLAGS) \

View file

@ -56,7 +56,7 @@ namespace belledonnecomm {
* @param ip tunnel server ip address
* @param port tunnel server tls port, recommended value is 443
* @param udpMirrorPort remote port on the tunnel server side used to test udp reachability
* @param delay udp packet round trip delay in ms considered as acceptable. recommanded value is 1000 ms.
* @param delay udp packet round trip delay in ms considered as acceptable. recommended value is 1000 ms.
*/
void addServer(const char *ip, int port,unsigned int udpMirrorPort,unsigned int delay);
/**

449
coreapi/account_creator.c Normal file
View file

@ -0,0 +1,449 @@
/*
linphone
Copyright (C) 2010-2015 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 "account_creator.h"
#include "private.h"
#if !_WIN32
#include "regex.h"
#endif
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneAccountCreatorCbs);
BELLE_SIP_INSTANCIATE_VPTR(LinphoneAccountCreatorCbs, belle_sip_object_t,
NULL, // destroy
NULL, // clone
NULL, // marshal
FALSE
);
static LinphoneAccountCreatorCbs * linphone_account_creator_cbs_new(void) {
return belle_sip_object_new(LinphoneAccountCreatorCbs);
}
LinphoneAccountCreatorCbs * linphone_account_creator_cbs_ref(LinphoneAccountCreatorCbs *cbs) {
belle_sip_object_ref(cbs);
return cbs;
}
void linphone_account_creator_cbs_unref(LinphoneAccountCreatorCbs *cbs) {
belle_sip_object_unref(cbs);
}
void *linphone_account_creator_cbs_get_user_data(const LinphoneAccountCreatorCbs *cbs) {
return cbs->user_data;
}
void linphone_account_creator_cbs_set_user_data(LinphoneAccountCreatorCbs *cbs, void *ud) {
cbs->user_data = ud;
}
LinphoneAccountCreatorCbsExistenceTestedCb linphone_account_creator_cbs_get_existence_tested(const LinphoneAccountCreatorCbs *cbs) {
return cbs->existence_tested;
}
void linphone_account_creator_cbs_set_existence_tested(LinphoneAccountCreatorCbs *cbs, LinphoneAccountCreatorCbsExistenceTestedCb cb) {
cbs->existence_tested = cb;
}
LinphoneAccountCreatorCbsValidationTestedCb linphone_account_creator_cbs_get_validation_tested(const LinphoneAccountCreatorCbs *cbs) {
return cbs->validation_tested;
}
void linphone_account_creator_cbs_set_validation_tested(LinphoneAccountCreatorCbs *cbs, LinphoneAccountCreatorCbsValidationTestedCb cb) {
cbs->validation_tested = cb;
}
LinphoneAccountCreatorCbsCreateAccountCb linphone_account_creator_cbs_get_create_account(const LinphoneAccountCreatorCbs *cbs) {
return cbs->create_account;
}
void linphone_account_creator_cbs_set_create_account(LinphoneAccountCreatorCbs *cbs, LinphoneAccountCreatorCbsCreateAccountCb cb) {
cbs->create_account = cb;
}
static void _linphone_account_creator_destroy(LinphoneAccountCreator *creator) {
linphone_xml_rpc_session_unref(creator->xmlrpc_session);
linphone_account_creator_cbs_unref(creator->callbacks);
if (creator->username) ms_free(creator->username);
if (creator->password) ms_free(creator->password);
if (creator->domain) ms_free(creator->domain);
if (creator->route) ms_free(creator->route);
if (creator->email) ms_free(creator->email);
if (creator->display_name) ms_free(creator->display_name);
}
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneAccountCreator);
BELLE_SIP_INSTANCIATE_VPTR(LinphoneAccountCreator, belle_sip_object_t,
(belle_sip_object_destroy_t)_linphone_account_creator_destroy,
NULL, // clone
NULL, // marshal
FALSE
);
LinphoneAccountCreator * linphone_account_creator_new(LinphoneCore *core, const char *xmlrpc_url) {
LinphoneAccountCreator *creator;
const char* domain = lp_config_get_string(core->config, "assistant", "domain", NULL);
creator = belle_sip_object_new(LinphoneAccountCreator);
creator->callbacks = linphone_account_creator_cbs_new();
creator->core = core;
creator->xmlrpc_session = linphone_xml_rpc_session_new(core, xmlrpc_url);
if (domain) {
linphone_account_creator_set_domain(creator, domain);
}
return creator;
}
LinphoneAccountCreator * linphone_account_creator_ref(LinphoneAccountCreator *creator) {
belle_sip_object_ref(creator);
return creator;
}
void linphone_account_creator_unref(LinphoneAccountCreator *creator) {
belle_sip_object_unref(creator);
}
void *linphone_account_creator_get_user_data(const LinphoneAccountCreator *creator) {
return creator->user_data;
}
void linphone_account_creator_set_user_data(LinphoneAccountCreator *creator, void *ud) {
creator->user_data = ud;
}
static LinphoneAccountCreatorStatus validate_uri(const char* username, const char* domain, const char* route, const char* display_name) {
LinphoneProxyConfig* proxy = linphone_proxy_config_new();
LinphoneAddress* addr;
linphone_proxy_config_set_identity(proxy, "sip:user@domain.com");
if (route && linphone_proxy_config_set_route(proxy, route) != 0) {
linphone_proxy_config_destroy(proxy);
return LinphoneAccountCreatorRouteInvalid;
}
if (username) {
addr = linphone_proxy_config_normalize_sip_uri(proxy, username);
} else {
addr = linphone_address_clone(linphone_proxy_config_get_identity_address(proxy));
}
linphone_proxy_config_destroy(proxy);
if (addr == NULL) {
return LinphoneAccountCreatorUsernameInvalid;
}
if (domain) {
ms_error("TODO: detect invalid domain");
linphone_address_set_domain(addr, domain);
}
if (display_name) {
ms_error("TODO: detect invalid display name");
linphone_address_set_display_name(addr, display_name);
}
linphone_address_unref(addr);
return LinphoneAccountCreatorOK;
}
static bool_t is_matching_regex(const char *entry, const char* regex) {
#if _WIN32
return TRUE;
#else
regex_t regex_pattern;
char err_msg[256];
int res;
res = regcomp(&regex_pattern, regex, REG_EXTENDED | REG_NOSUB);
if(res != 0) {
regerror(res, &regex_pattern, err_msg, sizeof(err_msg));
ms_error("Could not compile regex '%s: %s", regex, err_msg);
return FALSE;
}
res = regexec(&regex_pattern, entry, 0, NULL, 0);
regfree(&regex_pattern);
return (res != REG_NOMATCH);
#endif
}
LinphoneAccountCreatorStatus linphone_account_creator_set_username(LinphoneAccountCreator *creator, const char *username) {
int min_length = lp_config_get_int(creator->core->config, "assistant", "username_min_length", 0);
int fixed_length = lp_config_get_int(creator->core->config, "assistant", "username_length", 0);
bool_t use_phone_number = lp_config_get_int(creator->core->config, "assistant", "use_phone_number", 0);
const char* regex = lp_config_get_string(creator->core->config, "assistant", "username_regex", 0);
LinphoneAccountCreatorStatus status;
if (min_length > 0 && strlen(username) < min_length) {
return LinphoneAccountCreatorUsernameTooShort;
} else if (fixed_length > 0 && strlen(username) != fixed_length) {
return LinphoneAccountCreatorUsernameInvalidSize;
} else if (use_phone_number && !linphone_proxy_config_is_phone_number(NULL, username)) {
return LinphoneAccountCreatorUsernameInvalid;
} else if (regex && !is_matching_regex(username, regex)) {
return LinphoneAccountCreatorUsernameInvalid;
} else if ((status = validate_uri(username, NULL, NULL, NULL)) != LinphoneAccountCreatorOK) {
return status;
}
set_string(&creator->username, username, TRUE);
return LinphoneAccountCreatorOK;
}
const char * linphone_account_creator_get_username(const LinphoneAccountCreator *creator) {
return creator->username;
}
LinphoneAccountCreatorStatus linphone_account_creator_set_password(LinphoneAccountCreator *creator, const char *password){
int min_length = lp_config_get_int(creator->core->config, "assistant", "password_min_length", 0);
if (min_length > 0 && strlen(password) < min_length) {
return LinphoneAccountCreatorPasswordTooShort;
}
set_string(&creator->password, password, FALSE);
return LinphoneAccountCreatorOK;
}
const char * linphone_account_creator_get_password(const LinphoneAccountCreator *creator) {
return creator->password;
}
LinphoneAccountCreatorStatus linphone_account_creator_set_transport(LinphoneAccountCreator *creator, LinphoneTransportType transport){
if (!linphone_core_sip_transport_supported(creator->core, transport)) {
return LinphoneAccountCreatorTransportNotSupported;
}
creator->transport = transport;
return LinphoneAccountCreatorOK;
}
LinphoneTransportType linphone_account_creator_get_transport(const LinphoneAccountCreator *creator) {
return creator->transport;
}
LinphoneAccountCreatorStatus linphone_account_creator_set_domain(LinphoneAccountCreator *creator, const char *domain){
if (validate_uri(NULL, domain, NULL, NULL) != 0) {
return LinphoneAccountCreatorDomainInvalid;
}
set_string(&creator->domain, domain, TRUE);
return LinphoneAccountCreatorOK;
}
const char * linphone_account_creator_get_domain(const LinphoneAccountCreator *creator) {
return creator->domain;
}
LinphoneAccountCreatorStatus linphone_account_creator_set_route(LinphoneAccountCreator *creator, const char *route) {
if (validate_uri(NULL, NULL, route, NULL) != 0) {
return LinphoneAccountCreatorRouteInvalid;
}
set_string(&creator->route, route, TRUE);
return LinphoneAccountCreatorOK;
}
const char * linphone_account_creator_get_route(const LinphoneAccountCreator *creator) {
return creator->route;
}
LinphoneAccountCreatorStatus linphone_account_creator_set_display_name(LinphoneAccountCreator *creator, const char *display_name) {
if (validate_uri(NULL, NULL, NULL, display_name) != 0) {
return LinphoneAccountCreatorDisplayNameInvalid;
}
set_string(&creator->display_name, display_name, FALSE);
return LinphoneAccountCreatorOK;
}
const char * linphone_account_creator_get_display_name(const LinphoneAccountCreator *creator) {
return creator->display_name;
}
LinphoneAccountCreatorStatus linphone_account_creator_set_email(LinphoneAccountCreator *creator, const char *email) {
if (!is_matching_regex(email, "^.+@.+\\.[A-Za-z]{2}[A-Za-z]*$")) {
return LinphoneAccountCreatorEmailInvalid;
}
set_string(&creator->email, email, TRUE);
return LinphoneAccountCreatorOK;
}
const char * linphone_account_creator_get_email(const LinphoneAccountCreator *creator) {
return creator->email;
}
void linphone_account_creator_enable_newsletter_subscription(LinphoneAccountCreator *creator, bool_t subscribe) {
creator->subscribe_to_newsletter = subscribe;
}
bool_t linphone_account_creator_newsletter_subscription_enabled(const LinphoneAccountCreator *creator) {
return creator->subscribe_to_newsletter;
}
LinphoneAccountCreatorCbs * linphone_account_creator_get_callbacks(const LinphoneAccountCreator *creator) {
return creator->callbacks;
}
static void _test_existence_cb(LinphoneXmlRpcRequest *request) {
LinphoneAccountCreator *creator = (LinphoneAccountCreator *)linphone_xml_rpc_request_get_user_data(request);
if (creator->callbacks->existence_tested != NULL) {
LinphoneAccountCreatorStatus status = LinphoneAccountCreatorReqFailed;
if (linphone_xml_rpc_request_get_status(request) == LinphoneXmlRpcStatusOk) {
int resp = linphone_xml_rpc_request_get_int_response(request);
status = (resp == 0) ? LinphoneAccountCreatorAccountNotExist : LinphoneAccountCreatorAccountExist;
}
creator->callbacks->existence_tested(creator, status);
}
}
LinphoneAccountCreatorStatus linphone_account_creator_test_existence(LinphoneAccountCreator *creator) {
LinphoneXmlRpcRequest *request;
char *identity;
if (!creator->username || !creator->domain) {
if (creator->callbacks->existence_tested != NULL) {
creator->callbacks->existence_tested(creator, LinphoneAccountCreatorReqFailed);
}
return LinphoneAccountCreatorReqFailed;
}
identity = ms_strdup_printf("%s@%s", creator->username, creator->domain);
request = linphone_xml_rpc_request_new_with_args("check_account", LinphoneXmlRpcArgInt,
LinphoneXmlRpcArgString, identity,
LinphoneXmlRpcArgNone);
linphone_xml_rpc_request_set_user_data(request, creator);
linphone_xml_rpc_request_cbs_set_response(linphone_xml_rpc_request_get_callbacks(request), _test_existence_cb);
linphone_xml_rpc_session_send_request(creator->xmlrpc_session, request);
linphone_xml_rpc_request_unref(request);
ms_free(identity);
return LinphoneAccountCreatorOK;
}
static void _test_validation_cb(LinphoneXmlRpcRequest *request) {
LinphoneAccountCreator *creator = (LinphoneAccountCreator *)linphone_xml_rpc_request_get_user_data(request);
if (creator->callbacks->validation_tested != NULL) {
LinphoneAccountCreatorStatus status = LinphoneAccountCreatorReqFailed;
if (linphone_xml_rpc_request_get_status(request) == LinphoneXmlRpcStatusOk) {
int resp = linphone_xml_rpc_request_get_int_response(request);
status = (resp == 0) ? LinphoneAccountCreatorAccountNotValidated : LinphoneAccountCreatorAccountValidated;
}
creator->callbacks->validation_tested(creator, status);
}
}
LinphoneAccountCreatorStatus linphone_account_creator_test_validation(LinphoneAccountCreator *creator) {
LinphoneXmlRpcRequest *request;
char *identity;
if (!creator->username || !creator->domain) {
if (creator->callbacks->validation_tested != NULL) {
creator->callbacks->validation_tested(creator, LinphoneAccountCreatorReqFailed);
}
return LinphoneAccountCreatorReqFailed;
}
identity = ms_strdup_printf("%s@%s", creator->username, creator->domain);
request = linphone_xml_rpc_request_new_with_args("check_account_validated", LinphoneXmlRpcArgInt,
LinphoneXmlRpcArgString, identity,
LinphoneXmlRpcArgNone);
linphone_xml_rpc_request_set_user_data(request, creator);
linphone_xml_rpc_request_cbs_set_response(linphone_xml_rpc_request_get_callbacks(request), _test_validation_cb);
linphone_xml_rpc_session_send_request(creator->xmlrpc_session, request);
linphone_xml_rpc_request_unref(request);
ms_free(identity);
return LinphoneAccountCreatorOK;
}
static void _create_account_cb(LinphoneXmlRpcRequest *request) {
LinphoneAccountCreator *creator = (LinphoneAccountCreator *)linphone_xml_rpc_request_get_user_data(request);
if (creator->callbacks->create_account != NULL) {
LinphoneAccountCreatorStatus status = LinphoneAccountCreatorReqFailed;
if (linphone_xml_rpc_request_get_status(request) == LinphoneXmlRpcStatusOk) {
int resp = linphone_xml_rpc_request_get_int_response(request);
status = (resp == 0) ? LinphoneAccountCreatorAccountCreated : LinphoneAccountCreatorAccountNotCreated;
}
creator->callbacks->create_account(creator, status);
}
}
LinphoneAccountCreatorStatus linphone_account_creator_create_account(LinphoneAccountCreator *creator) {
LinphoneXmlRpcRequest *request;
char *identity;
if (!creator->username || !creator->domain || !creator->email) {
if (creator->callbacks->create_account != NULL) {
creator->callbacks->create_account(creator, LinphoneAccountCreatorReqFailed);
}
return LinphoneAccountCreatorReqFailed;
}
identity = ms_strdup_printf("%s@%s", creator->username, creator->domain);
request = linphone_xml_rpc_request_new_with_args("create_account", LinphoneXmlRpcArgInt,
LinphoneXmlRpcArgString, identity,
LinphoneXmlRpcArgString, creator->password,
LinphoneXmlRpcArgString, creator->email,
LinphoneXmlRpcArgInt, (creator->subscribe_to_newsletter == TRUE) ? 1 : 0,
LinphoneXmlRpcArgNone);
linphone_xml_rpc_request_set_user_data(request, creator);
linphone_xml_rpc_request_cbs_set_response(linphone_xml_rpc_request_get_callbacks(request), _create_account_cb);
linphone_xml_rpc_session_send_request(creator->xmlrpc_session, request);
linphone_xml_rpc_request_unref(request);
ms_free(identity);
return LinphoneAccountCreatorOK;
}
LinphoneProxyConfig * linphone_account_creator_configure(const LinphoneAccountCreator *creator) {
LinphoneAuthInfo *info;
LinphoneProxyConfig *cfg = linphone_core_create_proxy_config(creator->core);
char *identity_str = ms_strdup_printf("sip:%s@%s", creator->username, creator->domain);
LinphoneAddress *identity = linphone_address_new(identity_str);
if (creator->display_name) {
linphone_address_set_display_name(identity, creator->display_name);
}
linphone_proxy_config_set_identity(cfg, linphone_address_as_string(identity));
linphone_proxy_config_set_server_addr(cfg, creator->domain);
linphone_proxy_config_set_route(cfg, creator->route);
linphone_proxy_config_enable_publish(cfg, FALSE);
linphone_proxy_config_enable_register(cfg, TRUE);
ms_free(identity_str);
if (strcmp(creator->domain, "sip.linphone.org") == 0) {
linphone_proxy_config_enable_avpf(cfg, TRUE);
// If account created on sip.linphone.org, we configure linphone to use TLS by default
if (linphone_core_sip_transport_supported(creator->core, LinphoneTransportTls)) {
LinphoneAddress *addr = linphone_address_new(linphone_proxy_config_get_server_addr(cfg));
char *tmp;
linphone_address_set_transport(addr, LinphoneTransportTls);
tmp = linphone_address_as_string(addr);
linphone_proxy_config_set_server_addr(cfg, tmp);
linphone_proxy_config_set_route(cfg, tmp);
ms_free(tmp);
linphone_address_destroy(addr);
}
linphone_core_set_stun_server(creator->core, "stun.linphone.org");
linphone_core_set_firewall_policy(creator->core, LinphonePolicyUseIce);
}
info = linphone_auth_info_new(linphone_address_get_username(identity), NULL, creator->password, NULL, NULL, linphone_address_get_domain(identity));
linphone_core_add_auth_info(creator->core, info);
linphone_address_destroy(identity);
if (linphone_core_add_proxy_config(creator->core, cfg) != -1) {
linphone_core_set_default_proxy(creator->core, cfg);
return cfg;
}
linphone_core_remove_auth_info(creator->core, info);
linphone_proxy_config_unref(cfg);
return NULL;
}

361
coreapi/account_creator.h Normal file
View file

@ -0,0 +1,361 @@
/*
account_creator.h
Copyright (C) 2010-2015 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_ACCOUNT_CREATOR_H_
#define LINPHONE_ACCOUNT_CREATOR_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "linphonecore.h"
/**
* @addtogroup misc
* @{
*/
/**
* Enum describing the status of a LinphoneAccountCreator operation.
**/
typedef enum _LinphoneAccountCreatorStatus {
LinphoneAccountCreatorOK,
LinphoneAccountCreatorReqFailed,
LinphoneAccountCreatorAccountCreated,
LinphoneAccountCreatorAccountNotCreated,
LinphoneAccountCreatorAccountExist,
LinphoneAccountCreatorAccountNotExist,
LinphoneAccountCreatorAccountValidated,
LinphoneAccountCreatorAccountNotValidated,
LinphoneAccountCreatorEmailInvalid,
LinphoneAccountCreatorUsernameInvalid,
LinphoneAccountCreatorUsernameTooShort,
LinphoneAccountCreatorUsernameInvalidSize,
LinphoneAccountCreatorPasswordTooShort,
LinphoneAccountCreatorDomainInvalid,
LinphoneAccountCreatorRouteInvalid,
LinphoneAccountCreatorDisplayNameInvalid,
LinphoneAccountCreatorTransportNotSupported,
} LinphoneAccountCreatorStatus;
/**
* The LinphoneAccountCreator object used to create an account on a server via XML-RPC.
**/
typedef struct _LinphoneAccountCreator LinphoneAccountCreator;
/**
* An object to handle the callbacks for handling the LinphoneAccountCreator operations.
**/
typedef struct _LinphoneAccountCreatorCbs LinphoneAccountCreatorCbs;
/**
* Callback used to notify the end of a LinphoneAccountCreator test existence operation.
* @param[in] creator LinphoneAccountCreator object
* @param[in] status The status of the LinphoneAccountCreator test existence operation that has just finished
**/
typedef void (*LinphoneAccountCreatorCbsExistenceTestedCb)(LinphoneAccountCreator *creator, LinphoneAccountCreatorStatus status);
/**
* Callback used to notify the end of a LinphoneAccountCreator test validation operation.
* @param[in] creator LinphoneAccountCreator object
* @param[in] status The status of the LinphoneAccountCreator test validation operation that has just finished
**/
typedef void (*LinphoneAccountCreatorCbsValidationTestedCb)(LinphoneAccountCreator *creator, LinphoneAccountCreatorStatus status);
/**
* Callback used to notify the end of a LinphoneAccountCreator validate operation.
* @param[in] creator LinphoneAccountCreator object
* @param[in] status The status of the LinphoneAccountCreator validate operation that has just finished
**/
typedef void (*LinphoneAccountCreatorCbsCreateAccountCb)(LinphoneAccountCreator *creator, LinphoneAccountCreatorStatus status);
/**
* Create a LinphoneAccountCreator.
* @param[in] core The LinphoneCore used for the XML-RPC communication
* @param[in] xmlrpc_url The URL to the XML-RPC server. Must be NON NULL.
* @return The new LinphoneAccountCreator object
**/
LINPHONE_PUBLIC LinphoneAccountCreator * linphone_account_creator_new(LinphoneCore *core, const char *xmlrpc_url);
/**
* Acquire a reference to the LinphoneAccountCreator.
* @param[in] creator LinphoneAccountCreator object.
* @return The same LinphoneAccountCreator object.
**/
LINPHONE_PUBLIC LinphoneAccountCreator * linphone_account_creator_ref(LinphoneAccountCreator *creator);
/**
* Release reference to the LinphoneAccountCreator.
* @param[in] creator LinphoneAccountCreator object.
**/
LINPHONE_PUBLIC void linphone_account_creator_unref(LinphoneAccountCreator *creator);
/**
* Retrieve the user pointer associated with the LinphoneAccountCreator.
* @param[in] creator LinphoneAccountCreator object.
* @return The user pointer associated with the LinphoneAccountCreator.
**/
LINPHONE_PUBLIC void *linphone_account_creator_get_user_data(const LinphoneAccountCreator *creator);
/**
* Assign a user pointer to the LinphoneAccountCreator.
* @param[in] creator LinphoneAccountCreator object.
* @param[in] ud The user pointer to associate with the LinphoneAccountCreator.
**/
LINPHONE_PUBLIC void linphone_account_creator_set_user_data(LinphoneAccountCreator *creator, void *ud);
/**
* Set the username.
* @param[in] creator LinphoneAccountCreator object
* @param[in] username The username to set
* @return LinphoneAccountCreatorOk if everything is OK, or a specific error otherwise.
**/
LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_set_username(LinphoneAccountCreator *creator, const char *username);
/**
* Get the username.
* @param[in] creator LinphoneAccountCreator object
* @return The username of the LinphoneAccountCreator
**/
LINPHONE_PUBLIC const char * linphone_account_creator_get_username(const LinphoneAccountCreator *creator);
/**
* Set the password.
* @param[in] creator LinphoneAccountCreator object
* @param[in] password The password to set
* @return LinphoneAccountCreatorOk if everything is OK, or a specific error otherwise.
**/
LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_set_password(LinphoneAccountCreator *creator, const char *password);
/**
* Get the password.
* @param[in] creator LinphoneAccountCreator object
* @return The password of the LinphoneAccountCreator
**/
LINPHONE_PUBLIC const char * linphone_account_creator_get_password(const LinphoneAccountCreator *creator);
/**
* Set the transport.
* @param[in] creator LinphoneAccountCreator object
* @param[in] transport The transport to set
* @return LinphoneAccountCreatorOk if everything is OK, or a specific error if given transport is not supported by linphone core.
**/
LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_set_transport(LinphoneAccountCreator *creator, LinphoneTransportType transport);
/**
* Get the transport.
* @param[in] creator LinphoneAccountCreator object
* @return The transport of the LinphoneAccountCreator
**/
LINPHONE_PUBLIC LinphoneTransportType linphone_account_creator_get_transport(const LinphoneAccountCreator *creator);
/**
* Set the domain.
* @param[in] creator LinphoneAccountCreator object
* @param[in] domain The domain to set
* @return LinphoneAccountCreatorOk if everything is OK, or a specific error otherwise.
**/
LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_set_domain(LinphoneAccountCreator *creator, const char *domain);
/**
* Get the domain.
* @param[in] creator LinphoneAccountCreator object
* @return The domain of the LinphoneAccountCreator
**/
LINPHONE_PUBLIC const char * linphone_account_creator_get_domain(const LinphoneAccountCreator *creator);
/**
* Set the route.
* @param[in] creator LinphoneAccountCreator object
* @param[in] route The route to set
* @return LinphoneAccountCreatorOk if everything is OK, or a specific error otherwise.
**/
LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_set_route(LinphoneAccountCreator *creator, const char *route);
/**
* Get the route.
* @param[in] creator LinphoneAccountCreator object
* @return The route of the LinphoneAccountCreator
**/
LINPHONE_PUBLIC const char * linphone_account_creator_get_route(const LinphoneAccountCreator *creator);
/**
* Set the email.
* @param[in] creator LinphoneAccountCreator object
* @param[in] display_name The display name to set
* @return LinphoneAccountCreatorOk if everything is OK, or a specific error otherwise.
**/
LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_set_display_name(LinphoneAccountCreator *creator, const char *display_name);
/**
* Get the email.
* @param[in] creator LinphoneAccountCreator object
* @return The display name of the LinphoneAccountCreator
**/
LINPHONE_PUBLIC const char * linphone_account_creator_get_display_name(const LinphoneAccountCreator *creator);
/**
* Set the email.
* @param[in] creator LinphoneAccountCreator object
* @param[in] email The email to set
* @return LinphoneAccountCreatorOk if everything is OK, or a specific error otherwise.
**/
LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_set_email(LinphoneAccountCreator *creator, const char *email);
/**
* Get the email.
* @param[in] creator LinphoneAccountCreator object
* @return The email of the LinphoneAccountCreator
**/
LINPHONE_PUBLIC const char * linphone_account_creator_get_email(const LinphoneAccountCreator *creator);
/**
* Enable the newsletter subscription.
* @param[in] creator LinphoneAccountCreator object
* @param[in] subscribe A boolean telling whether to subscribe to the newsletter or not.
**/
LINPHONE_PUBLIC void linphone_account_creator_enable_newsletter_subscription(LinphoneAccountCreator *creator, bool_t subscribe);
/**
* Tell whether to subscribe to the newsletter or not.
* @param[in] creator LinphoneAccountCreator object
* @return A boolean telling whether to subscribe to the newsletter or not.
**/
LINPHONE_PUBLIC bool_t linphone_account_creator_newsletter_subscription_enabled(const LinphoneAccountCreator *creator);
/**
* Get the LinphoneAccountCreatorCbs object associated with a LinphoneAccountCreator.
* @param[in] creator LinphoneAccountCreator object
* @return The LinphoneAccountCreatorCbs object associated with the LinphoneAccountCreator.
**/
LINPHONE_PUBLIC LinphoneAccountCreatorCbs * linphone_account_creator_get_callbacks(const LinphoneAccountCreator *creator);
/**
* Send an XML-RPC request to test the existence of a Linphone account.
* @param[in] creator LinphoneAccountCreator object
* @return LinphoneAccountCreatorOk if the request has been sent, LinphoneAccountCreatorReqFailed otherwise
**/
LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_test_existence(LinphoneAccountCreator *creator);
/**
* Send an XML-RPC request to test the validation of a Linphone account.
* @param[in] creator LinphoneAccountCreator object
* @return LinphoneAccountCreatorOk if the request has been sent, LinphoneAccountCreatorReqFailed otherwise
**/
LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_test_validation(LinphoneAccountCreator *creator);
/**
* Send an XML-RPC request to create a Linphone account.
* @param[in] creator LinphoneAccountCreator object
* @return LinphoneAccountCreatorOk if the request has been sent, LinphoneAccountCreatorReqFailed otherwise
**/
LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_create_account(LinphoneAccountCreator *creator);
/**
* Configure an account (create a proxy config and authentication info for it).
* @param[in] creator LinphoneAccountCreator object
* @return A LinphoneProxyConfig object if successful, NULL otherwise
**/
LINPHONE_PUBLIC LinphoneProxyConfig * linphone_account_creator_configure(const LinphoneAccountCreator *creator);
/**
* Acquire a reference to a LinphoneAccountCreatorCbs object.
* @param[in] cbs LinphoneAccountCreatorCbs object.
* @return The same LinphoneAccountCreatorCbs object.
**/
LINPHONE_PUBLIC LinphoneAccountCreatorCbs * linphone_account_creator_cbs_ref(LinphoneAccountCreatorCbs *cbs);
/**
* Release a reference to a LinphoneAccountCreatorCbs object.
* @param[in] cbs LinphoneAccountCreatorCbs object.
**/
LINPHONE_PUBLIC void linphone_account_creator_cbs_unref(LinphoneAccountCreatorCbs *cbs);
/**
* Retrieve the user pointer associated with a LinphoneAccountCreatorCbs object.
* @param[in] cbs LinphoneAccountCreatorCbs object.
* @return The user pointer associated with the LinphoneAccountCreatorCbs object.
**/
LINPHONE_PUBLIC void *linphone_account_creator_cbs_get_user_data(const LinphoneAccountCreatorCbs *cbs);
/**
* Assign a user pointer to a LinphoneAccountCreatorCbs object.
* @param[in] cbs LinphoneAccountCreatorCbs object.
* @param[in] ud The user pointer to associate with the LinphoneAccountCreatorCbs object.
**/
LINPHONE_PUBLIC void linphone_account_creator_cbs_set_user_data(LinphoneAccountCreatorCbs *cbs, void *ud);
/**
* Get the existence tested callback.
* @param[in] cbs LinphoneAccountCreatorCbs object.
* @return The current existence tested callback.
**/
LINPHONE_PUBLIC LinphoneAccountCreatorCbsExistenceTestedCb linphone_account_creator_cbs_get_existence_tested(const LinphoneAccountCreatorCbs *cbs);
/**
* Set the existence tested callback.
* @param[in] cbs LinphoneAccountCreatorCbs object.
* @param[in] cb The existence tested callback to be used.
**/
LINPHONE_PUBLIC void linphone_account_creator_cbs_set_existence_tested(LinphoneAccountCreatorCbs *cbs, LinphoneAccountCreatorCbsExistenceTestedCb cb);
/**
* Get the validation tested callback.
* @param[in] cbs LinphoneAccountCreatorCbs object.
* @return The current validation tested callback.
**/
LINPHONE_PUBLIC LinphoneAccountCreatorCbsValidationTestedCb linphone_account_creator_cbs_get_validation_tested(const LinphoneAccountCreatorCbs *cbs);
/**
* Set the validation tested callback.
* @param[in] cbs LinphoneAccountCreatorCbs object.
* @param[in] cb The validation tested callback to be used.
**/
LINPHONE_PUBLIC void linphone_account_creator_cbs_set_validation_tested(LinphoneAccountCreatorCbs *cbs, LinphoneAccountCreatorCbsValidationTestedCb cb);
/**
* Get the create account callback.
* @param[in] cbs LinphoneAccountCreatorCbs object.
* @return The current create account callback.
**/
LINPHONE_PUBLIC LinphoneAccountCreatorCbsCreateAccountCb linphone_account_creator_cbs_get_create_account(const LinphoneAccountCreatorCbs *cbs);
/**
* Set the create account callback.
* @param[in] cbs LinphoneAccountCreatorCbs object.
* @param[in] cb The create account callback to be used.
**/
LINPHONE_PUBLIC void linphone_account_creator_cbs_set_create_account(LinphoneAccountCreatorCbs *cbs, LinphoneAccountCreatorCbsCreateAccountCb cb);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* LINPHONE_ACCOUNT_CREATOR_H_ */

View file

@ -141,13 +141,16 @@ void linphone_auth_info_destroy(LinphoneAuthInfo *obj){
void linphone_auth_info_write_config(LpConfig *config, LinphoneAuthInfo *obj, int pos)
{
char key[50];
bool_t store_ha1_passwd = lp_config_get_int(config, "sip", "store_ha1_passwd", 1);
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;
}
if (!obj->ha1 && obj->realm && obj->passwd && (obj->username||obj->userid) && lp_config_get_int(config, "sip", "store_ha1_passwd", 1) == 1) {
if (!obj->ha1 && obj->realm && obj->passwd && (obj->username||obj->userid) && store_ha1_passwd) {
/*compute ha1 to avoid storing clear text password*/
obj->ha1=ms_malloc(33);
sal_auth_compute_ha1(obj->userid?obj->userid:obj->username,obj->realm,obj->passwd,obj->ha1);
@ -160,8 +163,17 @@ void linphone_auth_info_write_config(LpConfig *config, LinphoneAuthInfo *obj, in
}
if (obj->ha1!=NULL){
lp_config_set_string(config,key,"ha1",obj->ha1);
} else if (obj->passwd!=NULL){ /*only write passwd if no ha1*/
lp_config_set_string(config,key,"passwd",obj->passwd);
}
if (obj->passwd != NULL){
if (store_ha1_passwd){
if (obj->ha1){
/*if we have our ha1 and store_ha1_passwd set to TRUE, then drop the clear text password for security*/
linphone_auth_info_set_passwd(obj, NULL);
}
}else{
/*we store clear text password only if store_ha1_passwd is FALSE*/
lp_config_set_string(config,key,"passwd",obj->passwd);
}
}
if (obj->realm!=NULL){
lp_config_set_string(config,key,"realm",obj->realm);
@ -218,7 +230,7 @@ static bool_t realm_match(const char *realm1, const char *realm2){
return FALSE;
}
static const LinphoneAuthInfo *find_auth_info(LinphoneCore *lc, const char *username, const char *realm, const char *domain){
static const LinphoneAuthInfo *find_auth_info(LinphoneCore *lc, const char *username, const char *realm, const char *domain, bool_t ignore_realm){
MSList *elem;
const LinphoneAuthInfo *ret=NULL;
@ -238,9 +250,9 @@ static const LinphoneAuthInfo *find_auth_info(LinphoneCore *lc, const char *user
}
ret=pinfo;
}
} else if (domain && pinfo->domain && strcmp(domain,pinfo->domain)==0 && pinfo->ha1==NULL) {
} else if (domain && pinfo->domain && strcmp(domain,pinfo->domain)==0 && (pinfo->ha1==NULL || ignore_realm)) {
return pinfo;
} else if (!domain && pinfo->ha1==NULL) {
} else if (!domain && (pinfo->ha1==NULL || ignore_realm)) {
return pinfo;
}
}
@ -248,38 +260,49 @@ static const LinphoneAuthInfo *find_auth_info(LinphoneCore *lc, const char *user
return ret;
}
/**
* 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)
* @param username the SIP username to be authenticated (mandatory)
* @param domain the SIP domain name (optional)
* @return a #LinphoneAuthInfo
**/
const LinphoneAuthInfo *linphone_core_find_auth_info(LinphoneCore *lc, const char *realm, const char *username, const char *domain){
const LinphoneAuthInfo *_linphone_core_find_auth_info(LinphoneCore *lc, const char *realm, const char *username, const char *domain, bool_t ignore_realm){
const LinphoneAuthInfo *ai=NULL;
if (realm){
ai=find_auth_info(lc,username,realm,NULL);
ai=find_auth_info(lc,username,realm,NULL, FALSE);
if (ai==NULL && domain){
ai=find_auth_info(lc,username,realm,domain);
ai=find_auth_info(lc,username,realm,domain, FALSE);
}
}
if (ai == NULL && domain != NULL) {
ai=find_auth_info(lc,username,NULL,domain);
ai=find_auth_info(lc,username,NULL,domain, ignore_realm);
}
if (ai==NULL){
ai=find_auth_info(lc,username,NULL,NULL);
ai=find_auth_info(lc,username,NULL,NULL, ignore_realm);
}
/*if (ai) ms_message("linphone_core_find_auth_info(): returning auth info username=%s, realm=%s", ai->username, ai->realm);*/
if (ai) ms_message("linphone_core_find_auth_info(): returning auth info username=%s, realm=%s", ai->username ? ai->username : "", ai->realm ? ai->realm : "");
return ai;
}
const LinphoneAuthInfo *linphone_core_find_auth_info(LinphoneCore *lc, const char *realm, const char *username, const char *domain){
return _linphone_core_find_auth_info(lc, realm, username, domain, TRUE);
}
/*the auth info is expected to be in the core's list*/
void linphone_core_write_auth_info(LinphoneCore *lc, LinphoneAuthInfo *ai){
int i;
MSList *elem = lc->auth_info;
if (!lc->sip_conf.save_auth_info) return;
for (i=0; elem != NULL; elem = elem->next, i++){
if (ai == elem->data){
linphone_auth_info_write_config(lc->config, ai, i);
}
}
}
static void write_auth_infos(LinphoneCore *lc){
MSList *elem;
int i;
if (!linphone_core_ready(lc)) return;
if (!lc->sip_conf.save_auth_info) return;
for(elem=lc->auth_info,i=0;elem!=NULL;elem=ms_list_next(elem),i++){
LinphoneAuthInfo *ai=(LinphoneAuthInfo*)(elem->data);
linphone_auth_info_write_config(lc->config,ai,i);
@ -321,7 +344,7 @@ void linphone_core_add_auth_info(LinphoneCore *lc, const LinphoneAuthInfo *info)
SalOp *op=(SalOp*)elem->data;
LinphoneAuthInfo *ai;
const SalAuthInfo *req_sai=sal_op_get_auth_requested(op);
ai=(LinphoneAuthInfo*)linphone_core_find_auth_info(lc,req_sai->realm,req_sai->username,req_sai->domain);
ai=(LinphoneAuthInfo*)_linphone_core_find_auth_info(lc,req_sai->realm,req_sai->username,req_sai->domain, FALSE);
if (ai){
SalAuthInfo sai;
MSList* proxy;
@ -353,7 +376,7 @@ void linphone_core_add_auth_info(LinphoneCore *lc, const LinphoneAuthInfo *info)
info->domain ? info->domain : "");
}
ms_list_free(l);
if(lc->sip_conf.save_auth_info) write_auth_infos(lc);
write_auth_infos(lc);
}
@ -373,7 +396,7 @@ void linphone_core_remove_auth_info(LinphoneCore *lc, const LinphoneAuthInfo *in
if (r){
lc->auth_info=ms_list_remove(lc->auth_info,r);
linphone_auth_info_destroy(r);
if(lc->sip_conf.save_auth_info) write_auth_infos(lc);
write_auth_infos(lc);
}
}

View file

@ -87,12 +87,31 @@ void _belle_sip_log(belle_sip_log_level lev, const char *fmt, va_list args) {
}
}
void sal_enable_logs(){
belle_sip_set_log_level(BELLE_SIP_LOG_MESSAGE);
void sal_enable_log(){
sal_set_log_level(ORTP_MESSAGE);
}
void sal_disable_logs() {
belle_sip_set_log_level(BELLE_SIP_LOG_ERROR);
void sal_disable_log() {
sal_set_log_level(ORTP_ERROR);
}
void sal_set_log_level(OrtpLogLevel level) {
belle_sip_log_level belle_sip_level;
if ((level&ORTP_FATAL) != 0) {
belle_sip_level = BELLE_SIP_LOG_FATAL;
} else if ((level&ORTP_ERROR) != 0) {
belle_sip_level = BELLE_SIP_LOG_ERROR;
} else if ((level&ORTP_WARNING) != 0) {
belle_sip_level = BELLE_SIP_LOG_WARNING;
} else if ((level&ORTP_MESSAGE) != 0) {
belle_sip_level = BELLE_SIP_LOG_MESSAGE;
} else if (((level&ORTP_DEBUG) != 0) || ((level&ORTP_TRACE) != 0)) {
belle_sip_level = BELLE_SIP_LOG_DEBUG;
} else {
//well, this should never occurs but...
belle_sip_level = BELLE_SIP_LOG_MESSAGE;
}
belle_sip_set_log_level(belle_sip_level);
}
void sal_add_pending_auth(Sal *sal, SalOp *op){
@ -221,6 +240,14 @@ static void process_request_event(void *ud, const belle_sip_request_event_t *eve
return;
}
}else if (strcmp("INVITE",method)==0) {
/*handle the case where we are receiving a request with to tag but it is not belonging to any dialog*/
belle_sip_header_to_t *to = belle_sip_message_get_header_by_type(req, belle_sip_header_to_t);
if (belle_sip_header_to_get_tag(to) != NULL){
ms_warning("Receiving INVITE with to-tag but no know dialog here. Rejecting.");
resp=belle_sip_response_create_from_request(req,481);
belle_sip_provider_send_response(sal->prov,resp);
return;
}
op=sal_op_new(sal);
op->dir=SalOpDirIncoming;
sal_op_call_fill_cbs(op);
@ -471,6 +498,7 @@ Sal * sal_init(){
sal->tls_verify_cn=TRUE;
sal->refresher_retry_after=60000; /*default value in ms*/
sal->enable_sip_update=TRUE;
sal->pending_trans_checking=TRUE;
return sal;
}
@ -482,7 +510,7 @@ void *sal_get_user_pointer(const Sal *sal){
return sal->up;
}
static void unimplemented_stub(){
static void unimplemented_stub(void){
ms_warning("Unimplemented SAL callback");
}
@ -594,7 +622,9 @@ static int sal_add_listen_port(Sal *ctx, SalAddress* addr, bool_t is_tunneled){
if (lp) {
belle_sip_listening_point_set_keep_alive(lp,ctx->keep_alive);
result = belle_sip_provider_add_listening_point(ctx->prov,lp);
if (sal_address_get_transport(addr)==SalTransportTLS) set_tls_properties(ctx);
if (sal_address_get_transport(addr)==SalTransportTLS) {
set_tls_properties(ctx);
}
} else {
return -1;
}
@ -749,9 +779,6 @@ MSList * sal_get_pending_auths(Sal *sal){
return ms_list_copy(sal->pending_auths);
}
#define payload_type_set_number(pt,n) (pt)->user_data=(void*)((long)n);
#define payload_type_get_number(pt) ((int)(long)(pt)->user_data)
/*misc*/
void sal_get_default_local_ip(Sal *sal, int address_family, char *ip, size_t iplen){
strncpy(ip,address_family==AF_INET6 ? "::1" : "127.0.0.1",iplen);
@ -897,6 +924,40 @@ const SalCustomHeader *sal_op_get_recv_custom_header(SalOp *op){
return b->recv_custom_headers;
}
SalCustomSdpAttribute * sal_custom_sdp_attribute_append(SalCustomSdpAttribute *csa, const char *name, const char *value) {
belle_sdp_session_description_t *desc = (belle_sdp_session_description_t *)csa;
belle_sdp_attribute_t *attr;
if (desc == NULL) {
desc = (belle_sdp_session_description_t *)belle_sdp_session_description_new();
belle_sip_object_ref(desc);
}
attr = BELLE_SDP_ATTRIBUTE(belle_sdp_raw_attribute_create(name, value));
if (attr == NULL) {
belle_sip_error("Fail to create custom SDP attribute.");
return (SalCustomSdpAttribute*)desc;
}
belle_sdp_session_description_add_attribute(desc, attr);
return (SalCustomSdpAttribute *)desc;
}
const char * sal_custom_sdp_attribute_find(const SalCustomSdpAttribute *csa, const char *name) {
if (csa) {
return belle_sdp_session_description_get_attribute_value((belle_sdp_session_description_t *)csa, name);
}
return NULL;
}
void sal_custom_sdp_attribute_free(SalCustomSdpAttribute *csa) {
if (csa == NULL) return;
belle_sip_object_unref((belle_sdp_session_description_t *)csa);
}
SalCustomSdpAttribute * sal_custom_sdp_attribute_clone(const SalCustomSdpAttribute *csa) {
if (csa == NULL) return NULL;
return (SalCustomSdpAttribute *)belle_sip_object_ref((belle_sdp_session_description_t *)csa);
}
void sal_set_uuid(Sal *sal, const char *uuid){
if (sal->uuid){
ms_free(sal->uuid);
@ -1153,3 +1214,28 @@ void sal_default_set_sdp_handling(Sal *sal, SalOpSDPHandling sdp_handling_method
if (sdp_handling_method != SalOpSDPNormal ) ms_message("Enabling special SDP handling for all new SalOp in Sal[%p]!", sal);
sal->default_sdp_handling = sdp_handling_method;
}
bool_t sal_pending_trans_checking_enabled(const Sal *sal) {
return sal->pending_trans_checking;
}
int sal_enable_pending_trans_checking(Sal *sal, bool_t value) {
sal->pending_trans_checking = value;
return 0;
}
void sal_set_http_proxy_host(Sal *sal, const char *host) {
belle_sip_stack_set_http_proxy_host(sal->stack, host);
}
void sal_set_http_proxy_port(Sal *sal, int port) {
belle_sip_stack_set_http_proxy_port(sal->stack, port);
}
const char *sal_get_http_proxy_host(const Sal *sal) {
return belle_sip_stack_get_http_proxy_host(sal->stack);
}
int sal_get_http_proxy_port(const Sal *sal) {
return belle_sip_stack_get_http_proxy_port(sal->stack);
}

View file

@ -51,6 +51,7 @@ struct Sal{
bool_t no_initial_route;
bool_t enable_sip_update; /*true by default*/
SalOpSDPHandling default_sdp_handling;
bool_t pending_trans_checking; /*testing purpose*/
};
typedef enum SalOpState {
@ -92,7 +93,6 @@ struct SalOp{
belle_sip_header_referred_by_t *referred_by;
SalMediaDescription *result;
belle_sdp_session_description_t *sdp_answer;
bool_t supports_session_timers;
SalOpState state;
SalOpDir dir;
belle_sip_refresher_t* refresher;
@ -100,14 +100,16 @@ struct SalOp{
SalOpType type;
SalPrivacyMask privacy;
belle_sip_header_t *event; /*used by SalOpSubscribe kinds*/
SalOpSDPHandling sdp_handling;
int auth_requests; /*number of auth requested for this op*/
bool_t cnx_ip_to_0000_if_sendonly_enabled;
bool_t auto_answer_asked;
bool_t sdp_offering;
bool_t call_released;
bool_t manual_refresher;
bool_t has_auth_pending;
SalOpSDPHandling sdp_handling;
int auth_requests; /*number of auth requested for this op*/
bool_t cnx_ip_to_0000_if_sendonly_enabled; /*for */
bool_t supports_session_timers;
bool_t op_released;
};

View file

@ -32,8 +32,9 @@ static void call_set_released(SalOp* op){
}
}
static void call_set_error(SalOp* op,belle_sip_response_t* response){
static void call_set_error(SalOp* op,belle_sip_response_t* response, bool_t fatal){
sal_op_set_error_info_from_response(op,response);
if (fatal) op->state = SalOpStateTerminating;
op->base.root->callbacks.call_failure(op);
}
static void set_addr_to_0000(char value[]) {
@ -66,7 +67,7 @@ static void sdp_process(SalOp *h){
/*for backward compatibility purpose*/
if(h->cnx_ip_to_0000_if_sendonly_enabled && sal_media_description_has_dir(h->result,SalStreamSendOnly)) {
set_addr_to_0000(h->result->addr);
for(i=0;i<h->result->nb_streams;++i){
for(i=0;i<SAL_MEDIA_DESCRIPTION_MAX_STREAMS;++i){
if (h->result->streams[i].dir == SalStreamSendOnly)
set_addr_to_0000(h->result->streams[i].rtp_addr);
set_addr_to_0000(h->result->streams[i].rtcp_addr);
@ -78,7 +79,7 @@ static void sdp_process(SalOp *h){
strcpy(h->result->addr,h->base.remote_media->addr);
h->result->bandwidth=h->base.remote_media->bandwidth;
for(i=0;i<h->result->nb_streams;++i){
for(i=0;i<SAL_MEDIA_DESCRIPTION_MAX_STREAMS;++i){
/*copy back parameters from remote description that we need in our result description*/
if (h->result->streams[i].rtp_port!=0){ /*if stream was accepted*/
strcpy(h->result->streams[i].rtp_addr,h->base.remote_media->streams[i].rtp_addr);
@ -88,7 +89,7 @@ static void sdp_process(SalOp *h){
strcpy(h->result->streams[i].rtcp_addr,h->base.remote_media->streams[i].rtcp_addr);
h->result->streams[i].rtcp_port=h->base.remote_media->streams[i].rtcp_port;
if ((h->result->streams[i].proto == SalProtoRtpSavpf) || (h->result->streams[i].proto == SalProtoRtpSavp)) {
if (sal_stream_description_has_srtp(&h->result->streams[i])) {
h->result->streams[i].crypto[0] = h->base.remote_media->streams[i].crypto[0];
}
}
@ -149,6 +150,7 @@ static void call_process_io_error(void *user_ctx, const belle_sip_io_error_event
/*call terminated very early*/
sal_error_info_set(&op->error_info,SalReasonIOError,503,"IO error",NULL);
op->base.root->callbacks.call_failure(op);
op->state = SalOpStateTerminating;
call_set_released(op);
} else {
/*dialog will terminated shortly, nothing to do*/
@ -162,6 +164,14 @@ static void process_dialog_terminated(void *ctx, const belle_sip_dialog_terminat
ms_message("Dialog [%p] terminated for op [%p]",belle_sip_dialog_terminated_event_get_dialog(event),op);
switch(belle_sip_dialog_get_previous_state(op->dialog)) {
case BELLE_SIP_DIALOG_EARLY:
case BELLE_SIP_DIALOG_NULL:
if (op->state!=SalOpStateTerminated && op->state!=SalOpStateTerminating) {
/*this is an early termination due to incorrect response received*/
op->base.root->callbacks.call_failure(op);
op->state=SalOpStateTerminating;
}
break;
case BELLE_SIP_DIALOG_CONFIRMED:
if (op->state!=SalOpStateTerminated && op->state!=SalOpStateTerminating) {
/*this is probably a normal termination from a BYE*/
@ -201,7 +211,23 @@ static void cancelling_invite(SalOp* op ){
belle_sip_request_t* cancel;
ms_message("Cancelling INVITE request from [%s] to [%s] ",sal_op_get_from(op), sal_op_get_to(op));
cancel = belle_sip_client_transaction_create_cancel(op->pending_client_trans);
sal_op_send_request(op,cancel);
if (cancel){
sal_op_send_request(op,cancel);
}else if (op->dialog){
belle_sip_dialog_state_t state = belle_sip_dialog_get_state(op->dialog);;
/*case where the response received is invalid (could not establish a dialog), but the transaction is not cancellable
* because already terminated*/
switch(state){
case BELLE_SIP_DIALOG_EARLY:
case BELLE_SIP_DIALOG_NULL:
/*force kill the dialog*/
ms_warning("op [%p]: force kill of dialog [%p]", op, op->dialog);
belle_sip_dialog_delete(op->dialog);
break;
default:
break;
}
}
op->state=SalOpStateTerminating;
}
@ -263,7 +289,7 @@ static void call_process_response(void *op_base, const belle_sip_response_event_
}
belle_sip_object_data_set(BELLE_SIP_OBJECT(dialog),"early_response",belle_sip_object_ref(response),belle_sip_object_unref);
} else if (code>=300){
call_set_error(op,response);
call_set_error(op, response, TRUE);
if (op->dialog==NULL) call_set_released(op);
}
} else if (code >=200
@ -295,17 +321,17 @@ static void call_process_response(void *op_base, const belle_sip_response_event_
op->base.root->callbacks.call_accepted(op); /*INVITE*/
op->state=SalOpStateActive;
}else if (code >= 300){
call_set_error(op,response);
call_set_error(op,response, FALSE);
}
}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) {
unsigned int retry_in =1000*((float)rand()/RAND_MAX);
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);
unsigned int retry_in = (unsigned int)(1000*((float)rand()/RAND_MAX));
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*/
}
@ -323,8 +349,8 @@ static void call_process_response(void *op_base, const belle_sip_response_event_
}
break;
case BELLE_SIP_DIALOG_TERMINATED: {
if (code >= 300){
call_set_error(op,response);
if (strcmp("INVITE",method)==0 && code >= 300){
call_set_error(op,response, TRUE);
}
}
break;
@ -345,6 +371,7 @@ static void call_process_timeout(void *user_ctx, const belle_sip_timeout_event_t
/*call terminated very early*/
sal_error_info_set(&op->error_info,SalReasonRequestTimeout,408,"Request timeout",NULL);
op->base.root->callbacks.call_failure(op);
op->state = SalOpStateTerminating;
call_set_released(op);
} else {
/*dialog will terminated shortly, nothing to do*/
@ -357,6 +384,7 @@ static void call_process_transaction_terminated(void *user_ctx, const belle_sip_
belle_sip_server_transaction_t *server_transaction=belle_sip_transaction_terminated_event_get_server_transaction(event);
belle_sip_request_t* req;
belle_sip_response_t* resp;
int code = 0;
bool_t release_call=FALSE;
if (client_transaction) {
@ -366,12 +394,20 @@ static void call_process_transaction_terminated(void *user_ctx, const belle_sip_
req=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(server_transaction));
resp=belle_sip_transaction_get_response(BELLE_SIP_TRANSACTION(server_transaction));
}
if (op->state ==SalOpStateTerminating
if (resp) code = belle_sip_response_get_status_code(resp);
if (op->state == SalOpStateTerminating
&& strcmp("BYE",belle_sip_request_get_method(req))==0
&& (!resp || (belle_sip_response_get_status_code(resp) !=401
&& belle_sip_response_get_status_code(resp) !=407))
&& (!resp || (belle_sip_response_get_status_code(resp) != 401
&& belle_sip_response_get_status_code(resp) != 407))
&& op->dialog==NULL) {
release_call=TRUE;
}else if (op->state == SalOpStateEarly && code < 200){
/*call terminated early*/
sal_error_info_set(&op->error_info,SalReasonIOError,503,"I/O error",NULL);
op->state = SalOpStateTerminating;
op->base.root->callbacks.call_failure(op);
release_call=TRUE;
}
if (server_transaction){
if (op->pending_server_trans==server_transaction){
@ -388,6 +424,7 @@ static void call_process_transaction_terminated(void *user_ctx, const belle_sip_
static void call_terminated(SalOp* op,belle_sip_server_transaction_t* server_transaction, belle_sip_request_t* request,int status_code) {
belle_sip_response_t* resp;
op->state = SalOpStateTerminating;
op->base.root->callbacks.call_terminated(op,op->dir==SalOpDirIncoming?sal_op_get_from(op):sal_op_get_to(op));
resp=sal_op_create_response_from_request(op,request,status_code);
belle_sip_server_transaction_send_response(server_transaction,resp);
@ -497,6 +534,7 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t
belle_sip_header_t* call_info;
const char *method=belle_sip_request_get_method(req);
bool_t is_update=FALSE;
bool_t drop_op = 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));
@ -540,12 +578,14 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t
}
}
op->base.root->callbacks.call_received(op);
}else{
/*the INVITE was declined by process_sdp_for_invite(). As we are not inside an established dialog, we can drop the op immediately*/
drop_op = TRUE;
}
break;
} /* else same behavior as for EARLY state*/
} /* else same behavior as for EARLY state, thus NO BREAK*/
}
case BELLE_SIP_DIALOG_EARLY: {
//hmm probably a cancel
if (strcmp("CANCEL",method)==0) {
if(belle_sip_request_event_get_server_transaction(event)) {
/*first answer 200 ok to cancel*/
@ -578,22 +618,27 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t
case BELLE_SIP_DIALOG_CONFIRMED:
/*great ACK received*/
if (strcmp("ACK",method)==0) {
if (op->sdp_offering){
SalReason reason;
if (extract_sdp(op,BELLE_SIP_MESSAGE(req),&sdp,&reason)==0){
if (sdp){
if (op->base.remote_media)
sal_media_description_unref(op->base.remote_media);
op->base.remote_media=sal_media_description_new();
sdp_to_media_description(sdp,op->base.remote_media);
sdp_process(op);
belle_sip_object_unref(sdp);
}else{
ms_warning("SDP expected in ACK but not found.");
if (!op->pending_client_trans ||
!belle_sip_transaction_state_is_transient(belle_sip_transaction_get_state((belle_sip_transaction_t*)op->pending_client_trans))){
if (op->sdp_offering){
SalReason reason;
if (extract_sdp(op,BELLE_SIP_MESSAGE(req),&sdp,&reason)==0){
if (sdp){
if (op->base.remote_media)
sal_media_description_unref(op->base.remote_media);
op->base.remote_media=sal_media_description_new();
sdp_to_media_description(sdp,op->base.remote_media);
sdp_process(op);
belle_sip_object_unref(sdp);
}else{
ms_warning("SDP expected in ACK but not found.");
}
}
}
op->base.root->callbacks.call_ack(op);
}else{
ms_message("Ignored received ack since a new client transaction has been started since.");
}
op->base.root->callbacks.call_ack(op);
} else if(strcmp("BYE",method)==0) {
resp=sal_op_create_response_from_request(op,req,200);
belle_sip_server_transaction_send_response(server_transaction,resp);
@ -662,7 +707,7 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t
}
if (server_transaction) belle_sip_object_unref(server_transaction);
if (drop_op) sal_op_release(op);
}
@ -855,6 +900,9 @@ int sal_call_accept(SalOp*h){
belle_sip_object_unref(h->pending_update_server_trans);
h->pending_update_server_trans=NULL;
}
if (h->state == SalOpStateEarly){
h->state = SalOpStateActive;
}
return 0;
}
@ -889,6 +937,8 @@ int sal_call_decline(SalOp *op, SalReason reason, const char *redirection /*opti
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);
belle_sip_dialog_enable_pending_trans_checking(op->dialog,op->base.root->pending_trans_checking);
/*check for dialog state*/
if ( state == BELLE_SIP_DIALOG_CONFIRMED) {
if (no_user_consent)
@ -906,6 +956,11 @@ int sal_call_update(SalOp *op, const char *subject, bool_t no_user_consent){
sal_op_fill_invite(op, update);
return sal_op_send_request(op,update);
}
/*it failed why ?*/
if (belle_sip_dialog_request_pending(op->dialog))
sal_error_info_set(&op->error_info,SalReasonRequestPending,491,NULL,NULL);
else
sal_error_info_set(&op->error_info,SalReasonUnknown,500,NULL,NULL);
return -1;
}

View file

@ -129,8 +129,7 @@ static void subscribe_process_request_event(void *op_base, const belle_sip_reque
if (!op->dialog) {
if (strcmp(method,"SUBSCRIBE")==0){
op->dialog=belle_sip_provider_create_dialog(op->base.root->prov,BELLE_SIP_TRANSACTION(server_transaction));
belle_sip_dialog_set_application_data(op->dialog,op);
sal_op_ref(op);
belle_sip_dialog_set_application_data(op->dialog, sal_op_ref(op));
ms_message("new incoming subscription from [%s] to [%s]",sal_op_get_from(op),sal_op_get_to(op));
}else{ /*this is a NOTIFY*/
handle_notify(op,req,eventname,&body);

View file

@ -38,6 +38,7 @@ void sal_op_release(SalOp *op){
if (op->refresher) {
belle_sip_refresher_stop(op->refresher);
}
op->op_released = TRUE;
sal_op_unref(op);
}
@ -72,7 +73,7 @@ void sal_op_authenticate(SalOp *op, const SalAuthInfo *info){
/*Registration authenticate is just about registering again*/
sal_register_refresh(op,-1);
}else {
/*for sure auth info will be accesible from the provider*/
/*for sure auth info will be accessible from the provider*/
sal_process_authentication(op);
}
return ;
@ -286,7 +287,7 @@ void _sal_op_add_custom_headers(SalOp *op, belle_sip_message_t *msg){
}
}
static int _sal_op_send_request_with_contact(SalOp* op, belle_sip_request_t* request,bool_t add_contact) {
static int _sal_op_send_request_with_contact(SalOp* op, belle_sip_request_t* request, bool_t add_contact) {
belle_sip_client_transaction_t* client_transaction;
belle_sip_provider_t* prov=op->base.root->prov;
belle_sip_uri_t* outbound_proxy=NULL;
@ -294,10 +295,10 @@ static int _sal_op_send_request_with_contact(SalOp* op, belle_sip_request_t* req
int result =-1;
belle_sip_uri_t *next_hop_uri=NULL;
if (add_contact) {
if (add_contact && !belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(request),belle_sip_header_contact_t)) {
contact = sal_op_create_contact(op);
belle_sip_message_set_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_HEADER(contact));
}
} /*keep existing*/
_sal_op_add_custom_headers(op, (belle_sip_message_t*)request);
@ -464,6 +465,9 @@ SalReason sal_reason_to_sip_code(SalReason r){
case SalReasonBadGateway:
ret=502;
break;
case SalReasonInternalError:
ret=500;
break;
}
return ret;
}
@ -508,6 +512,8 @@ SalReason _sal_reason_from_sip_code(int code) {
return SalReasonNotAcceptable;
case 491:
return SalReasonRequestPending;
case 500:
return SalReasonInternalError;
case 501:
return SalReasonNotImplemented;
case 502:
@ -608,7 +614,10 @@ void set_or_update_dialog(SalOp* op, belle_sip_dialog_t* dialog) {
unlink_op_with_dialog(op,op->dialog);
op->dialog=NULL;
}
if (dialog) op->dialog=link_op_with_dialog(op,dialog);
if (dialog) {
op->dialog=link_op_with_dialog(op,dialog);
belle_sip_dialog_enable_pending_trans_checking(dialog,op->base.root->pending_trans_checking);
}
}
sal_op_unref(op);
}
@ -806,6 +815,11 @@ void sal_call_set_sdp_handling(SalOp *h, SalOpSDPHandling handling) {
void sal_op_cnx_ip_to_0000_if_sendonly_enable(SalOp *op,bool_t yesno) {
op->cnx_ip_to_0000_if_sendonly_enabled = yesno;
}
bool_t sal_op_cnx_ip_to_0000_if_sendonly_enabled(SalOp *op) {
return op->cnx_ip_to_0000_if_sendonly_enabled;
}
bool_t sal_op_is_forked_of(const SalOp *op1, const SalOp *op2){
return op1->base.call_id && op2->base.call_id && strcmp(op1->base.call_id, op2->base.call_id) == 0;
}

View file

@ -21,7 +21,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
int sal_send_info(SalOp *op, const char *from, const char *to, const SalBody *body){
if (op->dialog){
belle_sip_request_t *req=belle_sip_dialog_create_queued_request(op->dialog,"INFO");
belle_sip_request_t *req;
belle_sip_dialog_enable_pending_trans_checking(op->dialog,op->base.root->pending_trans_checking);
req=belle_sip_dialog_create_queued_request(op->dialog,"INFO");
sal_op_add_body(op,(belle_sip_message_t*)req,body);
return sal_op_send_request(op,req);
}

View file

@ -47,42 +47,41 @@ void sal_add_presence_info(SalOp *op, belle_sip_message_t *notify, SalPresenceMo
}
static void presence_process_io_error(void *user_ctx, const belle_sip_io_error_event_t *event){
ms_error("presence_process_io_error not implemented yet");
/*ms_error("presence_process_io_error not implemented yet");*/
}
static void presence_process_dialog_terminated(void *ctx, const belle_sip_dialog_terminated_event_t *event) {
SalOp* op= (SalOp*)ctx;
if (op->dialog) {
sal_op_unref(op);
op->dialog=NULL;
if (belle_sip_dialog_is_server(op->dialog)){
ms_message("Incoming subscribtion from [%s] terminated",sal_op_get_from(op));
if (!op->op_released){
op->base.root->callbacks.subscribe_presence_closed(op, sal_op_get_from(op));
}
}
set_or_update_dialog(op, NULL);
}
}
static void presence_refresher_listener(belle_sip_refresher_t* refresher, void* user_pointer, unsigned int status_code, const char* reason_phrase){
SalOp* op = (SalOp*)user_pointer;
switch(status_code){
case 481: {
ms_message("The server or remote ua lost the SUBSCRIBE dialog context. Let's restart a new one.");
belle_sip_refresher_stop(op->refresher);
if (op->dialog) { /*delete previous dialog if any*/
belle_sip_dialog_set_application_data(op->dialog,NULL);
belle_sip_object_unref(op->dialog);
op->dialog=NULL;
}
if (sal_op_get_contact_address(op)) {
/*contact is also probably not good*/
SalAddress* contact=sal_address_clone(sal_op_get_contact_address(op));
sal_address_set_port(contact,-1);
sal_address_set_domain(contact,NULL);
sal_op_set_contact_address(op,contact);
sal_address_destroy(contact);
}
sal_subscribe_presence(op,NULL,NULL,-1);
break;
if (status_code >= 300) {
ms_message("The SUBSCRIBE dialog no longer works. Let's restart a new one.");
belle_sip_refresher_stop(op->refresher);
if (op->dialog) { /*delete previous dialog if any*/
set_or_update_dialog(op, NULL);
}
if (sal_op_get_contact_address(op)) {
/*contact is also probably not good*/
SalAddress* contact=sal_address_clone(sal_op_get_contact_address(op));
sal_address_set_port(contact,-1);
sal_address_set_domain(contact,NULL);
sal_op_set_contact_address(op,contact);
sal_address_destroy(contact);
}
/*send a new SUBSCRIBE, that will attempt to establish a new dialog*/
sal_subscribe_presence(op,NULL,NULL,-1);
}
}
@ -99,9 +98,13 @@ static void presence_response_event(void *op_base, const belle_sip_response_even
sal_op_set_error_info_from_response(op,response);
if (code>=300) {
ms_message("subscription to [%s] rejected",sal_op_get_to(op));
op->base.root->callbacks.notify_presence(op,SalSubscribeTerminated, NULL,NULL); /*NULL = offline*/
return;
if (strcmp("SUBSCRIBE",belle_sip_request_get_method(request))==0){
ms_message("subscription to [%s] rejected",sal_op_get_to(op));
if (!op->op_released){
op->base.root->callbacks.notify_presence(op,SalSubscribeTerminated, NULL,NULL); /*NULL = offline*/
}
return;
}
}
set_or_update_dialog(op_base,belle_sip_response_event_get_dialog(event));
if (!op->dialog) {
@ -144,11 +147,23 @@ static void presence_response_event(void *op_base, const belle_sip_response_even
}
/* no break */
}
}
static void presence_process_timeout(void *user_ctx, const belle_sip_timeout_event_t *event) {
ms_error("presence_process_timeout not implemented yet");
SalOp* op = (SalOp*)user_ctx;
belle_sip_client_transaction_t* client_transaction = belle_sip_timeout_event_get_client_transaction(event);
belle_sip_request_t* request;
if (!client_transaction) return;
request = belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction));
if (strcmp("SUBSCRIBE",belle_sip_request_get_method(request))==0){
ms_message("subscription to [%s] timeout",sal_op_get_to(op));
if (!op->op_released){
op->base.root->callbacks.notify_presence(op,SalSubscribeTerminated, NULL,NULL); /*NULL = offline*/
}
}
}
static void presence_process_transaction_terminated(void *user_ctx, const belle_sip_transaction_terminated_event_t *event) {
@ -167,25 +182,30 @@ static SalPresenceModel * process_presence_notification(SalOp *op, belle_sip_req
return NULL;
if (body==NULL) return NULL;
op->base.root->callbacks.parse_presence_requested(op,
if (!op->op_released){
op->base.root->callbacks.parse_presence_requested(op,
belle_sip_header_content_type_get_type(content_type),
belle_sip_header_content_type_get_subtype(content_type),
body,
&result);
}
return result;
}
static void handle_notify(SalOp *op, belle_sip_request_t *req){
static void handle_notify(SalOp *op, belle_sip_request_t *req, belle_sip_dialog_t *dialog){
belle_sip_response_t* resp=NULL;
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));
if (op->dialog !=NULL && dialog != op->dialog){
ms_warning("Receiving a NOTIFY from a dialog we haven't stored (op->dialog=%p dialog=%p)", op->dialog, dialog);
}
if (!subscription_state_header || strcasecmp(BELLE_SIP_SUBSCRIPTION_STATE_TERMINATED,belle_sip_header_subscription_state_get_state(subscription_state_header)) ==0) {
sub_state=SalSubscribeTerminated;
ms_message("Outgoing subscription terminated by remote [%s]",sal_op_get_to(op));
@ -197,7 +217,9 @@ static void handle_notify(SalOp *op, belle_sip_request_t *req){
/* 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);
if (!op->op_released){
op->base.root->callbacks.notify_presence(op, sub_state, presence_model, NULL);
}
} else if (body){
/* Formatting error in presence notification body. */
ms_warning("Wrongly formatted presence document.");
@ -212,7 +234,6 @@ static void presence_process_request_event(void *op_base, const belle_sip_reques
belle_sip_server_transaction_t* server_transaction = belle_sip_provider_create_server_transaction(op->base.root->prov,belle_sip_request_event_get_request(event));
belle_sip_request_t* req = belle_sip_request_event_get_request(event);
belle_sip_dialog_state_t dialog_state;
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);
@ -223,13 +244,12 @@ static void presence_process_request_event(void *op_base, const belle_sip_reques
if (!op->dialog) {
if (strcmp(method,"SUBSCRIBE")==0){
op->dialog=belle_sip_provider_create_dialog(op->base.root->prov,BELLE_SIP_TRANSACTION(server_transaction));
belle_sip_dialog_set_application_data(op->dialog,op);
sal_op_ref(op);
belle_sip_dialog_t *dialog = belle_sip_provider_create_dialog(op->base.root->prov,BELLE_SIP_TRANSACTION(server_transaction));
set_or_update_dialog(op, dialog);
ms_message("new incoming subscription from [%s] to [%s]",sal_op_get_from(op),sal_op_get_to(op));
}else{ /* this is a NOTIFY */
ms_message("Receiving out of dialog notify");
handle_notify(op,req);
handle_notify(op, req, belle_sip_request_event_get_dialog(event));
return;
}
}
@ -245,16 +265,13 @@ static void presence_process_request_event(void *op_base, const belle_sip_reques
case BELLE_SIP_DIALOG_CONFIRMED:
if (strcmp("NOTIFY",method)==0) {
handle_notify(op,req);
handle_notify(op, req, belle_sip_request_event_get_dialog(event));
} else if (strcmp("SUBSCRIBE",method)==0) {
/*either a refresh or an unsubscribe*/
if (expires && belle_sip_header_expires_get_expires(expires)>0) {
op->base.root->callbacks.subscribe_presence_received(op,sal_op_get_from(op));
} else if(expires) {
ms_message("Unsubscribe received from [%s]",sal_op_get_from(op));
resp=sal_op_create_response_from_request(op,req,200);
belle_sip_server_transaction_send_response(server_transaction,resp);
}
/*either a refresh or an unsubscribe.
If it is a refresh there is nothing to notify to the app. If it is an unSUBSCRIBE, then the dialog
will be terminated shortly, and this will be notified to the app through the dialog_terminated callback.*/
resp=sal_op_create_response_from_request(op,req,200);
belle_sip_server_transaction_send_response(server_transaction,resp);
}
break;
default:
@ -330,8 +347,8 @@ static int sal_op_check_dialog_state(SalOp *op) {
return -1;
} else
return 0;
}
int sal_notify_presence(SalOp *op, SalPresenceModel *presence){
belle_sip_request_t* notify=NULL;
if (sal_op_check_dialog_state(op)) {

View file

@ -40,6 +40,7 @@ static void register_refresher_listener (belle_sip_refresher_t* refresher
/*check service route rfc3608*/
belle_sip_header_service_route_t* service_route;
belle_sip_header_address_t* service_route_address=NULL;
belle_sip_header_contact_t *contact = belle_sip_refresher_get_contact(refresher);
if ((service_route=belle_sip_message_get_header_by_type(response,belle_sip_header_service_route_t))) {
service_route_address=belle_sip_header_address_create(NULL,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(service_route)));
}
@ -47,6 +48,9 @@ static void register_refresher_listener (belle_sip_refresher_t* refresher
if (service_route_address) belle_sip_object_unref(service_route_address);
sal_remove_pending_auth(op->base.root,op); /*just in case*/
if (contact) {
sal_op_set_contact_address(op,(SalAddress*)(BELLE_SIP_HEADER_ADDRESS(contact))); /*update contact with real value*/
}
op->base.root->callbacks.register_success(op,belle_sip_refresher_get_expires(op->refresher)>0);
} else if (status_code>=400) {
/* from rfc3608, 6.1.
@ -71,7 +75,7 @@ static void register_refresher_listener (belle_sip_refresher_t* refresher
}
}
int sal_register(SalOp *op, const char *proxy, const char *from, int expires){
int sal_register(SalOp *op, const char *proxy, const char *from, int expires,SalAddress* old_contact){
belle_sip_request_t *req;
belle_sip_uri_t* req_uri;
belle_sip_header_t* accept_header;
@ -96,6 +100,19 @@ int sal_register(SalOp *op, const char *proxy, const char *from, int expires){
accept_header = belle_sip_header_create("Accept", "application/sdp, text/plain, application/vnd.gsma.rcs-ft-http+xml");
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req), accept_header);
belle_sip_message_set_header(BELLE_SIP_MESSAGE(req),(belle_sip_header_t*)sal_op_create_contact(op));
if (old_contact) {
belle_sip_header_contact_t *contact=belle_sip_header_contact_create((const belle_sip_header_address_t *)old_contact);
if (contact) {
char * tmp;
belle_sip_header_contact_set_expires(contact,0); /*remove old aor*/
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req), BELLE_SIP_HEADER(contact));
tmp = belle_sip_object_to_string(contact);
ms_message("Clearing contact [%s] for op [%p]",tmp,op);
ms_free(tmp);
} else {
ms_error("Cannot add old contact header to op [%p]",op);
}
}
return sal_op_send_and_create_refresher(op,req,expires,register_refresher_listener);
}

View file

@ -93,6 +93,14 @@ static void add_rtcp_fb_trr_int_attribute(belle_sdp_media_description_t *media_d
belle_sdp_media_description_add_attribute(media_desc, BELLE_SDP_ATTRIBUTE(attribute));
}
static void add_rtcp_fb_ack_attribute(belle_sdp_media_description_t *media_desc, int8_t id, belle_sdp_rtcp_fb_val_param_t param) {
belle_sdp_rtcp_fb_attribute_t *attribute = belle_sdp_rtcp_fb_attribute_new();
belle_sdp_rtcp_fb_attribute_set_id(attribute, id);
belle_sdp_rtcp_fb_attribute_set_type(attribute, BELLE_SDP_RTCP_FB_ACK);
belle_sdp_rtcp_fb_attribute_set_param(attribute, param);
belle_sdp_media_description_add_attribute(media_desc, BELLE_SDP_ATTRIBUTE(attribute));
}
static void add_rtcp_fb_nack_attribute(belle_sdp_media_description_t *media_desc, int8_t id, belle_sdp_rtcp_fb_val_param_t param) {
belle_sdp_rtcp_fb_attribute_t *attribute = belle_sdp_rtcp_fb_attribute_new();
belle_sdp_rtcp_fb_attribute_set_id(attribute, id);
@ -120,6 +128,12 @@ static void add_rtcp_fb_attributes(belle_sdp_media_description_t *media_desc, co
if (general_trr_int == TRUE) {
add_rtcp_fb_trr_int_attribute(media_desc, -1, trr_int);
}
if (stream->rtcp_fb.generic_nack_enabled == TRUE) {
add_rtcp_fb_nack_attribute(media_desc, -1, BELLE_SDP_RTCP_FB_NONE);
}
if (stream->rtcp_fb.tmmbr_enabled == TRUE) {
add_rtcp_fb_ccm_attribute(media_desc, -1, BELLE_SDP_RTCP_FB_TMMBR);
}
for (pt_it = stream->payloads; pt_it != NULL; pt_it = pt_it->next) {
pt = (PayloadType *)pt_it->data;
@ -141,7 +155,11 @@ static void add_rtcp_fb_attributes(belle_sdp_media_description_t *media_desc, co
add_rtcp_fb_nack_attribute(media_desc, payload_type_get_number(pt), BELLE_SDP_RTCP_FB_SLI);
}
if (avpf_params.features & PAYLOAD_TYPE_AVPF_RPSI) {
add_rtcp_fb_nack_attribute(media_desc, payload_type_get_number(pt), BELLE_SDP_RTCP_FB_RPSI);
if (avpf_params.rpsi_compatibility == TRUE) {
add_rtcp_fb_nack_attribute(media_desc, payload_type_get_number(pt), BELLE_SDP_RTCP_FB_RPSI);
} else {
add_rtcp_fb_ack_attribute(media_desc, payload_type_get_number(pt), BELLE_SDP_RTCP_FB_RPSI);
}
}
if (avpf_params.features & PAYLOAD_TYPE_AVPF_FIR) {
add_rtcp_fb_ccm_attribute(media_desc, payload_type_get_number(pt), BELLE_SDP_RTCP_FB_FIR);
@ -232,7 +250,7 @@ static void stream_description_to_sdp ( belle_sdp_session_description_t *session
if ( stream->bandwidth>0 )
belle_sdp_media_description_set_bandwidth ( media_desc,"AS",stream->bandwidth );
if ((stream->proto == SalProtoRtpSavpf) || (stream->proto == SalProtoRtpSavp)) {
if (sal_stream_description_has_srtp(stream)) {
/* add crypto lines */
for ( j=0; j<SAL_CRYPTO_ALGO_MAX; j++ ) {
MSCryptoSuiteNameParams desc;
@ -249,7 +267,7 @@ static void stream_description_to_sdp ( belle_sdp_session_description_t *session
/* insert DTLS session attribute if needed */
if ((stream->proto == SalProtoUdpTlsRtpSavpf) || (stream->proto == SalProtoUdpTlsRtpSavp)) {
char* ssrc_attribute = ms_strdup_printf("%u cname:%s",htonl(stream->rtp_ssrc),stream->rtcp_cname);
char* ssrc_attribute = ms_strdup_printf("%u cname:%s",stream->rtp_ssrc,stream->rtcp_cname);
if ((stream->dtls_role != SalDtlsRoleInvalid) && (strlen(stream->dtls_fingerprint)>0)) {
switch(stream->dtls_role) {
case SalDtlsRoleIsClient:
@ -265,7 +283,7 @@ static void stream_description_to_sdp ( belle_sdp_session_description_t *session
}
belle_sdp_media_description_add_attribute(media_desc, belle_sdp_attribute_create("fingerprint",stream->dtls_fingerprint));
}
belle_sdp_media_description_add_attribute(media_desc, belle_sdp_attribute_create("ssrc",ssrc_attribute)); /* truc de Jehan a virer? */
belle_sdp_media_description_add_attribute(media_desc, belle_sdp_attribute_create("ssrc",ssrc_attribute));
ms_free(ssrc_attribute);
}
@ -286,6 +304,10 @@ static void stream_description_to_sdp ( belle_sdp_session_description_t *session
}
if ( dir ) belle_sdp_media_description_add_attribute ( media_desc,belle_sdp_attribute_create ( dir,NULL ) );
if (stream->rtcp_mux){
belle_sdp_media_description_add_attribute(media_desc, belle_sdp_attribute_create ("rtcp-mux",NULL ) );
}
if (rtp_port != 0) {
different_rtp_and_rtcp_addr = (rtcp_addr[0] != '\0') && (strcmp(rtp_addr, rtcp_addr) != 0);
if ((rtcp_port != (rtp_port + 1)) || (different_rtp_and_rtcp_addr == TRUE)) {
@ -313,7 +335,7 @@ static void stream_description_to_sdp ( belle_sdp_session_description_t *session
}
}
if ((rtp_port != 0) && ((stream->proto == SalProtoRtpAvpf) || (stream->proto == SalProtoRtpSavpf))) {
if ((rtp_port != 0) && sal_stream_description_has_avpf(stream)) {
add_rtcp_fb_attributes(media_desc, md, stream);
}
@ -337,6 +359,16 @@ static void stream_description_to_sdp ( belle_sdp_session_description_t *session
belle_sip_object_unref((belle_sip_object_t*)media_attribute);
}
}
if (stream->custom_sdp_attributes) {
belle_sdp_session_description_t *custom_desc = (belle_sdp_session_description_t *)stream->custom_sdp_attributes;
belle_sip_list_t *l = belle_sdp_session_description_get_attributes(custom_desc);
belle_sip_list_t *elem;
for (elem = l; elem != NULL; elem = elem->next) {
belle_sdp_media_description_add_attribute(media_desc, (belle_sdp_attribute_t *)elem->data);
}
}
/*
* rfc5576
* 4.1. The "ssrc" Media Attribute
@ -397,6 +429,14 @@ belle_sdp_session_description_t * media_description_to_sdp ( const SalMediaDescr
if (desc->rtcp_xr.enabled == TRUE) {
belle_sdp_session_description_add_attribute(session_desc, create_rtcp_xr_attribute(&desc->rtcp_xr));
}
if (desc->custom_sdp_attributes) {
belle_sdp_session_description_t *custom_desc = (belle_sdp_session_description_t *)desc->custom_sdp_attributes;
belle_sip_list_t *l = belle_sdp_session_description_get_attributes(custom_desc);
belle_sip_list_t *elem;
for (elem = l; elem != NULL; elem = elem->next) {
belle_sdp_session_description_add_attribute(session_desc, (belle_sdp_attribute_t *)elem->data);
}
}
for ( i=0; i<desc->nb_streams; i++ ) {
stream_description_to_sdp(session_desc, desc, &desc->streams[i]);
@ -538,9 +578,14 @@ static void enable_avpf_for_stream(SalStreamDescription *stream) {
}
}
static void apply_rtcp_fb_attribute_to_payload(belle_sdp_rtcp_fb_attribute_t *fb_attribute, PayloadType *pt) {
static void apply_rtcp_fb_attribute_to_payload(belle_sdp_rtcp_fb_attribute_t *fb_attribute, SalStreamDescription *stream, PayloadType *pt) {
PayloadTypeAvpfParams avpf_params = payload_type_get_avpf_params(pt);
switch (belle_sdp_rtcp_fb_attribute_get_type(fb_attribute)) {
case BELLE_SDP_RTCP_FB_ACK:
if (belle_sdp_rtcp_fb_attribute_get_param(fb_attribute) == BELLE_SDP_RTCP_FB_RPSI) {
avpf_params.features |= PAYLOAD_TYPE_AVPF_RPSI;
}
break;
case BELLE_SDP_RTCP_FB_NACK:
switch (belle_sdp_rtcp_fb_attribute_get_param(fb_attribute)) {
case BELLE_SDP_RTCP_FB_PLI:
@ -550,9 +595,15 @@ static void apply_rtcp_fb_attribute_to_payload(belle_sdp_rtcp_fb_attribute_t *fb
avpf_params.features |= PAYLOAD_TYPE_AVPF_SLI;
break;
case BELLE_SDP_RTCP_FB_RPSI:
/* Linphone uses positive feeback for RPSI. However first versions handling
* AVPF wrongly declared RPSI as negative feedback, so this is kept for compatibility
* with these versions but will probably be removed at some point in time. */
avpf_params.features |= PAYLOAD_TYPE_AVPF_RPSI;
avpf_params.rpsi_compatibility = TRUE;
break;
case BELLE_SDP_RTCP_FB_NONE:
stream->rtcp_fb.generic_nack_enabled = TRUE;
break;
default:
break;
}
@ -565,11 +616,13 @@ static void apply_rtcp_fb_attribute_to_payload(belle_sdp_rtcp_fb_attribute_t *fb
case BELLE_SDP_RTCP_FB_FIR:
avpf_params.features |= PAYLOAD_TYPE_AVPF_FIR;
break;
case BELLE_SDP_RTCP_FB_TMMBR:
stream->rtcp_fb.tmmbr_enabled = TRUE;
break;
default:
break;
}
break;
case BELLE_SDP_RTCP_FB_ACK:
default:
break;
}
@ -584,15 +637,6 @@ static void sdp_parse_rtcp_fb_parameters(belle_sdp_media_description_t *media_de
PayloadType *pt;
int8_t pt_num;
/* Clear the AVPF features for all payload types. */
for (pt_it = stream->payloads; pt_it != NULL; pt_it = pt_it->next) {
PayloadTypeAvpfParams avpf_params;
pt = (PayloadType *)pt_it->data;
avpf_params = payload_type_get_avpf_params(pt);
avpf_params.features = PAYLOAD_TYPE_AVPF_NONE;
payload_type_set_avpf_params(pt, avpf_params);
}
/* Handle rtcp-fb attributes that concern all payload types. */
for (it = belle_sdp_media_description_get_attributes(media_desc); it != NULL; it = it->next) {
attribute = BELLE_SDP_ATTRIBUTE(it->data);
@ -601,7 +645,7 @@ static void sdp_parse_rtcp_fb_parameters(belle_sdp_media_description_t *media_de
if (belle_sdp_rtcp_fb_attribute_get_id(fb_attribute) == -1) {
for (pt_it = stream->payloads; pt_it != NULL; pt_it = pt_it->next) {
pt = (PayloadType *)pt_it->data;
apply_rtcp_fb_attribute_to_payload(fb_attribute, pt);
apply_rtcp_fb_attribute_to_payload(fb_attribute, stream, pt);
}
}
}
@ -616,7 +660,7 @@ static void sdp_parse_rtcp_fb_parameters(belle_sdp_media_description_t *media_de
for (pt_it = stream->payloads; pt_it != NULL; pt_it = pt_it->next) {
pt = (PayloadType *)pt_it->data;
if (payload_type_get_number(pt) == (int)pt_num) {
apply_rtcp_fb_attribute_to_payload(fb_attribute, pt);
apply_rtcp_fb_attribute_to_payload(fb_attribute, stream, pt);
}
}
}
@ -680,6 +724,7 @@ static SalStreamDescription * sdp_to_stream_description(SalMediaDescription *md,
belle_sdp_connection_t* cnx;
belle_sdp_media_t* media;
belle_sdp_attribute_t* attribute;
belle_sip_list_t *custom_attribute_it;
const char* value;
const char *mtype,*proto;
@ -717,6 +762,8 @@ static SalStreamDescription * sdp_to_stream_description(SalMediaDescription *md,
stream->type=SalAudio;
} else if ( strcasecmp ( "video", mtype ) == 0 ) {
stream->type=SalVideo;
} else if ( strcasecmp ( "text", mtype ) == 0 ) {
stream->type=SalText;
} else {
stream->type=SalOther;
strncpy ( stream->typeother,mtype,sizeof ( stream->typeother )-1 );
@ -738,6 +785,8 @@ static SalStreamDescription * sdp_to_stream_description(SalMediaDescription *md,
stream->dir=md->dir; /*takes default value if not present*/
}
stream->rtcp_mux = belle_sdp_media_description_get_attribute(media_desc, "rtcp-mux") != NULL;
/* Get media payload types */
sdp_parse_payload_types(media_desc, stream);
@ -775,7 +824,7 @@ static SalStreamDescription * sdp_to_stream_description(SalMediaDescription *md,
}
/* Read crypto lines if any */
if ((stream->proto == SalProtoRtpSavpf) || (stream->proto == SalProtoRtpSavp)) {
if (sal_stream_description_has_srtp(stream)) {
sdp_parse_media_crypto_parameters(media_desc, stream);
}
@ -783,7 +832,7 @@ static SalStreamDescription * sdp_to_stream_description(SalMediaDescription *md,
sdp_parse_media_ice_parameters(media_desc, stream);
/* Get RTCP-FB attributes if any */
if ((stream->proto == SalProtoRtpAvpf) || (stream->proto == SalProtoRtpSavpf)) {
if (sal_stream_description_has_avpf(stream)) {
enable_avpf_for_stream(stream);
sdp_parse_rtcp_fb_parameters(media_desc, stream);
}
@ -792,6 +841,12 @@ static SalStreamDescription * sdp_to_stream_description(SalMediaDescription *md,
stream->rtcp_xr = md->rtcp_xr; // Use session parameters if no stream parameters are defined
sdp_parse_media_rtcp_xr_parameters(media_desc, &stream->rtcp_xr);
/* Get the custom attributes */
for (custom_attribute_it = belle_sdp_media_description_get_attributes(media_desc); custom_attribute_it != NULL; custom_attribute_it = custom_attribute_it->next) {
belle_sdp_attribute_t *attr = (belle_sdp_attribute_t *)custom_attribute_it->data;
stream->custom_sdp_attributes = sal_custom_sdp_attribute_append(stream->custom_sdp_attributes, belle_sdp_attribute_get_name(attr), belle_sdp_attribute_get_value(attr));
}
md->nb_streams++;
return stream;
}
@ -802,6 +857,7 @@ int sdp_to_media_description ( belle_sdp_session_description_t *session_desc, S
belle_sip_list_t* media_desc_it;
belle_sdp_media_description_t* media_desc;
belle_sdp_session_name_t *sname;
belle_sip_list_t *custom_attribute_it;
const char* value;
SalDtlsRole session_role=SalDtlsRoleInvalid;
int i;
@ -863,6 +919,12 @@ int sdp_to_media_description ( belle_sdp_session_description_t *session_desc, S
/* Get session RTCP-XR attributes if any */
sdp_parse_session_rtcp_xr_parameters(session_desc, &desc->rtcp_xr);
/* Get the custom attributes */
for (custom_attribute_it = belle_sdp_session_description_get_attributes(session_desc); custom_attribute_it != NULL; custom_attribute_it = custom_attribute_it->next) {
belle_sdp_attribute_t *attr = (belle_sdp_attribute_t *)custom_attribute_it->data;
desc->custom_sdp_attributes = sal_custom_sdp_attribute_append(desc->custom_sdp_attributes, belle_sdp_attribute_get_name(attr), belle_sdp_attribute_get_value(attr));
}
for ( media_desc_it=belle_sdp_session_description_get_media_descriptions ( session_desc )
; media_desc_it!=NULL
; media_desc_it=media_desc_it->next ) {

View file

@ -22,6 +22,20 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <time.h>
#include "private.h"
#ifdef CALL_LOGS_STORAGE_ENABLED
#ifndef _WIN32
#if !defined(ANDROID) && !defined(__QNXNTO__)
# include <langinfo.h>
# include <iconv.h>
# include <string.h>
#endif
#else
#include <Windows.h>
#endif
#define MAX_PATH_SIZE 1024
#include "sqlite3.h"
#endif
/*******************************************************************************
* Internal functions *
@ -33,7 +47,7 @@ static size_t my_strftime(char *s, size_t max, const char *fmt, const struct t
}
static time_t string_to_time(const char *date){
#ifndef WIN32
#ifndef _WIN32
struct tm tmtime={0};
strptime(date,"%c",&tmtime);
return mktime(&tmtime);
@ -44,7 +58,7 @@ static time_t string_to_time(const char *date){
static void set_call_log_date(LinphoneCallLog *cl, time_t start_time){
struct tm loctime;
#ifdef WIN32
#ifdef _WIN32
#if !defined(_WIN32_WCE)
loctime=*localtime(&start_time);
/*FIXME*/
@ -260,16 +274,17 @@ void linphone_call_log_unref(LinphoneCallLog *cl) {
* Constructor and destructor functions *
******************************************************************************/
static void _linphone_call_log_destroy(LinphoneCallLog *cl){
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]);
if (cl->reporting.reports[LINPHONE_CALL_STATS_TEXT]!=NULL) linphone_reporting_destroy(cl->reporting.reports[LINPHONE_CALL_STATS_TEXT]);
}
LinphoneCallLog * linphone_call_log_new(LinphoneCallDir dir, LinphoneAddress *from, LinphoneAddress *to){
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);
@ -278,9 +293,11 @@ LinphoneCallLog * linphone_call_log_new(LinphoneCallDir dir, LinphoneAddress *fr
cl->to=to;
cl->status=LinphoneCallAborted; /*default status*/
cl->quality=-1;
cl->storage_id=0;
cl->reporting.reports[LINPHONE_CALL_STATS_AUDIO]=linphone_reporting_new();
cl->reporting.reports[LINPHONE_CALL_STATS_VIDEO]=linphone_reporting_new();
cl->reporting.reports[LINPHONE_CALL_STATS_TEXT]=linphone_reporting_new();
cl->connected_date_time=0;
return cl;
}
@ -298,3 +315,392 @@ BELLE_SIP_INSTANCIATE_VPTR(LinphoneCallLog, belle_sip_object_t,
NULL, // marshal
FALSE
);
/*******************************************************************************
* SQL storage related functions *
******************************************************************************/
#ifdef CALL_LOGS_STORAGE_ENABLED
static void linphone_create_table(sqlite3* db) {
char* errmsg=NULL;
int ret;
ret=sqlite3_exec(db,"CREATE TABLE IF NOT EXISTS call_history ("
"id INTEGER PRIMARY KEY AUTOINCREMENT,"
"caller TEXT NOT NULL," // Can't name a field "from"...
"callee TEXT NOT NULL,"
"direction INTEGER,"
"duration INTEGER,"
"start_time TEXT NOT NULL,"
"connected_time TEXT NOT NULL,"
"status INTEGER,"
"videoEnabled INTEGER,"
"quality REAL"
");",
0,0,&errmsg);
if(ret != SQLITE_OK) {
ms_error("Error in creation: %s.\n", errmsg);
sqlite3_free(errmsg);
}
}
void linphone_update_call_log_table(sqlite3* db) {
char* errmsg=NULL;
int ret;
// for image url storage
ret=sqlite3_exec(db,"ALTER TABLE call_history ADD COLUMN call_id TEXT;",NULL,NULL,&errmsg);
if(ret != SQLITE_OK) {
ms_message("Table already up to date: %s.", errmsg);
sqlite3_free(errmsg);
} else {
ret=sqlite3_exec(db,"ALTER TABLE call_history ADD COLUMN refkey TEXT;",NULL,NULL,&errmsg);
if(ret != SQLITE_OK) {
ms_message("Table already up to date: %s.", errmsg);
sqlite3_free(errmsg);
} else {
ms_debug("Table call_history updated successfully for call_id and refkey.");
}
}
}
void linphone_core_call_log_storage_init(LinphoneCore *lc) {
int ret;
const char *errmsg;
sqlite3 *db;
linphone_core_call_log_storage_close(lc);
ret=_linphone_sqlite3_open(lc->logs_db_file, &db);
if(ret != SQLITE_OK) {
errmsg = sqlite3_errmsg(db);
ms_error("Error in the opening: %s.\n", errmsg);
sqlite3_close(db);
return;
}
linphone_create_table(db);
linphone_update_call_log_table(db);
lc->logs_db = db;
// Load the existing call logs
linphone_core_get_call_history(lc);
}
void linphone_core_call_log_storage_close(LinphoneCore *lc) {
if (lc->logs_db){
sqlite3_close(lc->logs_db);
lc->logs_db = NULL;
}
}
/* DB layout:
* | 0 | storage_id
* | 1 | from
* | 2 | to
* | 3 | direction flag
* | 4 | duration
* | 5 | start date time (time_t)
* | 6 | connected date time (time_t)
* | 7 | status
* | 8 | video enabled (1 or 0)
* | 9 | quality
* | 10 | call_id
* | 11 | refkey
*/
static int create_call_log(void *data, int argc, char **argv, char **colName) {
MSList **list = (MSList **)data;
LinphoneAddress *from;
LinphoneAddress *to;
LinphoneCallDir dir;
LinphoneCallLog *log;
unsigned int storage_id = atoi(argv[0]);
from = linphone_address_new(argv[1]);
to = linphone_address_new(argv[2]);
dir = (LinphoneCallDir) atoi(argv[3]);
log = linphone_call_log_new(dir, from, to);
log->storage_id = storage_id;
log->duration = atoi(argv[4]);
log->start_date_time = (time_t)atol(argv[5]);
set_call_log_date(log,log->start_date_time);
log->connected_date_time = (time_t)atol(argv[6]);
log->status = (LinphoneCallStatus) atoi(argv[7]);
log->video_enabled = atoi(argv[8]) == 1;
log->quality = atof(argv[9]);
if (argc > 10) {
if (argv[10] != NULL) {
log->call_id = ms_strdup(argv[10]);
}
if (argv[10] != NULL) {
log->refkey = ms_strdup(argv[11]);
}
}
*list = ms_list_append(*list, log);
return 0;
}
void linphone_sql_request_call_log(sqlite3 *db, const char *stmt, MSList **list) {
char* errmsg = NULL;
int ret;
ret = sqlite3_exec(db, stmt, create_call_log, list, &errmsg);
if (ret != SQLITE_OK) {
ms_error("linphone_sql_request: statement %s -> error sqlite3_exec(): %s.", stmt, errmsg);
sqlite3_free(errmsg);
}
}
int linphone_sql_request_generic(sqlite3* db, const char *stmt) {
char* errmsg = NULL;
int ret;
ret = sqlite3_exec(db, stmt, NULL, NULL, &errmsg);
if (ret != SQLITE_OK) {
ms_error("linphone_sql_request: statement %s -> error sqlite3_exec(): %s.", stmt, errmsg);
sqlite3_free(errmsg);
}
return ret;
}
void linphone_core_store_call_log(LinphoneCore *lc, LinphoneCallLog *log) {
if (lc && lc->logs_db){
char *from, *to;
char *buf;
from = linphone_address_as_string(log->from);
to = linphone_address_as_string(log->to);
buf = sqlite3_mprintf("INSERT INTO call_history VALUES(NULL,%Q,%Q,%i,%i,%lld,%lld,%i,%i,%f,%Q,%Q);",
from,
to,
log->dir,
log->duration,
(int64_t)log->start_date_time,
(int64_t)log->connected_date_time,
log->status,
log->video_enabled ? 1 : 0,
log->quality,
log->call_id,
log->refkey
);
linphone_sql_request_generic(lc->logs_db, buf);
sqlite3_free(buf);
ms_free(from);
ms_free(to);
log->storage_id = sqlite3_last_insert_rowid(lc->logs_db);
}
if (lc) {
lc->call_logs = ms_list_prepend(lc->call_logs, linphone_call_log_ref(log));
}
}
static void copy_user_data_from_existing_log(MSList *existing_logs, LinphoneCallLog *log) {
while (existing_logs) {
LinphoneCallLog *existing_log = (LinphoneCallLog *)existing_logs->data;
if (existing_log->storage_id == log->storage_id) {
log->user_data = existing_log->user_data;
break;
}
existing_logs = ms_list_next(existing_logs);
}
}
static void copy_user_data_from_existing_logs(MSList *existing_logs, MSList *new_logs) {
while (new_logs) {
LinphoneCallLog *new_log = (LinphoneCallLog *)new_logs->data;
copy_user_data_from_existing_log(existing_logs, new_log);
new_logs = ms_list_next(new_logs);
}
}
const MSList *linphone_core_get_call_history(LinphoneCore *lc) {
char *buf;
uint64_t begin,end;
MSList *result = NULL;
if (!lc || lc->logs_db == NULL) return NULL;
buf = sqlite3_mprintf("SELECT * FROM call_history ORDER BY id DESC LIMIT %i", lc->max_call_logs);
begin = ortp_get_cur_time_ms();
linphone_sql_request_call_log(lc->logs_db, buf, &result);
end = ortp_get_cur_time_ms();
ms_message("%s(): completed in %i ms",__FUNCTION__, (int)(end-begin));
sqlite3_free(buf);
if (lc->call_logs) {
copy_user_data_from_existing_logs(lc->call_logs, result);
}
lc->call_logs = ms_list_free_with_data(lc->call_logs, (void (*)(void*))linphone_call_log_unref);
lc->call_logs = result;
return lc->call_logs;
}
void linphone_core_delete_call_history(LinphoneCore *lc) {
char *buf;
if (!lc || lc->logs_db == NULL) return ;
buf = sqlite3_mprintf("DELETE FROM call_history");
linphone_sql_request_generic(lc->logs_db, buf);
sqlite3_free(buf);
}
void linphone_core_delete_call_log(LinphoneCore *lc, LinphoneCallLog *log) {
char *buf;
if (!lc || lc->logs_db == NULL) return ;
buf = sqlite3_mprintf("DELETE FROM call_history WHERE id = %i", log->storage_id);
linphone_sql_request_generic(lc->logs_db, buf);
sqlite3_free(buf);
}
int linphone_core_get_call_history_size(LinphoneCore *lc) {
int numrows = 0;
char *buf;
sqlite3_stmt *selectStatement;
int returnValue;
if (!lc || lc->logs_db == NULL) return 0;
buf = sqlite3_mprintf("SELECT count(*) FROM call_history");
returnValue = sqlite3_prepare_v2(lc->logs_db, buf, -1, &selectStatement, NULL);
if (returnValue == SQLITE_OK){
if(sqlite3_step(selectStatement) == SQLITE_ROW){
numrows = sqlite3_column_int(selectStatement, 0);
}
}
sqlite3_finalize(selectStatement);
sqlite3_free(buf);
return numrows;
}
MSList * linphone_core_get_call_history_for_address(LinphoneCore *lc, const LinphoneAddress *addr) {
char *buf;
char *sipAddress;
uint64_t begin,end;
MSList *result = NULL;
if (!lc || lc->logs_db == NULL || addr == NULL) return NULL;
/*since we want to append query parameters depending on arguments given, we use malloc instead of sqlite3_mprintf*/
sipAddress = linphone_address_as_string_uri_only(addr);
buf = sqlite3_mprintf("SELECT * FROM call_history WHERE caller LIKE '%%%q%%' OR callee LIKE '%%%q%%' ORDER BY id DESC", sipAddress, sipAddress); // The '%%%q%%' takes care of the eventual presence of a display name
begin = ortp_get_cur_time_ms();
linphone_sql_request_call_log(lc->logs_db, buf, &result);
end = ortp_get_cur_time_ms();
ms_message("%s(): completed in %i ms",__FUNCTION__, (int)(end-begin));
sqlite3_free(buf);
ms_free(sipAddress);
if (lc->call_logs) {
copy_user_data_from_existing_logs(lc->call_logs, result);
}
return result;
}
LinphoneCallLog * linphone_core_get_last_outgoing_call_log(LinphoneCore *lc) {
char *buf;
uint64_t begin,end;
MSList *list = NULL;
LinphoneCallLog* result = NULL;
if (!lc || lc->logs_db == NULL) return NULL;
/*since we want to append query parameters depending on arguments given, we use malloc instead of sqlite3_mprintf*/
buf = sqlite3_mprintf("SELECT * FROM call_history WHERE direction = 0 ORDER BY id DESC LIMIT 1");
begin = ortp_get_cur_time_ms();
linphone_sql_request_call_log(lc->logs_db, buf, &list);
end = ortp_get_cur_time_ms();
ms_message("%s(): completed in %i ms",__FUNCTION__, (int)(end-begin));
sqlite3_free(buf);
if (list) {
result = (LinphoneCallLog*)list->data;
}
if (lc->call_logs && result) {
copy_user_data_from_existing_log(lc->call_logs, result);
}
return result;
}
LinphoneCallLog * linphone_core_find_call_log_from_call_id(LinphoneCore *lc, const char *call_id) {
char *buf;
uint64_t begin,end;
MSList *list = NULL;
LinphoneCallLog* result = NULL;
if (!lc || lc->logs_db == NULL) return NULL;
/*since we want to append query parameters depending on arguments given, we use malloc instead of sqlite3_mprintf*/
buf = sqlite3_mprintf("SELECT * FROM call_history WHERE call_id = '%q' ORDER BY id DESC LIMIT 1", call_id);
begin = ortp_get_cur_time_ms();
linphone_sql_request_call_log(lc->logs_db, buf, &list);
end = ortp_get_cur_time_ms();
ms_message("%s(): completed in %i ms",__FUNCTION__, (int)(end-begin));
sqlite3_free(buf);
if (list) {
result = (LinphoneCallLog*)list->data;
}
if (lc->call_logs && result) {
copy_user_data_from_existing_log(lc->call_logs, result);
}
return result;
}
#else
void linphone_core_call_log_storage_init(LinphoneCore *lc) {
}
void linphone_core_call_log_storage_close(LinphoneCore *lc) {
}
void linphone_core_store_call_log(LinphoneCore *lc, LinphoneCallLog *log) {
}
const MSList *linphone_core_get_call_history(LinphoneCore *lc) {
return NULL;
}
void linphone_core_delete_call_history(LinphoneCore *lc) {
}
void linphone_core_delete_call_log(LinphoneCore *lc, LinphoneCallLog *log) {
}
int linphone_core_get_call_history_size(LinphoneCore *lc) {
return 0;
}
MSList * linphone_core_get_call_history_for_address(LinphoneCore *lc, const LinphoneAddress *addr) {
return NULL;
}
LinphoneCallLog * linphone_core_get_last_outgoing_call_log(LinphoneCore *lc) {
return NULL;
}
LinphoneCallLog * linphone_core_find_call_log_from_call_id(LinphoneCore *lc, const char *call_id) {
return NULL;
}
#endif

View file

@ -43,6 +43,9 @@ SalStreamDir sal_dir_from_call_params_dir(LinphoneMediaDirection cpdir) {
return SalStreamRecvOnly;
case LinphoneMediaDirectionSendRecv:
return SalStreamSendRecv;
case LinphoneMediaDirectionInvalid:
ms_error("LinphoneMediaDirectionInvalid shall not be used.");
return SalStreamInactive;
}
return SalStreamSendRecv;
}
@ -69,6 +72,36 @@ SalStreamDir get_video_dir_from_call_params(const LinphoneCallParams *params) {
return sal_dir_from_call_params_dir(linphone_call_params_get_video_direction(params));
}
void linphone_call_params_set_custom_headers(LinphoneCallParams *params, const SalCustomHeader *ch){
if (params->custom_headers){
sal_custom_header_free(params->custom_headers);
params->custom_headers = NULL;
}
if (ch){
params->custom_headers = sal_custom_header_clone(ch);
}
}
void linphone_call_params_set_custom_sdp_attributes(LinphoneCallParams *params, const SalCustomSdpAttribute *csa) {
if (params->custom_sdp_attributes) {
sal_custom_sdp_attribute_free(params->custom_sdp_attributes);
params->custom_sdp_attributes = NULL;
}
if (csa) {
params->custom_sdp_attributes = sal_custom_sdp_attribute_clone(csa);
}
}
void linphone_call_params_set_custom_sdp_media_attributes(LinphoneCallParams *params, LinphoneStreamType type, const SalCustomSdpAttribute *csa) {
if (params->custom_sdp_media_attributes[type]) {
sal_custom_sdp_attribute_free(params->custom_sdp_media_attributes[type]);
params->custom_sdp_media_attributes[type] = NULL;
}
if (csa) {
params->custom_sdp_media_attributes[type] = sal_custom_sdp_attribute_clone(csa);
}
}
/*******************************************************************************
* Public functions *
@ -78,7 +111,24 @@ void linphone_call_params_add_custom_header(LinphoneCallParams *params, const ch
params->custom_headers=sal_custom_header_append(params->custom_headers,header_name,header_value);
}
void linphone_call_params_add_custom_sdp_attribute(LinphoneCallParams *params, const char *attribute_name, const char *attribute_value) {
params->custom_sdp_attributes = sal_custom_sdp_attribute_append(params->custom_sdp_attributes, attribute_name, attribute_value);
}
void linphone_call_params_add_custom_sdp_media_attribute(LinphoneCallParams *params, LinphoneStreamType type, const char *attribute_name, const char *attribute_value) {
params->custom_sdp_media_attributes[type] = sal_custom_sdp_attribute_append(params->custom_sdp_media_attributes[type], attribute_name, attribute_value);
}
void linphone_call_params_clear_custom_sdp_attributes(LinphoneCallParams *params) {
linphone_call_params_set_custom_sdp_attributes(params, NULL);
}
void linphone_call_params_clear_custom_sdp_media_attributes(LinphoneCallParams *params, LinphoneStreamType type) {
linphone_call_params_set_custom_sdp_media_attributes(params, type, NULL);
}
LinphoneCallParams * linphone_call_params_copy(const LinphoneCallParams *cp){
unsigned int i;
LinphoneCallParams *ncp=linphone_call_params_new();
memcpy(ncp,cp,sizeof(LinphoneCallParams));
if (cp->record_file) ncp->record_file=ms_strdup(cp->record_file);
@ -87,6 +137,10 @@ LinphoneCallParams * linphone_call_params_copy(const LinphoneCallParams *cp){
* 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);
if (cp->custom_sdp_attributes) ncp->custom_sdp_attributes = sal_custom_sdp_attribute_clone(cp->custom_sdp_attributes);
for (i = 0; i < (unsigned int)LinphoneStreamTypeUnknown; i++) {
if (cp->custom_sdp_media_attributes[i]) ncp->custom_sdp_media_attributes[i] = sal_custom_sdp_attribute_clone(cp->custom_sdp_media_attributes[i]);
}
return ncp;
}
@ -103,6 +157,17 @@ void linphone_call_params_enable_low_bandwidth(LinphoneCallParams *cp, bool_t en
cp->low_bandwidth=enabled;
}
void linphone_call_params_enable_audio(LinphoneCallParams *cp, bool_t enabled){
cp->has_audio=enabled;
if (enabled && cp->audio_dir==LinphoneMediaDirectionInactive)
cp->audio_dir=LinphoneMediaDirectionSendRecv;
}
int linphone_call_params_enable_realtime_text(LinphoneCallParams *params, bool_t yesno) {
params->realtimetext_enabled=yesno;
return 0;
}
void linphone_call_params_enable_video(LinphoneCallParams *cp, bool_t enabled){
cp->has_video=enabled;
if (enabled && cp->video_dir==LinphoneMediaDirectionInactive)
@ -113,6 +178,14 @@ const char *linphone_call_params_get_custom_header(const LinphoneCallParams *par
return sal_custom_header_find(params->custom_headers,header_name);
}
const char * linphone_call_params_get_custom_sdp_attribute(const LinphoneCallParams *params, const char *attribute_name) {
return sal_custom_sdp_attribute_find(params->custom_sdp_attributes, attribute_name);
}
const char * linphone_call_params_get_custom_sdp_media_attribute(const LinphoneCallParams *params, LinphoneStreamType type, const char *attribute_name) {
return sal_custom_sdp_attribute_find(params->custom_sdp_media_attributes[type], attribute_name);
}
bool_t linphone_call_params_get_local_conference_mode(const LinphoneCallParams *cp){
return cp->in_conference;
}
@ -161,6 +234,11 @@ const LinphonePayloadType* linphone_call_params_get_used_video_codec(const Linph
return cp->video_codec;
}
const LinphonePayloadType* linphone_call_params_get_used_text_codec(const LinphoneCallParams *cp) {
return cp->text_codec;
}
bool_t linphone_call_params_low_bandwidth_enabled(const LinphoneCallParams *cp) {
return cp->low_bandwidth;
}
@ -193,6 +271,14 @@ void linphone_call_params_set_session_name(LinphoneCallParams *cp, const char *n
if (name) cp->session_name=ms_strdup(name);
}
bool_t linphone_call_params_audio_enabled(const LinphoneCallParams *cp){
return cp->has_audio;
}
bool_t linphone_call_params_realtime_text_enabled(const LinphoneCallParams *params) {
return params->realtimetext_enabled;
}
bool_t linphone_call_params_video_enabled(const LinphoneCallParams *cp){
return cp->has_video;
}
@ -255,14 +341,22 @@ bool_t linphone_call_params_video_multicast_enabled(const LinphoneCallParams *pa
******************************************************************************/
static void _linphone_call_params_destroy(LinphoneCallParams *cp){
unsigned int i;
if (cp->record_file) ms_free(cp->record_file);
if (cp->custom_headers) sal_custom_header_free(cp->custom_headers);
if (cp->custom_sdp_attributes) sal_custom_sdp_attribute_free(cp->custom_sdp_attributes);
for (i = 0; i < (unsigned int)LinphoneStreamTypeUnknown; i++) {
if (cp->custom_sdp_media_attributes[i]) sal_custom_sdp_attribute_free(cp->custom_sdp_media_attributes[i]);
}
if (cp->session_name) ms_free(cp->session_name);
}
LinphoneCallParams * linphone_call_params_new(void) {
LinphoneCallParams *cp=belle_sip_object_new(LinphoneCallParams);
cp->audio_dir=LinphoneMediaDirectionSendRecv;
cp->video_dir=LinphoneMediaDirectionSendRecv;
cp->has_audio=TRUE;
cp->realtimetext_enabled = FALSE;
return cp;
}

View file

@ -34,11 +34,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* Indicates for a given media the stream direction
* */
enum _LinphoneMediaDirection {
LinphoneMediaDirectionInvalid = -1,
LinphoneMediaDirectionInactive, /** No active media not supported yet*/
LinphoneMediaDirectionSendOnly, /** Send only mode*/
LinphoneMediaDirectionRecvOnly, /** recv only mode*/
LinphoneMediaDirectionSendRecv, /*send receive mode not supported yet*/
LinphoneMediaDirectionSendRecv, /** send receive*/
};
/**
* Typedef for enum
@ -101,6 +101,13 @@ LINPHONE_PUBLIC void linphone_call_params_enable_early_media_sending(LinphoneCal
**/
LINPHONE_PUBLIC void linphone_call_params_enable_low_bandwidth(LinphoneCallParams *cp, bool_t enabled);
/**
* Enable audio stream.
* @param[in] cp LinphoneCallParams object
* @param[in] enabled A boolean value telling whether to enable audio or not.
**/
LINPHONE_PUBLIC void linphone_call_params_enable_audio(LinphoneCallParams *cp, bool_t enabled);
/**
* Enable video stream.
* @param[in] cp LinphoneCallParams object
@ -201,6 +208,13 @@ LINPHONE_PUBLIC const LinphonePayloadType* linphone_call_params_get_used_audio_c
**/
LINPHONE_PUBLIC const LinphonePayloadType* linphone_call_params_get_used_video_codec(const LinphoneCallParams *cp);
/**
* Get the text codec used in the call, described as a LinphonePayloadType structure.
* @param[in] cp LinphoneCallParams object
* @return The LinphonePayloadType object corresponding to the text codec being used in the call.
**/
LINPHONE_PUBLIC const LinphonePayloadType* linphone_call_params_get_used_text_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.
@ -254,6 +268,13 @@ LINPHONE_PUBLIC void linphone_call_params_set_record_file(LinphoneCallParams *cp
**/
LINPHONE_PUBLIC void linphone_call_params_set_session_name(LinphoneCallParams *cp, const char *name);
/**
* Tell whether audio is enabled or not.
* @param[in] cp LinphoneCallParams object
* @return A boolean value telling whether audio is enabled or not.
**/
LINPHONE_PUBLIC bool_t linphone_call_params_audio_enabled(const LinphoneCallParams *cp);
/**
* Tell whether video is enabled or not.
* @param[in] cp LinphoneCallParams object
@ -276,14 +297,14 @@ LINPHONE_PUBLIC LinphoneMediaDirection linphone_call_params_get_audio_direction
LINPHONE_PUBLIC LinphoneMediaDirection linphone_call_params_get_video_direction(const LinphoneCallParams *cp);
/**
* Set the audio stream direction. Only relevant for multicast
* Set the audio stream direction.
* @param[in] cl LinphoneCallParams object
* @param[in] The audio stream direction associated with this call params.
**/
LINPHONE_PUBLIC void linphone_call_params_set_audio_direction(LinphoneCallParams *cp, LinphoneMediaDirection dir);
/**
* Set the video stream direction. Only relevant for multicast
* Set the video stream direction.
* @param[in] cl LinphoneCallParams object
* @param[in] The video stream direction associated with this call params.
**/
@ -348,14 +369,84 @@ LINPHONE_PUBLIC bool_t linphone_call_params_audio_multicast_enabled(const Linpho
* @param yesno if yes, subsequent outgoing calls will propose multicast ip set by #linphone_core_set_video_multicast_addr
* @ingroup media_parameters
**/
LINPHONE_PUBLIC void linphone_call_params_enable_video_multicast(LinphoneCallParams *param, bool_t yesno);
LINPHONE_PUBLIC void linphone_call_params_enable_video_multicast(LinphoneCallParams *params, bool_t yesno);
/**
* Use to get multicast state of video stream.
* @param core #LinphoneCallParams
* @param params #LinphoneCallParams
* @return true if subsequent calls will propose multicast ip set by #linphone_core_set_video_multicast_addr
* @ingroup media_parameters
**/
LINPHONE_PUBLIC bool_t linphone_call_params_video_multicast_enabled(const LinphoneCallParams *param);
LINPHONE_PUBLIC bool_t linphone_call_params_video_multicast_enabled(const LinphoneCallParams *params);
/**
* Use to enable real time text following rfc4103.
* If enabled, outgoing calls put a m=text line in SDP offer .
* @param params #LinphoneCallParams
* @param yesno if yes, subsequent outgoing calls will propose rtt
* @ingroup media_parameters
**/
LINPHONE_PUBLIC int linphone_call_params_enable_realtime_text(LinphoneCallParams *params, bool_t yesno);
/**
* Use to get real time text following rfc4103.
* @param params #LinphoneCallParams
* @returns returns true if call rtt is activated.
* @ingroup media_parameters
**/
LINPHONE_PUBLIC bool_t linphone_call_params_realtime_text_enabled(const LinphoneCallParams *params);
/**
* Add a custom attribute related to all the streams in the SDP exchanged within SIP messages during a call.
* @param[in] params The #LinphoneCallParams to add a custom SDP attribute to.
* @param[in] attribute_name The name of the attribute to add.
* @param[in] attribute_value The content value of the attribute to add.
* @ingroup media_parameters
**/
LINPHONE_PUBLIC void linphone_call_params_add_custom_sdp_attribute(LinphoneCallParams *params, const char *attribute_name, const char *attribute_value);
/**
* Add a custom attribute related to a specific stream in the SDP exchanged within SIP messages during a call.
* @param[in] params The #LinphoneCallParams to add a custom SDP attribute to.
* @param[in] type The type of the stream to add a custom SDP attribute to.
* @param[in] attribute_name The name of the attribute to add.
* @param[in] attribute_value The content value of the attribute to add.
* @ingroup media_parameters
**/
LINPHONE_PUBLIC void linphone_call_params_add_custom_sdp_media_attribute(LinphoneCallParams *params, LinphoneStreamType type, const char *attribute_name, const char *attribute_value);
/**
* Get a custom SDP attribute that is related to all the streams.
* @param[in] params The #LinphoneCallParams to get the custom SDP attribute from.
* @param[in] attribute_name The name of the attribute to get.
* @return The content value of the attribute or NULL if not found.
* @ingroup media_parameters
**/
LINPHONE_PUBLIC const char * linphone_call_params_get_custom_sdp_attribute(const LinphoneCallParams *params, const char *attribute_name);
/**
* Get a custom SDP attribute that is related to a specific stream.
* @param[in] params The #LinphoneCallParams to get the custom SDP attribute from.
* @param[in] type The type of the stream to add a custom SDP attribute to.
* @param[in] attribute_name The name of the attribute to get.
* @return The content value of the attribute or NULL if not found.
* @ingroup media_parameters
**/
LINPHONE_PUBLIC const char * linphone_call_params_get_custom_sdp_media_attribute(const LinphoneCallParams *params, LinphoneStreamType type, const char *attribute_name);
/**
* Clear the custom SDP attributes related to all the streams in the SDP exchanged within SIP messages during a call.
* @param[in] params The #LinphoneCallParams to clear the custom SDP attributes from.
* @ingroup media_parameters
**/
LINPHONE_PUBLIC void linphone_call_params_clear_custom_sdp_attributes(LinphoneCallParams *params);
/**
* Clear the custom SDP attributes related to a specific stream in the SDP exchanged within SIP messages during a call.
* @param[in] params The #LinphoneCallParams to clear the custom SDP attributes from.
* @param[in] type The type of the stream to clear the custom SDP attributes from.
* @ingroup media_parameters
**/
LINPHONE_PUBLIC void linphone_call_params_clear_custom_sdp_media_attributes(LinphoneCallParams *params, LinphoneStreamType type);
/*******************************************************************************

View file

@ -26,7 +26,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "lpconfig.h"
// stat
#ifndef WIN32
#ifndef _WIN32
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
@ -35,10 +35,19 @@ 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->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);
int result=0;
int otherdesc_changed;
char *tmp1=NULL;
char *tmp2=NULL;
if (call->params->in_conference != call->current_params->in_conference) return SAL_MEDIA_DESCRIPTION_FORCE_STREAM_RECONSTRUCTION;
if (call->up_bw != linphone_core_get_upload_bandwidth(call->core)) return SAL_MEDIA_DESCRIPTION_FORCE_STREAM_RECONSTRUCTION;
if (call->localdesc_changed) ms_message("Local description has changed: %s", tmp1 = sal_media_description_print_differences(call->localdesc_changed));
otherdesc_changed = sal_media_description_equals(oldmd, newmd);
if (otherdesc_changed) ms_message("Other description has changed: %s", tmp2 = sal_media_description_print_differences(otherdesc_changed));
result = call->localdesc_changed | otherdesc_changed;
if (tmp1) ms_free(tmp1);
if (tmp2) ms_free(tmp2);
return result;
}
void linphone_core_update_streams_destinations(LinphoneCore *lc, LinphoneCall *call, SalMediaDescription *old_md, SalMediaDescription *new_md) {
@ -47,7 +56,7 @@ void linphone_core_update_streams_destinations(LinphoneCore *lc, LinphoneCall *c
char *rtp_addr, *rtcp_addr;
int i;
for (i = 0; i < new_md->nb_streams; i++) {
for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) {
if (!sal_stream_description_active(&new_md->streams[i])) continue;
if (new_md->streams[i].type == SalAudio) {
new_audiodesc = &new_md->streams[i];
@ -109,18 +118,16 @@ void linphone_call_update_frozen_payloads(LinphoneCall *call, SalMediaDescriptio
/*new codec, needs to be added to the list*/
local->streams[i].already_assigned_payloads=ms_list_append(local->streams[i].already_assigned_payloads, payload_type_clone(pt));
ms_message("LinphoneCall[%p] : payload type %i %s/%i fmtp=%s added to frozen list.",
call, payload_type_get_number(pt), pt->mime_type, pt->clock_rate, pt->recv_fmtp ? pt->recv_fmtp : NULL);
call, payload_type_get_number(pt), pt->mime_type, pt->clock_rate, pt->recv_fmtp ? pt->recv_fmtp : "");
}
}
}
}
void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMediaDescription *new_md){
void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMediaDescription *new_md, LinphoneCallState target_state){
SalMediaDescription *oldmd=call->resultdesc;
bool_t all_muted=FALSE;
bool_t send_ringbacktone=FALSE;
int md_changed=0;
if (!((call->state == LinphoneCallIncomingEarlyMedia) && (linphone_core_get_ring_during_incoming_early_media(lc)))) {
linphone_core_stop_ringing(lc);
@ -129,20 +136,8 @@ void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMedia
ms_error("linphone_core_update_streams() called with null media description");
return;
}
if (call->biggestdesc==NULL || new_md->nb_streams>call->biggestdesc->nb_streams){
/*we have been offered and now are ready to proceed, or we added a new stream*/
/*store the media description to remember the mapping of calls*/
if (call->biggestdesc){
sal_media_description_unref(call->biggestdesc);
call->biggestdesc=NULL;
}
if (sal_call_is_offerer(call->op))
call->biggestdesc=sal_media_description_ref(call->localdesc);
else
call->biggestdesc=sal_media_description_ref(sal_call_get_remote_media_description(call->op));
}
linphone_call_update_biggest_desc(call, call->localdesc);
sal_media_description_ref(new_md);
call->expect_media_in_ack=FALSE;
call->resultdesc=new_md;
if ((call->audiostream && call->audiostream->ms.state==MSStreamStarted) || (call->videostream && call->videostream->ms.state==MSStreamStarted)){
clear_early_media_destinations(call);
@ -152,7 +147,9 @@ void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMedia
md_changed = media_parameters_changed(call, oldmd, new_md);
if ((md_changed & ( SAL_MEDIA_DESCRIPTION_CODEC_CHANGED
|SAL_MEDIA_DESCRIPTION_STREAMS_CHANGED
|SAL_MEDIA_DESCRIPTION_NETWORK_XXXCAST_CHANGED))){
|SAL_MEDIA_DESCRIPTION_NETWORK_XXXCAST_CHANGED
|SAL_MEDIA_DESCRIPTION_ICE_RESTART_DETECTED
|SAL_MEDIA_DESCRIPTION_FORCE_STREAM_RECONSTRUCTION ))){
ms_message("Media descriptions are different, need to restart the streams.");
} else if ( call->playing_ringbacktone) {
ms_message("Playing ringback tone, will restart the streams.");
@ -188,8 +185,9 @@ void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMedia
linphone_call_stop_media_streams (call);
if (md_changed & SAL_MEDIA_DESCRIPTION_NETWORK_XXXCAST_CHANGED){
ms_message("Media ip type has changed, destroying sessions context on call [%p]",call);
ms_media_stream_sessions_uninit(&call->sessions[0]);
ms_media_stream_sessions_uninit(&call->sessions[1]);
ms_media_stream_sessions_uninit(&call->sessions[call->main_audio_stream_index]);
ms_media_stream_sessions_uninit(&call->sessions[call->main_video_stream_index]);
if (call->params->realtimetext_enabled) ms_media_stream_sessions_uninit(&call->sessions[call->main_text_stream_index]);
}
linphone_call_init_media_streams (call);
}
@ -198,25 +196,11 @@ void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMedia
/*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);
}
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){
all_muted=TRUE;
}
if (call->params->real_early_media && call->state==LinphoneCallOutgoingEarlyMedia){
prepare_early_media_forking(call);
}
#ifdef VIDEO_ENABLED
if (call->state==LinphoneCallPausing) {
/*change cam to noweb cam*/
call->cam = get_nowebcam_device();
} else if (call->state != LinphoneCallPaused) {
/*restaure web cam*/
call->cam = lc->video_conf.device;
}
#endif /*VIDEO*/
linphone_call_start_media_streams(call,all_muted,send_ringbacktone);
linphone_call_start_media_streams(call, target_state);
if (call->state==LinphoneCallPausing && call->paused_by_app && ms_list_size(lc->calls)==1){
linphone_core_play_named_tone(lc,LinphoneToneCallOnHold);
}
@ -343,7 +327,7 @@ static void call_received(SalOp *h){
call=linphone_call_new_incoming(lc,from_addr,to_addr,h);
linphone_call_make_local_media_description(lc,call);
linphone_call_make_local_media_description(call);
sal_call_set_local_media_description(call->op,call->localdesc);
md=sal_call_get_final_media_description(call->op);
if (md){
@ -359,7 +343,7 @@ static void call_received(SalOp *h){
linphone_call_ref(call); /*prevent the call from being destroyed while we are notifying, if the user declines within the state callback */
call->bg_task_id=sal_begin_background_task("liblinphone call notification", NULL, 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");
@ -382,7 +366,7 @@ static void try_early_media_forking(LinphoneCall *call, SalMediaDescription *md)
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;i<cur_md->nb_streams;++i){
for (i=0;i<SAL_MEDIA_DESCRIPTION_MAX_STREAMS;++i){
if (!sal_stream_description_active(&cur_md->streams[i])) continue;
ref_stream=&cur_md->streams[i];
new_stream=&md->streams[i];
@ -451,6 +435,8 @@ static void call_ringing(SalOp *h){
linphone_core_notify_display_status(lc,_("Remote ringing..."));
linphone_call_set_state(call,LinphoneCallOutgoingRinging,"Remote ringing");
}else{
/*initialize the remote call params by invoking linphone_call_get_remote_params(). This is useful as the SDP may not be present in the 200Ok*/
linphone_call_get_remote_params(call);
/*accept early media */
if ((call->audiostream && audio_stream_started(call->audiostream))
#ifdef VIDEO_ENABLED
@ -473,7 +459,7 @@ static void call_ringing(SalOp *h){
linphone_call_set_state(call,LinphoneCallOutgoingEarlyMedia,"Early media");
linphone_core_stop_ringing(lc);
ms_message("Doing early media...");
linphone_core_update_streams(lc,call,md);
linphone_core_update_streams(lc,call,md, call->state);
if ((linphone_call_params_get_audio_direction(linphone_call_get_current_params(call)) == LinphoneMediaDirectionInactive) && call->audiostream) {
if (lc->ringstream != NULL) return; /* Already ringing! */
start_remote_ring(lc, call);
@ -481,24 +467,41 @@ static void call_ringing(SalOp *h){
}
}
/*
* could be reach :
* - when the call is accepted
* - when a request is accepted (pause, resume)
*/
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, *rmd;
bool_t update_state=TRUE;
static void start_pending_refer(LinphoneCall *call){
linphone_core_start_refered_call(call->core, call,NULL);
}
if (call==NULL){
ms_warning("No call to accept.");
return ;
static void process_call_accepted(LinphoneCore *lc, LinphoneCall *call, SalOp *op){
SalMediaDescription *md, *rmd;
LinphoneCallState next_state = LinphoneCallIdle;
const char *next_state_str = NULL;
LinphoneTaskList tl;
switch (call->state){/*immediately notify the connected state, even if errors occur after*/
case LinphoneCallOutgoingProgress:
case LinphoneCallOutgoingRinging:
case LinphoneCallOutgoingEarlyMedia:
/*immediately notify the connected state*/
linphone_call_set_state(call,LinphoneCallConnected,"Connected");
{
char *tmp=linphone_call_get_remote_address_as_string (call);
char *msg=ms_strdup_printf(_("Call answered by %s"),tmp);
linphone_core_notify_display_status(lc,msg);
ms_free(tmp);
ms_free(msg);
}
break;
default:
break;
}
linphone_task_list_init(&tl);
rmd=sal_call_get_remote_media_description(op);
/*set privacy*/
call->current_params->privacy=(LinphonePrivacyMask)sal_op_get_privacy(call->op);
/*reset the internal call update flag, so it doesn't risk to be copied and used in further re-INVITEs*/
if (call->params->internal_call_update)
call->params->internal_call_update = FALSE;
/* Handle remote ICE attributes if any. */
if (call->ice_session != NULL && rmd) {
@ -511,130 +514,108 @@ static void call_accepted(SalOp *op){
#endif //BUILD_UPNP
md=sal_call_get_final_media_description(op);
switch (call->state){
case LinphoneCallOutgoingProgress:
case LinphoneCallOutgoingRinging:
case LinphoneCallOutgoingEarlyMedia:
linphone_call_set_state(call,LinphoneCallConnected,"Connected");
if (call->referer) linphone_core_notify_refer_state(lc,call->referer,call);
break;
case LinphoneCallEarlyUpdating:
linphone_call_set_state(call,call->prevstate,"Early update accepted");
update_state=FALSE;
break;
default:
break;
if (md == NULL && call->prevstate == LinphoneCallOutgoingEarlyMedia && call->resultdesc != NULL){
ms_message("Using early media SDP since none was received with the 200 OK");
md = call->resultdesc;
}
if( (call->prevstate == LinphoneCallOutgoingEarlyMedia) && (md == NULL || sal_media_description_empty(md)) ){
/* media description is null or empty because no SDP was received in the 200 OK, we can possibly use the early-media SDP. */
if( call->resultdesc != NULL){
ms_message("Using early media SDP since none were received with the 200 OK");
md = call->resultdesc;
}
if (md && (sal_media_description_empty(md) || linphone_core_incompatible_security(lc,md))){
md = NULL;
}
if (md && !sal_media_description_empty(md) && !linphone_core_incompatible_security(lc,md)){
linphone_call_update_remote_session_id_and_ver(call);
linphone_core_update_ice_state_in_call_stats(call);
if (sal_media_description_has_dir(md,SalStreamSendOnly) ||
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);
linphone_core_notify_display_status(lc,msg);
ms_free(tmp);
ms_free(msg);
}
linphone_core_update_streams (lc,call,md);
if (update_state) linphone_call_set_state(call,LinphoneCallPaused,"Call paused");
if (call->refer_pending)
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 */
{
char *tmp=linphone_call_get_remote_address_as_string (call);
char *msg=ms_strdup_printf(_("Call answered by %s - on hold."),tmp);
linphone_core_notify_display_status(lc,msg);
ms_free(tmp);
ms_free(msg);
}
linphone_core_update_streams (lc,call,md);
if (update_state) linphone_call_set_state(call,LinphoneCallPausedByRemote,"Call paused by remote");
}else{
if (call->state!=LinphoneCallUpdating){
if (call->state==LinphoneCallResuming){
linphone_core_notify_display_status(lc,_("Call resumed."));
if (md){ /*there is a valid SDP in the response, either offer or answer, and we're able to start/update the streams*/
switch (call->state){
case LinphoneCallResuming:
linphone_core_notify_display_status(lc,_("Call resumed."));
/*intentionally no break*/
case LinphoneCallConnected:
if (call->referer) linphone_core_notify_refer_state(lc,call->referer,call);
/*intentionally no break*/
case LinphoneCallUpdating:
case LinphoneCallUpdatedByRemote:
if (!sal_media_description_has_dir(call->localdesc, SalStreamInactive) &&
(sal_media_description_has_dir(md,SalStreamRecvOnly) ||
sal_media_description_has_dir(md,SalStreamInactive))){
next_state = LinphoneCallPausedByRemote;
next_state_str = "Call paused by remote";
}else{
{
char *tmp=linphone_call_get_remote_address_as_string (call);
char *msg=ms_strdup_printf(_("Call answered by %s."),tmp);
linphone_core_notify_display_status(lc,msg);
ms_free(tmp);
ms_free(msg);
}
if (!call->params->in_conference)
lc->current_call=call;
next_state = LinphoneCallStreamsRunning;
next_state_str = "Streams running";
}
}
linphone_core_update_streams(lc,call,md);
/*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)
lc->current_call=call;
if (update_state) linphone_call_set_state(call, LinphoneCallStreamsRunning, "Streams running");
break;
case LinphoneCallEarlyUpdating:
next_state_str = "Early update accepted";
next_state = call->prevstate;
break;
case LinphoneCallPausing:
/*when we entered the pausing state, we always reach the paused state whatever the content of the remote SDP is.
Our streams are all send-only (with music), soundcard and camera are never used*/
next_state = LinphoneCallPaused;
next_state_str = "Call paused";
if (call->refer_pending)
linphone_task_list_add(&tl, (LinphoneCoreIterateHook)start_pending_refer, call);
break;
default:
ms_error("call_accepted(): don't know what to do in state [%s]", linphone_call_state_to_string(call->state));
break;
}
}else{
if (next_state != LinphoneCallIdle){
linphone_call_update_remote_session_id_and_ver(call);
linphone_core_update_ice_state_in_call_stats(call);
linphone_core_update_streams(lc, call, md, next_state);
linphone_call_fix_call_parameters(call, rmd);
linphone_call_set_state(call, next_state, next_state_str);
}else{
ms_error("BUG: next_state is not set in call_accepted(), current state is %s", linphone_call_state_to_string(call->state));
}
}else{ /*invalid or no SDP*/
switch (call->prevstate){
/*send a bye only in case of outgoing state*/
/*send a bye only in case of early states*/
case LinphoneCallOutgoingInit:
case LinphoneCallOutgoingProgress:
case LinphoneCallOutgoingRinging:
case LinphoneCallOutgoingEarlyMedia:
ms_error("Incompatible SDP offer received in 200 OK, need to abort the call");
case LinphoneCallIncomingReceived:
case LinphoneCallIncomingEarlyMedia:
ms_error("Incompatible SDP answer received, need to abort the call");
linphone_core_abort_call(lc,call,_("Incompatible, check codecs or security settings..."));
break;
/*otherwise we are able to resume previous state*/
default:
ms_message("Incompatible SDP offer received in 200 OK, restoring previous state[%s]",linphone_call_state_to_string(call->prevstate));
ms_message("Incompatible SDP answer received, restoring previous state [%s]",linphone_call_state_to_string(call->prevstate));
linphone_call_set_state(call,call->prevstate,_("Incompatible media parameters."));
break;
}
}
linphone_task_list_run(&tl);
linphone_task_list_free(&tl);
}
static void call_ack(SalOp *op){
/*
* could be reach :
* - when the call is accepted
* - when a request is accepted (pause, resume)
*/
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);
if (call==NULL){
ms_warning("No call to be ACK'd");
if (call == NULL){
ms_warning("call_accepted: call does no longer exist.");
return ;
}
if (call->expect_media_in_ack){
SalMediaDescription *md=sal_call_get_final_media_description(op);
if (md && !sal_media_description_empty(md)){
linphone_core_update_streams(lc,call,md);
linphone_call_set_state (call,LinphoneCallStreamsRunning,"Connected (streams running)");
}else{
/*send a bye*/
ms_error("Incompatible SDP response received in ACK, need to abort the call");
linphone_core_abort_call(lc,call,"No codec intersection");
return;
}
}
process_call_accepted(lc, call, op);
}
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);
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){
LinphoneCallParams *params;
/*when we are paused, increment session id, because sdp is changed (a=recvonly appears)*/
linphone_call_increment_local_media_description(call);
/* we are being paused */
linphone_core_notify_display_status(lc,_("We are paused by other party."));
params = linphone_call_params_copy(call->params);
@ -645,106 +626,59 @@ static void call_paused_by_remote(LinphoneCore *lc, LinphoneCall *call){
linphone_call_params_unref(params);
}
static void call_updated_by_remote(LinphoneCore *lc, LinphoneCall *call, bool_t is_update){
/*first check if media capabilities are compatible*/
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);
static void call_updated_by_remote(LinphoneCore *lc, LinphoneCall *call){
linphone_core_notify_display_status(lc,_("Call is updated by remote."));
linphone_call_set_state(call, LinphoneCallUpdatedByRemote,"Call updated by remote");
if (call->defer_update == FALSE){
linphone_core_accept_call_update(lc,call,NULL);
}else{
if (call->state == LinphoneCallUpdatedByRemote){
ms_message("LinphoneCall [%p]: UpdatedByRemoted was signaled but defered. LinphoneCore expects the application to call "
"linphone_core_accept_call_update() later.", call);
}
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_POLICY_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 ( call->state == LinphoneCallStreamsRunning) {
/*reINVITE and in-dialogs UPDATE go here*/
linphone_core_notify_display_status(lc,_("Call is updated by remote."));
call->defer_update = lp_config_get_int(lc->config, "sip", "defer_update_default", FALSE);
linphone_call_set_state(call, LinphoneCallUpdatedByRemote,"Call updated by remote");
if (call->defer_update==FALSE){
linphone_core_accept_call_update(lc,call,NULL);
}
if (rmd==NULL){
call->expect_media_in_ack=TRUE;
}
} else if( call->state == LinphoneCallPausedByRemote ){
/* Case where no SDP is present and we were paused by remote.
* We send back an ACK with our SDP and expect the remote to send its own.
* No state change here until an answer is received. */
call->defer_update = lp_config_get_int(lc->config, "sip", "defer_update_default", FALSE);
if (call->defer_update==FALSE){
_linphone_core_accept_call_update(lc,call,NULL,call->state,linphone_call_state_to_string(call->state));
}
if (rmd==NULL){
call->expect_media_in_ack=TRUE;
}
} else if (is_update){ /*SIP UPDATE case, can occur in early states*/
linphone_call_set_state(call, LinphoneCallEarlyUpdatedByRemote, "EarlyUpdatedByRemote");
_linphone_core_accept_call_update(lc,call,NULL,call->prevstate,linphone_call_state_to_string(call->prevstate));
}
}
/* this callback is called when an incoming re-INVITE/ SIP UPDATE modifies the session*/
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);
static void call_updated(LinphoneCore *lc, LinphoneCall *call, SalOp *op, bool_t is_update){
SalMediaDescription *rmd=sal_call_get_remote_media_description(op);
if (rmd==NULL){
/* case of a reINVITE or UPDATE without SDP */
call_updated_by_remote(lc,call,is_update);
return;
}
call->defer_update = lp_config_get_int(lc->config, "sip", "defer_update_default", FALSE);
switch(call->state){
case LinphoneCallPausedByRemote:
if (sal_media_description_has_dir(rmd,SalStreamSendRecv) || sal_media_description_has_dir(rmd,SalStreamRecvOnly)){
call_resumed(lc,call);
}else call_updated_by_remote(lc,call,is_update);
}else{
call_updated_by_remote(lc, call);
}
break;
/*SIP UPDATE CASE*/
case LinphoneCallOutgoingRinging:
case LinphoneCallOutgoingEarlyMedia:
case LinphoneCallIncomingEarlyMedia:
if (is_update) call_updated_by_remote(lc,call,is_update);
if (is_update) {
linphone_call_set_state(call, LinphoneCallEarlyUpdatedByRemote, "EarlyUpdatedByRemote");
_linphone_core_accept_call_update(lc,call,NULL,call->prevstate,linphone_call_state_to_string(call->prevstate));
}
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,is_update);
call_updated_by_remote(lc, call);
}
break;
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);
}
/*we'll remain in pause state but accept the offer anyway according to default parameters*/
_linphone_core_accept_call_update(lc,call,NULL,call->state,linphone_call_state_to_string(call->state));
break;
case LinphoneCallUpdating:
case LinphoneCallPausing:
case LinphoneCallResuming:
case LinphoneCallUpdatedByRemote:
sal_call_decline(call->op,SalReasonNotImplemented,NULL);
sal_call_decline(call->op,SalReasonInternalError,NULL);
/*no break*/
case LinphoneCallIdle:
case LinphoneCallOutgoingInit:
@ -761,6 +695,78 @@ static void call_updating(SalOp *op, bool_t is_update){
}
}
/* this callback is called when an incoming re-INVITE/ SIP UPDATE modifies the session*/
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 (!call) {
ms_error("call_updating(): call doesn't exist anymore");
return ;
}
linphone_call_fix_call_parameters(call, rmd);
if (call->state!=LinphoneCallPaused){
/*Refresh the local description, but in paused state, we don't change anything.*/
if (rmd == NULL && lp_config_get_int(call->core->config,"sip","sdp_200_ack_follow_video_policy",0)) {
LinphoneCallParams *p=linphone_core_create_call_params(lc, NULL);
ms_message("Applying default policy for offering SDP on call [%p]",call);
linphone_call_set_new_params(call, p);
linphone_call_params_destroy(p);
}
linphone_call_make_local_media_description(call);
sal_call_set_local_media_description(call->op,call->localdesc);
}
if (rmd == NULL){
/* case of a reINVITE or UPDATE without SDP */
call->expect_media_in_ack = TRUE;
sal_call_accept(op); /*respond with an offer*/
/*don't do anything else in this case, wait for the ACK to receive to notify the app*/
}else {
SalMediaDescription *md;
SalMediaDescription *prev_result_desc=call->resultdesc;
call->expect_media_in_ack = FALSE;
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_POLICY_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;
}
}
call_updated(lc, call, op, is_update);
}
}
static void call_ack(SalOp *op){
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op);
if (call == NULL){
ms_warning("call_ack(): no call for which an ack is expected");
return;
}
if (call->expect_media_in_ack){
switch(call->state){
case LinphoneCallStreamsRunning:
case LinphoneCallPausedByRemote:
linphone_call_set_state(call, LinphoneCallUpdatedByRemote, "UpdatedByRemote");
break;
default:
break;
}
process_call_accepted(lc, call, op);
}
}
static void call_terminated(SalOp *op, const char *from){
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op);
@ -770,7 +776,7 @@ static void call_terminated(SalOp *op, const char *from){
switch(linphone_call_get_state(call)){
case LinphoneCallEnd:
case LinphoneCallError:
ms_warning("call_terminated: ignoring.");
ms_warning("call_terminated: already terminated, ignoring.");
return;
break;
case LinphoneCallIncomingReceived:
@ -917,16 +923,11 @@ static void call_failure(SalOp *op){
msg=_("Incompatible media parameters.");
linphone_core_notify_display_status(lc,msg);
break;
case SalReasonRequestPending:
/*restore previous state, the application will decide to resubmit the action if relevant*/
linphone_call_set_state(call,call->prevstate,msg);
return;
break;
default:
linphone_core_notify_display_status(lc,_("Call failed."));
}
/*some call error are not fatal*/
/*some call errors are not fatal*/
switch (call->state) {
case LinphoneCallUpdating:
case LinphoneCallPausing:
@ -978,7 +979,7 @@ static void auth_failure(SalOp *op, SalAuthInfo* info) {
LinphoneAuthInfo *ai=NULL;
if( info != NULL ){
ai = (LinphoneAuthInfo*)linphone_core_find_auth_info(lc,info->realm,info->username,info->domain);
ai = (LinphoneAuthInfo*)_linphone_core_find_auth_info(lc,info->realm,info->username,info->domain, TRUE);
if (ai){
ms_message("%s/%s/%s authentication fails.",info->realm,info->username,info->domain);
@ -1057,6 +1058,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 (!call) return;
linphone_core_notify_dtmf_received(lc, call, dtmf);
}
@ -1116,6 +1118,7 @@ static void text_received(SalOp *op, const SalMessage *msg){
static void is_composing_received(SalOp *op, const SalIsComposing *is_composing) {
LinphoneCore *lc = (LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
linphone_core_is_composing_received(lc, op, is_composing);
sal_op_release(op);
}
static void parse_presence_requested(SalOp *op, const char *content_type, const char *content_subtype, const char *body, SalPresenceModel **result) {
@ -1157,35 +1160,40 @@ static void ping_reply(SalOp *op){
}
static bool_t fill_auth_info_with_client_certificate(LinphoneCore *lc, SalAuthInfo* sai) {
const char *chain_file = lp_config_get_string(lc->config,"sip","client_cert_chain", 0);
const char *key_file = lp_config_get_string(lc->config,"sip","client_cert_key", 0);;
const char *chain_file = lp_config_get_string(lc->config,"sip","client_cert_chain", 0);
const char *key_file = lp_config_get_string(lc->config,"sip","client_cert_key", 0);;
#ifndef WIN32
{
// optinal check for files
struct stat st;
if (stat(key_file,&st)) {
ms_warning("No client certificate key found in %s", key_file);
return FALSE;
}
if (stat(chain_file,&st)) {
ms_warning("No client certificate chain found in %s", chain_file);
return FALSE;
}
}
#ifndef _WIN32
{
// optinal check for files
struct stat st;
if (stat(key_file,&st)) {
ms_warning("No client certificate key found in %s", key_file);
return FALSE;
}
if (stat(chain_file,&st)) {
ms_warning("No client certificate chain found in %s", chain_file);
return FALSE;
}
}
#endif
sal_certificates_chain_parse_file(sai, chain_file, SAL_CERTIFICATE_RAW_FORMAT_PEM );
sal_signing_key_parse_file(sai, key_file, "");
return sai->certificates && sai->key;
sal_certificates_chain_parse_file(sai, chain_file, SAL_CERTIFICATE_RAW_FORMAT_PEM );
sal_signing_key_parse_file(sai, key_file, "");
return sai->certificates && sai->key;
}
static bool_t fill_auth_info(LinphoneCore *lc, SalAuthInfo* sai) {
LinphoneAuthInfo *ai=(LinphoneAuthInfo*)linphone_core_find_auth_info(lc,sai->realm,sai->username,sai->domain);
LinphoneAuthInfo *ai=(LinphoneAuthInfo*)_linphone_core_find_auth_info(lc,sai->realm,sai->username,sai->domain, FALSE);
if (ai) {
sai->userid=ms_strdup(ai->userid?ai->userid:ai->username);
sai->password=ai->passwd?ms_strdup(ai->passwd):NULL;
sai->ha1=ai->ha1?ms_strdup(ai->ha1):NULL;
if (sai->realm && !ai->realm){
/*if realm was not known, then set it so that ha1 may eventually be calculated and clear text password dropped*/
linphone_auth_info_set_realm(ai, sai->realm);
linphone_core_write_auth_info(lc, ai);
}
return TRUE;
} else {
return FALSE;
@ -1259,18 +1267,9 @@ static void text_delivery_update(SalOp *op, SalTextDeliveryStatus status){
// Do not handle delivery status for isComposing messages.
return;
}
chat_msg->state=chatStatusSal2Linphone(status);
linphone_chat_message_update_state(chat_msg);
if (chat_msg && (chat_msg->cb || (chat_msg->callbacks && linphone_chat_message_cbs_get_msg_state_changed(chat_msg->callbacks)))) {
ms_message("Notifying text delivery with status %i",chat_msg->state);
if (chat_msg->callbacks && linphone_chat_message_cbs_get_msg_state_changed(chat_msg->callbacks)) {
linphone_chat_message_cbs_get_msg_state_changed(chat_msg->callbacks)(chat_msg, chat_msg->state);
} else {
/* Legacy */
chat_msg->cb(chat_msg,chat_msg->state,chat_msg->cb_ud);
}
// check that the message does not belong to an already destroyed chat room - if so, do not invoke callbacks
if (chat_msg->chat_room != NULL) {
linphone_chat_message_update_state(chat_msg, chatStatusSal2Linphone(status));
}
if (status != SalTextDeliveryInProgress) { /*only release op if not in progress*/
linphone_chat_message_destroy(chat_msg);

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,592 @@
/***************************************************************************
* chat_file_transfer.c
*
* Sun Jun 5 19:34:18 2005
* Copyright 2005 Simon Morlat
* Email simon dot morlat at linphone dot org
****************************************************************************/
/*
* 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 "linphonecore.h"
#include "private.h"
#include "lime.h"
#include "ortp/b64.h"
#define FILE_TRANSFER_KEY_SIZE 32
static bool_t file_transfer_in_progress_and_valid(LinphoneChatMessage* msg) {
return (msg->chat_room && msg->http_request && !belle_http_request_is_cancelled(msg->http_request));
}
static void _release_http_request(LinphoneChatMessage* msg) {
if (msg->http_request) {
belle_sip_object_unref(msg->http_request);
msg->http_request = NULL;
if (msg->http_listener){
belle_sip_object_unref(msg->http_listener);
msg->http_listener = NULL;
// unhold the reference that the listener was holding on the message
linphone_chat_message_unref(msg);
}
}
}
static void linphone_chat_message_process_io_error_upload(void *data, const belle_sip_io_error_event_t *event) {
LinphoneChatMessage *msg = (LinphoneChatMessage *)data;
ms_error("I/O Error during file upload of msg [%p]", msg);
linphone_chat_message_set_state(msg, LinphoneChatMessageStateNotDelivered);
_release_http_request(msg);
}
static void linphone_chat_message_process_auth_requested_upload(void *data, belle_sip_auth_event_t *event) {
LinphoneChatMessage *msg = (LinphoneChatMessage *)data;
ms_error("Error during file upload: auth requested for msg [%p]", msg);
linphone_chat_message_set_state(msg, LinphoneChatMessageStateNotDelivered);
_release_http_request(msg);
}
static void linphone_chat_message_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 msg [%p]", msg);
linphone_chat_message_set_state(msg, LinphoneChatMessageStateFileTransferError);
_release_http_request(msg);
}
static void linphone_chat_message_process_auth_requested_download(void *data, belle_sip_auth_event_t *event) {
LinphoneChatMessage *msg = (LinphoneChatMessage *)data;
ms_error("Error during file download : auth requested for msg [%p]", msg);
linphone_chat_message_set_state(msg, LinphoneChatMessageStateFileTransferError);
_release_http_request(msg);
}
static void linphone_chat_message_file_transfer_on_progress(belle_sip_body_handler_t *bh, belle_sip_message_t *m,
void *data, size_t offset, size_t total) {
LinphoneChatMessage *msg = (LinphoneChatMessage *)data;
if (msg->http_request && !file_transfer_in_progress_and_valid(msg)) {
ms_warning("Cancelled request for %s msg [%p], ignoring %s", msg->chat_room?"":"ORPHAN", msg, __FUNCTION__);
_release_http_request(msg);
return;
}
if (linphone_chat_message_cbs_get_file_transfer_progress_indication(msg->callbacks)) {
linphone_chat_message_cbs_get_file_transfer_progress_indication(msg->callbacks)(
msg, msg->file_transfer_information, offset, total);
} else {
/* Legacy: call back given by application level */
linphone_core_notify_file_transfer_progress_indication(msg->chat_room->lc, msg, msg->file_transfer_information,
offset, total);
}
}
static int linphone_chat_message_file_transfer_on_send_body(belle_sip_user_body_handler_t *bh, belle_sip_message_t *m,
void *data, size_t offset, uint8_t *buffer, size_t *size) {
LinphoneChatMessage *msg = (LinphoneChatMessage *)data;
LinphoneCore *lc = NULL;
char *buf = (char *)buffer;
if (msg->http_request && !file_transfer_in_progress_and_valid(msg)) {
ms_warning("Cancelled request for %s msg [%p], ignoring %s", msg->chat_room?"":"ORPHAN", msg, __FUNCTION__);
_release_http_request(msg);
return BELLE_SIP_STOP;
}
lc = msg->chat_room->lc;
/* if we've not reach the end of file yet, ask for more data*/
if (offset < linphone_content_get_size(msg->file_transfer_information)) {
char *plainBuffer = NULL;
if (linphone_content_get_key(msg->file_transfer_information) !=
NULL) { /* if we have a key to cipher the msg, use it! */
/* if this chunk is not the last one, the lenght must be a multiple of block cipher size(16 bytes)*/
if (offset + *size < linphone_content_get_size(msg->file_transfer_information)) {
*size -= (*size % 16);
}
plainBuffer = (char *)ms_malloc0(*size);
}
/* get data from call back */
if (linphone_chat_message_cbs_get_file_transfer_send(msg->callbacks)) {
LinphoneBuffer *lb = linphone_chat_message_cbs_get_file_transfer_send(msg->callbacks)(
msg, msg->file_transfer_information, offset, *size);
if (lb == NULL) {
*size = 0;
} else {
*size = linphone_buffer_get_size(lb);
memcpy(plainBuffer ? plainBuffer : buf, linphone_buffer_get_content(lb), *size);
linphone_buffer_unref(lb);
}
} else {
/* Legacy */
linphone_core_notify_file_transfer_send(lc, msg, msg->file_transfer_information,
plainBuffer ? plainBuffer : buf, size);
}
if (linphone_content_get_key(msg->file_transfer_information) !=
NULL) { /* if we have a key to cipher the msg, use it! */
lime_encryptFile(linphone_content_get_cryptoContext_address(msg->file_transfer_information),
(unsigned char *)linphone_content_get_key(msg->file_transfer_information), *size,
plainBuffer, (char *)buffer);
ms_free(plainBuffer);
/* check if we reach the end of file */
if (offset + *size >= linphone_content_get_size(msg->file_transfer_information)) {
/* conclude file ciphering by calling it context with a zero size */
lime_encryptFile(linphone_content_get_cryptoContext_address(msg->file_transfer_information), NULL, 0,
NULL, NULL);
}
}
}
return BELLE_SIP_CONTINUE;
}
static void linphone_chat_message_process_response_from_post_file(void *data,
const belle_http_response_event_t *event) {
LinphoneChatMessage *msg = (LinphoneChatMessage *)data;
if (msg->http_request && !file_transfer_in_progress_and_valid(msg)) {
ms_warning("Cancelled request for %s msg [%p], ignoring %s", msg->chat_room?"":"ORPHAN", msg, __FUNCTION__);
_release_http_request(msg);
return;
}
/* check the answer code */
if (event->response) {
int code = belle_http_response_get_status_code(event->response);
if (code == 204) { /* this is the reply to the first post to the server - an empty msg */
/* start uploading the file */
belle_sip_multipart_body_handler_t *bh;
char *first_part_header;
belle_sip_body_handler_t *first_part_bh;
/* shall we encrypt the file */
if (linphone_core_lime_for_file_sharing_enabled(msg->chat_room->lc)) {
char keyBuffer
[FILE_TRANSFER_KEY_SIZE]; /* temporary storage of generated key: 192 bits of key + 64 bits of
initial vector */
/* generate a random 192 bits key + 64 bits of initial vector and store it into the
* file_transfer_information->key field of the msg */
sal_get_random_bytes((unsigned char *)keyBuffer, FILE_TRANSFER_KEY_SIZE);
linphone_content_set_key(
msg->file_transfer_information, keyBuffer,
FILE_TRANSFER_KEY_SIZE); /* key is duplicated in the content private structure */
/* temporary storage for the Content-disposition header value : use a generic filename to not leak it
* Actual filename stored in msg->file_transfer_information->name will be set in encrypted msg
* sended to the */
first_part_header = belle_sip_strdup_printf("form-data; name=\"File\"; filename=\"filename.txt\"");
} else {
/* temporary storage for the Content-disposition header value */
first_part_header = belle_sip_strdup_printf("form-data; name=\"File\"; filename=\"%s\"",
linphone_content_get_name(msg->file_transfer_information));
}
/* create a user body handler to take care of the file and add the content disposition and content-type
* headers */
if (msg->file_transfer_filepath != NULL) {
first_part_bh =
(belle_sip_body_handler_t *)belle_sip_file_body_handler_new(msg->file_transfer_filepath, NULL, msg);
} else if (linphone_content_get_buffer(msg->file_transfer_information) != NULL) {
first_part_bh = (belle_sip_body_handler_t *)belle_sip_memory_body_handler_new_from_buffer(
linphone_content_get_buffer(msg->file_transfer_information),
linphone_content_get_size(msg->file_transfer_information), NULL, msg);
} else {
first_part_bh = (belle_sip_body_handler_t *)belle_sip_user_body_handler_new(
linphone_content_get_size(msg->file_transfer_information), NULL, NULL,
linphone_chat_message_file_transfer_on_send_body, msg);
}
belle_sip_body_handler_add_header(first_part_bh,
belle_sip_header_create("Content-disposition", first_part_header));
belle_sip_free(first_part_header);
belle_sip_body_handler_add_header(first_part_bh,
(belle_sip_header_t *)belle_sip_header_content_type_create(
linphone_content_get_type(msg->file_transfer_information),
linphone_content_get_subtype(msg->file_transfer_information)));
/* insert it in a multipart body handler which will manage the boundaries of multipart msg */
bh = belle_sip_multipart_body_handler_new(linphone_chat_message_file_transfer_on_progress, msg, first_part_bh, NULL);
linphone_chat_message_ref(msg);
_release_http_request(msg);
linphone_chat_room_upload_file(msg);
belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(msg->http_request), BELLE_SIP_BODY_HANDLER(bh));
linphone_chat_message_unref(msg);
} else 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);
if (body && strlen(body) > 0) {
/* if we have an encryption key for the file, we must insert it into the msg and restore the correct
* filename */
if (linphone_content_get_key(msg->file_transfer_information) != NULL) {
/* parse the msg body */
xmlDocPtr xmlMessageBody = xmlParseDoc((const xmlChar *)body);
xmlNodePtr cur = xmlDocGetRootElement(xmlMessageBody);
if (cur != NULL) {
cur = cur->xmlChildrenNode;
while (cur != NULL) {
if (!xmlStrcmp(cur->name, (const xmlChar *)"file-info")) { /* we found a file info node, check
it has a type="file" attribute */
xmlChar *typeAttribute = xmlGetProp(cur, (const xmlChar *)"type");
if (!xmlStrcmp(typeAttribute,
(const xmlChar *)"file")) { /* this is the node we are looking for : add a
file-key children node */
xmlNodePtr fileInfoNodeChildren =
cur
->xmlChildrenNode; /* need to parse the children node to update the file-name
one */
/* convert key to base64 */
size_t b64Size = b64_encode(NULL, FILE_TRANSFER_KEY_SIZE, NULL, 0);
char *keyb64 = (char *)ms_malloc0(b64Size + 1);
int xmlStringLength;
b64Size = b64_encode(linphone_content_get_key(msg->file_transfer_information),
FILE_TRANSFER_KEY_SIZE, keyb64, b64Size);
keyb64[b64Size] = '\0'; /* libxml need a null terminated string */
/* add the node containing the key to the file-info node */
xmlNewTextChild(cur, NULL, (const xmlChar *)"file-key", (const xmlChar *)keyb64);
xmlFree(typeAttribute);
ms_free(keyb64);
/* look for the file-name node and update its content */
while (fileInfoNodeChildren != NULL) {
if (!xmlStrcmp(
fileInfoNodeChildren->name,
(const xmlChar *)"file-name")) { /* we found a the file-name node, update
its content with the real filename */
/* update node content */
xmlNodeSetContent(fileInfoNodeChildren,
(const xmlChar *)(linphone_content_get_name(
msg->file_transfer_information)));
break;
}
fileInfoNodeChildren = fileInfoNodeChildren->next;
}
/* dump the xml into msg->message */
xmlDocDumpFormatMemoryEnc(xmlMessageBody, (xmlChar **)&msg->message, &xmlStringLength,
"UTF-8", 0);
break;
}
xmlFree(typeAttribute);
}
cur = cur->next;
}
}
xmlFreeDoc(xmlMessageBody);
} else { /* no encryption key, transfer in plain, just copy the msg sent by server */
msg->message = ms_strdup(body);
}
msg->content_type = ms_strdup("application/vnd.gsma.rcs-ft-http+xml");
linphone_chat_message_set_state(msg, LinphoneChatMessageStateFileTransferDone);
linphone_chat_message_ref(msg);
_release_http_request(msg);
_linphone_chat_room_send_message(msg->chat_room, msg);
linphone_chat_message_unref(msg);
} else {
ms_warning("Received empty response from server, file transfer failed");
linphone_chat_message_set_state(msg, LinphoneChatMessageStateNotDelivered);
_release_http_request(msg);
}
} else {
ms_warning("Unhandled HTTP code response %d for file transfer", code);
linphone_chat_message_set_state(msg, LinphoneChatMessageStateNotDelivered);
_release_http_request(msg);
}
}
}
const LinphoneContent *linphone_chat_message_get_file_transfer_information(const LinphoneChatMessage *msg) {
return msg->file_transfer_information;
}
static void on_recv_body(belle_sip_user_body_handler_t *bh, belle_sip_message_t *m, void *data, size_t offset,
const uint8_t *buffer, size_t size) {
LinphoneChatMessage *msg = (LinphoneChatMessage *)data;
LinphoneCore *lc = msg->chat_room->lc;
if (!msg->http_request || belle_http_request_is_cancelled(msg->http_request)) {
ms_warning("Cancelled request for msg [%p], ignoring %s", msg, __FUNCTION__);
return;
}
if (!msg->chat_room) {
linphone_chat_message_cancel_file_transfer(msg);
}
/* first call may be with a zero size, ignore it */
if (size == 0) {
return;
}
if (linphone_content_get_key(msg->file_transfer_information) !=
NULL) { /* we have a key, we must decrypt the file */
/* get data from callback to a plainBuffer */
char *plainBuffer = (char *)ms_malloc0(size);
lime_decryptFile(linphone_content_get_cryptoContext_address(msg->file_transfer_information),
(unsigned char *)linphone_content_get_key(msg->file_transfer_information), size, plainBuffer,
(char *)buffer);
if (linphone_chat_message_cbs_get_file_transfer_recv(msg->callbacks)) {
LinphoneBuffer *lb = linphone_buffer_new_from_data((unsigned char *)plainBuffer, size);
linphone_chat_message_cbs_get_file_transfer_recv(msg->callbacks)(msg, msg->file_transfer_information, lb);
linphone_buffer_unref(lb);
} else {
/* legacy: call back given by application level */
linphone_core_notify_file_transfer_recv(lc, msg, msg->file_transfer_information, plainBuffer, size);
}
ms_free(plainBuffer);
} else { /* regular file, no deciphering */
if (linphone_chat_message_cbs_get_file_transfer_recv(msg->callbacks)) {
LinphoneBuffer *lb = linphone_buffer_new_from_data(buffer, size);
linphone_chat_message_cbs_get_file_transfer_recv(msg->callbacks)(msg, msg->file_transfer_information, lb);
linphone_buffer_unref(lb);
} else {
/* Legacy: call back given by application level */
linphone_core_notify_file_transfer_recv(lc, msg, msg->file_transfer_information, (char *)buffer, size);
}
}
return;
}
static LinphoneContent *linphone_chat_create_file_transfer_information_from_headers(const belle_sip_message_t *m) {
LinphoneContent *content = linphone_content_new();
belle_sip_header_content_length_t *content_length_hdr =
BELLE_SIP_HEADER_CONTENT_LENGTH(belle_sip_message_get_header(m, "Content-Length"));
belle_sip_header_content_type_t *content_type_hdr =
BELLE_SIP_HEADER_CONTENT_TYPE(belle_sip_message_get_header(m, "Content-Type"));
const char *type = NULL, *subtype = NULL;
linphone_content_set_name(content, "");
if (content_type_hdr) {
type = belle_sip_header_content_type_get_type(content_type_hdr);
subtype = belle_sip_header_content_type_get_subtype(content_type_hdr);
ms_message("Extracted content type %s / %s from header", type ? type : "", subtype ? subtype : "");
if (type)
linphone_content_set_type(content, type);
if (subtype)
linphone_content_set_subtype(content, subtype);
}
if (content_length_hdr) {
linphone_content_set_size(content, belle_sip_header_content_length_get_content_length(content_length_hdr));
ms_message("Extracted content length %i from header", (int)linphone_content_get_size(content));
}
return content;
}
static void linphone_chat_process_response_headers_from_get_file(void *data, const belle_http_response_event_t *event) {
LinphoneChatMessage *msg = (LinphoneChatMessage *)data;
if (event->response) {
/*we are receiving a response, set a specific body handler to acquire the response.
* if not done, belle-sip will create a memory body handler, the default*/
belle_sip_message_t *response = BELLE_SIP_MESSAGE(event->response);
size_t body_size = 0;
if (msg->file_transfer_information == NULL) {
ms_warning("No file transfer information for msg %p: creating...", msg);
msg->file_transfer_information = linphone_chat_create_file_transfer_information_from_headers(response);
}
if (msg->file_transfer_information) {
body_size = linphone_content_get_size(msg->file_transfer_information);
}
if (msg->file_transfer_filepath == NULL) {
belle_sip_message_set_body_handler(
(belle_sip_message_t *)event->response,
(belle_sip_body_handler_t *)belle_sip_user_body_handler_new(
body_size, linphone_chat_message_file_transfer_on_progress, on_recv_body, NULL, msg));
} else {
belle_sip_body_handler_t *bh = (belle_sip_body_handler_t *)belle_sip_file_body_handler_new(
msg->file_transfer_filepath, linphone_chat_message_file_transfer_on_progress, msg);
if (belle_sip_body_handler_get_size(bh) == 0) {
/* If the size of the body has not been initialized from the file stat, use the one from the
* file_transfer_information. */
belle_sip_body_handler_set_size(bh, body_size);
}
belle_sip_message_set_body_handler((belle_sip_message_t *)event->response, bh);
}
}
}
static void linphone_chat_process_response_from_get_file(void *data, const belle_http_response_event_t *event) {
LinphoneChatMessage *msg = (LinphoneChatMessage *)data;
/* check the answer code */
if (event->response) {
int code = belle_http_response_get_status_code(event->response);
if (code == 200) {
LinphoneCore *lc = msg->chat_room->lc;
/* if the file was encrypted, finish the decryption and free context */
if (linphone_content_get_key(msg->file_transfer_information) != NULL) {
lime_decryptFile(linphone_content_get_cryptoContext_address(msg->file_transfer_information), NULL, 0,
NULL, NULL);
}
/* file downloaded succesfully, call again the callback with size at zero */
if (linphone_chat_message_cbs_get_file_transfer_recv(msg->callbacks)) {
LinphoneBuffer *lb = linphone_buffer_new();
linphone_chat_message_cbs_get_file_transfer_recv(msg->callbacks)(msg, msg->file_transfer_information,
lb);
linphone_buffer_unref(lb);
} else {
linphone_core_notify_file_transfer_recv(lc, msg, msg->file_transfer_information, NULL, 0);
}
linphone_chat_message_set_state(msg, LinphoneChatMessageStateFileTransferDone);
} else if (code >= 400 && code < 500) {
ms_warning("File transfer failed with code %d", code);
linphone_chat_message_set_state(msg, LinphoneChatMessageStateFileTransferError);
} else {
ms_warning("Unhandled HTTP code response %d for file transfer", code);
}
_release_http_request(msg);
}
}
int _linphone_chat_room_start_http_transfer(LinphoneChatMessage *msg, const char* url, const char* action, const belle_http_request_listener_callbacks_t *cbs) {
belle_generic_uri_t *uri = NULL;
char* ua;
if (url == NULL) {
ms_warning("Cannot process file transfer msg: no file remote URI configured.");
goto error;
}
uri = belle_generic_uri_parse(url);
if (uri == NULL || belle_generic_uri_get_host(uri)==NULL) {
ms_warning("Cannot process file transfer msg: incorrect file remote URI configured '%s'.", url);
goto error;
}
ua = ms_strdup_printf("%s/%s", linphone_core_get_user_agent_name(), linphone_core_get_user_agent_version());
msg->http_request = belle_http_request_create(action, uri, belle_sip_header_create("User-Agent", ua), NULL);
ms_free(ua);
if (msg->http_request == NULL) {
ms_warning("Could not create http request for uri %s", url);
goto error;
}
/* keep a reference to the http request to be able to cancel it during upload */
belle_sip_object_ref(msg->http_request);
/* give msg to listener to be able to start the actual file upload when server answer a 204 No content */
msg->http_listener = belle_http_request_listener_create_from_callbacks(cbs, linphone_chat_message_ref(msg));
belle_http_provider_send_request(msg->chat_room->lc->http_provider, msg->http_request, msg->http_listener);
return 0;
error:
if (uri) {
belle_sip_object_unref(uri);
}
return -1;
}
int linphone_chat_room_upload_file(LinphoneChatMessage *msg) {
belle_http_request_listener_callbacks_t cbs = {0};
int err;
if (msg->http_request){
ms_error("linphone_chat_room_upload_file(): there is already an upload in progress.");
return -1;
}
cbs.process_response = linphone_chat_message_process_response_from_post_file;
cbs.process_io_error = linphone_chat_message_process_io_error_upload;
cbs.process_auth_requested = linphone_chat_message_process_auth_requested_upload;
err = _linphone_chat_room_start_http_transfer(msg, linphone_core_get_file_transfer_server(msg->chat_room->lc), "POST", &cbs);
if (err == -1){
linphone_chat_message_set_state(msg, LinphoneChatMessageStateNotDelivered);
}
return err;
}
int linphone_chat_message_download_file(LinphoneChatMessage *msg) {
belle_http_request_listener_callbacks_t cbs = {0};
int err;
if (msg->http_request){
ms_error("linphone_chat_message_download_file(): there is already a download in progress");
return -1;
}
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 = linphone_chat_message_process_io_error_download;
cbs.process_auth_requested = linphone_chat_message_process_auth_requested_download;
err = _linphone_chat_room_start_http_transfer(msg, msg->external_body_url, "GET", &cbs);
if (err == -1) return -1;
/* start the download, status is In Progress */
linphone_chat_message_set_state(msg, LinphoneChatMessageStateInProgress);
return 0;
}
void linphone_chat_message_start_file_download(LinphoneChatMessage *msg,
LinphoneChatMessageStateChangedCb status_cb, void *ud) {
msg->message_state_changed_cb = status_cb;
msg->message_state_changed_user_data = ud;
linphone_chat_message_download_file(msg);
}
void linphone_chat_message_cancel_file_transfer(LinphoneChatMessage *msg) {
if (msg->http_request) {
if (msg->state == LinphoneChatMessageStateInProgress) {
linphone_chat_message_set_state(msg, LinphoneChatMessageStateNotDelivered);
}
if (!belle_http_request_is_cancelled(msg->http_request)) {
if (msg->chat_room) {
ms_message("Canceling file transfer %s - msg [%p] chat room[%p]"
, (msg->external_body_url == NULL) ? linphone_core_get_file_transfer_server(msg->chat_room->lc) : msg->external_body_url
, msg
, msg->chat_room);
belle_http_provider_cancel_request(msg->chat_room->lc->http_provider, msg->http_request);
} else {
ms_message("Warning: http request still running for ORPHAN msg [%p]: this is a memory leak", msg);
}
}
_release_http_request(msg);
} else {
ms_message("No existing file transfer - nothing to cancel");
}
}
void linphone_chat_message_set_file_transfer_filepath(LinphoneChatMessage *msg, const char *filepath) {
if (msg->file_transfer_filepath != NULL) {
ms_free(msg->file_transfer_filepath);
}
msg->file_transfer_filepath = ms_strdup(filepath);
}
const char *linphone_chat_message_get_file_transfer_filepath(LinphoneChatMessage *msg) {
return msg->file_transfer_filepath;
}
LinphoneChatMessage *linphone_chat_room_create_file_transfer_message(LinphoneChatRoom *cr,
const LinphoneContent *initial_content) {
LinphoneChatMessage *msg = belle_sip_object_new(LinphoneChatMessage);
msg->callbacks = linphone_chat_message_cbs_new();
msg->chat_room = (LinphoneChatRoom *)cr;
msg->message = NULL;
msg->is_read = TRUE;
msg->file_transfer_information = linphone_content_copy(initial_content);
msg->dir = LinphoneChatMessageOutgoing;
linphone_chat_message_set_to(msg, linphone_chat_room_get_peer_address(cr));
msg->from = linphone_address_new(linphone_core_get_identity(cr->lc)); /*direct assignment*/
/* 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->content_type = NULL;
/* this will store the http request during file upload to the server */
msg->http_request = NULL;
msg->time = ms_time(0);
return msg;
}

View file

@ -22,7 +22,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 "private.h"
#include "lpconfig.h"
@ -87,7 +87,7 @@ void linphone_core_conference_check_uninit(LinphoneCore *lc){
ctx->record_endpoint=NULL;
}
}
if (ms_audio_conference_get_size(ctx->conf)==0){
ms_audio_conference_destroy(ctx->conf);
ctx->conf=NULL;
@ -110,7 +110,7 @@ void linphone_call_add_to_conf(LinphoneCall *call, bool_t muted){
void linphone_call_remove_from_conf(LinphoneCall *call){
LinphoneCore *lc=call->core;
LinphoneConference *conf=&lc->conf_ctx;
ms_audio_conference_remove_member(conf->conf,call->endpoint);
ms_audio_endpoint_release_from_stream(call->endpoint);
call->endpoint=NULL;
@ -128,12 +128,12 @@ static void add_local_endpoint(LinphoneConference *conf,LinphoneCore *lc){
/*create a dummy audiostream in order to extract the local part of it */
/* network address and ports have no meaning and are not used here. */
AudioStream *st=audio_stream_new(65000,65001,FALSE);
MSSndCard *playcard=lc->sound_conf.lsd_card ?
MSSndCard *playcard=lc->sound_conf.lsd_card ?
lc->sound_conf.lsd_card : lc->sound_conf.play_sndcard;
MSSndCard *captcard=lc->sound_conf.capt_sndcard;
const MSAudioConferenceParams *params=ms_audio_conference_get_params(conf->conf);
conf->local_dummy_profile=make_dummy_profile(params->samplerate);
audio_stream_start_full(st, conf->local_dummy_profile,
"127.0.0.1",
65000,
@ -151,7 +151,7 @@ static void add_local_endpoint(LinphoneConference *conf,LinphoneCore *lc){
conf->local_participant=st;
conf->local_endpoint=ms_audio_endpoint_get_from_stream(st,FALSE);
ms_audio_conference_add_member(conf->conf,conf->local_endpoint);
}
/**
@ -166,7 +166,7 @@ float linphone_core_get_conference_local_input_volume(LinphoneCore *lc){
float vol=0;
ms_filter_call_method(st->volsend,MS_VOLUME_GET,&vol);
return vol;
}
return LINPHONE_VOLUME_DB_LOWEST;
}
@ -175,22 +175,22 @@ float linphone_core_get_conference_local_input_volume(LinphoneCore *lc){
* Merge a call into a conference.
* @param lc the linphone core
* @param call an established call, either in LinphoneCallStreamsRunning or LinphoneCallPaused state.
*
*
* If this is the first call that enters the conference, the virtual conference will be created automatically.
* If the local user was actively part of the call (ie not in paused state), then the local user is automatically entered into the conference.
* If the call was in paused state, then it is automatically resumed when entering into the conference.
*
*
* @return 0 if successful, -1 otherwise.
**/
int linphone_core_add_to_conference(LinphoneCore *lc, LinphoneCall *call){
LinphoneConference *conf=&lc->conf_ctx;
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;
@ -199,7 +199,7 @@ int linphone_core_add_to_conference(LinphoneCore *lc, LinphoneCall *call){
LinphoneCallParams *params=linphone_call_params_copy(linphone_call_get_current_params(call));
params->in_conference=TRUE;
params->has_video=FALSE;
if (call->audiostream || call->videostream){
linphone_call_stop_media_streams(call); /*free the audio & video local resources*/
linphone_call_init_media_streams(call);
@ -276,21 +276,6 @@ static int convert_conference_to_call(LinphoneCore *lc){
return err;
}
/**
* Remove a call from the conference.
* @param lc the linphone core
* @param call a call that has been previously merged into the conference.
*
* After removing the remote participant belonging to the supplied call, the call becomes a normal call in paused state.
* If one single remote participant is left alone together with the local user in the conference after the removal, then the conference is
* automatically transformed into a simple call in StreamsRunning state.
* The conference's resources are then automatically destroyed.
*
* In other words, unless linphone_core_leave_conference() is explicitely called, the last remote participant of a conference is automatically
* put in a simple call in running state.
*
* @return 0 if successful, -1 otherwise.
**/
int linphone_core_remove_from_conference(LinphoneCore *lc, LinphoneCall *call){
int err;
char * str=linphone_call_get_remote_address_as_string(call);
@ -311,11 +296,6 @@ int linphone_core_remove_from_conference(LinphoneCore *lc, LinphoneCall *call){
return err;
}
/**
* Indicates whether the local participant is part of the conference.
* @param lc the linphone core
* @return TRUE if the local participant is in the conference, FALSE otherwise.
**/
bool_t linphone_core_is_in_conference(const LinphoneCore *lc){
return lc->conf_ctx.local_participant!=NULL;
}
@ -336,12 +316,12 @@ int linphone_core_leave_conference(LinphoneCore *lc){
/**
* Moves the local participant inside the conference.
* @param lc the linphone core
*
* Makes the local participant to join the conference.
*
* Makes the local participant to join the conference.
* Typically, the local participant is by default always part of the conference when joining an active call into a conference.
* However, by calling linphone_core_leave_conference() and linphone_core_enter_conference() the application can decide to temporarily
* move out and in the local participant from the conference.
*
*
* @return 0 if successful, -1 otherwise
**/
int linphone_core_enter_conference(LinphoneCore *lc){
@ -360,9 +340,9 @@ int linphone_core_enter_conference(LinphoneCore *lc){
/**
* Add all calls into a conference.
* @param lc the linphone core
*
*
* Merge all established calls (either in LinphoneCallStreamsRunning or LinphoneCallPaused) into a conference.
*
*
* @return 0 if successful, -1 otherwise
**/
int linphone_core_add_all_to_conference(LinphoneCore *lc) {
@ -381,9 +361,9 @@ int linphone_core_add_all_to_conference(LinphoneCore *lc) {
/**
* Terminates the conference and the calls associated with it.
* @param lc the linphone core
*
*
* All the calls that were merged to the conference are terminated, and the conference resources are destroyed.
*
*
* @return 0 if successful, -1 otherwise
**/
int linphone_core_terminate_conference(LinphoneCore *lc) {
@ -404,10 +384,10 @@ int linphone_core_terminate_conference(LinphoneCore *lc) {
/**
* Returns the number of participants to the conference, including the local participant.
* @param lc the linphone core
*
*
* Typically, after merging two calls into the conference, there is total of 3 participants:
* the local participant (or local user), and two remote participants that were the destinations of the two previously establised calls.
*
*
* @return the number of participants to the conference
**/
int linphone_core_get_conference_size(LinphoneCore *lc) {

View file

@ -103,7 +103,7 @@ int linphone_dictionary_haskey(const LinphoneDictionary* obj, const char* key)
void linphone_dictionary_foreach(const LinphoneDictionary* obj, void (*apply_func)(const char*, void*, void*), void* userdata)
{
return belle_sip_dict_foreach(obj, apply_func, userdata);
belle_sip_dict_foreach(obj, apply_func, userdata);
}
struct lp_config_to_dict {

View file

@ -114,8 +114,10 @@ static void ecc_deinit_filters(EcCalibrator *ecc){
static void on_tone_sent(void *data, MSFilter *f, unsigned int event_id, void *arg){
MSDtmfGenEvent *ev=(MSDtmfGenEvent*)arg;
EcCalibrator *ecc=(EcCalibrator*)data;
ecc->acc-=ev->tone_start_time;
ms_message("Sent tone at %u",(unsigned int)ev->tone_start_time);
if (ev->tone_name[0] != '\0'){
ecc->acc-=ev->tone_start_time;
ms_message("Sent tone at %u",(unsigned int)ev->tone_start_time);
}
}
static bool_t is_valid_tone(EcCalibrator *ecc, MSToneDetectorEvent *ev){
@ -159,23 +161,23 @@ static void ecc_play_tones(EcCalibrator *ecc){
/* configure the tones to be scanned */
strncpy(expected_tone.tone_name,"freq1",sizeof(expected_tone.tone_name));
expected_tone.frequency=2000;
expected_tone.frequency=(int)2349.32;
expected_tone.min_duration=40;
expected_tone.min_amplitude=0.1;
expected_tone.min_amplitude=0.1f;
ms_filter_call_method (ecc->det,MS_TONE_DETECTOR_ADD_SCAN,&expected_tone);
strncpy(expected_tone.tone_name,"freq2",sizeof(expected_tone.tone_name));
expected_tone.frequency=2300;
expected_tone.frequency=(int)2637.02;
expected_tone.min_duration=40;
expected_tone.min_amplitude=0.1;
expected_tone.min_amplitude=0.1f;
ms_filter_call_method (ecc->det,MS_TONE_DETECTOR_ADD_SCAN,&expected_tone);
strncpy(expected_tone.tone_name,"freq3",sizeof(expected_tone.tone_name));
expected_tone.frequency=2500;
expected_tone.frequency=(int)2093;
expected_tone.min_duration=40;
expected_tone.min_amplitude=0.1;
expected_tone.min_amplitude=0.1f;
ms_filter_call_method (ecc->det,MS_TONE_DETECTOR_ADD_SCAN,&expected_tone);
@ -191,24 +193,40 @@ static void ecc_play_tones(EcCalibrator *ecc){
ms_filter_add_notify_callback(ecc->gen,on_tone_sent,ecc,TRUE);
/* play the three tones*/
tone.frequencies[0]=2000;
strncpy(tone.tone_name, "D", sizeof(tone.tone_name));
tone.frequencies[0]=(int)2349.32;
tone.duration=100;
ms_filter_call_method(ecc->gen,MS_DTMF_GEN_PLAY_CUSTOM,&tone);
ms_usleep(300000);
tone.frequencies[0]=2300;
strncpy(tone.tone_name, "E", sizeof(tone.tone_name));
tone.frequencies[0]=(int)2637.02;
tone.duration=100;
ms_filter_call_method(ecc->gen,MS_DTMF_GEN_PLAY_CUSTOM,&tone);
ms_usleep(300000);
tone.frequencies[0]=2500;
strncpy(tone.tone_name, "C", sizeof(tone.tone_name));
tone.frequencies[0]=(int)2093;
tone.duration=100;
ms_filter_call_method(ecc->gen,MS_DTMF_GEN_PLAY_CUSTOM,&tone);
ms_usleep(300000);
/*these two next ones are for lyrism*/
tone.tone_name[0]='\0';
tone.frequencies[0]=(int)1046.5;
tone.duration=400;
ms_filter_call_method(ecc->gen,MS_DTMF_GEN_PLAY_CUSTOM,&tone);
ms_usleep(300000);
tone.tone_name[0]='\0';
tone.frequencies[0]=(int)1567.98;
tone.duration=400;
ms_filter_call_method(ecc->gen,MS_DTMF_GEN_PLAY_CUSTOM,&tone);
ms_sleep(1);
if (ecc->freq1 && ecc->freq2 && ecc->freq3) {
int delay=ecc->acc/3;
int delay=(int)(ecc->acc/3);
if (delay<0){
ms_error("Quite surprising calibration result, delay=%i",delay);
ecc->status=LinphoneEcCalibratorFailed;

View file

@ -31,10 +31,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
static char *create_enum_domain(const char *number){
int len=strlen(number);
size_t len=strlen(number);
char *domain=ms_malloc((len*2)+10);
int i,j;
long i,j;
for (i=0,j=len-1;j>=0;j--){
domain[i]=number[j];
i++;
@ -105,11 +105,11 @@ int enum_lookup(const char *enum_domain, enum_lookup_res_t **res){
/*
ns_msg handle;
int count;
memset(&handle,0,sizeof(handle));
*res=NULL;
ms_message("Resolving %s...",enum_domain);
err=res_search(enum_domain,ns_c_in,ns_t_naptr,dns_answer,DNS_ANSWER_MAX_SIZE);
if (err<0){
ms_warning("Error resolving enum:",herror(h_errno));
@ -117,7 +117,7 @@ int enum_lookup(const char *enum_domain, enum_lookup_res_t **res){
}
ns_initparse(dns_answer,DNS_ANSWER_MAX_SIZE,&handle);
count=ns_msg_count(handle,ns_s_an);
for(i=0;i<count;i++){
ns_rr rr;
memset(&rr,0,sizeof(rr));
@ -136,9 +136,9 @@ int enum_lookup(const char *enum_domain, enum_lookup_res_t **res){
}else{
ms_warning("Could not spawn the \'host\' command.");
return -1;
}
}
ms_message("Answer received from dns (err=%i): %s",err,host_result);
begin=strstr(host_result,"sip:");
if (begin==0) {
ms_warning("No sip address found in dns naptr answer.");

View file

@ -120,7 +120,7 @@ void linphone_event_set_publish_state(LinphoneEvent *lev, LinphonePublishState s
/*nothing special to do*/
break;
}
}
}
@ -153,7 +153,7 @@ LinphoneEvent *linphone_core_subscribe(LinphoneCore *lc, const LinphoneAddress *
int linphone_event_send_subscribe(LinphoneEvent *lev, const LinphoneContent *body){
SalBody salbody;
int err;
if (lev->dir!=LinphoneSubscriptionOutgoing){
ms_error("linphone_event_send_subscribe(): cannot send or update something that is not an outgoing subscription.");
return -1;
@ -173,12 +173,12 @@ int linphone_event_send_subscribe(LinphoneEvent *lev, const LinphoneContent *bod
/*those states are ok*/
break;
}
if (lev->send_custom_headers){
sal_op_set_sent_custom_header(lev->op,lev->send_custom_headers);
lev->send_custom_headers=NULL;
}else sal_op_set_sent_custom_header(lev->op,NULL);
err=sal_subscribe(lev->op,NULL,NULL,lev->name,lev->expires,sal_body_from_content(&salbody,body));
if (err==0){
if (lev->subscription_state==LinphoneSubscriptionNone)
@ -238,7 +238,7 @@ LinphoneEvent *linphone_core_create_publish(LinphoneCore *lc, const LinphoneAddr
static int _linphone_event_send_publish(LinphoneEvent *lev, const LinphoneContent *body, bool_t notify_err){
SalBody salbody;
int err;
if (lev->dir!=LinphoneSubscriptionInvalidDir){
ms_error("linphone_event_update_publish(): this is not a PUBLISH event.");
return -1;
@ -276,7 +276,6 @@ int linphone_event_update_publish(LinphoneEvent* lev, const LinphoneContent* bod
return linphone_event_send_publish(lev,body);
}
void linphone_event_set_user_data(LinphoneEvent *ev, void *up){
ev->userdata=up;
}
@ -302,7 +301,7 @@ void linphone_event_terminate(LinphoneEvent *lev){
}else if (lev->dir==LinphoneSubscriptionOutgoing){
sal_unsubscribe(lev->op);
}
if (lev->publish_state!=LinphonePublishNone){
if (lev->publish_state==LinphonePublishOk && lev->expires!=-1){
sal_publish(lev->op,NULL,NULL,NULL,0,NULL);
@ -310,7 +309,7 @@ void linphone_event_terminate(LinphoneEvent *lev){
linphone_event_set_publish_state(lev,LinphonePublishCleared);
return;
}
if (lev->subscription_state!=LinphoneSubscriptionNone){
linphone_event_set_state(lev,LinphoneSubscriptionTerminated);
return;

View file

@ -92,7 +92,7 @@ LinphoneFriend *linphone_find_friend_by_inc_subscribe(MSList *l, SalOp *op){
MSList *elem;
for (elem=l;elem!=NULL;elem=elem->next){
LinphoneFriend *lf=(LinphoneFriend*)elem->data;
if (lf->insub==op) return lf;
if (ms_list_find(lf->insubs, op)) return lf;
}
return NULL;
}
@ -102,7 +102,7 @@ LinphoneFriend *linphone_find_friend_by_out_subscribe(MSList *l, SalOp *op){
LinphoneFriend *lf;
for (elem=l;elem!=NULL;elem=elem->next){
lf=(LinphoneFriend*)elem->data;
if (lf->outsub==op) return lf;
if (lf->outsub && (lf->outsub == op || sal_op_is_forked_of(lf->outsub, op))) return lf;
}
return NULL;
}
@ -227,12 +227,29 @@ int linphone_friend_set_inc_subscribe_policy(LinphoneFriend *fr, LinphoneSubscri
}
void linphone_friend_notify(LinphoneFriend *lf, LinphonePresenceModel *presence){
char *addr=linphone_address_as_string(linphone_friend_get_address(lf));
ms_message("Want to notify %s, insub=%p",addr,lf->insub);
ms_free(addr);
if (lf->insub!=NULL){
sal_notify_presence(lf->insub,(SalPresenceModel *)presence);
MSList *elem;
if (lf->insubs){
char *addr=linphone_address_as_string(linphone_friend_get_address(lf));
ms_message("Want to notify %s",addr);
ms_free(addr);
}
for(elem=lf->insubs; elem!=NULL; elem=elem->next){
SalOp *op = (SalOp*)elem->data;
sal_notify_presence(op,(SalPresenceModel *)presence);
}
}
void linphone_friend_add_incoming_subscription(LinphoneFriend *lf, SalOp *op){
/*ownership of the op is transfered from sal to the LinphoneFriend*/
lf->insubs = ms_list_append(lf->insubs, op);
}
void linphone_friend_remove_incoming_subscription(LinphoneFriend *lf, SalOp *op){
if (ms_list_find(lf->insubs, op)){
sal_op_release(op);
lf->insubs = ms_list_remove(lf->insubs, op);
}
}
static void linphone_friend_unsubscribe(LinphoneFriend *lf){
@ -260,17 +277,12 @@ static void linphone_friend_invalidate_subscription(LinphoneFriend *lf){
void linphone_friend_close_subscriptions(LinphoneFriend *lf){
linphone_friend_unsubscribe(lf);
if (lf->insub){
sal_notify_presence_close(lf->insub);
}
ms_list_for_each(lf->insubs, (MSIterateFunc) sal_notify_presence_close);
lf->insubs = ms_list_free_with_data(lf->insubs, (MSIterateFunc)sal_op_release);
}
static void _linphone_friend_destroy(LinphoneFriend *lf){
if (lf->insub) {
sal_op_release(lf->insub);
lf->insub=NULL;
}
lf->insubs = ms_list_free_with_data(lf->insubs, (MSIterateFunc) sal_op_release);
if (lf->outsub){
sal_op_release(lf->outsub);
lf->outsub=NULL;
@ -280,6 +292,17 @@ static void _linphone_friend_destroy(LinphoneFriend *lf){
if (lf->info!=NULL) buddy_info_free(lf->info);
}
static belle_sip_error_code _linphone_friend_marshall(belle_sip_object_t *obj, char* buff, size_t buff_size, size_t *offset) {
LinphoneFriend *lf = (LinphoneFriend*)obj;
belle_sip_error_code err = BELLE_SIP_OK;
if (lf->uri){
char *tmp = linphone_address_as_string(lf->uri);
err = belle_sip_snprintf(buff, buff_size, offset, "%s", tmp);
ms_free(tmp);
}
return err;
}
const LinphoneAddress *linphone_friend_get_address(const LinphoneFriend *lf){
return lf->uri;
}
@ -366,7 +389,7 @@ LinphoneOnlineStatus linphone_friend_get_status(const LinphoneFriend *lf){
break;
case LinphonePresenceActivityOnline:
/* Should not happen! */
ms_warning("LinphonePresenceActivityOnline should not happen here!");
/*ms_warning("LinphonePresenceActivityOnline should not happen here!");*/
break;
case LinphonePresenceActivityOffline:
online_status = LinphoneStatusOffline;
@ -481,6 +504,11 @@ void linphone_core_add_friend(LinphoneCore *lc, LinphoneFriend *lf)
return ;
}
lc->friends=ms_list_append(lc->friends,linphone_friend_ref(lf));
if (ms_list_find(lc->subscribers, lf)){
/*if this friend was in the pending subscriber list, now remove it from this list*/
lc->subscribers = ms_list_remove(lc->subscribers, lf);
linphone_friend_unref(lf);
}
lf->lc=lc;
if ( linphone_core_ready(lc)) linphone_friend_apply(lf,lc);
else lf->commit=TRUE;
@ -490,7 +518,7 @@ void linphone_core_add_friend(LinphoneCore *lc, LinphoneFriend *lf)
void linphone_core_remove_friend(LinphoneCore *lc, LinphoneFriend* fl){
MSList *el=ms_list_find(lc->friends,fl);
if (el!=NULL){
linphone_friend_destroy((LinphoneFriend*)el->data);
linphone_friend_unref((LinphoneFriend*)el->data);
lc->friends=ms_list_remove_link(lc->friends,el);
linphone_core_write_friends_config(lc);
}else{
@ -703,6 +731,6 @@ BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneFriend);
BELLE_SIP_INSTANCIATE_VPTR(LinphoneFriend, belle_sip_object_t,
(belle_sip_object_destroy_t) _linphone_friend_destroy,
NULL, // clone
NULL, // marshal
_linphone_friend_marshall,
FALSE
);

View file

@ -27,13 +27,8 @@ if(GIT_EXECUTABLE)
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
)
set(GIT_REVISION "unknown")
endif()
configure_file("${WORK_DIR}/gitversion.h.in" "${OUTPUT_DIR}/liblinphone_gitversion.h" @ONLY)

21
coreapi/gitversion.h.in Normal file
View file

@ -0,0 +1,21 @@
/*
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 LIBLINPHONE_GIT_VERSION "@GIT_REVISION@"

View file

@ -24,7 +24,7 @@ find_package(Doxygen)
if(DOXYGEN_FOUND)
if(DOXYGEN_DOT_FOUND)
set(top_srcdir ${CMAKE_SOURCE_DIR})
set(top_srcdir "${CMAKE_CURRENT_LIST_DIR}/../../")
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
file(GLOB DOC_INPUT_FILES
[^.]*.c
@ -36,7 +36,7 @@ if(DOXYGEN_FOUND)
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")
add_custom_target(linphone-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 "share/doc/linphone-${LINPHONE_VERSION}")
else()

View file

@ -46,7 +46,7 @@ clean-local:
if ENABLE_TUTORIALS
noinst_PROGRAMS=helloworld registration buddy_status chatroom notify filetransfer
noinst_PROGRAMS=helloworld registration buddy_status chatroom notify filetransfer realtimetext_sender realtimetext_receiver
helloworld_SOURCES=helloworld.c
LINPHONE_TUTOS=$(helloworld_SOURCES)
@ -81,6 +81,16 @@ LINPHONE_TUTOS+=$(filetransfer_SOURCES)
filetransfer_LDADD=$(helloworld_LDADD)
realtimetext_sender_SOURCES=realtimetext_sender.c
LINPHONE_TUTOS+=$(realtimetext_sender_SOURCES)
realtimetext_sender_LDADD=$(helloworld_LDADD)
realtimetext_receiver_SOURCES=realtimetext_receiver.c
LINPHONE_TUTOS+=$(realtimetext_receiver_SOURCES)
realtimetext_receiver_LDADD=$(helloworld_LDADD)
AM_CFLAGS=\
-I$(top_srcdir)/coreapi \
$(STRICT_OPTIONS) \

View file

@ -81,7 +81,7 @@ int main(int argc, char *argv[]){
/*Next step is to create a chat root*/
chat_room = linphone_core_create_chat_room(lc,dest_friend);
chat_room = linphone_core_get_chat_room_from_uri(lc,dest_friend);
linphone_chat_room_send_message(chat_room,"Hello world"); /*sending message*/
@ -92,7 +92,6 @@ int main(int argc, char *argv[]){
}
printf("Shutting down...\n");
linphone_chat_room_destroy(chat_room);
linphone_core_destroy(lc);
printf("Exited\n");
return 0;

View file

@ -160,7 +160,7 @@ int main(int argc, char *argv[]){
/*Next step is to create a chat room*/
chat_room = linphone_core_create_chat_room(lc,dest_friend);
chat_room = linphone_core_get_chat_room_from_uri(lc,dest_friend);
content = linphone_core_create_content(lc);
linphone_content_set_type(content,"text");
@ -196,7 +196,6 @@ int main(int argc, char *argv[]){
printf("Shutting down...\n");
linphone_content_unref(content);
linphone_chat_room_destroy(chat_room);
linphone_core_destroy(lc);
printf("Exited\n");
return 0;

View file

@ -104,7 +104,6 @@ public class TutorialBuddyStatus implements LinphoneCoreListener {
public void displayMessage(LinphoneCore lc, String message) {}
public void displayWarning(LinphoneCore lc, String message) {}
public void globalState(LinphoneCore lc, GlobalState state, String message) {}
public void textReceived(LinphoneCore lc, LinphoneChatRoom cr,LinphoneAddress from, String message) {}
public void callState(LinphoneCore lc, LinphoneCall call, State cstate, String msg) {}
public void callStatsUpdated(LinphoneCore lc, LinphoneCall call, LinphoneCallStats stats) {}
public void ecCalibrationStatus(LinphoneCore lc, EcCalibratorStatus status,int delay_ms, Object data) {}

View file

@ -90,10 +90,6 @@ public class TutorialChatRoom implements LinphoneCoreListener, LinphoneChatMessa
public void callEncryptionChanged(LinphoneCore lc, LinphoneCall call,boolean encrypted, String authenticationToken) {}
public void notifyReceived(LinphoneCore lc, LinphoneCall call, LinphoneAddress from, byte[] event){}
public void dtmfReceived(LinphoneCore lc, LinphoneCall call, int dtmf) {}
public void textReceived(LinphoneCore lc, LinphoneChatRoom cr,LinphoneAddress from, String message) {
//Deprecated
}

View file

@ -88,7 +88,6 @@ public class TutorialRegistration implements LinphoneCoreListener {
public void globalState(LinphoneCore lc, GlobalState state, String message) {}
public void newSubscriptionRequest(LinphoneCore lc, LinphoneFriend lf,String url) {}
public void notifyPresenceReceived(LinphoneCore lc, LinphoneFriend lf) {}
public void textReceived(LinphoneCore lc, LinphoneChatRoom cr,LinphoneAddress from, String message) {}
public void callState(LinphoneCore lc, LinphoneCall call, State cstate, String msg) {}
public void callStatsUpdated(LinphoneCore lc, LinphoneCall call, LinphoneCallStats stats) {}
public void ecCalibrationStatus(LinphoneCore lc, EcCalibratorStatus status,int delay_ms, Object data) {}

View file

@ -0,0 +1,115 @@
/*
linphone
Copyright (C) 2015 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.
*/
/**
* @defgroup real_time_text Real Time Text Receiver
* @ingroup tutorials
This program is able to receive chat message in real time on port 5060. Use realtimetext_sender to generate chat message
usage: ./realtimetext_receiver
@include realtimetext_sender.c
*/
#ifdef IN_LINPHONE
#include "linphonecore.h"
#else
#include "linphone/linphonecore.h"
#endif
#include <signal.h>
static bool_t running=TRUE;
static void stop(int signum){
running=FALSE;
}
/*
* Call state notification callback
*/
static void call_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cstate, const char *msg){
switch(cstate){
case LinphoneCallIncomingReceived:
printf("It is now ringing remotely !\n");
linphone_core_accept_call(lc,call);
break;
case LinphoneCallReleased:
printf("call terminated, exit...\n");
running=FALSE;
break;
default:
printf("Unhandled notification %i\n",cstate);
}
}
/*
* Completed message received
*/
static void message_received(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMessage *message) {
char *from=linphone_address_as_string(linphone_chat_room_get_peer_address(room));
printf(" Message [%s] received from [%s] \n",linphone_chat_message_get_text(message),from);
ms_free(from);
}
/*
*
* Remote is typing
*/
static void is_composing_received(LinphoneCore *lc, LinphoneChatRoom *room) {
LinphoneCall *call = linphone_chat_room_get_call(room); /*get corresponding call*/
if (call && linphone_call_params_realtime_text_enabled(linphone_call_get_current_params(call))) /*check if realtime text enabled for this call*/
printf("%c",linphone_chat_room_get_char(room));
/*else ignored*/
}
int main(int argc, char *argv[]){
LinphoneCoreVTable vtable={0};
LinphoneCore *lc;
signal(SIGINT,stop);
#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 call_state_changed callbacks
in order to get notifications about the progress of the call.
*/
vtable.call_state_changed=call_state_changed; /*to receive incoming call*/
vtable.message_received=message_received; /*to receive committed messages*/
vtable.is_composing_received=is_composing_received; /*to receive char in real time*/
/*
Instanciate a LinphoneCore object given the LinphoneCoreVTable
*/
lc=linphone_core_new(&vtable,NULL,NULL,NULL);
/* main loop for receiving notifications and doing background linphonecore work: */
while(running){
linphone_core_iterate(lc);
ms_usleep(50000);
}
printf("Shutting down...\n");
linphone_core_destroy(lc);
printf("Exited\n");
return 0;
}

View file

@ -0,0 +1,158 @@
/*
linphone
Copyright (C) 2015 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.
*/
/**
* @defgroup real_time_text Real Time Text Sender
* @ingroup tutorials
This program just send chat message in real time to dest uri. Use realtimetext_receiver to receive message.
usage: ./realtimetext_sender sip:localhost:5060
@include realtimetext_sender.c
*/
#ifdef IN_LINPHONE
#include "linphonecore.h"
#else
#include "linphone/linphonecore.h"
#endif
#include <signal.h>
static bool_t running=TRUE;
static void stop(int signum){
running=FALSE;
}
int main(int argc, char *argv[]){
LinphoneCoreVTable vtable={0};
LinphoneCore *lc;
LinphoneCall *call=NULL;
LinphoneChatRoom *chat_room;
LinphoneChatMessage *chat_message=NULL;
const char *dest=NULL;
LCSipTransports tp;
tp.udp_port=LC_SIP_TRANSPORT_RANDOM;
tp.tcp_port=LC_SIP_TRANSPORT_RANDOM;
tp.tls_port=LC_SIP_TRANSPORT_RANDOM;
/* take the destination sip uri from the command line arguments */
if (argc>1){
dest=argv[1];
}
signal(SIGINT,stop);
#ifdef DEBUG
linphone_core_enable_logs(NULL); /*enable liblinphone logs.*/
#endif
/*
Instanciate a LinphoneCore object given the LinphoneCoreVTable
*/
lc=linphone_core_new(&vtable,NULL,NULL,NULL);
linphone_core_set_sip_transports(lc,&tp); /*to avoid port colliding with receiver*/
if (dest){
/*
Place an outgoing call with rtt enabled
*/
LinphoneCallParams *cp = linphone_core_create_call_params(lc, NULL);
linphone_call_params_enable_realtime_text(cp,TRUE); /*enable real time text*/
call=linphone_core_invite_with_params(lc,dest,cp);
linphone_call_params_destroy(cp);
if (call==NULL){
printf("Could not place call to %s\n",dest);
goto end;
}else printf("Call to %s is in progress...",dest);
linphone_call_ref(call);
}
/*wait for call to be established*/
while (running && (linphone_call_get_state(call) == LinphoneCallOutgoingProgress
|| linphone_call_get_state(call) == LinphoneCallOutgoingInit)) {
linphone_core_iterate(lc);
ms_usleep(50000);
}
/*check if call is established*/
switch (linphone_call_get_state(call)) {
case LinphoneCallError:
case LinphoneCallReleased:
case LinphoneCallEnd:
printf("Could not place call to %s\n",dest);
goto end;
break;
default:
break;
/*continue*/
}
chat_room=linphone_call_get_chat_room(call); /*create a chat room associated to this call*/
/* main loop for sending message and doing background linphonecore work: */
while(running){
char character;
/*to disable terminal buffering*/
if (system ("/bin/stty raw") == -1){
ms_error("/bin/stty error");
}
character = getchar();
if (system("/bin/stty cooked") == -1){
ms_error("/bin/stty error");
}
if (character==0x03) {/*CTRL C*/
running=0;
break;
}
if (character != EOF) {
/* user has typed something*/
if (chat_message == NULL) {
/*create a new message*/
chat_message = linphone_chat_room_create_message(chat_room,""); /*create an empty message*/
}
if (character == '\r') {
/*new line, committing message*/
linphone_chat_room_send_chat_message(chat_room,chat_message);
chat_message = NULL; /*reset message*/
} else {
linphone_chat_message_put_char(chat_message,character); /*send char in realtime*/
}
}
linphone_core_iterate(lc);
ms_usleep(50000);
}
if (call && linphone_call_get_state(call)!=LinphoneCallEnd){
/* terminate the call */
printf("Terminating the call...\n");
linphone_core_terminate_call(lc,call);
/*at this stage we don't need the call object */
linphone_call_unref(call);
}
end:
printf("Shutting down...\n");
linphone_core_destroy(lc);
printf("Exited\n");
return 0;
}

View file

@ -38,4 +38,4 @@ LINPHONE_PUBLIC unsigned int linphone_ldap_contact_provider_get_
LINPHONE_PUBLIC LinphoneLDAPContactProvider* linphone_ldap_contact_provider_ref( void* obj );
void linphone_ldap_contact_provider_unref( void* obj );
LinphoneLDAPContactProvider* linphone_ldap_contact_provider_cast( void* obj );
LINPHONE_PUBLIC int linphone_ldap_contact_provider_available();
LINPHONE_PUBLIC int linphone_ldap_contact_provider_available(void);

View file

@ -182,5 +182,5 @@ LINPHONE_PUBLIC char *lime_error_code_to_string(int errorCode);
*
* @return TRUE if Lime is available, FALSE if not
*/
LINPHONE_PUBLIC bool_t lime_is_available();
LINPHONE_PUBLIC bool_t lime_is_available(void);
#endif /* LIME_H */

View file

@ -0,0 +1,535 @@
/*
Copyright (C) 2010-2015 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_PROXY_CONFIG_H
#define LINPHONE_PROXY_CONFIG_H
/**
* @addtogroup proxies
* @{
**/
/**
* Creates an empty proxy config.
* @deprecated, use #linphone_core_create_proxy_config instead
**/
LINPHONE_PUBLIC LinphoneProxyConfig *linphone_proxy_config_new(void);
/**
* Acquire a reference to the proxy config.
* @param[in] cfg #LinphoneProxyConfig object.
* @return The same proxy config.
**/
LINPHONE_PUBLIC LinphoneProxyConfig *linphone_proxy_config_ref(LinphoneProxyConfig *cfg);
/**
* Release reference to the proxy config.
* @param[in] cfg #LinphoneProxyConfig object.
**/
LINPHONE_PUBLIC void linphone_proxy_config_unref(LinphoneProxyConfig *cfg);
/**
* Retrieve the user pointer associated with the proxy config.
* @param[in] cfg #LinphoneProxyConfig object.
* @return The user pointer associated with the proxy config.
**/
LINPHONE_PUBLIC void *linphone_proxy_config_get_user_data(const LinphoneProxyConfig *cfg);
/**
* Assign a user pointer to the proxy config.
* @param[in] cfg #LinphoneProxyConfig object.
* @param[in] ud The user pointer to associate with the proxy config.
**/
LINPHONE_PUBLIC void linphone_proxy_config_set_user_data(LinphoneProxyConfig *cfg, void *ud);
/**
* Sets the proxy address
*
* Examples of valid sip proxy address are:
* - IP address: sip:87.98.157.38
* - IP address with port: sip:87.98.157.38:5062
* - hostnames : sip:sip.example.net
**/
LINPHONE_PUBLIC int linphone_proxy_config_set_server_addr(LinphoneProxyConfig *cfg, const char *server_addr);
/**
* @deprecated Use linphone_proxy_config_set_identity_address()
**/
LINPHONE_PUBLIC int linphone_proxy_config_set_identity(LinphoneProxyConfig *cfg, const char *identity);
/**
* Sets the user identity as a SIP address.
*
* This identity is normally formed with display name, username and domain, such
* as:
* Alice <sip:alice@example.net>
* The REGISTER messages will have from and to set to this identity.
*
**/
LINPHONE_PUBLIC int linphone_proxy_config_set_identity_address(LinphoneProxyConfig *cfg, const LinphoneAddress *identity);
/**
* Sets a SIP route.
* When a route is set, all outgoing calls will go to the route's destination if this proxy
* is the default one (see linphone_core_set_default_proxy() ).
* @Return -1 if route is invalid, 0 otherwise.
**/
LINPHONE_PUBLIC int linphone_proxy_config_set_route(LinphoneProxyConfig *cfg, const char *route);
/**
* Sets the registration expiration time in seconds.
**/
LINPHONE_PUBLIC void linphone_proxy_config_set_expires(LinphoneProxyConfig *cfg, int expires);
#define linphone_proxy_config_expires linphone_proxy_config_set_expires
/**
* Indicates either or not, REGISTRATION must be issued for this #LinphoneProxyConfig .
* <br> In case this #LinphoneProxyConfig has been added to #LinphoneCore, follows the linphone_proxy_config_edit() rule.
* @param[in] cfg #LinphoneProxyConfig object.
* @param val if true, registration will be engaged
*/
LINPHONE_PUBLIC void linphone_proxy_config_enable_register(LinphoneProxyConfig *cfg, bool_t val);
#define linphone_proxy_config_enableregister linphone_proxy_config_enable_register
/**
* Starts editing a proxy configuration.
*
* Because proxy configuration must be consistent, applications MUST
* call linphone_proxy_config_edit() before doing any attempts to modify
* proxy configuration (such as identity, proxy address and so on).
* Once the modifications are done, then the application must call
* linphone_proxy_config_done() to commit the changes.
**/
LINPHONE_PUBLIC void linphone_proxy_config_edit(LinphoneProxyConfig *cfg);
/**
* Commits modification made to the proxy configuration.
**/
LINPHONE_PUBLIC int linphone_proxy_config_done(LinphoneProxyConfig *cfg);
/**
* Indicates either or not, PUBLISH must be issued for this #LinphoneProxyConfig .
* <br> In case this #LinphoneProxyConfig has been added to #LinphoneCore, follows the linphone_proxy_config_edit() rule.
* @param[in] cfg #LinphoneProxyConfig object.
* @param val if true, publish will be engaged
*
*/
LINPHONE_PUBLIC void linphone_proxy_config_enable_publish(LinphoneProxyConfig *cfg, bool_t val);
/**
* Set the publish expiration time in second.
* @param[in] cfg #LinphoneProxyConfig object.
* @param expires in second
* */
LINPHONE_PUBLIC void linphone_proxy_config_set_publish_expires(LinphoneProxyConfig *cfg, int expires);
/**
* get the publish expiration time in second. Default value is the registration expiration value.
* @param[in] cfg #LinphoneProxyConfig object.
* @return expires in second
* */
LINPHONE_PUBLIC int linphone_proxy_config_get_publish_expires(const LinphoneProxyConfig *cfg);
/**
* Sets whether liblinphone should replace "+" by international calling prefix in dialed numbers (passed to
* #linphone_core_invite ).
**/
LINPHONE_PUBLIC void linphone_proxy_config_set_dial_escape_plus(LinphoneProxyConfig *cfg, bool_t val);
/**
* Sets a dialing prefix to be automatically prepended when inviting a number with
* linphone_core_invite();
* This dialing prefix shall usually be the country code of the country where the user is living, without "+".
*
**/
LINPHONE_PUBLIC void linphone_proxy_config_set_dial_prefix(LinphoneProxyConfig *cfg, const char *prefix);
/**
* Indicates whether quality statistics during call should be stored and sent to a collector according to RFC 6035.
* @param[in] cfg #LinphoneProxyConfig object.
* @param[in] enable True to sotre quality statistics and sent them to the collector, false to disable it.
*/
LINPHONE_PUBLIC void linphone_proxy_config_enable_quality_reporting(LinphoneProxyConfig *cfg, bool_t enable);
/**
* Indicates whether quality statistics during call should be stored and sent to a collector according to RFC 6035.
* @param[in] cfg #LinphoneProxyConfig object.
* @return True if quality repotring is enabled, false otherwise.
*/
LINPHONE_PUBLIC bool_t linphone_proxy_config_quality_reporting_enabled(LinphoneProxyConfig *cfg);
/**
* Set the route of the collector end-point when using quality reporting. This SIP address
* should be used on server-side to process packets directly before discarding packets. Collector address
* should be a non existing account and will not receive any messages.
* If NULL, reports will be send to the proxy domain.
* @param[in] cfg #LinphoneProxyConfig object.
* @param[in] collector route of the collector end-point, if NULL PUBLISH will be sent to the proxy domain.
*/
LINPHONE_PUBLIC void linphone_proxy_config_set_quality_reporting_collector(LinphoneProxyConfig *cfg, const char *collector);
/**
* Get the route of the collector end-point when using quality reporting. This SIP address
* should be used on server-side to process packets directly before discarding packets. Collector address
* should be a non existing account and will not receive any messages.
* If NULL, reports will be send to the proxy domain.
* @param[in] cfg #LinphoneProxyConfig object.
* @return The SIP address of the collector end-point.
*/
LINPHONE_PUBLIC const char *linphone_proxy_config_get_quality_reporting_collector(const LinphoneProxyConfig *cfg);
/**
* Set the interval between 2 interval reports sending when using quality reporting. If call exceed interval size, an
* interval report will be sent to the collector. On call termination, a session report will be sent
* for the remaining period. Value must be 0 (disabled) or positive.
* @param[in] cfg #LinphoneProxyConfig object.
* @param[in] interval The interval in seconds, 0 means interval reports are disabled.
*/
LINPHONE_PUBLIC void linphone_proxy_config_set_quality_reporting_interval(LinphoneProxyConfig *cfg, uint8_t interval);
/**
* Get the interval between interval reports when using quality reporting.
* @param[in] cfg #LinphoneProxyConfig object.
* @return The interval in seconds, 0 means interval reports are disabled.
*/
LINPHONE_PUBLIC int linphone_proxy_config_get_quality_reporting_interval(LinphoneProxyConfig *cfg);
/**
* Get the registration state of the given proxy config.
* @param[in] cfg #LinphoneProxyConfig object.
* @return The registration state of the proxy config.
**/
LINPHONE_PUBLIC LinphoneRegistrationState linphone_proxy_config_get_state(const LinphoneProxyConfig *cfg);
/**
* @return a boolean indicating that the user is sucessfully registered on the proxy.
* @deprecated Use linphone_proxy_config_get_state() instead.
**/
LINPHONE_PUBLIC bool_t linphone_proxy_config_is_registered(const LinphoneProxyConfig *cfg);
/**
* Get the domain name of the given proxy config.
* @param[in] cfg #LinphoneProxyConfig object.
* @return The domain name of the proxy config.
**/
LINPHONE_PUBLIC const char *linphone_proxy_config_get_domain(const LinphoneProxyConfig *cfg);
/**
* Get the realm of the given proxy config.
* @param[in] cfg #LinphoneProxyConfig object.
* @return The realm of the proxy config.
**/
LINPHONE_PUBLIC const char *linphone_proxy_config_get_realm(const LinphoneProxyConfig *cfg);
/**
* Set the realm of the given proxy config.
* @param[in] cfg #LinphoneProxyConfig object.
* @param[in] realm New realm value.
* @return The realm of the proxy config.
**/
LINPHONE_PUBLIC void linphone_proxy_config_set_realm(LinphoneProxyConfig *cfg, const char * realm);
/**
* @return the route set for this proxy configuration.
**/
LINPHONE_PUBLIC const char *linphone_proxy_config_get_route(const LinphoneProxyConfig *cfg);
/**
* @return the SIP identity that belongs to this proxy configuration.
**/
LINPHONE_PUBLIC const LinphoneAddress *linphone_proxy_config_get_identity_address(const LinphoneProxyConfig *cfg);
/**
* @deprecated use linphone_proxy_config_get_identity_address()
**/
LINPHONE_PUBLIC const char *linphone_proxy_config_get_identity(const LinphoneProxyConfig *cfg);
/**
* @return TRUE if PUBLISH request is enabled for this proxy.
**/
LINPHONE_PUBLIC bool_t linphone_proxy_config_publish_enabled(const LinphoneProxyConfig *cfg);
/**
* @return the proxy's SIP address.
**/
LINPHONE_PUBLIC const char *linphone_proxy_config_get_server_addr(const LinphoneProxyConfig *cfg);
#define linphone_proxy_config_get_addr linphone_proxy_config_get_server_addr
/**
* @return the duration of registration.
**/
LINPHONE_PUBLIC int linphone_proxy_config_get_expires(const LinphoneProxyConfig *cfg);
/**
* @return TRUE if registration to the proxy is enabled.
**/
LINPHONE_PUBLIC bool_t linphone_proxy_config_register_enabled(const LinphoneProxyConfig *cfg);
/**
* Refresh a proxy registration.
* This is useful if for example you resuming from suspend, thus IP address may have changed.
**/
LINPHONE_PUBLIC void linphone_proxy_config_refresh_register(LinphoneProxyConfig *cfg);
/**
* Prevent a proxy config from refreshing its registration.
* This is useful to let registrations to expire naturally (or) when the application wants to keep control on when
* refreshes are sent.
* However, linphone_core_set_network_reachable(lc,TRUE) will always request the proxy configs to refresh their registrations.
* The refreshing operations can be resumed with linphone_proxy_config_refresh_register().
* @param[in] cfg #LinphoneProxyConfig object.
**/
LINPHONE_PUBLIC void linphone_proxy_config_pause_register(LinphoneProxyConfig *cfg);
LINPHONE_PUBLIC const LinphoneAddress* linphone_proxy_config_get_contact(const LinphoneProxyConfig *cfg);
/**
* @return previously set contact parameters.
**/
LINPHONE_PUBLIC const char *linphone_proxy_config_get_contact_parameters(const LinphoneProxyConfig *cfg);
/**
* Set optional contact parameters that will be added to the contact information sent in the registration.
* @param[in] cfg #LinphoneProxyConfig object.
* @param contact_params a string contaning the additional parameters in text form, like "myparam=something;myparam2=something_else"
*
* The main use case for this function is provide the proxy additional information regarding the user agent, like for example unique identifier or apple push id.
* As an example, the contact address in the SIP register sent will look like <sip:joe@15.128.128.93:50421>;apple-push-id=43143-DFE23F-2323-FA2232.
**/
LINPHONE_PUBLIC void linphone_proxy_config_set_contact_parameters(LinphoneProxyConfig *cfg, const char *contact_params);
/**
* Set optional contact parameters that will be added to the contact information sent in the registration, inside the URI.
* @param[in] cfg #LinphoneProxyConfig object.
* @param contact_uri_params a string containing the additional parameters in text form, like "myparam=something;myparam2=something_else"
*
* The main use case for this function is provide the proxy additional information regarding the user agent, like for example unique identifier or apple push id.
* As an example, the contact address in the SIP register sent will look like <sip:joe@15.128.128.93:50421;apple-push-id=43143-DFE23F-2323-FA2232>.
**/
LINPHONE_PUBLIC void linphone_proxy_config_set_contact_uri_parameters(LinphoneProxyConfig *cfg, const char *contact_uri_params);
/**
* @return previously set contact URI parameters.
**/
LINPHONE_PUBLIC const char* linphone_proxy_config_get_contact_uri_parameters(const LinphoneProxyConfig *cfg);
/**
* Get the #LinphoneCore object to which is associated the #LinphoneProxyConfig.
* @param[in] cfg #LinphoneProxyConfig object.
* @return The #LinphoneCore object to which is associated the #LinphoneProxyConfig.
**/
LINPHONE_PUBLIC LinphoneCore * linphone_proxy_config_get_core(const LinphoneProxyConfig *cfg);
/**
* @return whether liblinphone should replace "+" by "00" in dialed numbers (passed to
* #linphone_core_invite ).
*
**/
LINPHONE_PUBLIC bool_t linphone_proxy_config_get_dial_escape_plus(const LinphoneProxyConfig *cfg);
/**
* @return dialing prefix.
**/
LINPHONE_PUBLIC const char * linphone_proxy_config_get_dial_prefix(const LinphoneProxyConfig *cfg);
/**
* Get the reason why registration failed when the proxy config state is LinphoneRegistrationFailed.
* @param[in] cfg #LinphoneProxyConfig object.
* @return The reason why registration failed for this proxy config.
**/
LINPHONE_PUBLIC LinphoneReason linphone_proxy_config_get_error(const LinphoneProxyConfig *cfg);
/**
* Get detailed information why registration failed when the proxy config state is LinphoneRegistrationFailed.
* @param[in] cfg #LinphoneProxyConfig object.
* @return The details why registration failed for this proxy config.
**/
LINPHONE_PUBLIC const LinphoneErrorInfo *linphone_proxy_config_get_error_info(const LinphoneProxyConfig *cfg);
/**
* Get the transport from either service route, route or addr.
* @param[in] cfg #LinphoneProxyConfig object.
* @return The transport as a string (I.E udp, tcp, tls, dtls)
**/
LINPHONE_PUBLIC const char* linphone_proxy_config_get_transport(const LinphoneProxyConfig *cfg);
/**
* Destroys a proxy config.
* @deprecated
*
* @note: LinphoneProxyConfig that have been removed from LinphoneCore with
* linphone_core_remove_proxy_config() must not be freed.
**/
LINPHONE_PUBLIC void linphone_proxy_config_destroy(LinphoneProxyConfig *cfg);
LINPHONE_PUBLIC void linphone_proxy_config_set_sip_setup(LinphoneProxyConfig *cfg, const char *type);
LINPHONE_PUBLIC SipSetupContext *linphone_proxy_config_get_sip_setup_context(LinphoneProxyConfig *cfg);
LINPHONE_PUBLIC SipSetup *linphone_proxy_config_get_sip_setup(LinphoneProxyConfig *cfg);
/**
* Detect if the given input is a phone number or not.
* @param proxy #LinphoneProxyConfig argument, unused yet but may contain useful data. Can be NULL.
* @param username string to parse.
* @return TRUE if input is a phone number, FALSE otherwise.
**/
LINPHONE_PUBLIC bool_t linphone_proxy_config_is_phone_number(LinphoneProxyConfig *proxy, const char *username);
/**
* Normalize a human readable phone number into a basic string. 888-444-222 becomes 888444222
* or +33888444222 depending on the #LinphoneProxyConfig object. However this argument is OPTIONNAL
* and if not provided, a default one will be used.
* This function will always generate a normalized username; if input is not a phone number, output will be a copy of input.
* @param proxy #LinphoneProxyConfig object containing country code and/or escape symbol. If NULL passed, will use default configuration.
* @param username the string to parse
* @param result the newly normalized number
* @param result_len the size of the normalized number \a result
* @return TRUE if a phone number was recognized, FALSE otherwise.
* @deprecated use linphone_proxy_config_normalize_phone_number()
*/
LINPHONE_PUBLIC bool_t linphone_proxy_config_normalize_number(LinphoneProxyConfig *proxy, const char *username, char *result, size_t result_len);
/**
* Normalize a human readable phone number into a basic string. 888-444-222 becomes 888444222
* or +33888444222 depending on the #LinphoneProxyConfig object. However this argument is OPTIONNAL
* and if not provided, a default one will be used.
* This function will always generate a normalized username; if input is not a phone number, output will be a copy of input.
* @param proxy #LinphoneProxyConfig object containing country code and/or escape symbol. If NULL passed, will use default configuration.
* @param username the string to parse
* @return NULL if invalid phone number, normalized phone number from username input otherwise.
*/
LINPHONE_PUBLIC char* linphone_proxy_config_normalize_phone_number(LinphoneProxyConfig *proxy, const char *username);
/**
* Normalize a human readable sip uri into a fully qualified LinphoneAddress.
* A sip address should look like DisplayName \<sip:username\@domain:port\> .
* Basically this function performs the following tasks
* - if a phone number is entered, prepend country prefix and eventually escape the '+' by 00 of the proxy config.
* - if no domain part is supplied, append the domain name of the proxy config. Returns NULL if no proxy is provided at this point.
* - if no sip: is present, prepend it.
*
* The result is a syntactically correct SIP address.
* @param proxy #LinphoneProxyConfig object containing country code, escape symbol and/or domain name. Can be NULL if domain is already provided.
* @param username the string to parse
* @return NULL if invalid input, normalized sip address otherwise.
*/
LINPHONE_PUBLIC LinphoneAddress* linphone_proxy_config_normalize_sip_uri(LinphoneProxyConfig *proxy, const char *username);
/**
* Set default privacy policy for all calls routed through this proxy.
* @param[in] cfg #LinphoneProxyConfig object.
* @param privacy LinphonePrivacy to configure privacy
* */
LINPHONE_PUBLIC void linphone_proxy_config_set_privacy(LinphoneProxyConfig *cfg, LinphonePrivacyMask privacy);
/**
* Get default privacy policy for all calls routed through this proxy.
* @param[in] cfg #LinphoneProxyConfig object.
* @return Privacy mode
* */
LINPHONE_PUBLIC LinphonePrivacyMask linphone_proxy_config_get_privacy(const LinphoneProxyConfig *cfg);
/**
* Set the http file transfer server to be used for content type application/vnd.gsma.rcs-ft-http+xml
* @param[in] cfg #LinphoneProxyConfig object.
* @param server_url URL of the file server like https://file.linphone.org/upload.php
* */
LINPHONE_PUBLIC void linphone_proxy_config_set_file_transfer_server(LinphoneProxyConfig *cfg, const char * server_url);
/**
* Get the http file transfer server to be used for content type application/vnd.gsma.rcs-ft-http+xml
* @param[in] cfg #LinphoneProxyConfig object.
* @return URL of the file server like https://file.linphone.org/upload.php
* */
LINPHONE_PUBLIC const char* linphone_proxy_config_get_file_transfer_server(const LinphoneProxyConfig *cfg);
/**
* Indicates whether AVPF/SAVPF must be used for calls using this proxy config.
* @param[in] cfg #LinphoneProxyConfig object.
* @param[in] enable True to enable AVPF/SAVF, false to disable it.
* @deprecated use linphone_proxy_config_set_avpf_mode()
*/
LINPHONE_PUBLIC void linphone_proxy_config_enable_avpf(LinphoneProxyConfig *cfg, bool_t enable);
/**
* Indicates whether AVPF/SAVPF is being used for calls using this proxy config.
* @param[in] cfg #LinphoneProxyConfig object.
* @return True if AVPF/SAVPF is enabled, false otherwise.
* @deprecated use linphone_proxy_config_set_avpf_mode()
*/
LINPHONE_PUBLIC bool_t linphone_proxy_config_avpf_enabled(LinphoneProxyConfig *cfg);
/**
* Set the interval between regular RTCP reports when using AVPF/SAVPF.
* @param[in] cfg #LinphoneProxyConfig object.
* @param[in] interval The interval in seconds (between 0 and 5 seconds).
*/
LINPHONE_PUBLIC void linphone_proxy_config_set_avpf_rr_interval(LinphoneProxyConfig *cfg, uint8_t interval);
/**
* Get the interval between regular RTCP reports when using AVPF/SAVPF.
* @param[in] cfg #LinphoneProxyConfig object.
* @return The interval in seconds.
*/
LINPHONE_PUBLIC uint8_t linphone_proxy_config_get_avpf_rr_interval(const LinphoneProxyConfig *cfg);
/**
* Get enablement status of RTCP feedback (also known as AVPF profile).
* @param[in] cfg #LinphoneProxyConfig object.
* @return the enablement mode, which can be LinphoneAVPFDefault (use LinphoneCore's mode), LinphoneAVPFEnabled (avpf is enabled), or LinphoneAVPFDisabled (disabled).
**/
LINPHONE_PUBLIC LinphoneAVPFMode linphone_proxy_config_get_avpf_mode(const LinphoneProxyConfig *cfg);
/**
* Enable the use of RTCP feedback (also known as AVPF profile).
* @param[in] cfg #LinphoneProxyConfig object.
* @param[in] mode the enablement mode, which can be LinphoneAVPFDefault (use LinphoneCore's mode), LinphoneAVPFEnabled (avpf is enabled), or LinphoneAVPFDisabled (disabled).
**/
LINPHONE_PUBLIC void linphone_proxy_config_set_avpf_mode(LinphoneProxyConfig *cfg, LinphoneAVPFMode mode);
/**
* Obtain the value of a header sent by the server in last answer to REGISTER.
* @param[in] cfg #LinphoneProxyConfig object.
* @param header_name the header name for which to fetch corresponding value
* @return the value of the queried header.
**/
LINPHONE_PUBLIC const char *linphone_proxy_config_get_custom_header(LinphoneProxyConfig *cfg, const char *header_name);
/**
* Set the value of a custom header sent to the server in REGISTERs request.
* @param[in] cfg #LinphoneProxyConfig object.
* @param header_name the header name
* @param header_value the header's value
**/
LINPHONE_PUBLIC void linphone_proxy_config_set_custom_header(LinphoneProxyConfig *cfg, const char *header_name, const char *header_value);
/**
* Find authentication info matching proxy config, if any, similarly to linphone_core_find_auth_info.
* @param[in] cfg #LinphoneProxyConfig object.
* @return a #LinphoneAuthInfo matching proxy config criteria if possible, NULL if nothing can be found.
**/
LINPHONE_PUBLIC const struct _LinphoneAuthInfo* linphone_proxy_config_find_auth_info(const LinphoneProxyConfig *cfg);
/**
* @}
*/
#endif

View file

@ -162,7 +162,7 @@ static void linphone_tunnel_add_server_intern(LinphoneTunnel *tunnel, LinphoneTu
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);
tunnel->config_list = ms_list_append(tunnel->config_list, linphone_tunnel_config_ref(tunnel_config));
}
@ -211,7 +211,7 @@ 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_unref(tunnel_config);
linphone_tunnel_refresh_config(tunnel);
linphone_tunnel_save_config(tunnel);
}

View file

@ -176,12 +176,40 @@ LINPHONE_PUBLIC void linphone_tunnel_config_set_delay(LinphoneTunnelConfig *tunn
*/
LINPHONE_PUBLIC int linphone_tunnel_config_get_delay(const LinphoneTunnelConfig *tunnel);
/**
* Increment the refcount of LinphoneTunnelConfig object.
* @param cfg the LinphoneTunnelConfig object.
* @return the same cfg object.
**/
LINPHONE_PUBLIC LinphoneTunnelConfig * linphone_tunnel_config_ref(LinphoneTunnelConfig *cfg);
/**
* Decrement the refcount of LinphoneTunnelConfig object.
* @param cfg the LinphoneTunnelConfig object.
**/
LINPHONE_PUBLIC void linphone_tunnel_config_unref(LinphoneTunnelConfig *cfg);
/**
* Destroy a tunnel configuration
* @param tunnel LinphoneTunnelConfig object
* @deprecated use linphone_tunnel_config_unref().
*/
LINPHONE_PUBLIC void linphone_tunnel_config_destroy(LinphoneTunnelConfig *tunnel);
/**
* Store a user data in the tunnel config object
* @param cfg the tunnel config
* @param ud the user data
**/
LINPHONE_PUBLIC void linphone_tunnel_config_set_user_data(LinphoneTunnelConfig *cfg, void *ud);
/**
* Retrieve user data from the tunnel config
* @param cfg the tunnel config
* @return the user data
**/
LINPHONE_PUBLIC void *linphone_tunnel_config_get_user_data(LinphoneTunnelConfig *cfg);
/**
* Add a tunnel server configuration.
* @param tunnel LinphoneTunnel object

View file

@ -21,18 +21,23 @@
*/
#include "linphone_tunnel.h"
#include "private.h"
struct _LinphoneTunnelConfig {
belle_sip_object_t base;
char *host;
int port;
int remote_udp_mirror_port;
int delay;
int delay;
void *user_data;
};
LinphoneTunnelConfig *linphone_tunnel_config_new() {
LinphoneTunnelConfig *ltc = ms_new0(LinphoneTunnelConfig,1);
LinphoneTunnelConfig *ltc = belle_sip_object_new(LinphoneTunnelConfig);
ltc->remote_udp_mirror_port = 12345;
ltc->delay = 1000;
ltc->port = 443;
return ltc;
}
@ -74,10 +79,40 @@ int linphone_tunnel_config_get_delay(const LinphoneTunnelConfig *tunnel) {
return tunnel->delay;
}
void linphone_tunnel_config_destroy(LinphoneTunnelConfig *tunnel) {
static void _linphone_tunnel_config_destroy(LinphoneTunnelConfig *tunnel) {
if(tunnel->host != NULL) {
ms_free(tunnel->host);
}
ms_free(tunnel);
}
LinphoneTunnelConfig * linphone_tunnel_config_ref(LinphoneTunnelConfig *cfg){
return (LinphoneTunnelConfig*)belle_sip_object_ref(cfg);
}
void linphone_tunnel_config_unref(LinphoneTunnelConfig *cfg){
belle_sip_object_unref(cfg);
}
void linphone_tunnel_config_destroy(LinphoneTunnelConfig *tunnel){
linphone_tunnel_config_unref(tunnel);
}
void linphone_tunnel_config_set_user_data(LinphoneTunnelConfig *cfg, void *ud){
cfg->user_data = ud;
}
void *linphone_tunnel_config_get_user_data(LinphoneTunnelConfig *cfg){
return cfg->user_data;
}
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneTunnelConfig);
BELLE_SIP_INSTANCIATE_VPTR(LinphoneTunnelConfig, belle_sip_object_t,
(belle_sip_object_destroy_t)_linphone_tunnel_config_destroy,
NULL, // clone
NULL, // marshal
FALSE
);

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -32,7 +32,7 @@ static void _local_player_close(LinphonePlayer *obj);
static void _local_player_destroy(LinphonePlayer *obj);
static void _local_player_eof_callback(void *user_data);
LinphonePlayer *linphone_core_create_local_player(LinphoneCore *lc, MSSndCard *snd_card, const char *video_out, unsigned long window_id) {
LinphonePlayer *linphone_core_create_local_player(LinphoneCore *lc, MSSndCard *snd_card, const char *video_out, void *window_id) {
LinphonePlayer *obj = ms_new0(LinphonePlayer, 1);
if(snd_card == NULL) snd_card = lc->sound_conf.ring_sndcard;
if(video_out == NULL) video_out = linphone_core_get_video_display_filter(lc);

View file

@ -74,7 +74,7 @@ static void lpc2xml_log(lpc2xml_context *xmlCtx, int level, const char *fmt, ...
static void lpc2xml_genericxml_error(void *ctx, const char *fmt, ...) {
lpc2xml_context *xmlCtx = (lpc2xml_context *)ctx;
int sl = strlen(xmlCtx->errorBuffer);
size_t sl = strlen(xmlCtx->errorBuffer);
va_list args;
va_start(args, fmt);
vsnprintf(xmlCtx->errorBuffer + sl, LPC2XML_BZ-sl, fmt, args);
@ -101,6 +101,10 @@ static int processEntry(const char *section, const char *entry, xmlNode *node, l
lpc2xml_log(ctx, LPC2XML_MESSAGE, "Set %s|%s = %s", section, entry, content);
xmlNodeSetContent(node, (const xmlChar *) content);
if (lp_config_get_overwrite_flag_for_entry(ctx->lpc, section, entry) || lp_config_get_overwrite_flag_for_section(ctx->lpc, section)) {
xmlSetProp(node, (const xmlChar *)"overwrite", (const xmlChar *) "true");
}
return 0;
}

View file

@ -40,28 +40,29 @@
#endif /*_WIN32_WCE*/
#ifdef _MSC_VER
#ifdef WINAPI_FAMILY_PHONE_APP
#include <stdlib.h>
#else
#ifdef LINPHONE_WINDOWS_DESKTOP
#include <Shlwapi.h>
#else
#include <stdlib.h>
#endif
#else
#include <libgen.h>
#endif
#ifdef WIN32
#ifdef _WIN32
#define RENAME_REQUIRES_NONEXISTENT_NEW_PATH 1
#endif
#define lp_new0(type,n) (type*)calloc(sizeof(type),n)
#include "lpconfig.h"
#include "lpc2xml.h"
typedef struct _LpItem{
char *key;
char *value;
int is_comment;
bool_t overwrite; // If set to true, will add overwrite=true when converted to xml
} LpItem;
typedef struct _LpSectionParam{
@ -73,6 +74,7 @@ typedef struct _LpSection{
char *name;
MSList *items;
MSList *params;
bool_t overwrite; // If set to true, will add overwrite=true to all items of this section when converted to xml
} LpSection;
struct _LpConfig{
@ -85,6 +87,17 @@ struct _LpConfig{
int readonly;
};
char* lp_realpath(const char* file, char* name) {
#if defined(_WIN32) || defined(__QNX__) || defined(ANDROID)
return ms_strdup(file);
#else
char * output = realpath(file, name);
char * msoutput = ms_strdup(output);
free(output);
return msoutput;
#endif
}
LpItem * lp_item_new(const char *key, const char *value){
LpItem *item=lp_new0(LpItem,1);
item->key=ortp_strdup(key);
@ -160,6 +173,11 @@ void lp_config_remove_section(LpConfig *lpconfig, LpSection *section){
lp_section_destroy(section);
}
void lp_section_remove_item(LpSection *sec, LpItem *item){
sec->items=ms_list_remove(sec->items,(void *)item);
lp_item_destroy(item);
}
static bool_t is_first_char(const char *start, const char *pos){
const char *p;
for(p=start;p<pos;p++){
@ -202,6 +220,20 @@ LpSectionParam *lp_section_find_param(const LpSection *sec, const char *key){
return NULL;
}
LpItem *lp_section_find_comment(const LpSection *sec, const char *comment){
MSList *elem;
LpItem *item;
/*printf("Looking for item %s\n",name);*/
for (elem=sec->items;elem!=NULL;elem=ms_list_next(elem)){
item=(LpItem*)elem->data;
if (item->is_comment && strcmp(item->value,comment)==0) {
/*printf("Item %s found\n",name);*/
return item;
}
}
return NULL;
}
LpItem *lp_section_find_item(const LpSection *sec, const char *name){
MSList *elem;
LpItem *item;
@ -220,7 +252,7 @@ static LpSection* lp_config_parse_line(LpConfig* lpconfig, const char* line, LpS
LpSectionParam *params = NULL;
char *pos1,*pos2;
int nbs;
int size=strlen(line)+1;
size_t size=strlen(line)+1;
char *secname=ms_malloc(size);
char *key=ms_malloc(size);
char *value=ms_malloc(size);
@ -272,6 +304,10 @@ static LpSection* lp_config_parse_line(LpConfig* lpconfig, const char* line, LpS
if (is_a_comment(line)){
if (cur){
LpItem *comment=lp_comment_new(line);
item=lp_section_find_comment(cur,comment->value);
if (item!=NULL) {
lp_section_remove_item(cur, item);
}
lp_section_add_item(cur,comment);
}
}else{
@ -359,22 +395,30 @@ LpConfig *lp_config_new_with_factory(const char *config_filename, const char *fa
LpConfig *lpconfig=lp_new0(LpConfig,1);
lpconfig->refcnt=1;
if (config_filename!=NULL){
ms_message("Using (r/w) config information from %s", config_filename);
lpconfig->filename=ortp_strdup(config_filename);
lpconfig->tmpfilename=ortp_strdup_printf("%s.tmp",config_filename);
if(ortp_file_exist(config_filename) == 0) {
lpconfig->filename=lp_realpath(config_filename, NULL);
if(lpconfig->filename == NULL) {
ms_error("Could not find the real path of %s: %s", config_filename, strerror(errno));
goto fail;
}
} else {
lpconfig->filename = ms_strdup(config_filename);
}
lpconfig->tmpfilename=ortp_strdup_printf("%s.tmp",lpconfig->filename);
ms_message("Using (r/w) config information from %s", lpconfig->filename);
#if !defined(WIN32)
#if !defined(_WIN32)
{
struct stat fileStat;
if ((stat(config_filename,&fileStat) == 0) && (S_ISREG(fileStat.st_mode))) {
if ((stat(lpconfig->filename,&fileStat) == 0) && (S_ISREG(fileStat.st_mode))) {
/* make existing configuration files non-group/world-accessible */
if (chmod(config_filename, S_IRUSR | S_IWUSR) == -1) {
if (chmod(lpconfig->filename, S_IRUSR | S_IWUSR) == -1) {
ms_warning("unable to correct permissions on "
"configuration file: %s", strerror(errno));
}
}
}
#endif /*WIN32*/
#endif /*_WIN32*/
/*open with r+ to check if we can write on it later*/
lpconfig->file=fopen(lpconfig->filename,"r+");
#ifdef RENAME_REQUIRES_NONEXISTENT_NEW_PATH
@ -397,17 +441,24 @@ LpConfig *lp_config_new_with_factory(const char *config_filename, const char *fa
lp_config_read_file(lpconfig, factory_config_filename);
}
return lpconfig;
fail:
ms_free(lpconfig);
return NULL;
}
int lp_config_read_file(LpConfig *lpconfig, const char *filename){
FILE* f=fopen(filename,"r");
char* path = lp_realpath(filename, NULL);
FILE* f=fopen(path,"r");
if (f!=NULL){
ms_message("Reading config information from %s", filename);
ms_message("Reading config information from %s", path);
lp_config_parse(lpconfig,f);
fclose(f);
ms_free(path);
return 0;
}
ms_warning("Fail to open file %s",filename);
ms_warning("Fail to open file %s",path);
ms_free(path);
return -1;
}
@ -441,11 +492,6 @@ void lp_config_destroy(LpConfig *lpconfig){
lp_config_unref(lpconfig);
}
void lp_section_remove_item(LpSection *sec, LpItem *item){
sec->items=ms_list_remove(sec->items,(void *)item);
lp_item_destroy(item);
}
const char *lp_config_get_section_param_string(const LpConfig *lpconfig, const char *section, const char *key, const char *default_value){
LpSection *sec;
LpSectionParam *param;
@ -505,7 +551,7 @@ int lp_config_get_int(const LpConfig *lpconfig,const char *section, const char *
int64_t lp_config_get_int64(const LpConfig *lpconfig,const char *section, const char *key, int64_t default_value){
const char *str=lp_config_get_string(lpconfig,section,key,NULL);
if (str!=NULL) {
#ifdef WIN32
#ifdef _WIN32
return (int64_t)_atoi64(str);
#else
return atoll(str);
@ -522,6 +568,26 @@ float lp_config_get_float(const LpConfig *lpconfig,const char *section, const ch
return ret;
}
bool_t lp_config_get_overwrite_flag_for_entry(const LpConfig *lpconfig, const char *section, const char *key) {
LpSection *sec;
LpItem *item;
sec = lp_config_find_section(lpconfig, section);
if (sec != NULL){
item = lp_section_find_item(sec, key);
if (item != NULL) return item->overwrite;
}
return 0;
}
bool_t lp_config_get_overwrite_flag_for_section(const LpConfig *lpconfig, const char *section) {
LpSection *sec;
sec = lp_config_find_section(lpconfig, section);
if (sec != NULL){
return sec->overwrite;
}
return 0;
}
void lp_config_set_string(LpConfig *lpconfig,const char *section, const char *key, const char *value){
LpItem *item;
LpSection *sec=lp_config_find_section(lpconfig,section);
@ -574,6 +640,24 @@ void lp_config_set_float(LpConfig *lpconfig,const char *section, const char *key
lp_config_set_string(lpconfig,section,key,tmp);
}
void lp_config_set_overwrite_flag_for_entry(LpConfig *lpconfig, const char *section, const char *key, bool_t value) {
LpSection *sec;
LpItem *item;
sec = lp_config_find_section(lpconfig, section);
if (sec != NULL) {
item = lp_section_find_item(sec, key);
if (item != NULL) item->overwrite = value;
}
}
void lp_config_set_overwrite_flag_for_section(LpConfig *lpconfig, const char *section, bool_t value) {
LpSection *sec;
sec = lp_config_find_section(lpconfig, section);
if (sec != NULL) {
sec->overwrite = value;
}
}
void lp_item_write(LpItem *item, FILE *file){
if (item->is_comment)
fprintf(file,"%s\n",item->value);
@ -604,7 +688,7 @@ int lp_config_sync(LpConfig *lpconfig){
FILE *file;
if (lpconfig->filename==NULL) return -1;
if (lpconfig->readonly) return 0;
#ifndef WIN32
#ifndef _WIN32
/* don't create group/world-accessible files */
(void) umask(S_IRWXG | S_IRWXO);
#endif
@ -703,19 +787,30 @@ const char* lp_config_get_default_string(const LpConfig *lpconfig, const char *s
return lp_config_get_string(lpconfig, default_section, key, default_value);
}
static char *_lp_config_dirname(char *path) {
/*
* WARNING: this function is very dangerous.
* Read carefuly the folowing notices:
* 1. The 'path' parameter may be modify by
* the function. Be care to keep a copy of
* the original string.
* 2. The return pointer may points on a part of
* 'path'. So, be care to not free the string
* pointed by 'path' before the last used of
* the returned pointer.
* 3. Do not feed it after midnight
*/
static const char *_lp_config_dirname(char *path) {
#ifdef _MSC_VER
char drive[_MAX_DRIVE];
char dir[_MAX_DIR];
char fname[_MAX_FNAME];
char ext[_MAX_EXT];
static char dirname[_MAX_DRIVE + _MAX_DIR];
_splitpath(path, drive, dir, fname, ext);
return ms_strdup_printf("%s%s", drive, dir);
snprintf(dirname, sizeof(dirname), "%s%s", drive, dir);
return dirname;
#else
char *tmp = ms_strdup(path);
char *dir = ms_strdup(dirname(tmp));
ms_free(tmp);
return dir;
return dirname(path);
#endif
}
@ -723,11 +818,19 @@ bool_t lp_config_relative_file_exists(const LpConfig *lpconfig, const char *file
if (lpconfig->filename == NULL) {
return FALSE;
} else {
char *dir = _lp_config_dirname(lpconfig->filename);
char *filename = ms_strdup(lpconfig->filename);
const char *dir = _lp_config_dirname(filename);
char *filepath = ms_strdup_printf("%s/%s", dir, filename);
FILE *file = fopen(filepath, "r");
ms_free(dir);
char *realfilepath = lp_realpath(filepath, NULL);
FILE *file;
ms_free(filename);
ms_free(filepath);
if(realfilepath == NULL) return FALSE;
file = fopen(realfilepath, "r");
ms_free(realfilepath);
if (file) {
fclose(file);
}
@ -736,49 +839,110 @@ bool_t lp_config_relative_file_exists(const LpConfig *lpconfig, const char *file
}
void lp_config_write_relative_file(const LpConfig *lpconfig, const char *filename, const char *data) {
char *dup_config_file = NULL;
const char *dir = NULL;
char *filepath = NULL;
char *realfilepath = NULL;
FILE *file;
if (lpconfig->filename == NULL) return;
if(strlen(data) > 0) {
char *dir = _lp_config_dirname(lpconfig->filename);
char *filepath = ms_strdup_printf("%s/%s", dir, filename);
FILE *file = fopen(filepath, "w");
if(file != NULL) {
fprintf(file, "%s", data);
fclose(file);
} else {
ms_error("Could not open %s for write", filepath);
}
ms_free(dir);
ms_free(filepath);
} else {
if(strlen(data) == 0) {
ms_warning("%s has not been created because there is no data to write", filename);
return;
}
dup_config_file = ms_strdup(lpconfig->filename);
dir = _lp_config_dirname(dup_config_file);
filepath = ms_strdup_printf("%s/%s", dir, filename);
realfilepath = lp_realpath(filepath, NULL);
if(realfilepath == NULL) {
ms_error("Could not resolv %s: %s", filepath, strerror(errno));
goto end;
}
file = fopen(realfilepath, "w");
if(file == NULL) {
ms_error("Could not open %s for write", realfilepath);
goto end;
}
fprintf(file, "%s", data);
fclose(file);
end:
ms_free(dup_config_file);
ms_free(filepath);
if(realfilepath) ms_free(realfilepath);
}
int lp_config_read_relative_file(const LpConfig *lpconfig, const char *filename, char *data, size_t max_length) {
char *dir;
char *filepath;
FILE *file;
char *dup_config_file = NULL;
const char *dir = NULL;
char *filepath = NULL;
FILE *file = NULL;
char* realfilepath = NULL;
if (lpconfig->filename == NULL) return -1;
dir = _lp_config_dirname(lpconfig->filename);
dup_config_file = ms_strdup(lpconfig->filename);
dir = _lp_config_dirname(dup_config_file);
filepath = ms_strdup_printf("%s/%s", dir, filename);
file = fopen(filepath, "r");
if(file != NULL) {
if(fread(data, 1, max_length, file)<=0) {
ms_error("%s could not be loaded. %s", filepath, strerror(errno));
goto err;
}
fclose(file);
} else {
ms_error("Could not open %s for read. %s", filepath, strerror(errno));
realfilepath = lp_realpath(filepath, NULL);
if(realfilepath == NULL) {
ms_error("Could not resolv %s: %s", filepath, strerror(errno));
goto err;
}
ms_free(dir);
file = fopen(realfilepath, "r");
if(file == NULL) {
ms_error("Could not open %s for read. %s", realfilepath, strerror(errno));
goto err;
}
if(fread(data, 1, max_length, file)<=0) {
ms_error("%s could not be loaded. %s", realfilepath, strerror(errno));
goto err;
}
fclose(file);
ms_free(dup_config_file);
ms_free(filepath);
ms_free(realfilepath);
return 0;
err:
ms_free(dir);
ms_free(filepath);
ms_free(filepath);
if(realfilepath) ms_free(realfilepath);
return -1;
}
const char** lp_config_get_sections_names(LpConfig *lpconfig) {
const char **sections_names;
const MSList *sections = lpconfig->sections;
int ndev;
int i;
ndev = ms_list_size(sections);
sections_names = ms_malloc((ndev + 1) * sizeof(const char *));
for (i = 0; sections != NULL; sections = sections->next, i++) {
LpSection *section = (LpSection *)sections->data;
sections_names[i] = ms_strdup(section->name);
}
sections_names[ndev] = NULL;
return sections_names;
}
char* lp_config_dump_as_xml(const LpConfig *lpconfig) {
char *buffer;
lpc2xml_context *ctx = lpc2xml_context_new(NULL, NULL);
lpc2xml_set_lpc(ctx, lpconfig);
lpc2xml_convert_string(ctx, &buffer);
lpc2xml_context_destroy(ctx);
return buffer;
}

Some files were not shown because too many files have changed in this diff Show more