mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-05-02 02:16:24 +00:00
Merge branch 'master' of git.linphone.org:linphone
This commit is contained in:
commit
9ca718d11f
58 changed files with 1338 additions and 444 deletions
60
CMakeLists.txt
Normal file
60
CMakeLists.txt
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
cmake_minimum_required(VERSION 2.6)
|
||||||
|
project(LINPHONE C)
|
||||||
|
|
||||||
|
option(LINPHONE_ENABLE_VIDEO "Build linphone with video support." ON)
|
||||||
|
|
||||||
|
if(NOT ORTP_ROOT_DIR)
|
||||||
|
set(ORTP_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/oRTP)
|
||||||
|
endif()
|
||||||
|
if(NOT ORTP_INCLUDE_DIR)
|
||||||
|
set(ORTP_INCLUDE_DIR ${ORTP_ROOT_DIR}/include)
|
||||||
|
endif()
|
||||||
|
if(NOT MS2_ROOT_DIR)
|
||||||
|
set(MS2_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/mediastreamer2)
|
||||||
|
endif()
|
||||||
|
if(NOT MS2_INCLUDE_DIR)
|
||||||
|
set(MS2_INCLUDE_DIR ${MS2_ROOT_DIR}/include)
|
||||||
|
endif()
|
||||||
|
if(NOT LIBXML2_ROOT_DIR)
|
||||||
|
set(LIBXML2_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../libxml2)
|
||||||
|
endif()
|
||||||
|
if(NOT LIBXML2_INCLUDE_DIR)
|
||||||
|
set(LIBXML2_INCLUDE_DIR ${LIBXML2_ROOT_DIR}/include)
|
||||||
|
endif()
|
||||||
|
if(NOT BELLESIP_ROOT_DIR)
|
||||||
|
set(BELLESIP_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../belle-sip)
|
||||||
|
endif()
|
||||||
|
if(NOT BELLESIP_INCLUDE_DIR)
|
||||||
|
set(BELLESIP_INCLUDE_DIR ${BELLESIP_ROOT_DIR}/include)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
include_directories(
|
||||||
|
include/
|
||||||
|
coreapi/
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/coreapi/
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/../cmake/libxml2/
|
||||||
|
)
|
||||||
|
|
||||||
|
if(USE_INSTALLED_COMPONENTS)
|
||||||
|
include_directories(
|
||||||
|
${CMAKE_INSTALL_PREFIX}/include
|
||||||
|
${CMAKE_INSTALL_PREFIX}/include/libxml2
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
include_directories(
|
||||||
|
${ORTP_INCLUDE_DIR}
|
||||||
|
${MS2_INCLUDE_DIR}
|
||||||
|
${LIBXML2_INCLUDE_DIR}
|
||||||
|
${BELLESIP_INCLUDE_DIR}
|
||||||
|
)
|
||||||
|
if(WIN32)
|
||||||
|
include_directories(${ORTP_ROOT_DIR}/build/vsx/oRTP/oRTP/)
|
||||||
|
endif(WIN32)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_subdirectory(coreapi)
|
||||||
|
add_subdirectory(share)
|
||||||
|
|
||||||
|
if(INSTALL_COMPONENT_IN_POSTBUILD)
|
||||||
|
add_install_target(INSTALL_liblinphone COMP_liblinphone liblinphone)
|
||||||
|
endif()
|
||||||
9
README
9
README
|
|
@ -44,11 +44,12 @@ This is Linphone, a free (GPL) video softphone based on the SIP protocol.
|
||||||
$ sudo make install
|
$ sudo make install
|
||||||
|
|
||||||
+ Install zrtpcpp (optional), for unbreakable call encryption
|
+ Install zrtpcpp (optional), for unbreakable call encryption
|
||||||
$ sudo apt-get install cmake libssl-dev
|
$ sudo apt-get install cmake
|
||||||
$ git clone git://git.linphone.org/zrtpcpp.git
|
$ git clone https://github.com/wernerd/ZRTPCPP.git
|
||||||
$ cd zrtpcpp && cmake -Denable-ccrtp=false . && make
|
$ cd ZRTPCPP
|
||||||
|
$ cmake -DCORE_LIB=true -DSDES=false . && make
|
||||||
$ sudo make install
|
$ sudo make install
|
||||||
|
If you get this error: "cc1plus: error: unrecognized command line option ‘-std=c++11’", edit CMakeLists.txt and replace c++11 by c++0x .
|
||||||
|
|
||||||
- Compile linphone
|
- Compile linphone
|
||||||
|
|
||||||
|
|
|
||||||
95
README.mingw
95
README.mingw
|
|
@ -9,7 +9,7 @@ In the feature list, select:
|
||||||
* Mingw developer toolkit
|
* Mingw developer toolkit
|
||||||
Let the installer fetch and install everything.
|
Let the installer fetch and install everything.
|
||||||
|
|
||||||
In mingw shell, run
|
In mingw shell (also refered as msys), run
|
||||||
|
|
||||||
mingw-get install msys-zip
|
mingw-get install msys-zip
|
||||||
mingw-get install msys-unzip
|
mingw-get install msys-unzip
|
||||||
|
|
@ -45,70 +45,63 @@ libintl.a libintl.la libintl.dll.a
|
||||||
|
|
||||||
* Download and install Inno Setup Compiler (required only if you run 'make setup.exe'). Add it to your windows Path environment variable.
|
* Download and install Inno Setup Compiler (required only if you run 'make setup.exe'). Add it to your windows Path environment variable.
|
||||||
|
|
||||||
Get Linphone source code
|
* Install msys-git from (http://code.google.com/p/msysgit/). During installation you are asked to make a choice about how line endings are treated by git. Choose "Checkout line endings as they are, commit as they are". THIS CHOICE IS VERY IMPORTANT. OTHERS BREAK AUTOMAKE.
|
||||||
************************
|
|
||||||
|
|
||||||
Install msys-git from (http://code.google.com/p/msysgit/). During installation you are asked to make a choice about how line endings are treated by git.
|
|
||||||
Choose "Checkout line endings as they are, commit as they are". THIS CHOICE IS VERY IMPORTANT. OTHERS BREAK AUTOMAKE.
|
|
||||||
|
|
||||||
It is recommended that you create a directory somewhere with a path without any spaces or ~ characters, for example
|
General rules for compilation
|
||||||
c:\sources\
|
*****************************
|
||||||
Within msys-git bash, do
|
|
||||||
|
- It is recommended that you create a directory somewhere with a path without any spaces or ~ characters, for example c:\sources\.
|
||||||
|
This is the place where source code must be compiled.
|
||||||
|
- git commands (to retrieve source code) must be performed within msys-git terminal.
|
||||||
|
- all other commands (configure, autogen.sh, make) must be done within the mingw shell (msys).
|
||||||
|
In both msys and msys-git windows, change into the directory you created for sources:
|
||||||
cd /c/sources
|
cd /c/sources
|
||||||
git clone git://git.linphone.org/linphone.git --recursive
|
|
||||||
|
|
||||||
|
Building belle-sip
|
||||||
|
******************
|
||||||
|
* download the sources with msys-git shell using the following command:
|
||||||
|
$ git clone git://git.linphone.org/belle-sip.git
|
||||||
|
* compile and install
|
||||||
|
$ ./autogen.sh
|
||||||
|
$ ./configure --prefix=/usr --enable-shared --disable-static
|
||||||
|
$ make && make install
|
||||||
|
|
||||||
Building
|
Building Linphone
|
||||||
********
|
*****************
|
||||||
|
|
||||||
WARNING: During the build, windows might slow down suddenly. Using ctl+alt+del to start the windows system monitor,
|
* download the sources using the following command:
|
||||||
you might see a process 'LVpSRV.exe' or something like this that eats 90% of cpu.
|
$ git clone git://git.linphone.org/linphone.git --recursive
|
||||||
Kill it. Don't know what it is, but once killed, windows runs normally.
|
|
||||||
|
|
||||||
#Build linphone itself:
|
* compile
|
||||||
#run autogen.sh after a git checkout or update
|
#always run autogen.sh after a git checkout or update
|
||||||
|
$ ./autogen.sh
|
||||||
|
|
||||||
./autogen.sh
|
$ ./configure --prefix=/usr --enable-shared --disable-static
|
||||||
|
#note: in order to use the tunnel (commercial extension), append --enable-tunnel to the configure line above.
|
||||||
|
|
||||||
./configure --prefix=/usr --enable-shared --disable-static
|
$ make
|
||||||
#note: in order to use the tunnel, append --enable-tunnel to the configure line above.
|
$ make install
|
||||||
|
|
||||||
#compile:
|
#Option: make a portable binary zip of linphone
|
||||||
|
$ make zip
|
||||||
make
|
|
||||||
|
|
||||||
#now install to /usr, required for compilation of plugins.
|
|
||||||
|
|
||||||
make install
|
|
||||||
|
|
||||||
#make a binary zip of linphone
|
|
||||||
|
|
||||||
make zip
|
|
||||||
|
|
||||||
#additionally you can make binary installer if you have Inno Setup 5 installed in its default path
|
#additionally you can make binary installer if you have Inno Setup 5 installed in its default path
|
||||||
|
|
||||||
make setup.exe
|
$ make setup.exe
|
||||||
|
|
||||||
#now you're done, you have a fresh linphone windows installer in the current directory.
|
#now you're done, you have a fresh linphone windows installer in the current directory.
|
||||||
|
|
||||||
|
Building plugins (optional)
|
||||||
|
***************************
|
||||||
|
|
||||||
|
This the example for msx264 (H264 plugin), the same applies for other linphone plugins.
|
||||||
#build plugins
|
$ cd mediastreamer2/plugins/msx264
|
||||||
cd mediastreamer2/plugins/msx264
|
$ ./autogen.sh
|
||||||
./autogen.sh
|
$ PKG_CONFIG_PATH=/usr/lib/pkgconfig ./configure --prefix=/usr --enable-shared --disable-static
|
||||||
PKG_CONFIG_PATH=/usr/lib/pkgconfig ./configure --prefix=/usr --enable-shared --disable-static
|
|
||||||
#make a binary zip of this plugin
|
#make a binary zip of this plugin
|
||||||
make zip
|
$ make zip
|
||||||
#or make an installer
|
#or make an installer
|
||||||
make setup.exe
|
$ make setup.exe
|
||||||
|
|
||||||
#the buddylookup plugin enables lookup of buddies in a remote database using xml-rpc over http/https.
|
|
||||||
cd coreapi/plugins/buddylookup
|
|
||||||
./autogen.sh
|
|
||||||
PKG_CONFIG_PATH=/usr/lib/pkgconfig ./configure --prefix=/usr --enable-shared --disable-static
|
|
||||||
make
|
|
||||||
#make a binary zip of this plugin
|
|
||||||
make zip
|
|
||||||
|
|
||||||
|
|
||||||
******************************************************
|
******************************************************
|
||||||
|
|
@ -161,14 +154,6 @@ When running "make install DESTDIR=<somepath>", somepath must be absolute and sh
|
||||||
$ make install DESTDIR=/usr
|
$ make install DESTDIR=/usr
|
||||||
$ make install DESTDIR=/home/<myuser>/polarssl-install
|
$ make install DESTDIR=/home/<myuser>/polarssl-install
|
||||||
|
|
||||||
- building belle-sip
|
|
||||||
* download the sources with:
|
|
||||||
$ git clone git://git.linphone.org/belle-sip.git
|
|
||||||
* compile and install, assuming you have already compiled polarssl and antlr3c and installed in /.
|
|
||||||
$ ./autogen.sh
|
|
||||||
$ ./configure --prefix=/usr --enable-shared --disable-static
|
|
||||||
$ make && make install && make install DESTDIR=/home/<myuser>/belle-sip-install
|
|
||||||
|
|
||||||
- building libsrtp
|
- building libsrtp
|
||||||
* download the sources with
|
* download the sources with
|
||||||
$ git clone git://git.linphone.org/srtp.git
|
$ git clone git://git.linphone.org/srtp.git
|
||||||
|
|
|
||||||
94
README.zrtp
94
README.zrtp
|
|
@ -1,94 +0,0 @@
|
||||||
ZRTP guide
|
|
||||||
|
|
||||||
== Downloads ==
|
|
||||||
- SRTP
|
|
||||||
http://sourceforge.net/projects/srtp/
|
|
||||||
or "apt-get source libsrtp0" on Debian
|
|
||||||
|
|
||||||
- ZRTP (libzrtpcpp-2.0)
|
|
||||||
http://www.gnutelephony.org/index.php/GNU_ZRTP
|
|
||||||
|
|
||||||
|
|
||||||
== Patch libzrtpcpp ==
|
|
||||||
Index: src/ZIDFile.cpp
|
|
||||||
===================================================================
|
|
||||||
--- src/ZIDFile.cpp (révision 754)
|
|
||||||
+++ src/ZIDFile.cpp (copie de travail)
|
|
||||||
@@ -78,10 +78,11 @@
|
|
||||||
|
|
||||||
// create save file name, rename and re-open
|
|
||||||
// if rename fails, just unlink old ZID file and create a brand new file
|
|
||||||
- // just a little inconnvenience for the user, need to verify new SAS
|
|
||||||
+ // just a little inconvenience for the user, need to verify new SAS
|
|
||||||
std::string fn = std::string(name) + std::string(".save");
|
|
||||||
if (rename(name, fn.c_str()) < 0) {
|
|
||||||
- unlink(name);
|
|
||||||
+ // unlink(name);
|
|
||||||
createZIDFile(name);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Index: src/libzrtpcpp/ZrtpCallback.h
|
|
||||||
===================================================================
|
|
||||||
--- src/libzrtpcpp/ZrtpCallback.h (révision 754)
|
|
||||||
+++ src/libzrtpcpp/ZrtpCallback.h (copie de travail)
|
|
||||||
@@ -27,7 +27,7 @@
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <stdint.h>
|
|
||||||
-#include <commoncpp/config.h>
|
|
||||||
+//#include <commoncpp/config.h>
|
|
||||||
#include <libzrtpcpp/ZrtpCodes.h>
|
|
||||||
|
|
||||||
/**
|
|
||||||
Index: src/libzrtpcpp/ZIDRecord.h
|
|
||||||
===================================================================
|
|
||||||
--- src/libzrtpcpp/ZIDRecord.h (révision 754)
|
|
||||||
+++ src/libzrtpcpp/ZIDRecord.h (copie de travail)
|
|
||||||
@@ -33,7 +33,7 @@
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
-#include <commoncpp/config.h>
|
|
||||||
+//#include <commoncpp/config.h>
|
|
||||||
|
|
||||||
#define IDENTIFIER_LEN 12
|
|
||||||
#define RS_LENGTH 32
|
|
||||||
Index: CMakeLists.txt
|
|
||||||
===================================================================
|
|
||||||
--- CMakeLists.txt (révision 754)
|
|
||||||
+++ CMakeLists.txt (copie de travail)
|
|
||||||
@@ -124,11 +124,15 @@
|
|
||||||
if(CMAKE_COMPILER_IS_GNUCXX)
|
|
||||||
add_definitions(-Wno-long-long -Wno-char-subscripts)
|
|
||||||
add_definitions(-Wall -ansi -pedantic)
|
|
||||||
+ add_definitions(-DNEW_STDCPP)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
add_subdirectory(src)
|
|
||||||
-add_subdirectory(demo)
|
|
||||||
|
|
||||||
+if (enable_ccrtp)
|
|
||||||
+ add_subdirectory(demo)
|
|
||||||
+endif()
|
|
||||||
+
|
|
||||||
if (NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/package/)
|
|
||||||
MESSAGE(STATUS "package dir not found")
|
|
||||||
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/package/)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
== Create simlinks or move folders ==
|
|
||||||
submodules/external/srtp -> path_to_your_srtp_source
|
|
||||||
submodules/external/libzrtpcpp -> path_to_your_patched_zrtpcpp_source
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
== Compilation for Android ==
|
|
||||||
ndk-build BUILD_GPLV3_ZRTP=1 -j5
|
|
||||||
|
|
||||||
|
|
||||||
== Compilation for Desktop version ==
|
|
||||||
First ortp: ./autogen.sh && ./configure --enable-zrtp && make -j5 && sudo make install
|
|
||||||
Then mediastreamer2: ./autogen.sh && ./configure && make -j5 && sudo make install
|
|
||||||
Finally linphone: ./autogen.sh && ./configure --enable-external-ortp && make -j5 && sudo make install
|
|
||||||
|
|
||||||
|
|
@ -60,7 +60,8 @@ LOCAL_SRC_FILES := \
|
||||||
linphone_tunnel_config.c \
|
linphone_tunnel_config.c \
|
||||||
message_storage.c \
|
message_storage.c \
|
||||||
info.c \
|
info.c \
|
||||||
event.c
|
event.c \
|
||||||
|
xml.c
|
||||||
|
|
||||||
ifndef LINPHONE_VERSION
|
ifndef LINPHONE_VERSION
|
||||||
LINPHONE_VERSION = "Devel"
|
LINPHONE_VERSION = "Devel"
|
||||||
|
|
|
||||||
13
build/redhat/INSTALL
Normal file
13
build/redhat/INSTALL
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
INSTALL :
|
||||||
|
|
||||||
|
Download and install the repo rpmforge :
|
||||||
|
http://repoforge.org/use/
|
||||||
|
|
||||||
|
$ sudo rpm -Uvh <path to rpmforge rpm>
|
||||||
|
|
||||||
|
Download the linphone-release rpm
|
||||||
|
$ sudo rpm -Uvh <path to linphone rpm>
|
||||||
|
|
||||||
|
$ sudo yum install linphone
|
||||||
|
|
||||||
|
|
||||||
57
build/redhat/README
Normal file
57
build/redhat/README
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
**********************************
|
||||||
|
* Compiling linphone on RedHat *
|
||||||
|
**********************************
|
||||||
|
|
||||||
|
Download and install the repo rpmforge :
|
||||||
|
http://repoforge.org/use/
|
||||||
|
|
||||||
|
$ sudo rpm -Uhv <path to rpmforge rpm>
|
||||||
|
$ yum -y update
|
||||||
|
|
||||||
|
- Install build time dependencies
|
||||||
|
$ sudo yum install libtool intltool
|
||||||
|
|
||||||
|
- Install others dependencies
|
||||||
|
$ sudo yum install gtk2-devel
|
||||||
|
$ sudo yum install ffmpeg-devel
|
||||||
|
$ sudo yum install openldap-devel
|
||||||
|
|
||||||
|
- Download and install packages
|
||||||
|
$ sudo rpm -Uhv ftp://ftp.icm.edu.pl/vol/rzm2/linux-fedora/linux/epel/6/x86_64/polarssl-1.3.2-1.el6.x86_64.rpm
|
||||||
|
$ sudo rpm -Uvh ftp://ftp.icm.edu.pl/vol/rzm2/linux-fedora/linux/epel/6/x86_64/polarssl-devel-1.3.2-1.el6.x86_64.rpm
|
||||||
|
$ sudo rpm -Uhv ftp://ftp.pbone.net/mirror/archive.fedoraproject.org/fedora/linux/releases/15/Everything/x86_64/os/Packages/antlr3-C-3.2-14.fc15.x86_64.rpm
|
||||||
|
$ sudo rpm -Uhv ftp://ftp.pbone.net/mirror/archive.fedoraproject.org/fedora/linux/releases/15/Everything/x86_64/os/Packages/antlr3-C-devel-3.2-14.fc15.x86_64.rpm
|
||||||
|
$ sudo rpm -Uhv ftp://ftp.pbone.net/mirror/archive.fedoraproject.org/fedora/linux/releases/15/Everything/x86_64/os/Packages/antlr3-tool-3.2-14.fc15.noarch.rpm
|
||||||
|
$ sudo rpm -Uhv ftp://ftp.pbone.net/mirror/archive.fedoraproject.org/fedora/linux/releases/15/Fedora/i386/os/Packages/antlr3-java-3.2-14.fc15.noarch.rpm
|
||||||
|
|
||||||
|
- Git repository
|
||||||
|
|
||||||
|
Belle-sip : git clone git://git.linphone.org/belle-sip.git
|
||||||
|
oRTP : git clone git://git.linphone.org/ortp.git
|
||||||
|
Mediastreamer : git clone git://git.linphone.org/mediastreamer2.git
|
||||||
|
|
||||||
|
- Compile Belle-sip / oRTP / mediastreamer
|
||||||
|
$ ./autogen.sh
|
||||||
|
$ ./configure
|
||||||
|
$ make && make rpm
|
||||||
|
$ sudo rpm -Uvh <path to rpm and rpm-devel>
|
||||||
|
|
||||||
|
- Compile Linphone
|
||||||
|
$ ./autogen.sh
|
||||||
|
$ ./configure
|
||||||
|
$ make && make rpm
|
||||||
|
|
||||||
|
|
||||||
|
-Create yum repo :
|
||||||
|
$ cd rpmbuild/RPMS/*arch*/
|
||||||
|
$ createrepo .
|
||||||
|
|
||||||
|
Create a file "linphone-release.repo" in /etc/yum.repos.d/ with :
|
||||||
|
|
||||||
|
[linphone-release]
|
||||||
|
name = Linphone for redhat
|
||||||
|
baseurl = file/// *path to the new repo*
|
||||||
|
enabled = 1
|
||||||
|
gpgcheck = 0
|
||||||
|
|
||||||
|
$ sudo yum install linphone
|
||||||
|
|
@ -117,7 +117,7 @@
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<WarningLevel>Level4</WarningLevel>
|
<WarningLevel>Level4</WarningLevel>
|
||||||
<AdditionalIncludeDirectories>$(ProjectDir)..\..\..\..\belle-sip\include;$(ProjectDir)..\..\..\..\oRTP\include;$(ProjectDir)..\..\..\..\mediastreamer2\include;$(ProjectDIr)..\..\..\..\tunnel\include;$(ProjectDir)..\..\..\coreapi;$(ProjectDir)..\..\..\include;$(SolutionDir)$(Platform)\$(Configuration)\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>$(ProjectDir)..\..\..\..\belle-sip\include;$(ProjectDir)..\..\..\..\oRTP\include;$(ProjectDir)..\..\..\..\mediastreamer2\include;$(ProjectDIr)..\..\..\..\tunnel\include;$(ProjectDir)..\..\..\coreapi;$(ProjectDir)..\..\..\include;$(SolutionDir)$(Platform)\$(Configuration)\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<PreprocessorDefinitions>__STDC_CONSTANT_MACROS;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_WINDOWS;_USRDLL;WINDOW_NATIVE;_TRUE_TIME;IN_LINPHONE;USE_BELLESIP;TUNNEL_ENABLED;VIDEO_ENABLED;LINPHONE_PACKAGE_NAME="linphone";LINPHONE_VERSION="Devel";LIBLINPHONE_EXPORTS;LINPHONE_PLUGINS_DIR="";UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>__STDC_CONSTANT_MACROS;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_WINDOWS;_USRDLL;WINDOW_NATIVE;_TRUE_TIME;IN_LINPHONE;USE_BELLESIP;TUNNEL_ENABLED;VIDEO_ENABLED;LINPHONE_PACKAGE_NAME="linphone";LINPHONE_VERSION="Devel";LIBLINPHONE_EXPORTS;LINPHONE_PLUGINS_DIR="";UNICODE;_XKEYCHECK_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<MinimalRebuild>false</MinimalRebuild>
|
<MinimalRebuild>false</MinimalRebuild>
|
||||||
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
||||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||||
|
|
@ -147,7 +147,7 @@
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<WarningLevel>Level4</WarningLevel>
|
<WarningLevel>Level4</WarningLevel>
|
||||||
<AdditionalIncludeDirectories>$(ProjectDir)..\..\..\..\belle-sip\include;$(ProjectDir)..\..\..\..\oRTP\include;$(ProjectDir)..\..\..\..\mediastreamer2\include;$(ProjectDIr)..\..\..\..\tunnel\include;$(ProjectDir)..\..\..\coreapi;$(ProjectDir)..\..\..\include;$(SolutionDir)$(Platform)\$(Configuration)\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>$(ProjectDir)..\..\..\..\belle-sip\include;$(ProjectDir)..\..\..\..\oRTP\include;$(ProjectDir)..\..\..\..\mediastreamer2\include;$(ProjectDIr)..\..\..\..\tunnel\include;$(ProjectDir)..\..\..\coreapi;$(ProjectDir)..\..\..\include;$(SolutionDir)$(Platform)\$(Configuration)\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<PreprocessorDefinitions>__STDC_CONSTANT_MACROS;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_WINDOWS;_USRDLL;WINDOW_NATIVE;_TRUE_TIME;IN_LINPHONE;USE_BELLESIP;TUNNEL_ENABLED;VIDEO_ENABLED;LINPHONE_PACKAGE_NAME="linphone";LINPHONE_VERSION="Devel";LIBLINPHONE_EXPORTS;LINPHONE_PLUGINS_DIR="";UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>__STDC_CONSTANT_MACROS;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_WINDOWS;_USRDLL;WINDOW_NATIVE;_TRUE_TIME;IN_LINPHONE;USE_BELLESIP;TUNNEL_ENABLED;VIDEO_ENABLED;LINPHONE_PACKAGE_NAME="linphone";LINPHONE_VERSION="Devel";LIBLINPHONE_EXPORTS;LINPHONE_PLUGINS_DIR="";UNICODE;_XKEYCHECK_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<StringPooling>true</StringPooling>
|
<StringPooling>true</StringPooling>
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
||||||
|
|
@ -207,6 +207,7 @@
|
||||||
<ClCompile Include="..\..\..\coreapi\siplogin.c" />
|
<ClCompile Include="..\..\..\coreapi\siplogin.c" />
|
||||||
<ClCompile Include="..\..\..\coreapi\sipsetup.c" />
|
<ClCompile Include="..\..\..\coreapi\sipsetup.c" />
|
||||||
<ClCompile Include="..\..\..\coreapi\TunnelManager.cc" />
|
<ClCompile Include="..\..\..\coreapi\TunnelManager.cc" />
|
||||||
|
<ClCompile Include="..\..\..\coreapi\xml.c" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\..\..\coreapi\bellesip_sal\sal_impl.h" />
|
<ClInclude Include="..\..\..\coreapi\bellesip_sal\sal_impl.h" />
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,8 @@ COMMON_CFLAGS=\
|
||||||
$(MEDIASTREAMER_CFLAGS) \
|
$(MEDIASTREAMER_CFLAGS) \
|
||||||
$(VIDEO_CFLAGS) \
|
$(VIDEO_CFLAGS) \
|
||||||
$(READLINE_CFLAGS) \
|
$(READLINE_CFLAGS) \
|
||||||
$(SQLITE3_CFLAGS)
|
$(SQLITE3_CFLAGS) \
|
||||||
|
$(LIBXML2_CFLAGS)
|
||||||
|
|
||||||
if BUILD_CONSOLE
|
if BUILD_CONSOLE
|
||||||
|
|
||||||
|
|
@ -29,7 +30,8 @@ linphonec_LDADD=$(top_builddir)/coreapi/liblinphone.la \
|
||||||
$(READLINE_LIBS) \
|
$(READLINE_LIBS) \
|
||||||
$(SQLITE3_LIBS) \
|
$(SQLITE3_LIBS) \
|
||||||
$(X11_LIBS) \
|
$(X11_LIBS) \
|
||||||
$(BELLESIP_LIBS)
|
$(BELLESIP_LIBS) \
|
||||||
|
$(LIBXML2_LIBS)
|
||||||
|
|
||||||
if BUILD_WIN32
|
if BUILD_WIN32
|
||||||
#special build of linphonec to detach from the windows console
|
#special build of linphonec to detach from the windows console
|
||||||
|
|
|
||||||
140
coreapi/CMakeLists.txt
Normal file
140
coreapi/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,140 @@
|
||||||
|
find_program(GIT git)
|
||||||
|
|
||||||
|
set(GIT_VERSION "unknown")
|
||||||
|
if(GIT)
|
||||||
|
execute_process(
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
COMMAND ${GIT} describe --always
|
||||||
|
OUTPUT_VARIABLE GIT_DESCRIBE
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
|
)
|
||||||
|
execute_process(
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
COMMAND ${GIT} describe --abbrev=0
|
||||||
|
OUTPUT_VARIABLE GIT_TAG
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
|
)
|
||||||
|
execute_process(
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
COMMAND ${GIT} rev-parse HEAD
|
||||||
|
OUTPUT_VARIABLE GIT_REVISION
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
|
)
|
||||||
|
if(GIT_DESCRIBE)
|
||||||
|
set(GIT_VERSION ${GIT_DESCRIBE})
|
||||||
|
else(GIT_DESCRIBE)
|
||||||
|
if(GIT_REVISION)
|
||||||
|
set(GIT_VERSION ${GIT_REVISION})
|
||||||
|
endif(GIT_REVISION)
|
||||||
|
endif(GIT_DESCRIBE)
|
||||||
|
endif(GIT)
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E echo "#define LIBLINPHONE_GIT_VERSION \"${GIT_VERSION}\""
|
||||||
|
OUTPUT_FILE ${CMAKE_CURRENT_BINARY_DIR}/liblinphone_gitversion.h
|
||||||
|
)
|
||||||
|
|
||||||
|
set(SOURCE_FILES
|
||||||
|
address.c
|
||||||
|
authentication.c
|
||||||
|
bellesip_sal/sal_address_impl.c
|
||||||
|
bellesip_sal/sal_impl.c
|
||||||
|
bellesip_sal/sal_op_call.c
|
||||||
|
bellesip_sal/sal_op_call_transfer.c
|
||||||
|
bellesip_sal/sal_op_events.c
|
||||||
|
bellesip_sal/sal_op_impl.c
|
||||||
|
bellesip_sal/sal_op_info.c
|
||||||
|
bellesip_sal/sal_op_message.c
|
||||||
|
bellesip_sal/sal_op_presence.c
|
||||||
|
bellesip_sal/sal_op_publish.c
|
||||||
|
bellesip_sal/sal_op_registration.c
|
||||||
|
bellesip_sal/sal_sdp.c
|
||||||
|
callbacks.c
|
||||||
|
chat.c
|
||||||
|
conference.c
|
||||||
|
ec-calibrator.c
|
||||||
|
enum.c
|
||||||
|
event.c
|
||||||
|
friend.c
|
||||||
|
info.c
|
||||||
|
linphonecall.c
|
||||||
|
linphonecore.c
|
||||||
|
#linphone_tunnel.cc
|
||||||
|
linphone_tunnel_stubs.c
|
||||||
|
linphone_tunnel_config.c
|
||||||
|
lpconfig.c
|
||||||
|
lsd.c
|
||||||
|
message_storage.c
|
||||||
|
misc.c
|
||||||
|
offeranswer.c
|
||||||
|
presence.c
|
||||||
|
proxy.c
|
||||||
|
sal.c
|
||||||
|
siplogin.c
|
||||||
|
sipsetup.c
|
||||||
|
#TunnelManager.cc
|
||||||
|
xml.c
|
||||||
|
bellesip_sal/sal_impl.h
|
||||||
|
enum.h
|
||||||
|
event.h
|
||||||
|
linphonecore.h
|
||||||
|
linphonecore_utils.h
|
||||||
|
linphonefriend.h
|
||||||
|
linphone_tunnel.h
|
||||||
|
lpconfig.h
|
||||||
|
offeranswer.h
|
||||||
|
private.h
|
||||||
|
sipsetup.h
|
||||||
|
)
|
||||||
|
|
||||||
|
add_definitions(
|
||||||
|
-D_TRUE_TIME
|
||||||
|
-DIN_LINPHONE
|
||||||
|
-DUSE_BELLESIP
|
||||||
|
#-DTUNNEL_ENABLED
|
||||||
|
#-DVIDEO_ENABLED
|
||||||
|
-DLINPHONE_PACKAGE_NAME="linphone"
|
||||||
|
-DLINPHONE_VERSION="Devel"
|
||||||
|
-DLIBLINPHONE_EXPORTS
|
||||||
|
-DLINPHONE_PLUGINS_DIR=""
|
||||||
|
)
|
||||||
|
|
||||||
|
if(LINPHONE_ENABLE_VIDEO)
|
||||||
|
add_definitions(-DVIDEO_ENABLED)
|
||||||
|
endif(LINPHONE_ENABLE_VIDEO)
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
add_definitions(
|
||||||
|
-DWINDOW_NATIVE
|
||||||
|
/FIliblinphone_gitversion.h
|
||||||
|
)
|
||||||
|
|
||||||
|
set(LIBS ws2_32)
|
||||||
|
endif(WIN32)
|
||||||
|
set(LIBS ${LIBS} libortp libmediastreamer_base libmediastreamer_voip libbellesip libxml2)
|
||||||
|
|
||||||
|
add_library(liblinphone SHARED ${SOURCE_FILES})
|
||||||
|
set_target_properties(liblinphone PROPERTIES VERSION 3.6.99 SOVERSION 5)
|
||||||
|
|
||||||
|
target_link_libraries(liblinphone ${LIBS})
|
||||||
|
|
||||||
|
install(TARGETS liblinphone
|
||||||
|
COMPONENT COMP_liblinphone
|
||||||
|
DESTINATION ${LIB_INSTALL_DIR}
|
||||||
|
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
|
||||||
|
|
||||||
|
if(USE_INSTALLED_COMPONENTS)
|
||||||
|
add_dependencies(liblinphone
|
||||||
|
INSTALL_libortp
|
||||||
|
INSTALL_libmediastreamer2
|
||||||
|
INSTALL_libbellesip
|
||||||
|
INSTALL_libxml2)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
file(GLOB HEADER_FILES "*.h")
|
||||||
|
|
||||||
|
install(FILES ${HEADER_FILES}
|
||||||
|
COMPONENT COMP_liblinphone
|
||||||
|
DESTINATION include/linphone
|
||||||
|
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
|
||||||
|
|
@ -51,6 +51,7 @@ liblinphone_la_SOURCES=\
|
||||||
contactprovider.c contactprovider.h contact_providers_priv.h \
|
contactprovider.c contactprovider.h contact_providers_priv.h \
|
||||||
ldap/ldapprovider.c ldap/ldapprovider.h \
|
ldap/ldapprovider.c ldap/ldapprovider.h \
|
||||||
dict.c \
|
dict.c \
|
||||||
|
xml.c \
|
||||||
$(GITVERSION_FILE)
|
$(GITVERSION_FILE)
|
||||||
|
|
||||||
if BUILD_UPNP
|
if BUILD_UPNP
|
||||||
|
|
|
||||||
|
|
@ -464,6 +464,8 @@ void sal_set_callbacks(Sal *ctx, const SalCallbacks *cbs){
|
||||||
ctx->callbacks.subscribe_presence_received=(SalOnSubscribePresenceReceived)unimplemented_stub;
|
ctx->callbacks.subscribe_presence_received=(SalOnSubscribePresenceReceived)unimplemented_stub;
|
||||||
if (ctx->callbacks.text_received==NULL)
|
if (ctx->callbacks.text_received==NULL)
|
||||||
ctx->callbacks.text_received=(SalOnTextReceived)unimplemented_stub;
|
ctx->callbacks.text_received=(SalOnTextReceived)unimplemented_stub;
|
||||||
|
if (ctx->callbacks.is_composing_received==NULL)
|
||||||
|
ctx->callbacks.is_composing_received=(SalOnIsComposingReceived)unimplemented_stub;
|
||||||
if (ctx->callbacks.ping_reply==NULL)
|
if (ctx->callbacks.ping_reply==NULL)
|
||||||
ctx->callbacks.ping_reply=(SalOnPingReply)unimplemented_stub;
|
ctx->callbacks.ping_reply=(SalOnPingReply)unimplemented_stub;
|
||||||
if (ctx->callbacks.auth_requested==NULL)
|
if (ctx->callbacks.auth_requested==NULL)
|
||||||
|
|
@ -915,5 +917,12 @@ unsigned char * sal_get_random_bytes(unsigned char *ret, size_t size){
|
||||||
return belle_sip_random_bytes(ret,size);
|
return belle_sip_random_bytes(ret,size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
belle_sip_source_t * sal_create_timer(Sal *sal, belle_sip_source_func_t func, void *data, unsigned int timeout_value_ms, const char* timer_name) {
|
||||||
|
belle_sip_main_loop_t *ml = belle_sip_stack_get_main_loop(sal->stack);
|
||||||
|
return belle_sip_main_loop_create_timeout(ml, func, data, timeout_value_ms, timer_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sal_cancel_timer(Sal *sal, belle_sip_source_t *timer) {
|
||||||
|
belle_sip_main_loop_t *ml = belle_sip_stack_get_main_loop(sal->stack);
|
||||||
|
belle_sip_main_loop_remove_source(ml, timer);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
#include "sal_impl.h"
|
#include "sal_impl.h"
|
||||||
#include "offeranswer.h"
|
#include "offeranswer.h"
|
||||||
|
|
||||||
|
static int extract_sdp(belle_sip_message_t* message,belle_sdp_session_description_t** session_desc, SalReason *error);
|
||||||
|
|
||||||
/*used for calls terminated before creation of a dialog*/
|
/*used for calls terminated before creation of a dialog*/
|
||||||
static void call_set_released(SalOp* op){
|
static void call_set_released(SalOp* op){
|
||||||
if (!op->call_released){
|
if (!op->call_released){
|
||||||
|
|
@ -84,8 +86,8 @@ static void sdp_process(SalOp *h){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int set_sdp(belle_sip_message_t *msg,belle_sdp_session_description_t* session_desc) {
|
static int set_sdp(belle_sip_message_t *msg,belle_sdp_session_description_t* session_desc) {
|
||||||
belle_sip_header_content_type_t* content_type ;
|
belle_sip_header_content_type_t* content_type ;
|
||||||
belle_sip_header_content_length_t* content_length;
|
belle_sip_header_content_length_t* content_length;
|
||||||
|
|
@ -159,10 +161,13 @@ static void process_dialog_terminated(void *ctx, const belle_sip_dialog_terminat
|
||||||
|
|
||||||
static void handle_sdp_from_response(SalOp* op,belle_sip_response_t* response) {
|
static void handle_sdp_from_response(SalOp* op,belle_sip_response_t* response) {
|
||||||
belle_sdp_session_description_t* sdp;
|
belle_sdp_session_description_t* sdp;
|
||||||
if ((sdp=belle_sdp_session_description_create(BELLE_SIP_MESSAGE(response)))) {
|
SalReason reason;
|
||||||
|
if (extract_sdp(BELLE_SIP_MESSAGE(response),&sdp,&reason)==0) {
|
||||||
|
if (sdp){
|
||||||
op->base.remote_media=sal_media_description_new();
|
op->base.remote_media=sal_media_description_new();
|
||||||
sdp_to_media_description(sdp,op->base.remote_media);
|
sdp_to_media_description(sdp,op->base.remote_media);
|
||||||
if (op->base.local_media) sdp_process(op);
|
if (op->base.local_media) sdp_process(op);
|
||||||
|
}/*if no sdp in response, what can we do ?*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -322,15 +327,61 @@ static void unsupported_method(belle_sip_server_transaction_t* server_transactio
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void process_sdp_for_invite(SalOp* op,belle_sip_request_t* invite) {
|
/*
|
||||||
|
* Extract the sdp from a sip message.
|
||||||
|
* If there is no body in the message, the session_desc is set to null, 0 is returned.
|
||||||
|
* If body was present is not a SDP or parsing of SDP failed, -1 is returned and SalReason is set appropriately.
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
static int extract_sdp(belle_sip_message_t* message,belle_sdp_session_description_t** session_desc, SalReason *error) {
|
||||||
|
belle_sip_header_content_type_t* content_type=belle_sip_message_get_header_by_type(message,belle_sip_header_content_type_t);
|
||||||
|
if (content_type){
|
||||||
|
if (strcmp("application",belle_sip_header_content_type_get_type(content_type))==0
|
||||||
|
&& strcmp("sdp",belle_sip_header_content_type_get_subtype(content_type))==0) {
|
||||||
|
*session_desc=belle_sdp_session_description_parse(belle_sip_message_get_body(message));
|
||||||
|
if (*session_desc==NULL) {
|
||||||
|
ms_error("Failed to parse SDP message.");
|
||||||
|
*error=SalReasonNotAcceptable;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
*error=SalReasonUnsupportedContent;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}else *session_desc=NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int is_media_description_acceptable(SalMediaDescription *md){
|
||||||
|
if (md->n_total_streams==0){
|
||||||
|
ms_warning("Media description does not define any stream.");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int process_sdp_for_invite(SalOp* op,belle_sip_request_t* invite) {
|
||||||
belle_sdp_session_description_t* sdp;
|
belle_sdp_session_description_t* sdp;
|
||||||
if ((sdp=belle_sdp_session_description_create(BELLE_SIP_MESSAGE(invite)))) {
|
int err=0;
|
||||||
|
SalReason reason;
|
||||||
|
if (extract_sdp(BELLE_SIP_MESSAGE(invite),&sdp,&reason)==0) {
|
||||||
|
if (sdp){
|
||||||
op->sdp_offering=FALSE;
|
op->sdp_offering=FALSE;
|
||||||
op->base.remote_media=sal_media_description_new();
|
op->base.remote_media=sal_media_description_new();
|
||||||
sdp_to_media_description(sdp,op->base.remote_media);
|
sdp_to_media_description(sdp,op->base.remote_media);
|
||||||
|
/*make some sanity check about the SDP received*/
|
||||||
|
if (!is_media_description_acceptable(op->base.remote_media)){
|
||||||
|
err=-1;
|
||||||
|
reason=SalReasonNotAcceptable;
|
||||||
|
}
|
||||||
belle_sip_object_unref(sdp);
|
belle_sip_object_unref(sdp);
|
||||||
}else
|
}else op->sdp_offering=TRUE; /*INVITE without SDP*/
|
||||||
op->sdp_offering=TRUE;
|
}else err=-1;
|
||||||
|
|
||||||
|
if (err==-1){
|
||||||
|
sal_call_decline(op,reason,NULL);
|
||||||
|
}
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void process_request_event(void *op_base, const belle_sip_request_event_t *event) {
|
static void process_request_event(void *op_base, const belle_sip_request_event_t *event) {
|
||||||
|
|
@ -415,13 +466,18 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t
|
||||||
/*great ACK received*/
|
/*great ACK received*/
|
||||||
if (strcmp("ACK",belle_sip_request_get_method(req))==0) {
|
if (strcmp("ACK",belle_sip_request_get_method(req))==0) {
|
||||||
if (op->sdp_offering){
|
if (op->sdp_offering){
|
||||||
if ((sdp=belle_sdp_session_description_create(BELLE_SIP_MESSAGE(req)))){
|
SalReason reason;
|
||||||
|
if (extract_sdp(BELLE_SIP_MESSAGE(req),&sdp,&reason)==0){
|
||||||
|
if (sdp){
|
||||||
if (op->base.remote_media)
|
if (op->base.remote_media)
|
||||||
sal_media_description_unref(op->base.remote_media);
|
sal_media_description_unref(op->base.remote_media);
|
||||||
op->base.remote_media=sal_media_description_new();
|
op->base.remote_media=sal_media_description_new();
|
||||||
sdp_to_media_description(sdp,op->base.remote_media);
|
sdp_to_media_description(sdp,op->base.remote_media);
|
||||||
sdp_process(op);
|
sdp_process(op);
|
||||||
belle_sip_object_unref(sdp);
|
belle_sip_object_unref(sdp);
|
||||||
|
}else{
|
||||||
|
ms_warning("SDP expected in ACK but not found.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*FIXME
|
/*FIXME
|
||||||
|
|
@ -445,8 +501,7 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t
|
||||||
sal_media_description_unref(op->result);
|
sal_media_description_unref(op->result);
|
||||||
op->result=NULL;
|
op->result=NULL;
|
||||||
}
|
}
|
||||||
process_sdp_for_invite(op,req);
|
if (process_sdp_for_invite(op,req)==0)
|
||||||
|
|
||||||
op->base.root->callbacks.call_updating(op);
|
op->base.root->callbacks.call_updating(op);
|
||||||
} else if (strcmp("INFO",belle_sip_request_get_method(req))==0){
|
} else if (strcmp("INFO",belle_sip_request_get_method(req))==0){
|
||||||
if (belle_sip_message_get_body(BELLE_SIP_MESSAGE(req))
|
if (belle_sip_message_get_body(BELLE_SIP_MESSAGE(req))
|
||||||
|
|
|
||||||
|
|
@ -334,7 +334,7 @@ SalReason sal_reason_to_sip_code(SalReason r){
|
||||||
case SalReasonForbidden:
|
case SalReasonForbidden:
|
||||||
ret=403;
|
ret=403;
|
||||||
break;
|
break;
|
||||||
case SalReasonMedia:
|
case SalReasonUnsupportedContent:
|
||||||
ret=415;
|
ret=415;
|
||||||
break;
|
break;
|
||||||
case SalReasonNotFound:
|
case SalReasonNotFound:
|
||||||
|
|
@ -356,7 +356,7 @@ SalReason sal_reason_to_sip_code(SalReason r){
|
||||||
ret=401;
|
ret=401;
|
||||||
break;
|
break;
|
||||||
case SalReasonNotAcceptable:
|
case SalReasonNotAcceptable:
|
||||||
ret=488;
|
ret=488; /*or maybe 606 Not Acceptable ?*/
|
||||||
break;
|
break;
|
||||||
case SalReasonNoMatch:
|
case SalReasonNoMatch:
|
||||||
ret=481;
|
ret=481;
|
||||||
|
|
@ -385,7 +385,7 @@ void sal_compute_sal_errors_from_code(int code ,SalError* sal_err,SalReason* sal
|
||||||
break;
|
break;
|
||||||
case 415:
|
case 415:
|
||||||
*sal_err=SalErrorFailure;
|
*sal_err=SalErrorFailure;
|
||||||
*sal_reason=SalReasonMedia;
|
*sal_reason=SalReasonUnsupportedContent;
|
||||||
break;
|
break;
|
||||||
case 422:
|
case 422:
|
||||||
ms_error ("422 not implemented yet");;
|
ms_error ("422 not implemented yet");;
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,10 @@ static bool_t is_external_body(belle_sip_header_content_type_t* content_type) {
|
||||||
return strcmp("message",belle_sip_header_content_type_get_type(content_type))==0
|
return strcmp("message",belle_sip_header_content_type_get_type(content_type))==0
|
||||||
&& strcmp("external-body",belle_sip_header_content_type_get_subtype(content_type))==0;
|
&& strcmp("external-body",belle_sip_header_content_type_get_subtype(content_type))==0;
|
||||||
}
|
}
|
||||||
|
static bool_t is_im_iscomposing(belle_sip_header_content_type_t* content_type) {
|
||||||
|
return strcmp("application",belle_sip_header_content_type_get_type(content_type))==0
|
||||||
|
&& strcmp("im-iscomposing+xml",belle_sip_header_content_type_get_subtype(content_type))==0;
|
||||||
|
}
|
||||||
|
|
||||||
static void process_request_event(void *op_base, const belle_sip_request_event_t *event) {
|
static void process_request_event(void *op_base, const belle_sip_request_event_t *event) {
|
||||||
SalOp* op = (SalOp*)op_base;
|
SalOp* op = (SalOp*)op_base;
|
||||||
|
|
@ -88,8 +92,6 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t
|
||||||
belle_sip_header_call_id_t* call_id = belle_sip_message_get_header_by_type(req,belle_sip_header_call_id_t);
|
belle_sip_header_call_id_t* call_id = belle_sip_message_get_header_by_type(req,belle_sip_header_call_id_t);
|
||||||
belle_sip_header_cseq_t* cseq = belle_sip_message_get_header_by_type(req,belle_sip_header_cseq_t);
|
belle_sip_header_cseq_t* cseq = belle_sip_message_get_header_by_type(req,belle_sip_header_cseq_t);
|
||||||
belle_sip_header_date_t *date=belle_sip_message_get_header_by_type(req,belle_sip_header_date_t);
|
belle_sip_header_date_t *date=belle_sip_message_get_header_by_type(req,belle_sip_header_date_t);
|
||||||
SalMessage salmsg;
|
|
||||||
char message_id[256]={0};
|
|
||||||
int response_code=501;
|
int response_code=501;
|
||||||
char* from;
|
char* from;
|
||||||
bool_t plain_text=FALSE;
|
bool_t plain_text=FALSE;
|
||||||
|
|
@ -99,7 +101,8 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t
|
||||||
content_type=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_content_type_t);
|
content_type=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_content_type_t);
|
||||||
if (content_type && ((plain_text=is_plain_text(content_type))
|
if (content_type && ((plain_text=is_plain_text(content_type))
|
||||||
|| (external_body=is_external_body(content_type)))) {
|
|| (external_body=is_external_body(content_type)))) {
|
||||||
|
SalMessage salmsg;
|
||||||
|
char message_id[256]={0};
|
||||||
address=belle_sip_header_address_create(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(from_header))
|
address=belle_sip_header_address_create(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(from_header))
|
||||||
,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(from_header)));
|
,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(from_header)));
|
||||||
from=belle_sip_object_to_string(BELLE_SIP_OBJECT(address));
|
from=belle_sip_object_to_string(BELLE_SIP_OBJECT(address));
|
||||||
|
|
@ -121,6 +124,17 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t
|
||||||
belle_sip_free(from);
|
belle_sip_free(from);
|
||||||
if (salmsg.url) ms_free((char*)salmsg.url);
|
if (salmsg.url) ms_free((char*)salmsg.url);
|
||||||
response_code=200;
|
response_code=200;
|
||||||
|
} else if (content_type && is_im_iscomposing(content_type)) {
|
||||||
|
SalIsComposing saliscomposing;
|
||||||
|
address=belle_sip_header_address_create(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(from_header))
|
||||||
|
,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(from_header)));
|
||||||
|
from=belle_sip_object_to_string(BELLE_SIP_OBJECT(address));
|
||||||
|
saliscomposing.from=from;
|
||||||
|
saliscomposing.text=belle_sip_message_get_body(BELLE_SIP_MESSAGE(req));
|
||||||
|
op->base.root->callbacks.is_composing_received(op,&saliscomposing);
|
||||||
|
belle_sip_object_unref(address);
|
||||||
|
belle_sip_free(from);
|
||||||
|
response_code=200;
|
||||||
} else {
|
} else {
|
||||||
ms_error("Unsupported MESSAGE with content type [%s/%s]",belle_sip_header_content_type_get_type(content_type)
|
ms_error("Unsupported MESSAGE with content type [%s/%s]",belle_sip_header_content_type_get_type(content_type)
|
||||||
,belle_sip_header_content_type_get_subtype(content_type));
|
,belle_sip_header_content_type_get_subtype(content_type));
|
||||||
|
|
|
||||||
|
|
@ -612,7 +612,8 @@ static void call_failure(SalOp *op, SalError error, SalReason sr, const char *de
|
||||||
if (lc->vtable.display_status)
|
if (lc->vtable.display_status)
|
||||||
lc->vtable.display_status(lc,msg600);
|
lc->vtable.display_status(lc,msg600);
|
||||||
break;
|
break;
|
||||||
case SalReasonMedia:
|
case SalReasonUnsupportedContent: /*<this is for compatibility: linphone sent 415 because of SDP offer answer failure*/
|
||||||
|
case SalReasonNotAcceptable:
|
||||||
//media_encryption_mandatory
|
//media_encryption_mandatory
|
||||||
if (call->params.media_encryption == LinphoneMediaEncryptionSRTP &&
|
if (call->params.media_encryption == LinphoneMediaEncryptionSRTP &&
|
||||||
!linphone_core_is_media_encryption_mandatory(lc)) {
|
!linphone_core_is_media_encryption_mandatory(lc)) {
|
||||||
|
|
@ -843,6 +844,11 @@ 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);
|
||||||
|
}
|
||||||
|
|
||||||
static void parse_presence_requested(SalOp *op, const char *content_type, const char *content_subtype, const char *body, SalPresenceModel **result) {
|
static void parse_presence_requested(SalOp *op, const char *content_type, const char *content_subtype, const char *body, SalPresenceModel **result) {
|
||||||
linphone_notify_parse_presence(op, content_type, content_subtype, body, result);
|
linphone_notify_parse_presence(op, content_type, content_subtype, body, result);
|
||||||
}
|
}
|
||||||
|
|
@ -1001,7 +1007,13 @@ static int op_equals(LinphoneCall *a, SalOp *b) {
|
||||||
|
|
||||||
static void text_delivery_update(SalOp *op, SalTextDeliveryStatus status){
|
static void text_delivery_update(SalOp *op, SalTextDeliveryStatus status){
|
||||||
LinphoneChatMessage *chat_msg=(LinphoneChatMessage* )sal_op_get_user_pointer(op);
|
LinphoneChatMessage *chat_msg=(LinphoneChatMessage* )sal_op_get_user_pointer(op);
|
||||||
const MSList* calls = linphone_core_get_calls(chat_msg->chat_room->lc);
|
const MSList* calls;
|
||||||
|
|
||||||
|
if (chat_msg == NULL) {
|
||||||
|
// Do not handle delivery status for isComposing messages.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
calls = linphone_core_get_calls(chat_msg->chat_room->lc);
|
||||||
|
|
||||||
chat_msg->state=chatStatusSal2Linphone(status);
|
chat_msg->state=chatStatusSal2Linphone(status);
|
||||||
linphone_chat_message_store_state(chat_msg);
|
linphone_chat_message_store_state(chat_msg);
|
||||||
|
|
@ -1123,6 +1135,7 @@ SalCallbacks linphone_sal_callbacks={
|
||||||
refer_received,
|
refer_received,
|
||||||
text_received,
|
text_received,
|
||||||
text_delivery_update,
|
text_delivery_update,
|
||||||
|
is_composing_received,
|
||||||
notify_refer,
|
notify_refer,
|
||||||
subscribe_received,
|
subscribe_received,
|
||||||
subscribe_closed,
|
subscribe_closed,
|
||||||
|
|
|
||||||
248
coreapi/chat.c
248
coreapi/chat.c
|
|
@ -26,6 +26,12 @@
|
||||||
#include "private.h"
|
#include "private.h"
|
||||||
#include "lpconfig.h"
|
#include "lpconfig.h"
|
||||||
|
|
||||||
|
#include <libxml/xmlwriter.h>
|
||||||
|
|
||||||
|
#define COMPOSING_DEFAULT_IDLE_TIMEOUT 15
|
||||||
|
#define COMPOSING_DEFAULT_REFRESH_TIMEOUT 60
|
||||||
|
#define COMPOSING_DEFAULT_REMOTE_REFRESH_TIMEOUT 120
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @addtogroup chatroom
|
* @addtogroup chatroom
|
||||||
* @{
|
* @{
|
||||||
|
|
@ -86,12 +92,39 @@ LinphoneChatRoom* linphone_core_get_or_create_chat_room(LinphoneCore* lc, const
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void linphone_chat_room_delete_composing_idle_timer(LinphoneChatRoom *cr) {
|
||||||
|
if (cr->composing_idle_timer) {
|
||||||
|
sal_cancel_timer(cr->lc->sal, cr->composing_idle_timer);
|
||||||
|
belle_sip_object_unref(cr->composing_idle_timer);
|
||||||
|
cr->composing_idle_timer = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void linphone_chat_room_delete_composing_refresh_timer(LinphoneChatRoom *cr) {
|
||||||
|
if (cr->composing_refresh_timer) {
|
||||||
|
sal_cancel_timer(cr->lc->sal, cr->composing_refresh_timer);
|
||||||
|
belle_sip_object_unref(cr->composing_refresh_timer);
|
||||||
|
cr->composing_refresh_timer = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void linphone_chat_room_delete_remote_composing_refresh_timer(LinphoneChatRoom *cr) {
|
||||||
|
if (cr->remote_composing_refresh_timer) {
|
||||||
|
sal_cancel_timer(cr->lc->sal, cr->remote_composing_refresh_timer);
|
||||||
|
belle_sip_object_unref(cr->remote_composing_refresh_timer);
|
||||||
|
cr->remote_composing_refresh_timer = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroy a LinphoneChatRoom.
|
* Destroy a LinphoneChatRoom.
|
||||||
* @param cr #LinphoneChatRoom object
|
* @param cr #LinphoneChatRoom object
|
||||||
*/
|
*/
|
||||||
void linphone_chat_room_destroy(LinphoneChatRoom *cr){
|
void linphone_chat_room_destroy(LinphoneChatRoom *cr){
|
||||||
LinphoneCore *lc=cr->lc;
|
LinphoneCore *lc=cr->lc;
|
||||||
|
linphone_chat_room_delete_composing_idle_timer(cr);
|
||||||
|
linphone_chat_room_delete_composing_refresh_timer(cr);
|
||||||
|
linphone_chat_room_delete_remote_composing_refresh_timer(cr);
|
||||||
lc->chatrooms=ms_list_remove(lc->chatrooms,(void *) cr);
|
lc->chatrooms=ms_list_remove(lc->chatrooms,(void *) cr);
|
||||||
linphone_address_destroy(cr->peer_url);
|
linphone_address_destroy(cr->peer_url);
|
||||||
ms_free(cr->peer);
|
ms_free(cr->peer);
|
||||||
|
|
@ -142,6 +175,12 @@ static void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatM
|
||||||
msg->dir=LinphoneChatMessageOutgoing;
|
msg->dir=LinphoneChatMessageOutgoing;
|
||||||
msg->from=linphone_address_new(identity);
|
msg->from=linphone_address_new(identity);
|
||||||
msg->storage_id=linphone_chat_message_store(msg);
|
msg->storage_id=linphone_chat_message_store(msg);
|
||||||
|
|
||||||
|
if (cr->is_composing == LinphoneIsComposingActive) {
|
||||||
|
cr->is_composing = LinphoneIsComposingIdle;
|
||||||
|
}
|
||||||
|
linphone_chat_room_delete_composing_idle_timer(cr);
|
||||||
|
linphone_chat_room_delete_composing_refresh_timer(cr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -159,7 +198,10 @@ void linphone_chat_room_message_received(LinphoneChatRoom *cr, LinphoneCore *lc,
|
||||||
//legacy API
|
//legacy API
|
||||||
if (lc->vtable.text_received!=NULL) lc->vtable.text_received(lc, cr, msg->from, msg->message);
|
if (lc->vtable.text_received!=NULL) lc->vtable.text_received(lc, cr, msg->from, msg->message);
|
||||||
if (lc->vtable.message_received!=NULL) lc->vtable.message_received(lc, cr,msg);
|
if (lc->vtable.message_received!=NULL) lc->vtable.message_received(lc, cr,msg);
|
||||||
|
if (cr->lc->vtable.is_composing_received != NULL) {
|
||||||
|
cr->remote_is_composing = LinphoneIsComposingIdle;
|
||||||
|
cr->lc->vtable.is_composing_received(cr->lc, cr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -225,6 +267,85 @@ void linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessag
|
||||||
ms_free(from);
|
ms_free(from);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int linphone_chat_room_remote_refresh_composing_expired(void *data, unsigned int revents) {
|
||||||
|
LinphoneChatRoom *cr = (LinphoneChatRoom *)data;
|
||||||
|
belle_sip_object_unref(cr->remote_composing_refresh_timer);
|
||||||
|
cr->remote_composing_refresh_timer = NULL;
|
||||||
|
cr->remote_is_composing = LinphoneIsComposingIdle;
|
||||||
|
if (cr->lc->vtable.is_composing_received != NULL)
|
||||||
|
cr->lc->vtable.is_composing_received(cr->lc, cr);
|
||||||
|
return BELLE_SIP_STOP;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *iscomposing_prefix = "/xsi:isComposing";
|
||||||
|
|
||||||
|
static void process_im_is_composing_notification(LinphoneChatRoom *cr, xmlparsing_context_t *xml_ctx) {
|
||||||
|
char xpath_str[MAX_XPATH_LENGTH];
|
||||||
|
xmlXPathObjectPtr iscomposing_object;
|
||||||
|
const char *state_str = NULL;
|
||||||
|
const char *refresh_str = NULL;
|
||||||
|
int refresh_duration = lp_config_get_int(cr->lc->config, "sip", "composing_remote_refresh_timeout", COMPOSING_DEFAULT_REMOTE_REFRESH_TIMEOUT);
|
||||||
|
int i;
|
||||||
|
LinphoneIsComposingState state = LinphoneIsComposingIdle;
|
||||||
|
|
||||||
|
if (linphone_create_xml_xpath_context(xml_ctx) < 0) return;
|
||||||
|
|
||||||
|
xmlXPathRegisterNs(xml_ctx->xpath_ctx, (const xmlChar *)"xsi", (const xmlChar *)"urn:ietf:params:xml:ns:im-iscomposing");
|
||||||
|
iscomposing_object = linphone_get_xml_xpath_object_for_node_list(xml_ctx, iscomposing_prefix);
|
||||||
|
if ((iscomposing_object != NULL) && (iscomposing_object->nodesetval != NULL)) {
|
||||||
|
for (i = 1; i <= iscomposing_object->nodesetval->nodeNr; i++) {
|
||||||
|
snprintf(xpath_str, sizeof(xpath_str), "%s[%i]/xsi:state", iscomposing_prefix, i);
|
||||||
|
state_str = linphone_get_xml_text_content(xml_ctx, xpath_str);
|
||||||
|
if (state_str == NULL) continue;
|
||||||
|
snprintf(xpath_str, sizeof(xpath_str), "%s[%i]/xsi:refresh", iscomposing_prefix, i);
|
||||||
|
refresh_str = linphone_get_xml_text_content(xml_ctx, xpath_str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state_str != NULL) {
|
||||||
|
if (strcmp(state_str, "active") == 0) {
|
||||||
|
state = LinphoneIsComposingActive;
|
||||||
|
if (refresh_str != NULL) {
|
||||||
|
refresh_duration = atoi(refresh_str);
|
||||||
|
}
|
||||||
|
if (!cr->remote_composing_refresh_timer) {
|
||||||
|
cr->remote_composing_refresh_timer = sal_create_timer(cr->lc->sal, linphone_chat_room_remote_refresh_composing_expired, cr, refresh_duration * 1000, "composing remote refresh timeout");
|
||||||
|
} else {
|
||||||
|
belle_sip_source_set_timeout(cr->remote_composing_refresh_timer, refresh_duration * 1000);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
linphone_chat_room_delete_remote_composing_refresh_timer(cr);
|
||||||
|
}
|
||||||
|
|
||||||
|
cr->remote_is_composing = state;
|
||||||
|
if (cr->lc->vtable.is_composing_received != NULL)
|
||||||
|
cr->lc->vtable.is_composing_received(cr->lc, cr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void linphone_chat_room_notify_is_composing(LinphoneChatRoom *cr, const char *text) {
|
||||||
|
xmlparsing_context_t *xml_ctx = linphone_xmlparsing_context_new();
|
||||||
|
xmlSetGenericErrorFunc(xml_ctx, linphone_xmlparsing_genericxml_error);
|
||||||
|
xml_ctx->doc = xmlReadDoc((const unsigned char*)text, 0, NULL, 0);
|
||||||
|
if (xml_ctx->doc != NULL) {
|
||||||
|
process_im_is_composing_notification(cr, xml_ctx);
|
||||||
|
} else {
|
||||||
|
ms_warning("Wrongly formatted presence XML: %s", xml_ctx->errorBuffer);
|
||||||
|
}
|
||||||
|
linphone_xmlparsing_context_destroy(xml_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void linphone_core_is_composing_received(LinphoneCore *lc, SalOp *op, const SalIsComposing *is_composing) {
|
||||||
|
LinphoneChatRoom *cr = linphone_core_get_or_create_chat_room(lc, is_composing->from);
|
||||||
|
if (cr != NULL) {
|
||||||
|
linphone_chat_room_notify_is_composing(cr, is_composing->text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool_t linphone_chat_room_is_remote_composing(const LinphoneChatRoom *cr) {
|
||||||
|
return (cr->remote_is_composing == LinphoneIsComposingActive) ? TRUE : FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns back pointer to LinphoneCore object.
|
* Returns back pointer to LinphoneCore object.
|
||||||
**/
|
**/
|
||||||
|
|
@ -319,6 +440,131 @@ void linphone_chat_room_send_message2(LinphoneChatRoom *cr, LinphoneChatMessage*
|
||||||
_linphone_chat_room_send_message(cr, msg);
|
_linphone_chat_room_send_message(cr, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char * linphone_chat_room_create_is_composing_xml(LinphoneChatRoom *cr) {
|
||||||
|
xmlBufferPtr buf;
|
||||||
|
xmlTextWriterPtr writer;
|
||||||
|
int err;
|
||||||
|
char *content = NULL;
|
||||||
|
|
||||||
|
buf = xmlBufferCreate();
|
||||||
|
if (buf == NULL) {
|
||||||
|
ms_error("Error creating the XML buffer");
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
writer = xmlNewTextWriterMemory(buf, 0);
|
||||||
|
if (writer == NULL) {
|
||||||
|
ms_error("Error creating the XML writer");
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = xmlTextWriterStartDocument(writer, "1.0", "UTF-8", NULL);
|
||||||
|
if (err >= 0) {
|
||||||
|
err = xmlTextWriterStartElementNS(writer, NULL, (const xmlChar *)"isComposing", (const xmlChar *)"urn:ietf:params:xml:ns:im-iscomposing");
|
||||||
|
}
|
||||||
|
if (err >= 0) {
|
||||||
|
err = xmlTextWriterWriteAttributeNS(writer, (const xmlChar *)"xmlns", (const xmlChar *)"xsi",
|
||||||
|
NULL, (const xmlChar *)"http://www.w3.org/2001/XMLSchema-instance");
|
||||||
|
}
|
||||||
|
if (err >= 0) {
|
||||||
|
err = xmlTextWriterWriteAttributeNS(writer, (const xmlChar *)"xsi", (const xmlChar *)"schemaLocation",
|
||||||
|
NULL, (const xmlChar *)"urn:ietf:params:xml:ns:im-composing iscomposing.xsd");
|
||||||
|
}
|
||||||
|
if (err >= 0) {
|
||||||
|
err = xmlTextWriterWriteElement(writer, (const xmlChar *)"state",
|
||||||
|
(cr->is_composing == LinphoneIsComposingActive) ? (const xmlChar *)"active" : (const xmlChar *)"idle");
|
||||||
|
}
|
||||||
|
if ((err >= 0) && (cr->is_composing == LinphoneIsComposingActive)) {
|
||||||
|
char refresh_str[4] = { 0 };
|
||||||
|
int refresh_timeout = lp_config_get_int(cr->lc->config, "sip", "composing_refresh_timeout", COMPOSING_DEFAULT_REFRESH_TIMEOUT);
|
||||||
|
snprintf(refresh_str, sizeof(refresh_str), "%u", refresh_timeout);
|
||||||
|
err = xmlTextWriterWriteElement(writer, (const xmlChar *)"refresh", (const xmlChar *)refresh_str);
|
||||||
|
}
|
||||||
|
if (err >= 0) {
|
||||||
|
/* Close the "isComposing" element. */
|
||||||
|
err = xmlTextWriterEndElement(writer);
|
||||||
|
}
|
||||||
|
if (err >= 0) {
|
||||||
|
err = xmlTextWriterEndDocument(writer);
|
||||||
|
}
|
||||||
|
if (err > 0) {
|
||||||
|
/* xmlTextWriterEndDocument returns the size of the content. */
|
||||||
|
content = ms_strdup((char *)buf->content);
|
||||||
|
}
|
||||||
|
xmlFreeTextWriter(writer);
|
||||||
|
xmlBufferFree(buf);
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void linphone_chat_room_send_is_composing_notification(LinphoneChatRoom *cr) {
|
||||||
|
SalOp *op = NULL;
|
||||||
|
LinphoneCall *call;
|
||||||
|
const char *identity = NULL;
|
||||||
|
char *content = NULL;
|
||||||
|
|
||||||
|
if (lp_config_get_int(cr->lc->config, "sip", "chat_use_call_dialogs", 0)) {
|
||||||
|
if ((call = linphone_core_get_call_by_remote_address(cr->lc, cr->peer)) != NULL) {
|
||||||
|
if (call->state == LinphoneCallConnected ||
|
||||||
|
call->state == LinphoneCallStreamsRunning ||
|
||||||
|
call->state == LinphoneCallPaused ||
|
||||||
|
call->state == LinphoneCallPausing ||
|
||||||
|
call->state == LinphoneCallPausedByRemote) {
|
||||||
|
ms_message("send SIP message through the existing call.");
|
||||||
|
op = call->op;
|
||||||
|
identity = linphone_core_find_best_identity(cr->lc, linphone_call_get_remote_address(call));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (op == NULL) {
|
||||||
|
LinphoneProxyConfig *proxy = linphone_core_lookup_known_proxy(cr->lc, cr->peer_url);
|
||||||
|
if (proxy)
|
||||||
|
identity = linphone_proxy_config_get_identity(proxy);
|
||||||
|
else
|
||||||
|
identity = linphone_core_get_primary_contact(cr->lc);
|
||||||
|
/*sending out of calls*/
|
||||||
|
op = sal_op_new(cr->lc->sal);
|
||||||
|
linphone_configure_op(cr->lc, op, cr->peer_url, NULL, lp_config_get_int(cr->lc->config, "sip", "chat_msg_with_contact", 0));
|
||||||
|
}
|
||||||
|
content = linphone_chat_room_create_is_composing_xml(cr);
|
||||||
|
if (content != NULL) {
|
||||||
|
sal_message_send(op, identity, cr->peer, "application/im-iscomposing+xml", content);
|
||||||
|
ms_free(content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int linphone_chat_room_stop_composing(void *data, unsigned int revents) {
|
||||||
|
LinphoneChatRoom *cr = (LinphoneChatRoom *)data;
|
||||||
|
cr->is_composing = LinphoneIsComposingIdle;
|
||||||
|
linphone_chat_room_send_is_composing_notification(cr);
|
||||||
|
linphone_chat_room_delete_composing_refresh_timer(cr);
|
||||||
|
belle_sip_object_unref(cr->composing_idle_timer);
|
||||||
|
cr->composing_idle_timer = NULL;
|
||||||
|
return BELLE_SIP_STOP;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int linphone_chat_room_refresh_composing(void *data, unsigned int revents) {
|
||||||
|
LinphoneChatRoom *cr = (LinphoneChatRoom *)data;
|
||||||
|
linphone_chat_room_send_is_composing_notification(cr);
|
||||||
|
return BELLE_SIP_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void linphone_chat_room_compose(LinphoneChatRoom *cr) {
|
||||||
|
int idle_timeout = lp_config_get_int(cr->lc->config, "sip", "composing_idle_timeout", COMPOSING_DEFAULT_IDLE_TIMEOUT);
|
||||||
|
int refresh_timeout = lp_config_get_int(cr->lc->config, "sip", "composing_refresh_timeout", COMPOSING_DEFAULT_REFRESH_TIMEOUT);
|
||||||
|
if (cr->is_composing == LinphoneIsComposingIdle) {
|
||||||
|
cr->is_composing = LinphoneIsComposingActive;
|
||||||
|
linphone_chat_room_send_is_composing_notification(cr);
|
||||||
|
if (!cr->composing_refresh_timer) {
|
||||||
|
cr->composing_refresh_timer = sal_create_timer(cr->lc->sal, linphone_chat_room_refresh_composing, cr, refresh_timeout * 1000, "composing refresh timeout");
|
||||||
|
} else {
|
||||||
|
belle_sip_source_set_timeout(cr->composing_refresh_timer, refresh_timeout * 1000);
|
||||||
|
}
|
||||||
|
if (!cr->composing_idle_timer) {
|
||||||
|
cr->composing_idle_timer = sal_create_timer(cr->lc->sal, linphone_chat_room_stop_composing, cr, idle_timeout * 1000, "composing idle timeout");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
belle_sip_source_set_timeout(cr->composing_idle_timer, idle_timeout * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a #LinphoneChatMessageState as a string.
|
* Returns a #LinphoneChatMessageState as a string.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
#ifndef CONTACT_PROVIDERS_PRIV_H
|
#ifndef CONTACT_PROVIDERS_PRIV_H
|
||||||
#define CONTACT_PROVIDERS_PRIV_H
|
#define CONTACT_PROVIDERS_PRIV_H
|
||||||
|
|
||||||
#include <belle-sip/object.h>
|
#include "private.h"
|
||||||
#include "linphonecore.h"
|
#include "linphonecore.h"
|
||||||
|
|
||||||
/* Base for contact search and contact provider */
|
/* Base for contact search and contact provider */
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ int linphone_contact_search_compare(const void* a, const void* b) {
|
||||||
return !(ra->id == rb->id); // return 0 if id is equal, 1 otherwise
|
return !(ra->id == rb->id); // return 0 if id is equal, 1 otherwise
|
||||||
}
|
}
|
||||||
|
|
||||||
LinphoneContactSearch*linphone_ldap_contact_search_ref(void* obj)
|
LinphoneContactSearch*linphone_contact_search_ref(void* obj)
|
||||||
{
|
{
|
||||||
return LINPHONE_CONTACT_SEARCH(belle_sip_object_ref(obj));
|
return LINPHONE_CONTACT_SEARCH(belle_sip_object_ref(obj));
|
||||||
}
|
}
|
||||||
|
|
@ -136,4 +136,3 @@ BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_BEGIN(LinphoneContactProvider)
|
||||||
NULL, /* begin_search -> pure virtual */
|
NULL, /* begin_search -> pure virtual */
|
||||||
NULL /* cancel_search -> pure virtual */
|
NULL /* cancel_search -> pure virtual */
|
||||||
BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_END
|
BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_END
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -280,5 +280,11 @@ public class TutorialBuddyStatus implements LinphoneCoreListener {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void isComposingReceived(LinphoneCore lc, LinphoneChatRoom cr) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -202,5 +202,13 @@ public class TutorialChatRoom implements LinphoneCoreListener, LinphoneChatMessa
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void isComposingReceived(LinphoneCore lc, LinphoneChatRoom cr) {
|
||||||
|
if (cr.isRemoteComposing())
|
||||||
|
write("Remote is writing a message");
|
||||||
|
else
|
||||||
|
write("Remote has stop writing");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -206,5 +206,11 @@ public class TutorialHelloWorld implements LinphoneCoreListener {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void isComposingReceived(LinphoneCore lc, LinphoneChatRoom cr) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -237,6 +237,12 @@ public class TutorialRegistration implements LinphoneCoreListener {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void isComposingReceived(LinphoneCore lc, LinphoneChatRoom cr) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -595,9 +595,14 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro
|
||||||
linphone_call_init_common(call, from, to);
|
linphone_call_init_common(call, from, to);
|
||||||
call->log->call_id=ms_strdup(sal_op_get_call_id(op)); /*must be known at that time*/
|
call->log->call_id=ms_strdup(sal_op_get_call_id(op)); /*must be known at that time*/
|
||||||
linphone_core_init_default_params(lc, &call->params);
|
linphone_core_init_default_params(lc, &call->params);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize call parameters according to incoming call parameters. This is to avoid to ask later (during reINVITEs) for features that the remote
|
||||||
|
* end apparently does not support. This features are: privacy, video
|
||||||
|
*/
|
||||||
/*set privacy*/
|
/*set privacy*/
|
||||||
call->current_params.privacy=(LinphonePrivacyMask)sal_op_get_privacy(call->op);
|
call->current_params.privacy=(LinphonePrivacyMask)sal_op_get_privacy(call->op);
|
||||||
|
/*set video support */
|
||||||
md=sal_call_get_remote_media_description(op);
|
md=sal_call_get_remote_media_description(op);
|
||||||
call->params.has_video &= !!lc->video_policy.automatically_accept;
|
call->params.has_video &= !!lc->video_policy.automatically_accept;
|
||||||
if (md) {
|
if (md) {
|
||||||
|
|
@ -605,6 +610,7 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro
|
||||||
// In this case WE chose the media parameters according to policy.
|
// In this case WE chose the media parameters according to policy.
|
||||||
call->params.has_video &= linphone_core_media_description_contains_video_stream(md);
|
call->params.has_video &= linphone_core_media_description_contains_video_stream(md);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (linphone_core_get_firewall_policy(call->core)) {
|
switch (linphone_core_get_firewall_policy(call->core)) {
|
||||||
case LinphonePolicyUseIce:
|
case LinphonePolicyUseIce:
|
||||||
call->ice_session = ice_session_new();
|
call->ice_session = ice_session_new();
|
||||||
|
|
@ -1760,8 +1766,7 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cna
|
||||||
|
|
||||||
/* valid local tags are > 0 */
|
/* valid local tags are > 0 */
|
||||||
if (stream->proto == SalProtoRtpSavp) {
|
if (stream->proto == SalProtoRtpSavp) {
|
||||||
local_st_desc=sal_media_description_find_stream(call->localdesc,
|
local_st_desc=sal_media_description_find_stream(call->localdesc,SalProtoRtpSavp,SalAudio);
|
||||||
SalProtoRtpSavp,SalAudio);
|
|
||||||
crypto_idx = find_crypto_index_from_tag(local_st_desc->crypto, stream->crypto_local_tag);
|
crypto_idx = find_crypto_index_from_tag(local_st_desc->crypto, stream->crypto_local_tag);
|
||||||
|
|
||||||
if (crypto_idx >= 0) {
|
if (crypto_idx >= 0) {
|
||||||
|
|
@ -1929,7 +1934,7 @@ void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_mut
|
||||||
|
|
||||||
params.zid_file=lc->zrtp_secrets_cache;
|
params.zid_file=lc->zrtp_secrets_cache;
|
||||||
audio_stream_enable_zrtp(call->audiostream,¶ms);
|
audio_stream_enable_zrtp(call->audiostream,¶ms);
|
||||||
}else if (call->params.media_encryption==LinphoneMediaEncryptionSRTP){
|
}else{
|
||||||
call->current_params.media_encryption=linphone_call_are_all_streams_encrypted(call) ?
|
call->current_params.media_encryption=linphone_call_are_all_streams_encrypted(call) ?
|
||||||
LinphoneMediaEncryptionSRTP : LinphoneMediaEncryptionNone;
|
LinphoneMediaEncryptionSRTP : LinphoneMediaEncryptionNone;
|
||||||
}
|
}
|
||||||
|
|
@ -2247,6 +2252,111 @@ const LinphoneCallStats *linphone_call_get_video_stats(LinphoneCall *call) {
|
||||||
return stats;
|
return stats;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float linphone_call_stats_update_sender_loss_rate(const LinphoneCallStats *stats) {
|
||||||
|
const report_block_t *srb = NULL;
|
||||||
|
|
||||||
|
if (!stats || !stats->sent_rtcp)
|
||||||
|
return 0.0;
|
||||||
|
/* Perform msgpullup() to prevent crashes in rtcp_is_SR() or rtcp_is_RR() if the RTCP packet is composed of several mblk_t structure */
|
||||||
|
if (stats->sent_rtcp->b_cont != NULL)
|
||||||
|
msgpullup(stats->sent_rtcp, -1);
|
||||||
|
if (rtcp_is_SR(stats->sent_rtcp))
|
||||||
|
srb = rtcp_SR_get_report_block(stats->sent_rtcp, 0);
|
||||||
|
else if (rtcp_is_RR(stats->sent_rtcp))
|
||||||
|
srb = rtcp_RR_get_report_block(stats->sent_rtcp, 0);
|
||||||
|
if (!srb)
|
||||||
|
return 0.0;
|
||||||
|
return 100.0 * report_block_get_fraction_lost(srb) / 256.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
float linphone_call_stats_update_receiver_loss_rate(const LinphoneCallStats *stats) {
|
||||||
|
const report_block_t *rrb = NULL;
|
||||||
|
|
||||||
|
if (!stats || !stats->received_rtcp)
|
||||||
|
return 0.0;
|
||||||
|
/* Perform msgpullup() to prevent crashes in rtcp_is_SR() or rtcp_is_RR() if the RTCP packet is composed of several mblk_t structure */
|
||||||
|
if (stats->received_rtcp->b_cont != NULL)
|
||||||
|
msgpullup(stats->received_rtcp, -1);
|
||||||
|
if (rtcp_is_RR(stats->received_rtcp))
|
||||||
|
rrb = rtcp_RR_get_report_block(stats->received_rtcp, 0);
|
||||||
|
else if (rtcp_is_SR(stats->received_rtcp))
|
||||||
|
rrb = rtcp_SR_get_report_block(stats->received_rtcp, 0);
|
||||||
|
if (!rrb)
|
||||||
|
return 0.0;
|
||||||
|
return 100.0 * report_block_get_fraction_lost(rrb) / 256.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
float linphone_call_stats_update_sender_interarrival_jitter(const LinphoneCallStats *stats, LinphoneCall *call) {
|
||||||
|
const LinphoneCallParams *params;
|
||||||
|
const PayloadType *pt;
|
||||||
|
const report_block_t *srb = NULL;
|
||||||
|
|
||||||
|
if (!stats || !call || !stats->sent_rtcp)
|
||||||
|
return 0.0;
|
||||||
|
params = linphone_call_get_current_params(call);
|
||||||
|
if (!params)
|
||||||
|
return 0.0;
|
||||||
|
/* Perform msgpullup() to prevent crashes in rtcp_is_SR() or rtcp_is_RR() if the RTCP packet is composed of several mblk_t structure */
|
||||||
|
if (stats->sent_rtcp->b_cont != NULL)
|
||||||
|
msgpullup(stats->sent_rtcp, -1);
|
||||||
|
if (rtcp_is_SR(stats->sent_rtcp))
|
||||||
|
srb = rtcp_SR_get_report_block(stats->sent_rtcp, 0);
|
||||||
|
else if (rtcp_is_RR(stats->sent_rtcp))
|
||||||
|
srb = rtcp_RR_get_report_block(stats->sent_rtcp, 0);
|
||||||
|
if (!srb)
|
||||||
|
return 0.0;
|
||||||
|
if (stats->type == LINPHONE_CALL_STATS_AUDIO)
|
||||||
|
pt = linphone_call_params_get_used_audio_codec(params);
|
||||||
|
else
|
||||||
|
pt = linphone_call_params_get_used_video_codec(params);
|
||||||
|
if (!pt || (pt->clock_rate == 0))
|
||||||
|
return 0.0;
|
||||||
|
return (float)report_block_get_interarrival_jitter(srb) / (float)pt->clock_rate;
|
||||||
|
}
|
||||||
|
|
||||||
|
float linphone_call_stats_update_receiver_interarrival_jitter(const LinphoneCallStats *stats, LinphoneCall *call) {
|
||||||
|
const LinphoneCallParams *params;
|
||||||
|
const PayloadType *pt;
|
||||||
|
const report_block_t *rrb = NULL;
|
||||||
|
|
||||||
|
if (!stats || !call || !stats->received_rtcp)
|
||||||
|
return 0.0;
|
||||||
|
params = linphone_call_get_current_params(call);
|
||||||
|
if (!params)
|
||||||
|
return 0.0;
|
||||||
|
/* Perform msgpullup() to prevent crashes in rtcp_is_SR() or rtcp_is_RR() if the RTCP packet is composed of several mblk_t structure */
|
||||||
|
if (stats->received_rtcp->b_cont != NULL)
|
||||||
|
msgpullup(stats->received_rtcp, -1);
|
||||||
|
if (rtcp_is_SR(stats->received_rtcp))
|
||||||
|
rrb = rtcp_SR_get_report_block(stats->received_rtcp, 0);
|
||||||
|
else if (rtcp_is_RR(stats->received_rtcp))
|
||||||
|
rrb = rtcp_RR_get_report_block(stats->received_rtcp, 0);
|
||||||
|
if (!rrb)
|
||||||
|
return 0.0;
|
||||||
|
if (stats->type == LINPHONE_CALL_STATS_AUDIO)
|
||||||
|
pt = linphone_call_params_get_used_audio_codec(params);
|
||||||
|
else
|
||||||
|
pt = linphone_call_params_get_used_video_codec(params);
|
||||||
|
if (!pt || (pt->clock_rate == 0))
|
||||||
|
return 0.0;
|
||||||
|
return (float)report_block_get_interarrival_jitter(rrb) / (float)pt->clock_rate;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t linphone_call_stats_update_late_packets_cumulative_number(const LinphoneCallStats *stats, LinphoneCall *call) {
|
||||||
|
rtp_stats_t rtp_stats;
|
||||||
|
|
||||||
|
if (!stats || !call)
|
||||||
|
return 0;
|
||||||
|
memset(&rtp_stats, 0, sizeof(rtp_stats));
|
||||||
|
if (stats->type == LINPHONE_CALL_STATS_AUDIO)
|
||||||
|
audio_stream_get_local_rtp_stats(call->audiostream, &rtp_stats);
|
||||||
|
#ifdef VIDEO_ENABLED
|
||||||
|
else
|
||||||
|
video_stream_get_local_rtp_stats(call->videostream, &rtp_stats);
|
||||||
|
#endif
|
||||||
|
return rtp_stats.outoftime;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enable recording of the call (voice-only).
|
* Enable recording of the call (voice-only).
|
||||||
* This function must be used before the call parameters are assigned to the call.
|
* This function must be used before the call parameters are assigned to the call.
|
||||||
|
|
@ -2572,7 +2682,6 @@ bool_t linphone_call_is_in_conference(const LinphoneCall *call) {
|
||||||
return call->params.in_conference;
|
return call->params.in_conference;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform a zoom of the video displayed during a call.
|
* Perform a zoom of the video displayed during a call.
|
||||||
* @param call the call.
|
* @param call the call.
|
||||||
|
|
@ -2608,28 +2717,16 @@ void linphone_call_zoom_video(LinphoneCall* call, float zoom_factor, float* cx,
|
||||||
}else ms_warning("Could not apply zoom: video output wasn't activated.");
|
}else ms_warning("Could not apply zoom: video output wasn't activated.");
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef USE_BELLESIP
|
|
||||||
static char *get_fixed_contact(LinphoneCore *lc, LinphoneCall *call , LinphoneProxyConfig *dest_proxy){
|
|
||||||
#else
|
|
||||||
static LinphoneAddress *get_fixed_contact(LinphoneCore *lc, LinphoneCall *call , LinphoneProxyConfig *dest_proxy){
|
static LinphoneAddress *get_fixed_contact(LinphoneCore *lc, LinphoneCall *call , LinphoneProxyConfig *dest_proxy){
|
||||||
#endif
|
|
||||||
LinphoneAddress *ctt=NULL;
|
LinphoneAddress *ctt=NULL;
|
||||||
#ifdef USE_BELLESIP
|
|
||||||
LinphoneAddress *ret=NULL;
|
LinphoneAddress *ret=NULL;
|
||||||
#else
|
|
||||||
char* ret;
|
|
||||||
#endif
|
|
||||||
const char *localip=call->localip;
|
const char *localip=call->localip;
|
||||||
|
|
||||||
/* first use user's supplied ip address if asked*/
|
/* first use user's supplied ip address if asked*/
|
||||||
if (linphone_core_get_firewall_policy(lc)==LinphonePolicyUseNatAddress){
|
if (linphone_core_get_firewall_policy(lc)==LinphonePolicyUseNatAddress){
|
||||||
ctt=linphone_core_get_primary_contact_parsed(lc);
|
ctt=linphone_core_get_primary_contact_parsed(lc);
|
||||||
linphone_address_set_domain(ctt,linphone_core_get_nat_address_resolved(lc));
|
linphone_address_set_domain(ctt,linphone_core_get_nat_address_resolved(lc));
|
||||||
#ifdef USE_BELLESIP
|
|
||||||
ret=ctt;
|
ret=ctt;
|
||||||
#else
|
|
||||||
ret=linphone_address_as_string(ctt);
|
|
||||||
#endif
|
|
||||||
} else if (call->op && sal_op_get_contact(call->op)!=NULL){
|
} else if (call->op && sal_op_get_contact(call->op)!=NULL){
|
||||||
/* if already choosed, don't change it */
|
/* if already choosed, don't change it */
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -2637,19 +2734,11 @@ static LinphoneAddress *get_fixed_contact(LinphoneCore *lc, LinphoneCall *call ,
|
||||||
/* if the ping OPTIONS request succeeded use the contact guessed from the
|
/* if the ping OPTIONS request succeeded use the contact guessed from the
|
||||||
received, rport*/
|
received, rport*/
|
||||||
ms_message("Contact has been fixed using OPTIONS"/* to %s",guessed*/);
|
ms_message("Contact has been fixed using OPTIONS"/* to %s",guessed*/);
|
||||||
#ifdef USE_BELLESIP
|
|
||||||
ret=linphone_address_clone(sal_op_get_contact(call->ping_op));;
|
ret=linphone_address_clone(sal_op_get_contact(call->ping_op));;
|
||||||
#else
|
|
||||||
ret=ms_strdup(sal_op_get_contact(call->ping_op));
|
|
||||||
#endif
|
|
||||||
} else if (dest_proxy && dest_proxy->op && sal_op_get_contact(dest_proxy->op)){
|
} else if (dest_proxy && dest_proxy->op && sal_op_get_contact(dest_proxy->op)){
|
||||||
/*if using a proxy, use the contact address as guessed with the REGISTERs*/
|
/*if using a proxy, use the contact address as guessed with the REGISTERs*/
|
||||||
ms_message("Contact has been fixed using proxy" /*to %s",fixed_contact*/);
|
ms_message("Contact has been fixed using proxy" /*to %s",fixed_contact*/);
|
||||||
#ifdef USE_BELLESIP
|
|
||||||
ret=linphone_address_clone(sal_op_get_contact(dest_proxy->op));
|
ret=linphone_address_clone(sal_op_get_contact(dest_proxy->op));
|
||||||
#else
|
|
||||||
ret=ms_strdup(sal_op_get_contact(dest_proxy->op));
|
|
||||||
#endif
|
|
||||||
} else {
|
} else {
|
||||||
ctt=linphone_core_get_primary_contact_parsed(lc);
|
ctt=linphone_core_get_primary_contact_parsed(lc);
|
||||||
if (ctt!=NULL){
|
if (ctt!=NULL){
|
||||||
|
|
@ -2657,16 +2746,9 @@ static LinphoneAddress *get_fixed_contact(LinphoneCore *lc, LinphoneCall *call ,
|
||||||
linphone_address_set_domain(ctt,localip);
|
linphone_address_set_domain(ctt,localip);
|
||||||
linphone_address_set_port(ctt,linphone_core_get_sip_port(lc));
|
linphone_address_set_port(ctt,linphone_core_get_sip_port(lc));
|
||||||
ms_message("Contact has been fixed using local ip"/* to %s",ret*/);
|
ms_message("Contact has been fixed using local ip"/* to %s",ret*/);
|
||||||
#ifdef USE_BELLESIP
|
|
||||||
ret=ctt;
|
ret=ctt;
|
||||||
#else
|
|
||||||
ret=linphone_address_as_string_uri_only(ctt);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifndef USE_BELLESIP
|
|
||||||
if (ctt) linphone_address_destroy(ctt);
|
|
||||||
#endif
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2873,17 +2873,21 @@ bool_t linphone_core_inc_invite_pending(LinphoneCore*lc){
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool_t linphone_core_incompatible_security(LinphoneCore *lc, SalMediaDescription *md){
|
bool_t linphone_core_media_description_has_srtp(const SalMediaDescription *md){
|
||||||
if (linphone_core_is_media_encryption_mandatory(lc) && linphone_core_get_media_encryption(lc)==LinphoneMediaEncryptionSRTP){
|
|
||||||
int i;
|
int i;
|
||||||
|
if (md->n_active_streams==0) return FALSE;
|
||||||
|
|
||||||
for(i=0;i<md->n_active_streams;i++){
|
for(i=0;i<md->n_active_streams;i++){
|
||||||
SalStreamDescription *sd=&md->streams[i];
|
const SalStreamDescription *sd=&md->streams[i];
|
||||||
if (sd->proto!=SalProtoRtpSavp){
|
if (sd->proto!=SalProtoRtpSavp){
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
bool_t linphone_core_incompatible_security(LinphoneCore *lc, SalMediaDescription *md){
|
||||||
return FALSE;
|
return linphone_core_is_media_encryption_mandatory(lc) && linphone_core_get_media_encryption(lc)==LinphoneMediaEncryptionSRTP && !linphone_core_media_description_has_srtp(md);
|
||||||
}
|
}
|
||||||
|
|
||||||
void linphone_core_notify_incoming_call(LinphoneCore *lc, LinphoneCall *call){
|
void linphone_core_notify_incoming_call(LinphoneCore *lc, LinphoneCall *call){
|
||||||
|
|
@ -2899,7 +2903,7 @@ void linphone_core_notify_incoming_call(LinphoneCore *lc, LinphoneCall *call){
|
||||||
md=sal_call_get_final_media_description(call->op);
|
md=sal_call_get_final_media_description(call->op);
|
||||||
if (md){
|
if (md){
|
||||||
if (sal_media_description_empty(md) || linphone_core_incompatible_security(lc,md)){
|
if (sal_media_description_empty(md) || linphone_core_incompatible_security(lc,md)){
|
||||||
sal_call_decline(call->op,SalReasonMedia,NULL);
|
sal_call_decline(call->op,SalReasonNotAcceptable,NULL);
|
||||||
linphone_call_stop_media_streams(call);
|
linphone_call_stop_media_streams(call);
|
||||||
linphone_core_del_call(lc,call);
|
linphone_core_del_call(lc,call);
|
||||||
linphone_call_unref(call);
|
linphone_call_unref(call);
|
||||||
|
|
@ -3325,6 +3329,7 @@ int linphone_core_accept_call_with_params(LinphoneCore *lc, LinphoneCall *call,
|
||||||
linphone_call_set_state(call,LinphoneCallConnected,"Connected");
|
linphone_call_set_state(call,LinphoneCallConnected,"Connected");
|
||||||
new_md=sal_call_get_final_media_description(call->op);
|
new_md=sal_call_get_final_media_description(call->op);
|
||||||
linphone_core_update_streams(lc, call, new_md);
|
linphone_core_update_streams(lc, call, new_md);
|
||||||
|
linphone_call_fix_call_parameters(call);
|
||||||
if (new_md){
|
if (new_md){
|
||||||
linphone_call_set_state(call,LinphoneCallStreamsRunning,"Connected (streams running)");
|
linphone_call_set_state(call,LinphoneCallStreamsRunning,"Connected (streams running)");
|
||||||
}else call->media_pending=TRUE;
|
}else call->media_pending=TRUE;
|
||||||
|
|
@ -6267,7 +6272,7 @@ void linphone_core_set_video_dscp(LinphoneCore *lc, int dscp){
|
||||||
*
|
*
|
||||||
**/
|
**/
|
||||||
int linphone_core_get_video_dscp(const LinphoneCore *lc){
|
int linphone_core_get_video_dscp(const LinphoneCore *lc){
|
||||||
return lp_config_get_int(lc->config,"rtp","video_dscp",0x2e);
|
return lp_config_get_int(lc->config,"rtp","video_dscp",0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
#include "ortp/payloadtype.h"
|
#include "ortp/payloadtype.h"
|
||||||
#include "mediastreamer2/mscommon.h"
|
#include "mediastreamer2/mscommon.h"
|
||||||
#include "mediastreamer2/msvideo.h"
|
#include "mediastreamer2/msvideo.h"
|
||||||
|
#include "mediastreamer2/mediastream.h"
|
||||||
|
|
||||||
#ifdef IN_LINPHONE
|
#ifdef IN_LINPHONE
|
||||||
#include "sipsetup.h"
|
#include "sipsetup.h"
|
||||||
|
|
@ -32,9 +33,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
#include "lpconfig.h"
|
#include "lpconfig.h"
|
||||||
|
|
||||||
#include <belle-sip/object.h>
|
|
||||||
#include <belle-sip/dict.h>
|
|
||||||
|
|
||||||
#define LINPHONE_IPADDR_SIZE 64
|
#define LINPHONE_IPADDR_SIZE 64
|
||||||
#define LINPHONE_HOSTNAME_SIZE 128
|
#define LINPHONE_HOSTNAME_SIZE 128
|
||||||
|
|
||||||
|
|
@ -94,6 +92,7 @@ typedef struct _LCSipTransports{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enum describing transport type for LinphoneAddress.
|
* Enum describing transport type for LinphoneAddress.
|
||||||
|
* @ingroup linphone_address
|
||||||
**/
|
**/
|
||||||
enum _LinphoneTransportType{
|
enum _LinphoneTransportType{
|
||||||
LinphoneTransportUdp,
|
LinphoneTransportUdp,
|
||||||
|
|
@ -103,6 +102,10 @@ enum _LinphoneTransportType{
|
||||||
};
|
};
|
||||||
/*this enum MUST be kept in sync with the SalTransport from sal.h*/
|
/*this enum MUST be kept in sync with the SalTransport from sal.h*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Typedef for transport type enum.
|
||||||
|
* @ingroup linphone_address
|
||||||
|
**/
|
||||||
typedef enum _LinphoneTransportType LinphoneTransportType;
|
typedef enum _LinphoneTransportType LinphoneTransportType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -166,7 +169,7 @@ enum _LinphoneReason{
|
||||||
LinphoneReasonNotFound, /**<Destination of the calls was not found.*/
|
LinphoneReasonNotFound, /**<Destination of the calls was not found.*/
|
||||||
LinphoneReasonNotAnswered, /**<The call was not answered in time*/
|
LinphoneReasonNotAnswered, /**<The call was not answered in time*/
|
||||||
LinphoneReasonBusy, /**<Phone line was busy */
|
LinphoneReasonBusy, /**<Phone line was busy */
|
||||||
LinphoneReasonMedia, /**<Incompatible media */
|
LinphoneReasonUnsupportedContent, /**<Unsupported content */
|
||||||
LinphoneReasonIOError, /**<Transport error: connection failures, disconnections etc...*/
|
LinphoneReasonIOError, /**<Transport error: connection failures, disconnections etc...*/
|
||||||
LinphoneReasonDoNotDisturb, /**<Do not disturb reason*/
|
LinphoneReasonDoNotDisturb, /**<Do not disturb reason*/
|
||||||
LinphoneReasonUnauthorized, /**<Operation is unauthorized because missing credential*/
|
LinphoneReasonUnauthorized, /**<Operation is unauthorized because missing credential*/
|
||||||
|
|
@ -174,6 +177,9 @@ enum _LinphoneReason{
|
||||||
LinphoneReasonNoMatch /**<Operation could not be executed by server or remote client because it didn't have any context for it*/
|
LinphoneReasonNoMatch /**<Operation could not be executed by server or remote client because it didn't have any context for it*/
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*for compatibility*/
|
||||||
|
#define LinphoneReasonMedia LinphoneReasonUnsupportedContent
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enum describing failure reasons.
|
* Enum describing failure reasons.
|
||||||
* @ingroup misc
|
* @ingroup misc
|
||||||
|
|
@ -579,7 +585,11 @@ struct _LinphoneCallStats {
|
||||||
|
|
||||||
LINPHONE_PUBLIC const LinphoneCallStats *linphone_call_get_audio_stats(LinphoneCall *call);
|
LINPHONE_PUBLIC const LinphoneCallStats *linphone_call_get_audio_stats(LinphoneCall *call);
|
||||||
LINPHONE_PUBLIC const LinphoneCallStats *linphone_call_get_video_stats(LinphoneCall *call);
|
LINPHONE_PUBLIC const LinphoneCallStats *linphone_call_get_video_stats(LinphoneCall *call);
|
||||||
|
LINPHONE_PUBLIC float linphone_call_stats_update_sender_loss_rate(const LinphoneCallStats *stats);
|
||||||
|
LINPHONE_PUBLIC float linphone_call_stats_update_receiver_loss_rate(const LinphoneCallStats *stats);
|
||||||
|
LINPHONE_PUBLIC float linphone_call_stats_update_sender_interarrival_jitter(const LinphoneCallStats *stats, LinphoneCall *call);
|
||||||
|
LINPHONE_PUBLIC float linphone_call_stats_update_receiver_interarrival_jitter(const LinphoneCallStats *stats, LinphoneCall *call);
|
||||||
|
LINPHONE_PUBLIC uint64_t linphone_call_stats_update_late_packets_cumulative_number(const LinphoneCallStats *stats, LinphoneCall *call);
|
||||||
|
|
||||||
/** Callback prototype */
|
/** Callback prototype */
|
||||||
typedef void (*LinphoneCallCbFunc)(LinphoneCall *call,void * user_data);
|
typedef void (*LinphoneCallCbFunc)(LinphoneCall *call,void * user_data);
|
||||||
|
|
@ -652,6 +662,7 @@ LINPHONE_PUBLIC LinphoneCallState linphone_call_get_transfer_state(LinphoneCall
|
||||||
LINPHONE_PUBLIC void linphone_call_zoom_video(LinphoneCall* call, float zoom_factor, float* cx, float* cy);
|
LINPHONE_PUBLIC void linphone_call_zoom_video(LinphoneCall* call, float zoom_factor, float* cx, float* cy);
|
||||||
LINPHONE_PUBLIC void linphone_call_start_recording(LinphoneCall *call);
|
LINPHONE_PUBLIC void linphone_call_start_recording(LinphoneCall *call);
|
||||||
LINPHONE_PUBLIC void linphone_call_stop_recording(LinphoneCall *call);
|
LINPHONE_PUBLIC void linphone_call_stop_recording(LinphoneCall *call);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return TRUE if this call is currently part of a conference
|
* Return TRUE if this call is currently part of a conference
|
||||||
* @param call #LinphoneCall
|
* @param call #LinphoneCall
|
||||||
|
|
@ -977,6 +988,20 @@ LINPHONE_PUBLIC MSList *linphone_chat_room_get_history(LinphoneChatRoom *cr,int
|
||||||
LINPHONE_PUBLIC void linphone_chat_room_mark_as_read(LinphoneChatRoom *cr);
|
LINPHONE_PUBLIC void linphone_chat_room_mark_as_read(LinphoneChatRoom *cr);
|
||||||
LINPHONE_PUBLIC void linphone_chat_room_delete_message(LinphoneChatRoom *cr, LinphoneChatMessage *msg);
|
LINPHONE_PUBLIC void linphone_chat_room_delete_message(LinphoneChatRoom *cr, LinphoneChatMessage *msg);
|
||||||
LINPHONE_PUBLIC void linphone_chat_room_delete_history(LinphoneChatRoom *cr);
|
LINPHONE_PUBLIC void linphone_chat_room_delete_history(LinphoneChatRoom *cr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notify the destination of the chat message being composed that the user is typing a new message.
|
||||||
|
* @param[in] cr The #LinphoneChatRoom object corresponding to the conversation for which a new message is being typed.
|
||||||
|
*/
|
||||||
|
LINPHONE_PUBLIC void linphone_chat_room_compose(LinphoneChatRoom *cr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tells whether the remote is currently composing a message.
|
||||||
|
* @param[in] cr The "LinphoneChatRoom object corresponding to the conversation.
|
||||||
|
* @return TRUE if the remote is currently composing a message, FALSE otherwise.
|
||||||
|
*/
|
||||||
|
LINPHONE_PUBLIC bool_t linphone_chat_room_is_remote_composing(const LinphoneChatRoom *cr);
|
||||||
|
|
||||||
LINPHONE_PUBLIC int linphone_chat_room_get_unread_messages_count(LinphoneChatRoom *cr);
|
LINPHONE_PUBLIC int linphone_chat_room_get_unread_messages_count(LinphoneChatRoom *cr);
|
||||||
LINPHONE_PUBLIC LinphoneCore* linphone_chat_room_get_lc(LinphoneChatRoom *cr);
|
LINPHONE_PUBLIC LinphoneCore* linphone_chat_room_get_lc(LinphoneChatRoom *cr);
|
||||||
LINPHONE_PUBLIC void linphone_chat_room_set_user_data(LinphoneChatRoom *cr, void * ud);
|
LINPHONE_PUBLIC void linphone_chat_room_set_user_data(LinphoneChatRoom *cr, void * ud);
|
||||||
|
|
@ -1130,6 +1155,14 @@ typedef void (*LinphoneCoreTextMessageReceivedCb)(LinphoneCore *lc, LinphoneChat
|
||||||
*/
|
*/
|
||||||
typedef void (*LinphoneCoreMessageReceivedCb)(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMessage *message);
|
typedef void (*LinphoneCoreMessageReceivedCb)(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMessage *message);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is composing notification callback prototype.
|
||||||
|
*
|
||||||
|
* @param[in] lc #LinphoneCore object
|
||||||
|
* @param[in] room #LinphoneChatRoom involved in the conversation.
|
||||||
|
*/
|
||||||
|
typedef void (*LinphoneCoreIsComposingReceivedCb)(LinphoneCore *lc, LinphoneChatRoom *room);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback for being notified of DTMFs received.
|
* Callback for being notified of DTMFs received.
|
||||||
* @param lc the linphone core
|
* @param lc the linphone core
|
||||||
|
|
@ -1179,6 +1212,7 @@ typedef struct _LinphoneCoreVTable{
|
||||||
LinphoneCoreAuthInfoRequestedCb auth_info_requested; /**< Ask the application some authentication information */
|
LinphoneCoreAuthInfoRequestedCb auth_info_requested; /**< Ask the application some authentication information */
|
||||||
LinphoneCoreCallLogUpdatedCb call_log_updated; /**< Notifies that call log list has been updated */
|
LinphoneCoreCallLogUpdatedCb call_log_updated; /**< Notifies that call log list has been updated */
|
||||||
LinphoneCoreMessageReceivedCb message_received; /** a message is received, can be text or external body*/
|
LinphoneCoreMessageReceivedCb message_received; /** a message is received, can be text or external body*/
|
||||||
|
LinphoneCoreIsComposingReceivedCb is_composing_received; /**< An is-composing notification has been received */
|
||||||
LinphoneCoreDtmfReceivedCb dtmf_received; /**< A dtmf has been received received */
|
LinphoneCoreDtmfReceivedCb dtmf_received; /**< A dtmf has been received received */
|
||||||
LinphoneCoreReferReceivedCb refer_received; /**< An out of call refer was received */
|
LinphoneCoreReferReceivedCb refer_received; /**< An out of call refer was received */
|
||||||
LinphoneCoreCallEncryptionChangedCb call_encryption_changed; /**<Notifies on change in the encryption of call streams */
|
LinphoneCoreCallEncryptionChangedCb call_encryption_changed; /**<Notifies on change in the encryption of call streams */
|
||||||
|
|
@ -2202,18 +2236,6 @@ LINPHONE_PUBLIC int linphone_core_get_video_dscp(const LinphoneCore *lc);
|
||||||
LINPHONE_PUBLIC const char *linphone_core_get_video_display_filter(LinphoneCore *lc);
|
LINPHONE_PUBLIC const char *linphone_core_get_video_display_filter(LinphoneCore *lc);
|
||||||
LINPHONE_PUBLIC void linphone_core_set_video_display_filter(LinphoneCore *lc, const char *filtername);
|
LINPHONE_PUBLIC void linphone_core_set_video_display_filter(LinphoneCore *lc, const char *filtername);
|
||||||
|
|
||||||
|
|
||||||
/** Belle Sip-based objects need unique ids
|
|
||||||
*/
|
|
||||||
|
|
||||||
BELLE_SIP_DECLARE_TYPES_BEGIN(linphone,10000)
|
|
||||||
BELLE_SIP_TYPE_ID(LinphoneContactSearch),
|
|
||||||
BELLE_SIP_TYPE_ID(LinphoneContactProvider),
|
|
||||||
BELLE_SIP_TYPE_ID(LinphoneLDAPContactProvider),
|
|
||||||
BELLE_SIP_TYPE_ID(LinphoneLDAPContactSearch)
|
|
||||||
BELLE_SIP_DECLARE_TYPES_END
|
|
||||||
|
|
||||||
|
|
||||||
/** Contact Providers
|
/** Contact Providers
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -170,6 +170,7 @@ public:
|
||||||
vTable.call_encryption_changed = callEncryptionChange;
|
vTable.call_encryption_changed = callEncryptionChange;
|
||||||
vTable.text_received = text_received;
|
vTable.text_received = text_received;
|
||||||
vTable.message_received = message_received;
|
vTable.message_received = message_received;
|
||||||
|
vTable.is_composing_received = is_composing_received;
|
||||||
vTable.dtmf_received = dtmf_received;
|
vTable.dtmf_received = dtmf_received;
|
||||||
vTable.new_subscription_requested = new_subscription_requested;
|
vTable.new_subscription_requested = new_subscription_requested;
|
||||||
vTable.notify_presence_received = notify_presence_received;
|
vTable.notify_presence_received = notify_presence_received;
|
||||||
|
|
@ -225,6 +226,7 @@ public:
|
||||||
/*void textReceived(LinphoneCore lc, LinphoneChatRoom cr,LinphoneAddress from,String message);*/
|
/*void textReceived(LinphoneCore lc, LinphoneChatRoom cr,LinphoneAddress from,String message);*/
|
||||||
textReceivedId = env->GetMethodID(listenerClass,"textReceived","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneChatRoom;Lorg/linphone/core/LinphoneAddress;Ljava/lang/String;)V");
|
textReceivedId = env->GetMethodID(listenerClass,"textReceived","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneChatRoom;Lorg/linphone/core/LinphoneAddress;Ljava/lang/String;)V");
|
||||||
messageReceivedId = env->GetMethodID(listenerClass,"messageReceived","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneChatRoom;Lorg/linphone/core/LinphoneChatMessage;)V");
|
messageReceivedId = env->GetMethodID(listenerClass,"messageReceived","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneChatRoom;Lorg/linphone/core/LinphoneChatMessage;)V");
|
||||||
|
isComposingReceivedId = env->GetMethodID(listenerClass,"isComposingReceived","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneChatRoom;)V");
|
||||||
dtmfReceivedId = env->GetMethodID(listenerClass,"dtmfReceived","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCall;I)V");
|
dtmfReceivedId = env->GetMethodID(listenerClass,"dtmfReceived","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCall;I)V");
|
||||||
infoReceivedId = env->GetMethodID(listenerClass,"infoReceived",
|
infoReceivedId = env->GetMethodID(listenerClass,"infoReceived",
|
||||||
"(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCall;Lorg/linphone/core/LinphoneInfoMessage;)V");
|
"(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCall;Lorg/linphone/core/LinphoneInfoMessage;)V");
|
||||||
|
|
@ -307,6 +309,7 @@ public:
|
||||||
jmethodID notifyPresenceReceivedId;
|
jmethodID notifyPresenceReceivedId;
|
||||||
jmethodID textReceivedId;
|
jmethodID textReceivedId;
|
||||||
jmethodID messageReceivedId;
|
jmethodID messageReceivedId;
|
||||||
|
jmethodID isComposingReceivedId;
|
||||||
jmethodID dtmfReceivedId;
|
jmethodID dtmfReceivedId;
|
||||||
jmethodID callStatsUpdatedId;
|
jmethodID callStatsUpdatedId;
|
||||||
jmethodID transferStateId;
|
jmethodID transferStateId;
|
||||||
|
|
@ -550,6 +553,19 @@ public:
|
||||||
,env->NewObject(lcData->chatRoomClass,lcData->chatRoomCtrId,(jlong)room)
|
,env->NewObject(lcData->chatRoomClass,lcData->chatRoomCtrId,(jlong)room)
|
||||||
,env->NewObject(lcData->chatMessageClass,lcData->chatMessageCtrId,(jlong)msg));
|
,env->NewObject(lcData->chatMessageClass,lcData->chatMessageCtrId,(jlong)msg));
|
||||||
}
|
}
|
||||||
|
static void is_composing_received(LinphoneCore *lc, LinphoneChatRoom *room) {
|
||||||
|
JNIEnv *env = 0;
|
||||||
|
jint result = jvm->AttachCurrentThread(&env,NULL);
|
||||||
|
if (result != 0) {
|
||||||
|
ms_error("cannot attach VM");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_get_user_data(lc);
|
||||||
|
env->CallVoidMethod(lcData->listener
|
||||||
|
,lcData->isComposingReceivedId
|
||||||
|
,lcData->core
|
||||||
|
,env->NewObject(lcData->chatRoomClass,lcData->chatRoomCtrId,(jlong)room));
|
||||||
|
}
|
||||||
static void ecCalibrationStatus(LinphoneCore *lc, LinphoneEcCalibratorStatus status, int delay_ms, void *data) {
|
static void ecCalibrationStatus(LinphoneCore *lc, LinphoneEcCalibratorStatus status, int delay_ms, void *data) {
|
||||||
JNIEnv *env = 0;
|
JNIEnv *env = 0;
|
||||||
jint result = jvm->AttachCurrentThread(&env,NULL);
|
jint result = jvm->AttachCurrentThread(&env,NULL);
|
||||||
|
|
@ -2311,6 +2327,12 @@ extern "C" void Java_org_linphone_core_LinphoneChatRoomImpl_deleteHistory(JNIEnv
|
||||||
,jlong ptr) {
|
,jlong ptr) {
|
||||||
linphone_chat_room_delete_history((LinphoneChatRoom*)ptr);
|
linphone_chat_room_delete_history((LinphoneChatRoom*)ptr);
|
||||||
}
|
}
|
||||||
|
JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneChatRoomImpl_compose(JNIEnv *env, jobject thiz, jlong ptr) {
|
||||||
|
linphone_chat_room_compose((LinphoneChatRoom *)ptr);
|
||||||
|
}
|
||||||
|
JNIEXPORT jboolean JNICALL Java_org_linphone_core_LinphoneChatRoomImpl_isRemoteComposing(JNIEnv *env, jobject thiz, jlong ptr) {
|
||||||
|
return (jboolean)linphone_chat_room_is_remote_composing((LinphoneChatRoom *)ptr);
|
||||||
|
}
|
||||||
extern "C" void Java_org_linphone_core_LinphoneChatRoomImpl_deleteMessage(JNIEnv* env
|
extern "C" void Java_org_linphone_core_LinphoneChatRoomImpl_deleteMessage(JNIEnv* env
|
||||||
,jobject thiz
|
,jobject thiz
|
||||||
,jlong room
|
,jlong room
|
||||||
|
|
|
||||||
|
|
@ -1239,16 +1239,16 @@ SalReason linphone_reason_to_sal(LinphoneReason reason){
|
||||||
return SalReasonTemporarilyUnavailable;
|
return SalReasonTemporarilyUnavailable;
|
||||||
case LinphoneReasonBusy:
|
case LinphoneReasonBusy:
|
||||||
return SalReasonBusy;
|
return SalReasonBusy;
|
||||||
case LinphoneReasonMedia:
|
case LinphoneReasonNotAcceptable:
|
||||||
return SalReasonMedia;
|
return SalReasonNotAcceptable;
|
||||||
case LinphoneReasonIOError:
|
case LinphoneReasonIOError:
|
||||||
return SalReasonServiceUnavailable;
|
return SalReasonServiceUnavailable;
|
||||||
case LinphoneReasonDoNotDisturb:
|
case LinphoneReasonDoNotDisturb:
|
||||||
return SalReasonDoNotDisturb;
|
return SalReasonDoNotDisturb;
|
||||||
case LinphoneReasonUnauthorized:
|
case LinphoneReasonUnauthorized:
|
||||||
return SalReasonUnauthorized;
|
return SalReasonUnauthorized;
|
||||||
case LinphoneReasonNotAcceptable:
|
case LinphoneReasonUnsupportedContent:
|
||||||
return SalReasonNotAcceptable;
|
return SalReasonUnsupportedContent;
|
||||||
case LinphoneReasonNoMatch:
|
case LinphoneReasonNoMatch:
|
||||||
return SalReasonNoMatch;
|
return SalReasonNoMatch;
|
||||||
}
|
}
|
||||||
|
|
@ -1273,8 +1273,8 @@ LinphoneReason linphone_reason_from_sal(SalReason r){
|
||||||
case SalReasonForbidden:
|
case SalReasonForbidden:
|
||||||
ret=LinphoneReasonBadCredentials;
|
ret=LinphoneReasonBadCredentials;
|
||||||
break;
|
break;
|
||||||
case SalReasonMedia:
|
case SalReasonNotAcceptable:
|
||||||
ret=LinphoneReasonMedia;
|
ret=LinphoneReasonNotAcceptable;
|
||||||
break;
|
break;
|
||||||
case SalReasonNotFound:
|
case SalReasonNotFound:
|
||||||
ret=LinphoneReasonNotFound;
|
ret=LinphoneReasonNotFound;
|
||||||
|
|
@ -1294,8 +1294,8 @@ LinphoneReason linphone_reason_from_sal(SalReason r){
|
||||||
case SalReasonUnauthorized:
|
case SalReasonUnauthorized:
|
||||||
ret=LinphoneReasonUnauthorized;
|
ret=LinphoneReasonUnauthorized;
|
||||||
break;
|
break;
|
||||||
case SalReasonNotAcceptable:
|
case SalReasonUnsupportedContent:
|
||||||
ret=LinphoneReasonNotAcceptable;
|
ret=LinphoneReasonUnsupportedContent;
|
||||||
break;
|
break;
|
||||||
case SalReasonNoMatch:
|
case SalReasonNoMatch:
|
||||||
ret=LinphoneReasonNoMatch;
|
ret=LinphoneReasonNoMatch;
|
||||||
|
|
|
||||||
|
|
@ -22,15 +22,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
#include "lpconfig.h"
|
#include "lpconfig.h"
|
||||||
#include "linphonepresence.h"
|
#include "linphonepresence.h"
|
||||||
|
|
||||||
#include <libxml/xmlreader.h>
|
|
||||||
#include <libxml/xmlwriter.h>
|
|
||||||
#include <libxml/xpath.h>
|
|
||||||
#include <libxml/xpathInternals.h>
|
|
||||||
|
|
||||||
|
|
||||||
#define XMLPARSING_BUFFER_LEN 2048
|
|
||||||
#define MAX_XPATH_LENGTH 256
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
extern const char *__policy_enum_to_str(LinphoneSubscribePolicy pol);
|
extern const char *__policy_enum_to_str(LinphoneSubscribePolicy pol);
|
||||||
|
|
@ -83,13 +74,6 @@ struct _LinphonePresenceModel {
|
||||||
MSList *notes; /**< A list of _LinphonePresenceNote structures. */
|
MSList *notes; /**< A list of _LinphonePresenceNote structures. */
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct _xmlparsing_context {
|
|
||||||
xmlDoc *doc;
|
|
||||||
xmlXPathContextPtr xpath_ctx;
|
|
||||||
char errorBuffer[XMLPARSING_BUFFER_LEN];
|
|
||||||
char warningBuffer[XMLPARSING_BUFFER_LEN];
|
|
||||||
} xmlparsing_context_t;
|
|
||||||
|
|
||||||
|
|
||||||
static const char *person_prefix = "/pidf:presence/dm:person";
|
static const char *person_prefix = "/pidf:presence/dm:person";
|
||||||
|
|
||||||
|
|
@ -98,38 +82,6 @@ static const char *person_prefix = "/pidf:presence/dm:person";
|
||||||
* PRIVATE FUNCTIONS *
|
* PRIVATE FUNCTIONS *
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static xmlparsing_context_t * xmlparsing_context_new() {
|
|
||||||
xmlparsing_context_t *xmlCtx = (xmlparsing_context_t *)malloc(sizeof(xmlparsing_context_t));
|
|
||||||
if (xmlCtx != NULL) {
|
|
||||||
xmlCtx->doc = NULL;
|
|
||||||
xmlCtx->xpath_ctx = NULL;
|
|
||||||
xmlCtx->errorBuffer[0] = '\0';
|
|
||||||
xmlCtx->warningBuffer[0] = '\0';
|
|
||||||
}
|
|
||||||
return xmlCtx;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void xmlparsing_context_destroy(xmlparsing_context_t *ctx) {
|
|
||||||
if (ctx->doc != NULL) {
|
|
||||||
xmlFreeDoc(ctx->doc);
|
|
||||||
ctx->doc = NULL;
|
|
||||||
}
|
|
||||||
if (ctx->xpath_ctx != NULL) {
|
|
||||||
xmlXPathFreeContext(ctx->xpath_ctx);
|
|
||||||
ctx->xpath_ctx = NULL;
|
|
||||||
}
|
|
||||||
free(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void xmlparsing_genericxml_error(void *ctx, const char *fmt, ...) {
|
|
||||||
xmlparsing_context_t *xmlCtx = (xmlparsing_context_t *)ctx;
|
|
||||||
int sl = strlen(xmlCtx->errorBuffer);
|
|
||||||
va_list args;
|
|
||||||
va_start(args, fmt);
|
|
||||||
vsnprintf(xmlCtx->errorBuffer + sl, XMLPARSING_BUFFER_LEN - sl, fmt, args);
|
|
||||||
va_end(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
static char presence_id_valid_characters[] = "0123456789abcdefghijklmnopqrstuvwxyz";
|
static char presence_id_valid_characters[] = "0123456789abcdefghijklmnopqrstuvwxyz";
|
||||||
|
|
||||||
static char * generate_presence_id(void) {
|
static char * generate_presence_id(void) {
|
||||||
|
|
@ -1183,45 +1135,6 @@ void * linphone_presence_note_get_user_data(LinphonePresenceNote *note) {
|
||||||
* XML PRESENCE INTERNAL HANDLING *
|
* XML PRESENCE INTERNAL HANDLING *
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static int create_xml_xpath_context(xmlparsing_context_t *xml_ctx) {
|
|
||||||
if (xml_ctx->xpath_ctx != NULL) {
|
|
||||||
xmlXPathFreeContext(xml_ctx->xpath_ctx);
|
|
||||||
}
|
|
||||||
xml_ctx->xpath_ctx = xmlXPathNewContext(xml_ctx->doc);
|
|
||||||
if (xml_ctx->xpath_ctx == NULL) return -1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char * get_xml_text_content(xmlparsing_context_t *xml_ctx, const char *xpath_expression) {
|
|
||||||
xmlXPathObjectPtr xpath_obj;
|
|
||||||
xmlChar *text = NULL;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
xpath_obj = xmlXPathEvalExpression((const xmlChar *)xpath_expression, xml_ctx->xpath_ctx);
|
|
||||||
if (xpath_obj != NULL) {
|
|
||||||
if (xpath_obj->nodesetval != NULL) {
|
|
||||||
xmlNodeSetPtr nodes = xpath_obj->nodesetval;
|
|
||||||
for (i = 0; i < nodes->nodeNr; i++) {
|
|
||||||
xmlNodePtr node = nodes->nodeTab[i];
|
|
||||||
if (node->children != NULL) {
|
|
||||||
text = xmlNodeListGetString(xml_ctx->doc, node->children, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
xmlXPathFreeObject(xpath_obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (char *)text;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void free_xml_text_content(const char *text) {
|
|
||||||
xmlFree((xmlChar *)text);
|
|
||||||
}
|
|
||||||
|
|
||||||
static xmlXPathObjectPtr get_xml_xpath_object_for_node_list(xmlparsing_context_t *xml_ctx, const char *xpath_expression) {
|
|
||||||
return xmlXPathEvalExpression((const xmlChar *)xpath_expression, xml_ctx->xpath_ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char *service_prefix = "/pidf:presence/pidf:tuple";
|
static const char *service_prefix = "/pidf:presence/pidf:tuple";
|
||||||
|
|
||||||
static int process_pidf_xml_presence_service_notes(xmlparsing_context_t *xml_ctx, LinphonePresenceService *service, unsigned int service_idx) {
|
static int process_pidf_xml_presence_service_notes(xmlparsing_context_t *xml_ctx, LinphonePresenceService *service, unsigned int service_idx) {
|
||||||
|
|
@ -1233,19 +1146,19 @@ static int process_pidf_xml_presence_service_notes(xmlparsing_context_t *xml_ctx
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
snprintf(xpath_str, sizeof(xpath_str), "%s[%i]/pidf:note", service_prefix, service_idx);
|
snprintf(xpath_str, sizeof(xpath_str), "%s[%i]/pidf:note", service_prefix, service_idx);
|
||||||
note_object = get_xml_xpath_object_for_node_list(xml_ctx, xpath_str);
|
note_object = linphone_get_xml_xpath_object_for_node_list(xml_ctx, xpath_str);
|
||||||
if ((note_object != NULL) && (note_object->nodesetval != NULL)) {
|
if ((note_object != NULL) && (note_object->nodesetval != NULL)) {
|
||||||
for (i = 1; i <= note_object->nodesetval->nodeNr; i++) {
|
for (i = 1; i <= note_object->nodesetval->nodeNr; i++) {
|
||||||
snprintf(xpath_str, sizeof(xpath_str), "%s[%i]/pidf:note[%i]", service_prefix, service_idx, i);
|
snprintf(xpath_str, sizeof(xpath_str), "%s[%i]/pidf:note[%i]", service_prefix, service_idx, i);
|
||||||
note_str = get_xml_text_content(xml_ctx, xpath_str);
|
note_str = linphone_get_xml_text_content(xml_ctx, xpath_str);
|
||||||
if (note_str == NULL) continue;
|
if (note_str == NULL) continue;
|
||||||
snprintf(xpath_str, sizeof(xpath_str), "%s[%i]/pidf:note[%i]/@xml:lang", service_prefix, service_idx, i);
|
snprintf(xpath_str, sizeof(xpath_str), "%s[%i]/pidf:note[%i]/@xml:lang", service_prefix, service_idx, i);
|
||||||
lang = get_xml_text_content(xml_ctx, xpath_str);
|
lang = linphone_get_xml_text_content(xml_ctx, xpath_str);
|
||||||
|
|
||||||
note = linphone_presence_note_new(note_str, lang);
|
note = linphone_presence_note_new(note_str, lang);
|
||||||
presence_service_add_note(service, note);
|
presence_service_add_note(service, note);
|
||||||
if (lang != NULL) free_xml_text_content(lang);
|
if (lang != NULL) linphone_free_xml_text_content(lang);
|
||||||
free_xml_text_content(note_str);
|
linphone_free_xml_text_content(note_str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (note_object != NULL) xmlXPathFreeObject(note_object);
|
if (note_object != NULL) xmlXPathFreeObject(note_object);
|
||||||
|
|
@ -1264,11 +1177,11 @@ static int process_pidf_xml_presence_services(xmlparsing_context_t *xml_ctx, Lin
|
||||||
LinphonePresenceBasicStatus basic_status;
|
LinphonePresenceBasicStatus basic_status;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
service_object = get_xml_xpath_object_for_node_list(xml_ctx, service_prefix);
|
service_object = linphone_get_xml_xpath_object_for_node_list(xml_ctx, service_prefix);
|
||||||
if ((service_object != NULL) && (service_object->nodesetval != NULL)) {
|
if ((service_object != NULL) && (service_object->nodesetval != NULL)) {
|
||||||
for (i = 1; i <= service_object->nodesetval->nodeNr; i++) {
|
for (i = 1; i <= service_object->nodesetval->nodeNr; i++) {
|
||||||
snprintf(xpath_str, sizeof(xpath_str), "%s[%i]/pidf:status/pidf:basic", service_prefix, i);
|
snprintf(xpath_str, sizeof(xpath_str), "%s[%i]/pidf:status/pidf:basic", service_prefix, i);
|
||||||
basic_status_str = get_xml_text_content(xml_ctx, xpath_str);
|
basic_status_str = linphone_get_xml_text_content(xml_ctx, xpath_str);
|
||||||
if (basic_status_str == NULL)
|
if (basic_status_str == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
@ -1278,33 +1191,33 @@ static int process_pidf_xml_presence_services(xmlparsing_context_t *xml_ctx, Lin
|
||||||
basic_status = LinphonePresenceBasicStatusClosed;
|
basic_status = LinphonePresenceBasicStatusClosed;
|
||||||
} else {
|
} else {
|
||||||
/* Invalid value for basic status. */
|
/* Invalid value for basic status. */
|
||||||
free_xml_text_content(basic_status_str);
|
linphone_free_xml_text_content(basic_status_str);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(xpath_str, sizeof(xpath_str), "%s[%i]/pidf:timestamp", service_prefix, i);
|
snprintf(xpath_str, sizeof(xpath_str), "%s[%i]/pidf:timestamp", service_prefix, i);
|
||||||
timestamp_str = get_xml_text_content(xml_ctx, xpath_str);
|
timestamp_str = linphone_get_xml_text_content(xml_ctx, xpath_str);
|
||||||
|
|
||||||
snprintf(xpath_str, sizeof(xpath_str), "%s[%i]/pidf:contact", service_prefix, i);
|
snprintf(xpath_str, sizeof(xpath_str), "%s[%i]/pidf:contact", service_prefix, i);
|
||||||
contact_str = get_xml_text_content(xml_ctx, xpath_str);
|
contact_str = linphone_get_xml_text_content(xml_ctx, xpath_str);
|
||||||
|
|
||||||
snprintf(xpath_str, sizeof(xpath_str), "%s[%i]/@id", service_prefix, i);
|
snprintf(xpath_str, sizeof(xpath_str), "%s[%i]/@id", service_prefix, i);
|
||||||
service_id_str = get_xml_text_content(xml_ctx, xpath_str);
|
service_id_str = linphone_get_xml_text_content(xml_ctx, xpath_str);
|
||||||
service = presence_service_new(service_id_str, basic_status);
|
service = presence_service_new(service_id_str, basic_status);
|
||||||
if (service != NULL) {
|
if (service != NULL) {
|
||||||
if (timestamp_str != NULL) {
|
if (timestamp_str != NULL) {
|
||||||
presence_service_set_timestamp(service, parse_timestamp(timestamp_str));
|
presence_service_set_timestamp(service, parse_timestamp(timestamp_str));
|
||||||
free_xml_text_content(timestamp_str);
|
linphone_free_xml_text_content(timestamp_str);
|
||||||
}
|
}
|
||||||
if (contact_str != NULL) {
|
if (contact_str != NULL) {
|
||||||
linphone_presence_service_set_contact(service, contact_str);
|
linphone_presence_service_set_contact(service, contact_str);
|
||||||
free_xml_text_content(contact_str);
|
linphone_free_xml_text_content(contact_str);
|
||||||
}
|
}
|
||||||
process_pidf_xml_presence_service_notes(xml_ctx, service, i);
|
process_pidf_xml_presence_service_notes(xml_ctx, service, i);
|
||||||
linphone_presence_model_add_service(model, service);
|
linphone_presence_model_add_service(model, service);
|
||||||
}
|
}
|
||||||
free_xml_text_content(basic_status_str);
|
linphone_free_xml_text_content(basic_status_str);
|
||||||
if (service_id_str != NULL) free_xml_text_content(service_id_str);
|
if (service_id_str != NULL) linphone_free_xml_text_content(service_id_str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (service_object != NULL) xmlXPathFreeObject(service_object);
|
if (service_object != NULL) xmlXPathFreeObject(service_object);
|
||||||
|
|
@ -1333,11 +1246,11 @@ static int process_pidf_xml_presence_person_activities(xmlparsing_context_t *xml
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
snprintf(xpath_str, sizeof(xpath_str), "%s[%i]/rpid:activities", person_prefix, person_idx);
|
snprintf(xpath_str, sizeof(xpath_str), "%s[%i]/rpid:activities", person_prefix, person_idx);
|
||||||
activities_nodes_object = get_xml_xpath_object_for_node_list(xml_ctx, xpath_str);
|
activities_nodes_object = linphone_get_xml_xpath_object_for_node_list(xml_ctx, xpath_str);
|
||||||
if ((activities_nodes_object != NULL) && (activities_nodes_object->nodesetval != NULL)) {
|
if ((activities_nodes_object != NULL) && (activities_nodes_object->nodesetval != NULL)) {
|
||||||
for (i = 1; i <= activities_nodes_object->nodesetval->nodeNr; i++) {
|
for (i = 1; i <= activities_nodes_object->nodesetval->nodeNr; i++) {
|
||||||
snprintf(xpath_str, sizeof(xpath_str), "%s[%i]/rpid:activities[%i]/rpid:*", person_prefix, person_idx, i);
|
snprintf(xpath_str, sizeof(xpath_str), "%s[%i]/rpid:activities[%i]/rpid:*", person_prefix, person_idx, i);
|
||||||
activities_object = get_xml_xpath_object_for_node_list(xml_ctx, xpath_str);
|
activities_object = linphone_get_xml_xpath_object_for_node_list(xml_ctx, xpath_str);
|
||||||
if ((activities_object != NULL) && (activities_object->nodesetval != NULL)) {
|
if ((activities_object != NULL) && (activities_object->nodesetval != NULL)) {
|
||||||
for (j = 0; j < activities_object->nodesetval->nodeNr; j++) {
|
for (j = 0; j < activities_object->nodesetval->nodeNr; j++) {
|
||||||
activity_node = activities_object->nodesetval->nodeTab[j];
|
activity_node = activities_object->nodesetval->nodeTab[j];
|
||||||
|
|
@ -1345,14 +1258,14 @@ static int process_pidf_xml_presence_person_activities(xmlparsing_context_t *xml
|
||||||
LinphonePresenceActivityType acttype;
|
LinphonePresenceActivityType acttype;
|
||||||
description = (const char *)xmlNodeGetContent(activity_node);
|
description = (const char *)xmlNodeGetContent(activity_node);
|
||||||
if ((description != NULL) && (description[0] == '\0')) {
|
if ((description != NULL) && (description[0] == '\0')) {
|
||||||
free_xml_text_content(description);
|
linphone_free_xml_text_content(description);
|
||||||
description = NULL;
|
description = NULL;
|
||||||
}
|
}
|
||||||
err = activity_name_to_presence_activity_type((const char *)activity_node->name, &acttype);
|
err = activity_name_to_presence_activity_type((const char *)activity_node->name, &acttype);
|
||||||
if (err < 0) break;
|
if (err < 0) break;
|
||||||
activity = linphone_presence_activity_new(acttype, description);
|
activity = linphone_presence_activity_new(acttype, description);
|
||||||
linphone_presence_person_add_activity(person, activity);
|
linphone_presence_person_add_activity(person, activity);
|
||||||
if (description != NULL) free_xml_text_content(description);
|
if (description != NULL) linphone_free_xml_text_content(description);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1374,37 +1287,37 @@ static int process_pidf_xml_presence_person_notes(xmlparsing_context_t *xml_ctx,
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
snprintf(xpath_str, sizeof(xpath_str), "%s[%i]/rpid:activities/rpid:note", person_prefix, person_idx);
|
snprintf(xpath_str, sizeof(xpath_str), "%s[%i]/rpid:activities/rpid:note", person_prefix, person_idx);
|
||||||
note_object = get_xml_xpath_object_for_node_list(xml_ctx, xpath_str);
|
note_object = linphone_get_xml_xpath_object_for_node_list(xml_ctx, xpath_str);
|
||||||
if ((note_object != NULL) && (note_object->nodesetval != NULL)) {
|
if ((note_object != NULL) && (note_object->nodesetval != NULL)) {
|
||||||
for (i = 1; i <= note_object->nodesetval->nodeNr; i++) {
|
for (i = 1; i <= note_object->nodesetval->nodeNr; i++) {
|
||||||
snprintf(xpath_str, sizeof(xpath_str), "%s[%i]/rpid:activities/rpid:note[%i]", person_prefix, person_idx, i);
|
snprintf(xpath_str, sizeof(xpath_str), "%s[%i]/rpid:activities/rpid:note[%i]", person_prefix, person_idx, i);
|
||||||
note_str = get_xml_text_content(xml_ctx, xpath_str);
|
note_str = linphone_get_xml_text_content(xml_ctx, xpath_str);
|
||||||
if (note_str == NULL) continue;
|
if (note_str == NULL) continue;
|
||||||
snprintf(xpath_str, sizeof(xpath_str), "%s[%i]/rpid:activities/rpid:note[%i]/@xml:lang", person_prefix, person_idx, i);
|
snprintf(xpath_str, sizeof(xpath_str), "%s[%i]/rpid:activities/rpid:note[%i]/@xml:lang", person_prefix, person_idx, i);
|
||||||
lang = get_xml_text_content(xml_ctx, xpath_str);
|
lang = linphone_get_xml_text_content(xml_ctx, xpath_str);
|
||||||
|
|
||||||
note = linphone_presence_note_new(note_str, lang);
|
note = linphone_presence_note_new(note_str, lang);
|
||||||
presence_person_add_activities_note(person, note);
|
presence_person_add_activities_note(person, note);
|
||||||
if (lang != NULL) free_xml_text_content(lang);
|
if (lang != NULL) linphone_free_xml_text_content(lang);
|
||||||
free_xml_text_content(note_str);
|
linphone_free_xml_text_content(note_str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (note_object != NULL) xmlXPathFreeObject(note_object);
|
if (note_object != NULL) xmlXPathFreeObject(note_object);
|
||||||
|
|
||||||
snprintf(xpath_str, sizeof(xpath_str), "%s[%i]/dm:note", person_prefix, person_idx);
|
snprintf(xpath_str, sizeof(xpath_str), "%s[%i]/dm:note", person_prefix, person_idx);
|
||||||
note_object = get_xml_xpath_object_for_node_list(xml_ctx, xpath_str);
|
note_object = linphone_get_xml_xpath_object_for_node_list(xml_ctx, xpath_str);
|
||||||
if ((note_object != NULL) && (note_object->nodesetval != NULL)) {
|
if ((note_object != NULL) && (note_object->nodesetval != NULL)) {
|
||||||
for (i = 1; i <= note_object->nodesetval->nodeNr; i++) {
|
for (i = 1; i <= note_object->nodesetval->nodeNr; i++) {
|
||||||
snprintf(xpath_str, sizeof(xpath_str), "%s[%i]/dm:note[%i]", person_prefix, person_idx, i);
|
snprintf(xpath_str, sizeof(xpath_str), "%s[%i]/dm:note[%i]", person_prefix, person_idx, i);
|
||||||
note_str = get_xml_text_content(xml_ctx, xpath_str);
|
note_str = linphone_get_xml_text_content(xml_ctx, xpath_str);
|
||||||
if (note_str == NULL) continue;
|
if (note_str == NULL) continue;
|
||||||
snprintf(xpath_str, sizeof(xpath_str), "%s[%i]/dm:note[%i]/@xml:lang", person_prefix, person_idx, i);
|
snprintf(xpath_str, sizeof(xpath_str), "%s[%i]/dm:note[%i]/@xml:lang", person_prefix, person_idx, i);
|
||||||
lang = get_xml_text_content(xml_ctx, xpath_str);
|
lang = linphone_get_xml_text_content(xml_ctx, xpath_str);
|
||||||
|
|
||||||
note = linphone_presence_note_new(note_str, lang);
|
note = linphone_presence_note_new(note_str, lang);
|
||||||
presence_person_add_note(person, note);
|
presence_person_add_note(person, note);
|
||||||
if (lang != NULL) free_xml_text_content(lang);
|
if (lang != NULL) linphone_free_xml_text_content(lang);
|
||||||
free_xml_text_content(note_str);
|
linphone_free_xml_text_content(note_str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (note_object != NULL) xmlXPathFreeObject(note_object);
|
if (note_object != NULL) xmlXPathFreeObject(note_object);
|
||||||
|
|
@ -1422,13 +1335,13 @@ static int process_pidf_xml_presence_persons(xmlparsing_context_t *xml_ctx, Linp
|
||||||
int i;
|
int i;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
person_object = get_xml_xpath_object_for_node_list(xml_ctx, person_prefix);
|
person_object = linphone_get_xml_xpath_object_for_node_list(xml_ctx, person_prefix);
|
||||||
if ((person_object != NULL) && (person_object->nodesetval != NULL)) {
|
if ((person_object != NULL) && (person_object->nodesetval != NULL)) {
|
||||||
for (i = 1; i <= person_object->nodesetval->nodeNr; i++) {
|
for (i = 1; i <= person_object->nodesetval->nodeNr; i++) {
|
||||||
snprintf(xpath_str, sizeof(xpath_str), "%s[%i]/@id", person_prefix, i);
|
snprintf(xpath_str, sizeof(xpath_str), "%s[%i]/@id", person_prefix, i);
|
||||||
person_id_str = get_xml_text_content(xml_ctx, xpath_str);
|
person_id_str = linphone_get_xml_text_content(xml_ctx, xpath_str);
|
||||||
snprintf(xpath_str, sizeof(xpath_str), "%s[%i]/pidf:timestamp", person_prefix, i);
|
snprintf(xpath_str, sizeof(xpath_str), "%s[%i]/pidf:timestamp", person_prefix, i);
|
||||||
person_timestamp_str = get_xml_text_content(xml_ctx, xpath_str);
|
person_timestamp_str = linphone_get_xml_text_content(xml_ctx, xpath_str);
|
||||||
if (person_timestamp_str == NULL)
|
if (person_timestamp_str == NULL)
|
||||||
timestamp = time(NULL);
|
timestamp = time(NULL);
|
||||||
else
|
else
|
||||||
|
|
@ -1446,8 +1359,8 @@ static int process_pidf_xml_presence_persons(xmlparsing_context_t *xml_ctx, Linp
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (person_id_str != NULL) free_xml_text_content(person_id_str);
|
if (person_id_str != NULL) linphone_free_xml_text_content(person_id_str);
|
||||||
if (person_timestamp_str != NULL) free_xml_text_content(person_timestamp_str);
|
if (person_timestamp_str != NULL) linphone_free_xml_text_content(person_timestamp_str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (person_object != NULL) xmlXPathFreeObject(person_object);
|
if (person_object != NULL) xmlXPathFreeObject(person_object);
|
||||||
|
|
@ -1467,19 +1380,19 @@ static int process_pidf_xml_presence_notes(xmlparsing_context_t *xml_ctx, Linpho
|
||||||
const char *lang;
|
const char *lang;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
note_object = get_xml_xpath_object_for_node_list(xml_ctx, "/pidf:presence/pidf:note");
|
note_object = linphone_get_xml_xpath_object_for_node_list(xml_ctx, "/pidf:presence/pidf:note");
|
||||||
if ((note_object != NULL) && (note_object->nodesetval != NULL)) {
|
if ((note_object != NULL) && (note_object->nodesetval != NULL)) {
|
||||||
for (i = 1; i <= note_object->nodesetval->nodeNr; i++) {
|
for (i = 1; i <= note_object->nodesetval->nodeNr; i++) {
|
||||||
snprintf(xpath_str, sizeof(xpath_str), "/pidf:presence/pidf:note[%i]", i);
|
snprintf(xpath_str, sizeof(xpath_str), "/pidf:presence/pidf:note[%i]", i);
|
||||||
note_str = get_xml_text_content(xml_ctx, xpath_str);
|
note_str = linphone_get_xml_text_content(xml_ctx, xpath_str);
|
||||||
if (note_str == NULL) continue;
|
if (note_str == NULL) continue;
|
||||||
snprintf(xpath_str, sizeof(xpath_str), "/pidf:presence/pidf:note[%i]/@xml:lang", i);
|
snprintf(xpath_str, sizeof(xpath_str), "/pidf:presence/pidf:note[%i]/@xml:lang", i);
|
||||||
lang = get_xml_text_content(xml_ctx, xpath_str);
|
lang = linphone_get_xml_text_content(xml_ctx, xpath_str);
|
||||||
|
|
||||||
note = linphone_presence_note_new(note_str, lang);
|
note = linphone_presence_note_new(note_str, lang);
|
||||||
presence_model_add_note(model, note);
|
presence_model_add_note(model, note);
|
||||||
if (lang != NULL) free_xml_text_content(lang);
|
if (lang != NULL) linphone_free_xml_text_content(lang);
|
||||||
free_xml_text_content(note_str);
|
linphone_free_xml_text_content(note_str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (note_object != NULL) xmlXPathFreeObject(note_object);
|
if (note_object != NULL) xmlXPathFreeObject(note_object);
|
||||||
|
|
@ -1491,7 +1404,7 @@ static LinphonePresenceModel * process_pidf_xml_presence_notification(xmlparsing
|
||||||
LinphonePresenceModel *model = NULL;
|
LinphonePresenceModel *model = NULL;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (create_xml_xpath_context(xml_ctx) < 0)
|
if (linphone_create_xml_xpath_context(xml_ctx) < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
model = linphone_presence_model_new();
|
model = linphone_presence_model_new();
|
||||||
|
|
@ -1606,15 +1519,15 @@ void linphone_notify_parse_presence(SalOp *op, const char *content_type, const c
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(content_subtype, "pidf+xml") == 0) {
|
if (strcmp(content_subtype, "pidf+xml") == 0) {
|
||||||
xml_ctx = xmlparsing_context_new();
|
xml_ctx = linphone_xmlparsing_context_new();
|
||||||
xmlSetGenericErrorFunc(xml_ctx, xmlparsing_genericxml_error);
|
xmlSetGenericErrorFunc(xml_ctx, linphone_xmlparsing_genericxml_error);
|
||||||
xml_ctx->doc = xmlReadDoc((const unsigned char*)body, 0, NULL, 0);
|
xml_ctx->doc = xmlReadDoc((const unsigned char*)body, 0, NULL, 0);
|
||||||
if (xml_ctx->doc != NULL) {
|
if (xml_ctx->doc != NULL) {
|
||||||
model = process_pidf_xml_presence_notification(xml_ctx);
|
model = process_pidf_xml_presence_notification(xml_ctx);
|
||||||
} else {
|
} else {
|
||||||
ms_warning("Wrongly formatted presence XML: %s", xml_ctx->errorBuffer);
|
ms_warning("Wrongly formatted presence XML: %s", xml_ctx->errorBuffer);
|
||||||
}
|
}
|
||||||
xmlparsing_context_destroy(xml_ctx);
|
linphone_xmlparsing_context_destroy(xml_ctx);
|
||||||
} else {
|
} else {
|
||||||
ms_error("Unknown content type '%s/%s' for presence", content_type, content_subtype);
|
ms_error("Unknown content type '%s/%s' for presence", content_type, content_subtype);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,9 @@ extern "C" {
|
||||||
#include "sal/sal.h"
|
#include "sal/sal.h"
|
||||||
#include "sipsetup.h"
|
#include "sipsetup.h"
|
||||||
|
|
||||||
|
#include <belle-sip/object.h>
|
||||||
|
#include <belle-sip/dict.h>
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -320,6 +323,7 @@ void linphone_core_update_ice_state_in_call_stats(LinphoneCall *call);
|
||||||
void linphone_core_update_local_media_description_from_ice(SalMediaDescription *desc, IceSession *session);
|
void linphone_core_update_local_media_description_from_ice(SalMediaDescription *desc, IceSession *session);
|
||||||
void linphone_core_update_ice_from_remote_media_description(LinphoneCall *call, const SalMediaDescription *md);
|
void linphone_core_update_ice_from_remote_media_description(LinphoneCall *call, const SalMediaDescription *md);
|
||||||
bool_t linphone_core_media_description_contains_video_stream(const SalMediaDescription *md);
|
bool_t linphone_core_media_description_contains_video_stream(const SalMediaDescription *md);
|
||||||
|
bool_t linphone_core_media_description_has_srtp(const SalMediaDescription *md);
|
||||||
|
|
||||||
void linphone_core_send_initial_subscribes(LinphoneCore *lc);
|
void linphone_core_send_initial_subscribes(LinphoneCore *lc);
|
||||||
void linphone_core_write_friends_config(LinphoneCore* lc);
|
void linphone_core_write_friends_config(LinphoneCore* lc);
|
||||||
|
|
@ -338,6 +342,7 @@ void linphone_proxy_config_write_to_config_file(struct _LpConfig* config,Linphon
|
||||||
int linphone_proxy_config_normalize_number(LinphoneProxyConfig *cfg, const char *username, char *result, size_t result_len);
|
int linphone_proxy_config_normalize_number(LinphoneProxyConfig *cfg, const char *username, char *result, size_t result_len);
|
||||||
|
|
||||||
void linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessage *msg);
|
void linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessage *msg);
|
||||||
|
void linphone_core_is_composing_received(LinphoneCore *lc, SalOp *op, const SalIsComposing *is_composing);
|
||||||
|
|
||||||
void linphone_core_play_tone(LinphoneCore *lc);
|
void linphone_core_play_tone(LinphoneCore *lc);
|
||||||
|
|
||||||
|
|
@ -426,12 +431,22 @@ struct _LinphoneAuthInfo
|
||||||
bool_t works;
|
bool_t works;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef enum _LinphoneIsComposingState {
|
||||||
|
LinphoneIsComposingIdle,
|
||||||
|
LinphoneIsComposingActive
|
||||||
|
} LinphoneIsComposingState;
|
||||||
|
|
||||||
struct _LinphoneChatRoom{
|
struct _LinphoneChatRoom{
|
||||||
struct _LinphoneCore *lc;
|
struct _LinphoneCore *lc;
|
||||||
char *peer;
|
char *peer;
|
||||||
LinphoneAddress *peer_url;
|
LinphoneAddress *peer_url;
|
||||||
void * user_data;
|
void * user_data;
|
||||||
MSList *messages_hist;
|
MSList *messages_hist;
|
||||||
|
LinphoneIsComposingState remote_is_composing;
|
||||||
|
LinphoneIsComposingState is_composing;
|
||||||
|
belle_sip_source_t *remote_composing_refresh_timer;
|
||||||
|
belle_sip_source_t *composing_idle_timer;
|
||||||
|
belle_sip_source_t *composing_refresh_timer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -788,6 +803,46 @@ LinphoneSubscriptionState linphone_subscription_state_from_sal(SalSubscribeStatu
|
||||||
const LinphoneContent *linphone_content_from_sal_body(LinphoneContent *obj, const SalBody *ref);
|
const LinphoneContent *linphone_content_from_sal_body(LinphoneContent *obj, const SalBody *ref);
|
||||||
void linphone_core_invalidate_friend_subscriptions(LinphoneCore *lc);
|
void linphone_core_invalidate_friend_subscriptions(LinphoneCore *lc);
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* XML UTILITY FUNCTIONS *
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <libxml/xmlreader.h>
|
||||||
|
#include <libxml/xmlwriter.h>
|
||||||
|
#include <libxml/xpath.h>
|
||||||
|
#include <libxml/xpathInternals.h>
|
||||||
|
|
||||||
|
#define XMLPARSING_BUFFER_LEN 2048
|
||||||
|
#define MAX_XPATH_LENGTH 256
|
||||||
|
|
||||||
|
typedef struct _xmlparsing_context {
|
||||||
|
xmlDoc *doc;
|
||||||
|
xmlXPathContextPtr xpath_ctx;
|
||||||
|
char errorBuffer[XMLPARSING_BUFFER_LEN];
|
||||||
|
char warningBuffer[XMLPARSING_BUFFER_LEN];
|
||||||
|
} xmlparsing_context_t;
|
||||||
|
|
||||||
|
xmlparsing_context_t * linphone_xmlparsing_context_new(void);
|
||||||
|
void linphone_xmlparsing_context_destroy(xmlparsing_context_t *ctx);
|
||||||
|
void linphone_xmlparsing_genericxml_error(void *ctx, const char *fmt, ...);
|
||||||
|
int linphone_create_xml_xpath_context(xmlparsing_context_t *xml_ctx);
|
||||||
|
char * linphone_get_xml_text_content(xmlparsing_context_t *xml_ctx, const char *xpath_expression);
|
||||||
|
void linphone_free_xml_text_content(const char *text);
|
||||||
|
xmlXPathObjectPtr linphone_get_xml_xpath_object_for_node_list(xmlparsing_context_t *xml_ctx, const char *xpath_expression);
|
||||||
|
|
||||||
|
|
||||||
|
/** Belle Sip-based objects need unique ids
|
||||||
|
*/
|
||||||
|
|
||||||
|
BELLE_SIP_DECLARE_TYPES_BEGIN(linphone,10000)
|
||||||
|
BELLE_SIP_TYPE_ID(LinphoneContactSearch),
|
||||||
|
BELLE_SIP_TYPE_ID(LinphoneContactProvider),
|
||||||
|
BELLE_SIP_TYPE_ID(LinphoneLDAPContactProvider),
|
||||||
|
BELLE_SIP_TYPE_ID(LinphoneLDAPContactSearch)
|
||||||
|
BELLE_SIP_DECLARE_TYPES_END
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -530,7 +530,7 @@ const char* sal_reason_to_string(const SalReason reason) {
|
||||||
case SalReasonTemporarilyUnavailable: return "SalReasonTemporarilyUnavailable";
|
case SalReasonTemporarilyUnavailable: return "SalReasonTemporarilyUnavailable";
|
||||||
case SalReasonNotFound: return "SalReasonNotFound";
|
case SalReasonNotFound: return "SalReasonNotFound";
|
||||||
case SalReasonDoNotDisturb: return "SalReasonDoNotDisturb";
|
case SalReasonDoNotDisturb: return "SalReasonDoNotDisturb";
|
||||||
case SalReasonMedia: return "SalReasonMedia";
|
case SalReasonUnsupportedContent: return "SalReasonUnsupportedContent";
|
||||||
case SalReasonForbidden: return "SalReasonForbidden";
|
case SalReasonForbidden: return "SalReasonForbidden";
|
||||||
case SalReasonUnknown: return "SalReasonUnknown";
|
case SalReasonUnknown: return "SalReasonUnknown";
|
||||||
case SalReasonServiceUnavailable: return "SalReasonServiceUnavailable";
|
case SalReasonServiceUnavailable: return "SalReasonServiceUnavailable";
|
||||||
|
|
|
||||||
98
coreapi/xml.c
Normal file
98
coreapi/xml.c
Normal file
|
|
@ -0,0 +1,98 @@
|
||||||
|
/*
|
||||||
|
linphone
|
||||||
|
Copyright (C) 2010-2013 Belledonne Communications SARL
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License
|
||||||
|
as published by the Free Software Foundation; either version 2
|
||||||
|
of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "private.h"
|
||||||
|
|
||||||
|
#include <libxml/xmlreader.h>
|
||||||
|
#include <libxml/xmlwriter.h>
|
||||||
|
#include <libxml/xpath.h>
|
||||||
|
#include <libxml/xpathInternals.h>
|
||||||
|
|
||||||
|
|
||||||
|
xmlparsing_context_t * linphone_xmlparsing_context_new(void) {
|
||||||
|
xmlparsing_context_t *xmlCtx = (xmlparsing_context_t *)malloc(sizeof(xmlparsing_context_t));
|
||||||
|
if (xmlCtx != NULL) {
|
||||||
|
xmlCtx->doc = NULL;
|
||||||
|
xmlCtx->xpath_ctx = NULL;
|
||||||
|
xmlCtx->errorBuffer[0] = '\0';
|
||||||
|
xmlCtx->warningBuffer[0] = '\0';
|
||||||
|
}
|
||||||
|
return xmlCtx;
|
||||||
|
}
|
||||||
|
|
||||||
|
void linphone_xmlparsing_context_destroy(xmlparsing_context_t *ctx) {
|
||||||
|
if (ctx->doc != NULL) {
|
||||||
|
xmlFreeDoc(ctx->doc);
|
||||||
|
ctx->doc = NULL;
|
||||||
|
}
|
||||||
|
if (ctx->xpath_ctx != NULL) {
|
||||||
|
xmlXPathFreeContext(ctx->xpath_ctx);
|
||||||
|
ctx->xpath_ctx = NULL;
|
||||||
|
}
|
||||||
|
free(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void linphone_xmlparsing_genericxml_error(void *ctx, const char *fmt, ...) {
|
||||||
|
xmlparsing_context_t *xmlCtx = (xmlparsing_context_t *)ctx;
|
||||||
|
int sl = strlen(xmlCtx->errorBuffer);
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
vsnprintf(xmlCtx->errorBuffer + sl, XMLPARSING_BUFFER_LEN - sl, fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
int linphone_create_xml_xpath_context(xmlparsing_context_t *xml_ctx) {
|
||||||
|
if (xml_ctx->xpath_ctx != NULL) {
|
||||||
|
xmlXPathFreeContext(xml_ctx->xpath_ctx);
|
||||||
|
}
|
||||||
|
xml_ctx->xpath_ctx = xmlXPathNewContext(xml_ctx->doc);
|
||||||
|
if (xml_ctx->xpath_ctx == NULL) return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char * linphone_get_xml_text_content(xmlparsing_context_t *xml_ctx, const char *xpath_expression) {
|
||||||
|
xmlXPathObjectPtr xpath_obj;
|
||||||
|
xmlChar *text = NULL;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
xpath_obj = xmlXPathEvalExpression((const xmlChar *)xpath_expression, xml_ctx->xpath_ctx);
|
||||||
|
if (xpath_obj != NULL) {
|
||||||
|
if (xpath_obj->nodesetval != NULL) {
|
||||||
|
xmlNodeSetPtr nodes = xpath_obj->nodesetval;
|
||||||
|
for (i = 0; i < nodes->nodeNr; i++) {
|
||||||
|
xmlNodePtr node = nodes->nodeTab[i];
|
||||||
|
if (node->children != NULL) {
|
||||||
|
text = xmlNodeListGetString(xml_ctx->doc, node->children, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xmlXPathFreeObject(xpath_obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (char *)text;
|
||||||
|
}
|
||||||
|
|
||||||
|
void linphone_free_xml_text_content(const char *text) {
|
||||||
|
xmlFree((xmlChar *)text);
|
||||||
|
}
|
||||||
|
|
||||||
|
xmlXPathObjectPtr linphone_get_xml_xpath_object_for_node_list(xmlparsing_context_t *xml_ctx, const char *xpath_expression) {
|
||||||
|
return xmlXPathEvalExpression((const xmlChar *)xpath_expression, xml_ctx->xpath_ctx);
|
||||||
|
}
|
||||||
21
gtk/chat.c
21
gtk/chat.c
|
|
@ -279,6 +279,16 @@ static void on_chat_state_changed(LinphoneChatMessage *msg, LinphoneChatMessageS
|
||||||
update_chat_state_message(state,msg);
|
update_chat_state_message(state,msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void linphone_gtk_compose_text(void) {
|
||||||
|
GtkWidget *main_window=linphone_gtk_get_main_window();
|
||||||
|
GtkWidget *friendlist=linphone_gtk_get_widget(main_window,"contact_list");
|
||||||
|
GtkWidget *w=(GtkWidget*)g_object_get_data(G_OBJECT(friendlist),"chatview");
|
||||||
|
LinphoneChatRoom *cr=g_object_get_data(G_OBJECT(w),"cr");
|
||||||
|
if (cr) {
|
||||||
|
linphone_chat_room_compose(cr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void linphone_gtk_send_text(){
|
void linphone_gtk_send_text(){
|
||||||
GtkWidget *main_window=linphone_gtk_get_main_window();
|
GtkWidget *main_window=linphone_gtk_get_main_window();
|
||||||
GtkWidget *friendlist=linphone_gtk_get_widget(main_window,"contact_list");
|
GtkWidget *friendlist=linphone_gtk_get_widget(main_window,"contact_list");
|
||||||
|
|
@ -293,7 +303,11 @@ void linphone_gtk_send_text(){
|
||||||
linphone_chat_room_send_message2(cr,msg,on_chat_state_changed,NULL);
|
linphone_chat_room_send_message2(cr,msg,on_chat_state_changed,NULL);
|
||||||
linphone_gtk_push_text(w,linphone_chat_message_get_from(msg),
|
linphone_gtk_push_text(w,linphone_chat_message_get_from(msg),
|
||||||
TRUE,cr,msg,FALSE);
|
TRUE,cr,msg,FALSE);
|
||||||
|
|
||||||
|
// Disconnect and reconnect the "changed" signal to prevent triggering it when clearing the text entry.
|
||||||
|
g_signal_handlers_disconnect_by_func(G_OBJECT(entry),(GCallback)linphone_gtk_compose_text,NULL);
|
||||||
gtk_entry_set_text(GTK_ENTRY(entry),"");
|
gtk_entry_set_text(GTK_ENTRY(entry),"");
|
||||||
|
g_signal_connect_swapped(G_OBJECT(entry),"changed",(GCallback)linphone_gtk_compose_text,NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -410,6 +424,7 @@ GtkWidget* linphone_gtk_init_chatroom(LinphoneChatRoom *cr, const LinphoneAddres
|
||||||
g_signal_connect_swapped(G_OBJECT(button),"clicked",(GCallback)linphone_gtk_send_text,NULL);
|
g_signal_connect_swapped(G_OBJECT(button),"clicked",(GCallback)linphone_gtk_send_text,NULL);
|
||||||
entry = linphone_gtk_get_widget(chat_view,"text_entry");
|
entry = linphone_gtk_get_widget(chat_view,"text_entry");
|
||||||
g_signal_connect_swapped(G_OBJECT(entry),"activate",(GCallback)linphone_gtk_send_text,NULL);
|
g_signal_connect_swapped(G_OBJECT(entry),"activate",(GCallback)linphone_gtk_send_text,NULL);
|
||||||
|
g_signal_connect_swapped(G_OBJECT(entry),"changed",(GCallback)linphone_gtk_compose_text,NULL);
|
||||||
g_signal_connect(G_OBJECT(notebook),"switch_page",(GCallback)linphone_gtk_notebook_tab_select,NULL);
|
g_signal_connect(G_OBJECT(notebook),"switch_page",(GCallback)linphone_gtk_notebook_tab_select,NULL);
|
||||||
ms_free(with_str);
|
ms_free(with_str);
|
||||||
return chat_view;
|
return chat_view;
|
||||||
|
|
@ -417,7 +432,7 @@ GtkWidget* linphone_gtk_init_chatroom(LinphoneChatRoom *cr, const LinphoneAddres
|
||||||
|
|
||||||
LinphoneChatRoom * linphone_gtk_create_chatroom(const LinphoneAddress *with){
|
LinphoneChatRoom * linphone_gtk_create_chatroom(const LinphoneAddress *with){
|
||||||
char *tmp=linphone_address_as_string(with);
|
char *tmp=linphone_address_as_string(with);
|
||||||
LinphoneChatRoom *cr=linphone_core_create_chat_room(linphone_gtk_get_core(),tmp);
|
LinphoneChatRoom *cr=linphone_core_get_or_create_chat_room(linphone_gtk_get_core(),tmp);
|
||||||
ms_free(tmp);
|
ms_free(tmp);
|
||||||
return cr;
|
return cr;
|
||||||
}
|
}
|
||||||
|
|
@ -516,3 +531,7 @@ void linphone_gtk_text_received ( LinphoneCore *lc, LinphoneChatRoom *room,
|
||||||
linphone_gtk_show_friends();
|
linphone_gtk_show_friends();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void linphone_gtk_is_composing_received(LinphoneCore *lc, LinphoneChatRoom *room) {
|
||||||
|
linphone_gtk_friend_list_update_chat_picture();
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -87,6 +87,18 @@ static GdkPixbuf *create_chat_picture(){
|
||||||
return pixbuf;
|
return pixbuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GdkPixbuf *create_composing_unread_msg(){
|
||||||
|
GdkPixbuf *pixbuf;
|
||||||
|
pixbuf = create_pixbuf("composing_active_chat.png");
|
||||||
|
return pixbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GdkPixbuf *create_composing_chat_picture(){
|
||||||
|
GdkPixbuf *pixbuf;
|
||||||
|
pixbuf = create_pixbuf("composing_chat.png");
|
||||||
|
return pixbuf;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
void linphone_gtk_set_friend_status(GtkWidget *friendlist , LinphoneFriend * fid, const gchar *url, const gchar *status, const gchar *img){
|
void linphone_gtk_set_friend_status(GtkWidget *friendlist , LinphoneFriend * fid, const gchar *url, const gchar *status, const gchar *img){
|
||||||
GtkTreeIter iter;
|
GtkTreeIter iter;
|
||||||
|
|
@ -227,14 +239,22 @@ void linphone_gtk_friend_list_update_chat_picture(){
|
||||||
GtkWidget *friendlist=linphone_gtk_get_widget(w,"contact_list");
|
GtkWidget *friendlist=linphone_gtk_get_widget(w,"contact_list");
|
||||||
GtkTreeModel *model=gtk_tree_view_get_model(GTK_TREE_VIEW(friendlist));
|
GtkTreeModel *model=gtk_tree_view_get_model(GTK_TREE_VIEW(friendlist));
|
||||||
LinphoneChatRoom *cr=NULL;
|
LinphoneChatRoom *cr=NULL;
|
||||||
|
bool_t is_composing;
|
||||||
int nbmsg=0;
|
int nbmsg=0;
|
||||||
if (gtk_tree_model_get_iter_first(model,&iter)) {
|
if (gtk_tree_model_get_iter_first(model,&iter)) {
|
||||||
do{
|
do{
|
||||||
gtk_tree_model_get (model, &iter,FRIEND_CHATROOM , &cr, -1);
|
gtk_tree_model_get (model, &iter,FRIEND_CHATROOM , &cr, -1);
|
||||||
nbmsg=linphone_chat_room_get_unread_messages_count(cr);
|
nbmsg=linphone_chat_room_get_unread_messages_count(cr);
|
||||||
|
is_composing=linphone_chat_room_is_remote_composing(cr);
|
||||||
if(nbmsg != 0){
|
if(nbmsg != 0){
|
||||||
|
if (is_composing == TRUE)
|
||||||
|
gtk_list_store_set(GTK_LIST_STORE(model),&iter,FRIEND_CHAT,create_composing_unread_msg(),-1);
|
||||||
|
else
|
||||||
gtk_list_store_set(GTK_LIST_STORE(model),&iter,FRIEND_CHAT,create_unread_msg(),-1);
|
gtk_list_store_set(GTK_LIST_STORE(model),&iter,FRIEND_CHAT,create_unread_msg(),-1);
|
||||||
} else {
|
} else {
|
||||||
|
if (is_composing == TRUE)
|
||||||
|
gtk_list_store_set(GTK_LIST_STORE(model),&iter,FRIEND_CHAT,create_composing_chat_picture(),-1);
|
||||||
|
else
|
||||||
gtk_list_store_set(GTK_LIST_STORE(model),&iter,FRIEND_CHAT,create_chat_picture(),-1);
|
gtk_list_store_set(GTK_LIST_STORE(model),&iter,FRIEND_CHAT,create_chat_picture(),-1);
|
||||||
}
|
}
|
||||||
}while(gtk_tree_model_iter_next(model,&iter));
|
}while(gtk_tree_model_iter_next(model,&iter));
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<interface>
|
<interface>
|
||||||
<requires lib="gtk+" version="2.24"/>
|
<requires lib="gtk+" version="2.16"/>
|
||||||
<!-- interface-naming-policy project-wide -->
|
<!-- interface-naming-policy project-wide -->
|
||||||
<object class="GtkWindow" id="ldap">
|
<object class="GtkWindow" id="ldap">
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
|
|
|
||||||
|
|
@ -116,6 +116,7 @@ void linphone_gtk_send_text();
|
||||||
GtkWidget * linphone_gtk_init_chatroom(LinphoneChatRoom *cr, const LinphoneAddress *with);
|
GtkWidget * linphone_gtk_init_chatroom(LinphoneChatRoom *cr, const LinphoneAddress *with);
|
||||||
LinphoneChatRoom * linphone_gtk_create_chatroom(const LinphoneAddress *with);
|
LinphoneChatRoom * linphone_gtk_create_chatroom(const LinphoneAddress *with);
|
||||||
void linphone_gtk_text_received(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMessage *msg);
|
void linphone_gtk_text_received(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMessage *msg);
|
||||||
|
void linphone_gtk_is_composing_received(LinphoneCore *lc, LinphoneChatRoom *room);
|
||||||
|
|
||||||
void linphone_gtk_friend_list_update_chat_picture();
|
void linphone_gtk_friend_list_update_chat_picture();
|
||||||
void linphone_gtk_friend_list_set_chat_conversation(const LinphoneAddress *la);
|
void linphone_gtk_friend_list_set_chat_conversation(const LinphoneAddress *la);
|
||||||
|
|
|
||||||
|
|
@ -266,6 +266,7 @@ static void linphone_gtk_init_liblinphone(const char *config_file,
|
||||||
vtable.call_log_updated=linphone_gtk_call_log_updated;
|
vtable.call_log_updated=linphone_gtk_call_log_updated;
|
||||||
//vtable.text_received=linphone_gtk_text_received;
|
//vtable.text_received=linphone_gtk_text_received;
|
||||||
vtable.message_received=linphone_gtk_text_received;
|
vtable.message_received=linphone_gtk_text_received;
|
||||||
|
vtable.is_composing_received=linphone_gtk_is_composing_received;
|
||||||
vtable.refer_received=linphone_gtk_refer_received;
|
vtable.refer_received=linphone_gtk_refer_received;
|
||||||
vtable.buddy_info_updated=linphone_gtk_buddy_info_updated;
|
vtable.buddy_info_updated=linphone_gtk_buddy_info_updated;
|
||||||
vtable.call_encryption_changed=linphone_gtk_call_encryption_changed;
|
vtable.call_encryption_changed=linphone_gtk_call_encryption_changed;
|
||||||
|
|
@ -846,7 +847,7 @@ static gboolean launch_contact_provider_search(void *userdata)
|
||||||
);
|
);
|
||||||
|
|
||||||
if(search)
|
if(search)
|
||||||
belle_sip_object_ref(search);
|
linphone_contact_search_ref(search);
|
||||||
}
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
#include "mediastreamer2/mscommon.h"
|
#include "mediastreamer2/mscommon.h"
|
||||||
#include "ortp/ortp_srtp.h"
|
#include "ortp/ortp_srtp.h"
|
||||||
|
#include "belle-sip/belle-sip.h"
|
||||||
|
|
||||||
#ifndef LINPHONE_PUBLIC
|
#ifndef LINPHONE_PUBLIC
|
||||||
#define LINPHONE_PUBLIC MS2_PUBLIC
|
#define LINPHONE_PUBLIC MS2_PUBLIC
|
||||||
|
|
@ -224,6 +225,11 @@ typedef struct SalMessage{
|
||||||
time_t time;
|
time_t time;
|
||||||
}SalMessage;
|
}SalMessage;
|
||||||
|
|
||||||
|
typedef struct SalIsComposing {
|
||||||
|
const char *from;
|
||||||
|
const char *text;
|
||||||
|
} SalIsComposing;
|
||||||
|
|
||||||
#define SAL_MEDIA_DESCRIPTION_MAX_MESSAGE_ATTRIBUTES 5
|
#define SAL_MEDIA_DESCRIPTION_MAX_MESSAGE_ATTRIBUTES 5
|
||||||
|
|
||||||
SalMediaDescription *sal_media_description_new();
|
SalMediaDescription *sal_media_description_new();
|
||||||
|
|
@ -241,11 +247,7 @@ typedef struct SalOpBase{
|
||||||
Sal *root;
|
Sal *root;
|
||||||
char *route; /*or request-uri for REGISTER*/
|
char *route; /*or request-uri for REGISTER*/
|
||||||
MSList* route_addresses; /*list of SalAddress* */
|
MSList* route_addresses; /*list of SalAddress* */
|
||||||
#ifndef USE_BELLESIP
|
|
||||||
char *contact;
|
|
||||||
#else
|
|
||||||
SalAddress* contact_address;
|
SalAddress* contact_address;
|
||||||
#endif
|
|
||||||
char *from;
|
char *from;
|
||||||
SalAddress* from_address;
|
SalAddress* from_address;
|
||||||
char *to;
|
char *to;
|
||||||
|
|
@ -279,7 +281,7 @@ typedef enum SalReason{
|
||||||
SalReasonTemporarilyUnavailable,
|
SalReasonTemporarilyUnavailable,
|
||||||
SalReasonNotFound,
|
SalReasonNotFound,
|
||||||
SalReasonDoNotDisturb,
|
SalReasonDoNotDisturb,
|
||||||
SalReasonMedia,
|
SalReasonUnsupportedContent,
|
||||||
SalReasonForbidden,
|
SalReasonForbidden,
|
||||||
SalReasonUnknown,
|
SalReasonUnknown,
|
||||||
SalReasonServiceUnavailable,
|
SalReasonServiceUnavailable,
|
||||||
|
|
@ -390,6 +392,7 @@ typedef void (*SalOnDtmfReceived)(SalOp *op, char dtmf);
|
||||||
typedef void (*SalOnRefer)(Sal *sal, SalOp *op, const char *referto);
|
typedef void (*SalOnRefer)(Sal *sal, SalOp *op, const char *referto);
|
||||||
typedef void (*SalOnTextReceived)(SalOp *op, const SalMessage *msg);
|
typedef void (*SalOnTextReceived)(SalOp *op, const SalMessage *msg);
|
||||||
typedef void (*SalOnTextDeliveryUpdate)(SalOp *op, SalTextDeliveryStatus status);
|
typedef void (*SalOnTextDeliveryUpdate)(SalOp *op, SalTextDeliveryStatus status);
|
||||||
|
typedef void (*SalOnIsComposingReceived)(SalOp *op, const SalIsComposing *is_composing);
|
||||||
typedef void (*SalOnNotifyRefer)(SalOp *op, SalReferStatus state);
|
typedef void (*SalOnNotifyRefer)(SalOp *op, SalReferStatus state);
|
||||||
typedef void (*SalOnSubscribeResponse)(SalOp *op, SalSubscribeStatus status, SalError error, SalReason reason);
|
typedef void (*SalOnSubscribeResponse)(SalOp *op, SalSubscribeStatus status, SalError error, SalReason reason);
|
||||||
typedef void (*SalOnNotify)(SalOp *op, SalSubscribeStatus status, const char *event, const SalBody *body);
|
typedef void (*SalOnNotify)(SalOp *op, SalSubscribeStatus status, const char *event, const SalBody *body);
|
||||||
|
|
@ -425,6 +428,7 @@ typedef struct SalCallbacks{
|
||||||
SalOnRefer refer_received;
|
SalOnRefer refer_received;
|
||||||
SalOnTextReceived text_received;
|
SalOnTextReceived text_received;
|
||||||
SalOnTextDeliveryUpdate text_delivery_update;
|
SalOnTextDeliveryUpdate text_delivery_update;
|
||||||
|
SalOnIsComposingReceived is_composing_received;
|
||||||
SalOnNotifyRefer notify_refer;
|
SalOnNotifyRefer notify_refer;
|
||||||
SalOnSubscribeReceived subscribe_received;
|
SalOnSubscribeReceived subscribe_received;
|
||||||
SalOnSubscribeClosed subscribe_closed;
|
SalOnSubscribeClosed subscribe_closed;
|
||||||
|
|
@ -690,6 +694,8 @@ LINPHONE_PUBLIC bool_t sal_dns_srv_enabled(const Sal *sal);
|
||||||
LINPHONE_PUBLIC void sal_set_dns_user_hosts_file(Sal *sal, const char *hosts_file);
|
LINPHONE_PUBLIC void sal_set_dns_user_hosts_file(Sal *sal, const char *hosts_file);
|
||||||
LINPHONE_PUBLIC const char *sal_get_dns_user_hosts_file(const Sal *sal);
|
LINPHONE_PUBLIC const char *sal_get_dns_user_hosts_file(const Sal *sal);
|
||||||
unsigned char * sal_get_random_bytes(unsigned char *ret, size_t size);
|
unsigned char * sal_get_random_bytes(unsigned char *ret, size_t size);
|
||||||
|
belle_sip_source_t * sal_create_timer(Sal *sal, belle_sip_source_func_t func, void *data, unsigned int timeout_value_ms, const char* timer_name);
|
||||||
|
void sal_cancel_timer(Sal *sal, belle_sip_source_t *timer);
|
||||||
|
|
||||||
int sal_body_has_type(const SalBody *body, const char *type, const char *subtype);
|
int sal_body_has_type(const SalBody *body, const char *type, const char *subtype);
|
||||||
/*this function parses a document with key=value pairs separated by new lines, and extracts the value for a given key*/
|
/*this function parses a document with key=value pairs separated by new lines, and extracts the value for a given key*/
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,17 @@ public interface LinphoneChatRoom {
|
||||||
*/
|
*/
|
||||||
void deleteHistory();
|
void deleteHistory();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notify the destination of the chat message being composed that the user is typing a new message.
|
||||||
|
*/
|
||||||
|
void compose();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tells whether the remote is currently composing a message.
|
||||||
|
* @return true if the remote is currently composing a message, false otherwise.
|
||||||
|
*/
|
||||||
|
boolean isRemoteComposing();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Marks all the messages in this conversation as read
|
* Marks all the messages in this conversation as read
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -91,6 +91,13 @@ public interface LinphoneCoreListener {
|
||||||
*/
|
*/
|
||||||
void messageReceived(LinphoneCore lc, LinphoneChatRoom cr, LinphoneChatMessage message);
|
void messageReceived(LinphoneCore lc, LinphoneChatRoom cr, LinphoneChatMessage message);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* invoked when a composing notification is received
|
||||||
|
* @param lc LinphoneCore
|
||||||
|
* @param room LinphoneChatRoom involved in the conversation.
|
||||||
|
*/
|
||||||
|
void isComposingReceived(LinphoneCore lc, LinphoneChatRoom cr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* invoked when a new dtmf is received
|
* invoked when a new dtmf is received
|
||||||
* @param lc LinphoneCore
|
* @param lc LinphoneCore
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,8 @@ class LinphoneChatRoomImpl implements LinphoneChatRoom {
|
||||||
private native void destroy(long ptr);
|
private native void destroy(long ptr);
|
||||||
private native int getUnreadMessagesCount(long ptr);
|
private native int getUnreadMessagesCount(long ptr);
|
||||||
private native void deleteHistory(long ptr);
|
private native void deleteHistory(long ptr);
|
||||||
|
private native void compose(long ptr);
|
||||||
|
private native boolean isRemoteComposing(long ptr);
|
||||||
private native void markAsRead(long ptr);
|
private native void markAsRead(long ptr);
|
||||||
private native void deleteMessage(long room, long message);
|
private native void deleteMessage(long room, long message);
|
||||||
private native void updateUrl(long room, long message);
|
private native void updateUrl(long room, long message);
|
||||||
|
|
@ -88,6 +90,14 @@ class LinphoneChatRoomImpl implements LinphoneChatRoom {
|
||||||
deleteHistory(nativePtr);
|
deleteHistory(nativePtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void compose() {
|
||||||
|
compose(nativePtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isRemoteComposing() {
|
||||||
|
return isRemoteComposing(nativePtr);
|
||||||
|
}
|
||||||
|
|
||||||
public void markAsRead() {
|
public void markAsRead() {
|
||||||
markAsRead(nativePtr);
|
markAsRead(nativePtr);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ Libraries and headers required to develop software with linphone.
|
||||||
%if !%{video}
|
%if !%{video}
|
||||||
--disable-video \
|
--disable-video \
|
||||||
%endif
|
%endif
|
||||||
--disable-tests --docdir=%{_docdir} --enable-ipv6 --enable-static --enable-external-mediastreamer --enable-external-ortp
|
--disable-tests --docdir=%{_docdir} --enable-ipv6 --enable-static --enable-external-mediastreamer --enable-external-ortp --enable-ldap
|
||||||
%__make %{?_smp_mflags}
|
%__make %{?_smp_mflags}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit 4103f0b1d7757558d06e6e32b657308bb2556c9b
|
Subproject commit ce1127bbf74a1bc1113a048195db3cf2ed49c946
|
||||||
2
oRTP
2
oRTP
|
|
@ -1 +1 @@
|
||||||
Subproject commit 37b81a118760caa22a5a89d56945acea9aa52523
|
Subproject commit d4241929983c8f0114f8de04dca6ecbc42b9607e
|
||||||
|
|
@ -11,7 +11,7 @@ status-orange.png \
|
||||||
status-red.png \
|
status-red.png \
|
||||||
status-offline.png \
|
status-offline.png \
|
||||||
call.png \
|
call.png \
|
||||||
chat.png active_chat.png\
|
chat.png active_chat.png composing_chat.png composing_active_chat.png\
|
||||||
chat_message_inprogress.png chat_message_delivered.png chat_message_not_delivered.png\
|
chat_message_inprogress.png chat_message_delivered.png chat_message_not_delivered.png\
|
||||||
contact-orange.png dialer-orange.png history-orange.png\
|
contact-orange.png dialer-orange.png history-orange.png\
|
||||||
startcall-green.png startcall-small.png stopcall-red.png stopcall-small.png addcall-green.png linphone.icns \
|
startcall-green.png startcall-small.png stopcall-red.png stopcall-small.png addcall-green.png linphone.icns \
|
||||||
|
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
BIN
pixmaps/composing_active_chat.png
Normal file
BIN
pixmaps/composing_active_chat.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.3 KiB |
BIN
pixmaps/composing_chat.png
Normal file
BIN
pixmaps/composing_chat.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.2 KiB |
|
|
@ -27,6 +27,7 @@ gtk/loginframe.c
|
||||||
[type: gettext/glade]gtk/call_statistics.ui
|
[type: gettext/glade]gtk/call_statistics.ui
|
||||||
[type: gettext/glade]gtk/tunnel_config.ui
|
[type: gettext/glade]gtk/tunnel_config.ui
|
||||||
[type: gettext/glade]gtk/keypad.ui
|
[type: gettext/glade]gtk/keypad.ui
|
||||||
|
[type: gettext/glade]gtk/ldap.ui
|
||||||
coreapi/linphonecore.c
|
coreapi/linphonecore.c
|
||||||
coreapi/misc.c
|
coreapi/misc.c
|
||||||
coreapi/presence.c
|
coreapi/presence.c
|
||||||
|
|
|
||||||
17
share/CMakeLists.txt
Normal file
17
share/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
install(FILES archived-rootca.pem
|
||||||
|
RENAME rootca.pem
|
||||||
|
COMPONENT COMP_liblinphone
|
||||||
|
DESTINATION share/linphone
|
||||||
|
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
|
||||||
|
|
||||||
|
install(FILES ringback.wav
|
||||||
|
COMPONENT COMP_liblinphone
|
||||||
|
DESTINATION share/sounds/linphone
|
||||||
|
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
|
||||||
|
|
||||||
|
add_subdirectory(rings)
|
||||||
|
|
||||||
|
install(FILES ../mediastreamer2/src/voip/nowebcamCIF.jpg
|
||||||
|
COMPONENT COMP_liblinphone
|
||||||
|
DESTINATION share/images
|
||||||
|
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
|
||||||
4
share/rings/CMakeLists.txt
Normal file
4
share/rings/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
install(FILES oldphone.wav toy-mono.wav
|
||||||
|
COMPONENT COMP_liblinphone
|
||||||
|
DESTINATION share/sounds/linphone/rings
|
||||||
|
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
|
||||||
|
|
@ -23,11 +23,11 @@ liblinphone_tester_SOURCES= liblinphone_tester.c liblinphone_tester.h\
|
||||||
|
|
||||||
AM_CPPFLAGS=-I$(top_srcdir)/include -I$(top_srcdir)/coreapi
|
AM_CPPFLAGS=-I$(top_srcdir)/include -I$(top_srcdir)/coreapi
|
||||||
|
|
||||||
LDADD=$(top_builddir)/coreapi/liblinphone.la $(BELLESIP_LIBS)
|
LDADD=$(top_builddir)/coreapi/liblinphone.la $(BELLESIP_LIBS) $(LIBXML2_LIBS)
|
||||||
|
|
||||||
AM_LDFLAGS=$(CUNIT_LIBS)
|
AM_LDFLAGS=$(CUNIT_LIBS)
|
||||||
|
|
||||||
AM_CFLAGS=$(STRICT_OPTIONS) -DIN_LINPHONE $(ORTP_CFLAGS) $(MEDIASTREAMER_CFLAGS) $(CUNIT_CFLAGS) $(BELLESIP_CFLAGS)
|
AM_CFLAGS=$(STRICT_OPTIONS) -DIN_LINPHONE $(ORTP_CFLAGS) $(MEDIASTREAMER_CFLAGS) $(CUNIT_CFLAGS) $(BELLESIP_CFLAGS) $(LIBXML2_CFLAGS)
|
||||||
|
|
||||||
test: liblinphone_tester
|
test: liblinphone_tester
|
||||||
./liblinphone_tester --config $(abs_srcdir)
|
./liblinphone_tester --config $(abs_srcdir)
|
||||||
|
|
|
||||||
|
|
@ -331,9 +331,9 @@ static void call_failed_because_of_codecs(void) {
|
||||||
linphone_call_ref(out_call);
|
linphone_call_ref(out_call);
|
||||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallOutgoingInit,1));
|
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallOutgoingInit,1));
|
||||||
|
|
||||||
/*flexisip will retain the 415 until the "urgent reply" timeout arrives.*/
|
/*flexisip will retain the 488 until the "urgent reply" timeout arrives.*/
|
||||||
CU_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallError,1,6000));
|
CU_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallError,1,6000));
|
||||||
CU_ASSERT_EQUAL(linphone_call_get_reason(out_call),LinphoneReasonMedia);
|
CU_ASSERT_EQUAL(linphone_call_get_reason(out_call),LinphoneReasonNotAcceptable);
|
||||||
CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallIncomingReceived,0);
|
CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallIncomingReceived,0);
|
||||||
|
|
||||||
linphone_call_unref(out_call);
|
linphone_call_unref(out_call);
|
||||||
|
|
@ -1387,6 +1387,41 @@ static void call_established_with_rejected_reinvite(void) {
|
||||||
linphone_core_manager_destroy(pauline);
|
linphone_core_manager_destroy(pauline);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void call_established_with_rejected_incoming_reinvite(void) {
|
||||||
|
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
|
||||||
|
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
|
||||||
|
|
||||||
|
CU_ASSERT_TRUE(call(pauline,marie));
|
||||||
|
|
||||||
|
/*wait for ACK to be transmitted before going to reINVITE*/
|
||||||
|
wait_for_until(marie->lc,pauline->lc,NULL,0,1000);
|
||||||
|
|
||||||
|
linphone_core_enable_payload_type(pauline->lc,linphone_core_find_payload_type(pauline->lc,"PCMU",8000,1),FALSE); /*disable PCMU*/
|
||||||
|
linphone_core_enable_payload_type(pauline->lc,linphone_core_find_payload_type(pauline->lc,"PCMA",8000,1),TRUE); /*enable PCMA*/
|
||||||
|
|
||||||
|
linphone_core_update_call(marie->lc
|
||||||
|
,linphone_core_get_current_call(marie->lc)
|
||||||
|
,linphone_call_get_current_params(linphone_core_get_current_call(marie->lc)));
|
||||||
|
|
||||||
|
|
||||||
|
CU_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallUpdating,1));
|
||||||
|
CU_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallStreamsRunning,2));
|
||||||
|
|
||||||
|
CU_ASSERT_EQUAL(linphone_call_get_reason(linphone_core_get_current_call(marie->lc)),LinphoneReasonNotAcceptable);
|
||||||
|
|
||||||
|
CU_ASSERT_EQUAL(pauline->stat.number_of_LinphoneCallStreamsRunning,1);
|
||||||
|
check_call_state(pauline,LinphoneCallStreamsRunning);
|
||||||
|
check_call_state(marie,LinphoneCallStreamsRunning);
|
||||||
|
|
||||||
|
/*just to sleep*/
|
||||||
|
linphone_core_terminate_all_calls(pauline->lc);
|
||||||
|
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallEnd,1));
|
||||||
|
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallEnd,1));
|
||||||
|
|
||||||
|
linphone_core_manager_destroy(marie);
|
||||||
|
linphone_core_manager_destroy(pauline);
|
||||||
|
}
|
||||||
|
|
||||||
static void call_established_with_rejected_reinvite_with_error(void) {
|
static void call_established_with_rejected_reinvite_with_error(void) {
|
||||||
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
|
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
|
||||||
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
|
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
|
||||||
|
|
@ -1460,6 +1495,7 @@ test_t call_tests[] = {
|
||||||
{ "Call with custom headers",call_with_custom_headers},
|
{ "Call with custom headers",call_with_custom_headers},
|
||||||
{ "Call established with rejected INFO",call_established_with_rejected_info},
|
{ "Call established with rejected INFO",call_established_with_rejected_info},
|
||||||
{ "Call established with rejected RE-INVITE",call_established_with_rejected_reinvite},
|
{ "Call established with rejected RE-INVITE",call_established_with_rejected_reinvite},
|
||||||
|
{ "Call established with rejected incoming RE-INVITE", call_established_with_rejected_incoming_reinvite },
|
||||||
{ "Call established with rejected RE-INVITE in error", call_established_with_rejected_reinvite_with_error}
|
{ "Call established with rejected RE-INVITE in error", call_established_with_rejected_reinvite_with_error}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -136,9 +136,11 @@ bool_t wait_for_until(LinphoneCore* lc_1, LinphoneCore* lc_2,int* counter,int va
|
||||||
ms_list_free(lcs);
|
ms_list_free(lcs);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool_t wait_for(LinphoneCore* lc_1, LinphoneCore* lc_2,int* counter,int value) {
|
bool_t wait_for(LinphoneCore* lc_1, LinphoneCore* lc_2,int* counter,int value) {
|
||||||
return wait_for_until(lc_1, lc_2,counter,value,3000);
|
return wait_for_until(lc_1, lc_2,counter,value,3000);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool_t wait_for_list(MSList* lcs,int* counter,int value,int timeout_ms) {
|
bool_t wait_for_list(MSList* lcs,int* counter,int value,int timeout_ms) {
|
||||||
int retry=0;
|
int retry=0;
|
||||||
MSList* iterator;
|
MSList* iterator;
|
||||||
|
|
@ -189,6 +191,7 @@ LinphoneCoreManager* linphone_core_manager_new2(const char* rc_file, int check_f
|
||||||
mgr->v_table.call_state_changed=call_state_changed;
|
mgr->v_table.call_state_changed=call_state_changed;
|
||||||
mgr->v_table.text_received=text_message_received;
|
mgr->v_table.text_received=text_message_received;
|
||||||
mgr->v_table.message_received=message_received;
|
mgr->v_table.message_received=message_received;
|
||||||
|
mgr->v_table.is_composing_received=is_composing_received;
|
||||||
mgr->v_table.new_subscription_requested=new_subscription_requested;
|
mgr->v_table.new_subscription_requested=new_subscription_requested;
|
||||||
mgr->v_table.notify_presence_received=notify_presence_received;
|
mgr->v_table.notify_presence_received=notify_presence_received;
|
||||||
mgr->v_table.transfer_state_changed=linphone_transfer_state_changed;
|
mgr->v_table.transfer_state_changed=linphone_transfer_state_changed;
|
||||||
|
|
|
||||||
|
|
@ -117,7 +117,8 @@ typedef struct _stats {
|
||||||
int number_of_LinphoneMessageInProgress;
|
int number_of_LinphoneMessageInProgress;
|
||||||
int number_of_LinphoneMessageDelivered;
|
int number_of_LinphoneMessageDelivered;
|
||||||
int number_of_LinphoneMessageNotDelivered;
|
int number_of_LinphoneMessageNotDelivered;
|
||||||
|
int number_of_LinphoneIsComposingActiveReceived;
|
||||||
|
int number_of_LinphoneIsComposingIdleReceived;
|
||||||
|
|
||||||
int number_of_IframeDecoded;
|
int number_of_IframeDecoded;
|
||||||
|
|
||||||
|
|
@ -194,6 +195,7 @@ void linphone_transfer_state_changed(LinphoneCore *lc, LinphoneCall *transfered,
|
||||||
void notify_presence_received(LinphoneCore *lc, LinphoneFriend * lf);
|
void notify_presence_received(LinphoneCore *lc, LinphoneFriend * lf);
|
||||||
void text_message_received(LinphoneCore *lc, LinphoneChatRoom *room, const LinphoneAddress *from_address, const char *message);
|
void text_message_received(LinphoneCore *lc, LinphoneChatRoom *room, const LinphoneAddress *from_address, const char *message);
|
||||||
void message_received(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMessage* message);
|
void message_received(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMessage* message);
|
||||||
|
void is_composing_received(LinphoneCore *lc, LinphoneChatRoom *room);
|
||||||
void info_message_received(LinphoneCore *lc, LinphoneCall *call, const LinphoneInfoMessage *msg);
|
void info_message_received(LinphoneCore *lc, LinphoneCall *call, const LinphoneInfoMessage *msg);
|
||||||
void new_subscription_requested(LinphoneCore *lc, LinphoneFriend *lf, const char *url);
|
void new_subscription_requested(LinphoneCore *lc, LinphoneFriend *lf, const char *url);
|
||||||
void auth_info_requested(LinphoneCore *lc, const char *realm, const char *username, const char *domain);
|
void auth_info_requested(LinphoneCore *lc, const char *realm, const char *username, const char *domain);
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ sip_tls_port=5083
|
||||||
default_proxy=0
|
default_proxy=0
|
||||||
ping_with_options=0
|
ping_with_options=0
|
||||||
register_only_when_network_is_up=0
|
register_only_when_network_is_up=0
|
||||||
|
composing_idle_timeout=1
|
||||||
|
|
||||||
[auth_info_0]
|
[auth_info_0]
|
||||||
username=marie
|
username=marie
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,15 @@ void message_received(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMess
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void is_composing_received(LinphoneCore *lc, LinphoneChatRoom *room) {
|
||||||
|
stats *counters = get_stats(lc);
|
||||||
|
if (room->remote_is_composing == LinphoneIsComposingActive) {
|
||||||
|
counters->number_of_LinphoneIsComposingActiveReceived++;
|
||||||
|
} else {
|
||||||
|
counters->number_of_LinphoneIsComposingIdleReceived++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void linphone_chat_message_state_change(LinphoneChatMessage* msg,LinphoneChatMessageState state,void* ud) {
|
void linphone_chat_message_state_change(LinphoneChatMessage* msg,LinphoneChatMessageState state,void* ud) {
|
||||||
LinphoneCore* lc=(LinphoneCore*)ud;
|
LinphoneCore* lc=(LinphoneCore*)ud;
|
||||||
stats* counters = get_stats(lc);
|
stats* counters = get_stats(lc);
|
||||||
|
|
@ -264,6 +273,24 @@ static void info_message_with_body(){
|
||||||
info_message_with_args(TRUE);
|
info_message_with_args(TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void is_composing_notification(void) {
|
||||||
|
LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
|
||||||
|
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
|
||||||
|
char* to = linphone_address_as_string(marie->identity);
|
||||||
|
LinphoneChatRoom* chat_room = linphone_core_create_chat_room(pauline->lc, to);
|
||||||
|
int dummy = 0;
|
||||||
|
|
||||||
|
ms_free(to);
|
||||||
|
linphone_chat_room_compose(chat_room);
|
||||||
|
wait_for_until(pauline->lc, marie->lc, &dummy, 1, 1500); /*just to sleep while iterating*/
|
||||||
|
linphone_chat_room_send_message(chat_room, "Composing a message");
|
||||||
|
CU_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneIsComposingActiveReceived, 1));
|
||||||
|
CU_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneIsComposingIdleReceived, 2));
|
||||||
|
|
||||||
|
linphone_core_manager_destroy(marie);
|
||||||
|
linphone_core_manager_destroy(pauline);
|
||||||
|
}
|
||||||
|
|
||||||
test_t message_tests[] = {
|
test_t message_tests[] = {
|
||||||
{ "Text message", text_message },
|
{ "Text message", text_message },
|
||||||
{ "Text message with privacy", text_message_with_privacy },
|
{ "Text message with privacy", text_message_with_privacy },
|
||||||
|
|
@ -272,7 +299,8 @@ test_t message_tests[] = {
|
||||||
{ "Text message with send error", text_message_with_send_error },
|
{ "Text message with send error", text_message_with_send_error },
|
||||||
{ "Text message with external body", text_message_with_external_body },
|
{ "Text message with external body", text_message_with_external_body },
|
||||||
{ "Info message", info_message },
|
{ "Info message", info_message },
|
||||||
{ "Info message with body", info_message_with_body }
|
{ "Info message with body", info_message_with_body },
|
||||||
|
{ "IsComposing notification", is_composing_notification }
|
||||||
};
|
};
|
||||||
|
|
||||||
test_suite_t message_test_suite = {
|
test_suite_t message_test_suite = {
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ sip_tls_port=5073
|
||||||
default_proxy=0
|
default_proxy=0
|
||||||
ping_with_options=0
|
ping_with_options=0
|
||||||
register_only_when_network_is_up=0
|
register_only_when_network_is_up=0
|
||||||
|
composing_idle_timeout=1
|
||||||
|
|
||||||
[auth_info_0]
|
[auth_info_0]
|
||||||
username=pauline
|
username=pauline
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue