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

This commit is contained in:
Simon Morlat 2014-01-14 13:06:39 +01:00
commit 9ca718d11f
58 changed files with 1338 additions and 444 deletions

60
CMakeLists.txt Normal file
View 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
View file

@ -44,11 +44,12 @@ This is Linphone, a free (GPL) video softphone based on the SIP protocol.
$ sudo make install
+ Install zrtpcpp (optional), for unbreakable call encryption
$ sudo apt-get install cmake libssl-dev
$ git clone git://git.linphone.org/zrtpcpp.git
$ cd zrtpcpp && cmake -Denable-ccrtp=false . && make
$ sudo apt-get install cmake
$ git clone https://github.com/wernerd/ZRTPCPP.git
$ cd ZRTPCPP
$ cmake -DCORE_LIB=true -DSDES=false . && make
$ 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

View file

@ -9,7 +9,7 @@ In the feature list, select:
* Mingw developer toolkit
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-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.
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
c:\sources\
Within msys-git bash, do
General rules for compilation
*****************************
- 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
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,
you might see a process 'LVpSRV.exe' or something like this that eats 90% of cpu.
Kill it. Don't know what it is, but once killed, windows runs normally.
* download the sources using the following command:
$ git clone git://git.linphone.org/linphone.git --recursive
#Build linphone itself:
#run autogen.sh after a git checkout or update
* compile
#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
#note: in order to use the tunnel, append --enable-tunnel to the configure line above.
$ make
$ make install
#compile:
#Option: make a portable binary zip of linphone
$ make zip
make
#additionally you can make binary installer if you have Inno Setup 5 installed in its default path
#now install to /usr, required for compilation of plugins.
$ make setup.exe
#now you're done, you have a fresh linphone windows installer in the current directory.
make install
Building plugins (optional)
***************************
#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
make setup.exe
#now you're done, you have a fresh linphone windows installer in the current directory.
#build plugins
cd mediastreamer2/plugins/msx264
./autogen.sh
PKG_CONFIG_PATH=/usr/lib/pkgconfig ./configure --prefix=/usr --enable-shared --disable-static
#make a binary zip of this plugin
make zip
#or make an installer
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
This the example for msx264 (H264 plugin), the same applies for other linphone plugins.
$ cd mediastreamer2/plugins/msx264
$ ./autogen.sh
$ PKG_CONFIG_PATH=/usr/lib/pkgconfig ./configure --prefix=/usr --enable-shared --disable-static
#make a binary zip of this plugin
$ make zip
#or make an installer
$ make setup.exe
******************************************************
@ -161,14 +154,6 @@ When running "make install DESTDIR=<somepath>", somepath must be absolute and sh
$ make install DESTDIR=/usr
$ 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
* download the sources with
$ git clone git://git.linphone.org/srtp.git

View file

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

View file

@ -60,7 +60,8 @@ LOCAL_SRC_FILES := \
linphone_tunnel_config.c \
message_storage.c \
info.c \
event.c
event.c \
xml.c
ifndef LINPHONE_VERSION
LINPHONE_VERSION = "Devel"

13
build/redhat/INSTALL Normal file
View 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
View 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

View file

@ -117,7 +117,7 @@
<ClCompile>
<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>
<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>
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
@ -147,7 +147,7 @@
<ClCompile>
<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>
<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>
<FunctionLevelLinking>true</FunctionLevelLinking>
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
@ -207,6 +207,7 @@
<ClCompile Include="..\..\..\coreapi\siplogin.c" />
<ClCompile Include="..\..\..\coreapi\sipsetup.c" />
<ClCompile Include="..\..\..\coreapi\TunnelManager.cc" />
<ClCompile Include="..\..\..\coreapi\xml.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\coreapi\bellesip_sal\sal_impl.h" />

View file

@ -13,7 +13,8 @@ COMMON_CFLAGS=\
$(MEDIASTREAMER_CFLAGS) \
$(VIDEO_CFLAGS) \
$(READLINE_CFLAGS) \
$(SQLITE3_CFLAGS)
$(SQLITE3_CFLAGS) \
$(LIBXML2_CFLAGS)
if BUILD_CONSOLE
@ -29,7 +30,8 @@ linphonec_LDADD=$(top_builddir)/coreapi/liblinphone.la \
$(READLINE_LIBS) \
$(SQLITE3_LIBS) \
$(X11_LIBS) \
$(BELLESIP_LIBS)
$(BELLESIP_LIBS) \
$(LIBXML2_LIBS)
if BUILD_WIN32
#special build of linphonec to detach from the windows console

140
coreapi/CMakeLists.txt Normal file
View 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)

View file

@ -51,6 +51,7 @@ liblinphone_la_SOURCES=\
contactprovider.c contactprovider.h contact_providers_priv.h \
ldap/ldapprovider.c ldap/ldapprovider.h \
dict.c \
xml.c \
$(GITVERSION_FILE)
if BUILD_UPNP

View file

@ -464,6 +464,8 @@ void sal_set_callbacks(Sal *ctx, const SalCallbacks *cbs){
ctx->callbacks.subscribe_presence_received=(SalOnSubscribePresenceReceived)unimplemented_stub;
if (ctx->callbacks.text_received==NULL)
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)
ctx->callbacks.ping_reply=(SalOnPingReply)unimplemented_stub;
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);
}
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);
}

View file

@ -19,6 +19,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "sal_impl.h"
#include "offeranswer.h"
static int extract_sdp(belle_sip_message_t* message,belle_sdp_session_description_t** session_desc, SalReason *error);
/*used for calls terminated before creation of a dialog*/
static void call_set_released(SalOp* op){
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) {
belle_sip_header_content_type_t* content_type ;
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) {
belle_sdp_session_description_t* sdp;
if ((sdp=belle_sdp_session_description_create(BELLE_SIP_MESSAGE(response)))) {
op->base.remote_media=sal_media_description_new();
sdp_to_media_description(sdp,op->base.remote_media);
if (op->base.local_media) sdp_process(op);
SalReason reason;
if (extract_sdp(BELLE_SIP_MESSAGE(response),&sdp,&reason)==0) {
if (sdp){
op->base.remote_media=sal_media_description_new();
sdp_to_media_description(sdp,op->base.remote_media);
if (op->base.local_media) sdp_process(op);
}/*if no sdp in response, what can we do ?*/
}
}
@ -322,15 +327,61 @@ static void unsupported_method(belle_sip_server_transaction_t* server_transactio
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;
if ((sdp=belle_sdp_session_description_create(BELLE_SIP_MESSAGE(invite)))) {
op->sdp_offering=FALSE;
op->base.remote_media=sal_media_description_new();
sdp_to_media_description(sdp,op->base.remote_media);
belle_sip_object_unref(sdp);
}else
op->sdp_offering=TRUE;
int err=0;
SalReason reason;
if (extract_sdp(BELLE_SIP_MESSAGE(invite),&sdp,&reason)==0) {
if (sdp){
op->sdp_offering=FALSE;
op->base.remote_media=sal_media_description_new();
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);
}else op->sdp_offering=TRUE; /*INVITE without SDP*/
}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) {
@ -415,13 +466,18 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t
/*great ACK received*/
if (strcmp("ACK",belle_sip_request_get_method(req))==0) {
if (op->sdp_offering){
if ((sdp=belle_sdp_session_description_create(BELLE_SIP_MESSAGE(req)))){
if (op->base.remote_media)
sal_media_description_unref(op->base.remote_media);
op->base.remote_media=sal_media_description_new();
sdp_to_media_description(sdp,op->base.remote_media);
sdp_process(op);
belle_sip_object_unref(sdp);
SalReason reason;
if (extract_sdp(BELLE_SIP_MESSAGE(req),&sdp,&reason)==0){
if (sdp){
if (op->base.remote_media)
sal_media_description_unref(op->base.remote_media);
op->base.remote_media=sal_media_description_new();
sdp_to_media_description(sdp,op->base.remote_media);
sdp_process(op);
belle_sip_object_unref(sdp);
}else{
ms_warning("SDP expected in ACK but not found.");
}
}
}
/*FIXME
@ -445,9 +501,8 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t
sal_media_description_unref(op->result);
op->result=NULL;
}
process_sdp_for_invite(op,req);
op->base.root->callbacks.call_updating(op);
if (process_sdp_for_invite(op,req)==0)
op->base.root->callbacks.call_updating(op);
} else if (strcmp("INFO",belle_sip_request_get_method(req))==0){
if (belle_sip_message_get_body(BELLE_SIP_MESSAGE(req))
&& strstr(belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)),"picture_fast_update")) {

View file

@ -334,7 +334,7 @@ SalReason sal_reason_to_sip_code(SalReason r){
case SalReasonForbidden:
ret=403;
break;
case SalReasonMedia:
case SalReasonUnsupportedContent:
ret=415;
break;
case SalReasonNotFound:
@ -356,7 +356,7 @@ SalReason sal_reason_to_sip_code(SalReason r){
ret=401;
break;
case SalReasonNotAcceptable:
ret=488;
ret=488; /*or maybe 606 Not Acceptable ?*/
break;
case SalReasonNoMatch:
ret=481;
@ -385,7 +385,7 @@ void sal_compute_sal_errors_from_code(int code ,SalError* sal_err,SalReason* sal
break;
case 415:
*sal_err=SalErrorFailure;
*sal_reason=SalReasonMedia;
*sal_reason=SalReasonUnsupportedContent;
break;
case 422:
ms_error ("422 not implemented yet");;

View file

@ -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
&& 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) {
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_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);
SalMessage salmsg;
char message_id[256]={0};
int response_code=501;
char* from;
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);
if (content_type && ((plain_text=is_plain_text(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))
,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(from_header)));
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);
if (salmsg.url) ms_free((char*)salmsg.url);
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 {
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));

View file

@ -612,7 +612,8 @@ static void call_failure(SalOp *op, SalError error, SalReason sr, const char *de
if (lc->vtable.display_status)
lc->vtable.display_status(lc,msg600);
break;
case SalReasonMedia:
case SalReasonUnsupportedContent: /*<this is for compatibility: linphone sent 415 because of SDP offer answer failure*/
case SalReasonNotAcceptable:
//media_encryption_mandatory
if (call->params.media_encryption == LinphoneMediaEncryptionSRTP &&
!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) {
linphone_notify_parse_presence(op, content_type, content_subtype, body, result);
}
@ -1001,8 +1007,14 @@ static int op_equals(LinphoneCall *a, SalOp *b) {
static void text_delivery_update(SalOp *op, SalTextDeliveryStatus status){
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);
linphone_chat_message_store_state(chat_msg);
if (chat_msg && chat_msg->cb) {
@ -1123,6 +1135,7 @@ SalCallbacks linphone_sal_callbacks={
refer_received,
text_received,
text_delivery_update,
is_composing_received,
notify_refer,
subscribe_received,
subscribe_closed,

View file

@ -26,6 +26,12 @@
#include "private.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
* @{
@ -85,13 +91,40 @@ LinphoneChatRoom* linphone_core_get_or_create_chat_room(LinphoneCore* lc, const
}
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.
* @param cr #LinphoneChatRoom object
*/
void linphone_chat_room_destroy(LinphoneChatRoom *cr){
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);
linphone_address_destroy(cr->peer_url);
ms_free(cr->peer);
@ -142,6 +175,12 @@ static void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatM
msg->dir=LinphoneChatMessageOutgoing;
msg->from=linphone_address_new(identity);
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
if (lc->vtable.text_received!=NULL) lc->vtable.text_received(lc, cr, msg->from, msg->message);
if (lc->vtable.message_received!=NULL) lc->vtable.message_received(lc, cr,msg);
if (cr->lc->vtable.is_composing_received != NULL) {
cr->remote_is_composing = LinphoneIsComposingIdle;
cr->lc->vtable.is_composing_received(cr->lc, cr);
}
}
/**
@ -225,6 +267,85 @@ void linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessag
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.
**/
@ -319,6 +440,131 @@ void linphone_chat_room_send_message2(LinphoneChatRoom *cr, LinphoneChatMessage*
_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.
*/

View file

@ -17,7 +17,7 @@
#ifndef CONTACT_PROVIDERS_PRIV_H
#define CONTACT_PROVIDERS_PRIV_H
#include <belle-sip/object.h>
#include "private.h"
#include "linphonecore.h"
/* Base for contact search and contact provider */

View file

@ -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
}
LinphoneContactSearch*linphone_ldap_contact_search_ref(void* obj)
LinphoneContactSearch*linphone_contact_search_ref(void* 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 /* cancel_search -> pure virtual */
BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_END

View file

@ -280,5 +280,11 @@ public class TutorialBuddyStatus implements LinphoneCoreListener {
}
@Override
public void isComposingReceived(LinphoneCore lc, LinphoneChatRoom cr) {
// TODO Auto-generated method stub
}
}

View file

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

View file

@ -206,5 +206,11 @@ public class TutorialHelloWorld implements LinphoneCoreListener {
}
@Override
public void isComposingReceived(LinphoneCore lc, LinphoneChatRoom cr) {
// TODO Auto-generated method stub
}
}

View file

@ -237,6 +237,12 @@ public class TutorialRegistration implements LinphoneCoreListener {
}
@Override
public void isComposingReceived(LinphoneCore lc, LinphoneChatRoom cr) {
// TODO Auto-generated method stub
}
}

View file

@ -595,9 +595,14 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro
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*/
linphone_core_init_default_params(lc, &call->params);
/*
* Initialize call parameters according to incoming call parameters. This is to avoid to ask later (during reINVITEs) for features that the remote
* end apparently does not support. This features are: privacy, video
*/
/*set privacy*/
call->current_params.privacy=(LinphonePrivacyMask)sal_op_get_privacy(call->op);
/*set video support */
md=sal_call_get_remote_media_description(op);
call->params.has_video &= !!lc->video_policy.automatically_accept;
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.
call->params.has_video &= linphone_core_media_description_contains_video_stream(md);
}
switch (linphone_core_get_firewall_policy(call->core)) {
case LinphonePolicyUseIce:
call->ice_session = ice_session_new();
@ -1760,21 +1766,20 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cna
/* valid local tags are > 0 */
if (stream->proto == SalProtoRtpSavp) {
local_st_desc=sal_media_description_find_stream(call->localdesc,
SalProtoRtpSavp,SalAudio);
crypto_idx = find_crypto_index_from_tag(local_st_desc->crypto, stream->crypto_local_tag);
local_st_desc=sal_media_description_find_stream(call->localdesc,SalProtoRtpSavp,SalAudio);
crypto_idx = find_crypto_index_from_tag(local_st_desc->crypto, stream->crypto_local_tag);
if (crypto_idx >= 0) {
audio_stream_enable_srtp(
call->audiostream,
stream->crypto[0].algo,
local_st_desc->crypto[crypto_idx].master_key,
stream->crypto[0].master_key);
call->audiostream_encrypted=TRUE;
} else {
ms_warning("Failed to find local crypto algo with tag: %d", stream->crypto_local_tag);
call->audiostream_encrypted=FALSE;
}
if (crypto_idx >= 0) {
audio_stream_enable_srtp(
call->audiostream,
stream->crypto[0].algo,
local_st_desc->crypto[crypto_idx].master_key,
stream->crypto[0].master_key);
call->audiostream_encrypted=TRUE;
} else {
ms_warning("Failed to find local crypto algo with tag: %d", stream->crypto_local_tag);
call->audiostream_encrypted=FALSE;
}
}else call->audiostream_encrypted=FALSE;
if (call->params.in_conference){
/*transform the graph to connect it to the conference filter */
@ -1929,7 +1934,7 @@ void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_mut
params.zid_file=lc->zrtp_secrets_cache;
audio_stream_enable_zrtp(call->audiostream,&params);
}else if (call->params.media_encryption==LinphoneMediaEncryptionSRTP){
}else{
call->current_params.media_encryption=linphone_call_are_all_streams_encrypted(call) ?
LinphoneMediaEncryptionSRTP : LinphoneMediaEncryptionNone;
}
@ -2247,6 +2252,111 @@ const LinphoneCallStats *linphone_call_get_video_stats(LinphoneCall *call) {
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).
* 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;
}
/**
* Perform a zoom of the video displayed during a 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.");
}
#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){
#endif
LinphoneAddress *ctt=NULL;
#ifdef USE_BELLESIP
LinphoneAddress *ret=NULL;
#else
char* ret;
#endif
const char *localip=call->localip;
/* first use user's supplied ip address if asked*/
if (linphone_core_get_firewall_policy(lc)==LinphonePolicyUseNatAddress){
ctt=linphone_core_get_primary_contact_parsed(lc);
linphone_address_set_domain(ctt,linphone_core_get_nat_address_resolved(lc));
#ifdef USE_BELLESIP
ret=ctt;
#else
ret=linphone_address_as_string(ctt);
#endif
} else if (call->op && sal_op_get_contact(call->op)!=NULL){
/* if already choosed, don't change it */
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
received, rport*/
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));;
#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)){
/*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*/);
#ifdef USE_BELLESIP
ret=linphone_address_clone(sal_op_get_contact(dest_proxy->op));
#else
ret=ms_strdup(sal_op_get_contact(dest_proxy->op));
#endif
} else {
ctt=linphone_core_get_primary_contact_parsed(lc);
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_port(ctt,linphone_core_get_sip_port(lc));
ms_message("Contact has been fixed using local ip"/* to %s",ret*/);
#ifdef USE_BELLESIP
ret=ctt;
#else
ret=linphone_address_as_string_uri_only(ctt);
#endif
}
}
#ifndef USE_BELLESIP
if (ctt) linphone_address_destroy(ctt);
#endif
return ret;
@ -2688,4 +2770,4 @@ void linphone_call_set_contact_op(LinphoneCall* call) {
sal_op_set_contact(call->op, contact);
linphone_address_destroy(contact);
}
}
}

View file

@ -2873,17 +2873,21 @@ bool_t linphone_core_inc_invite_pending(LinphoneCore*lc){
return FALSE;
}
bool_t linphone_core_incompatible_security(LinphoneCore *lc, SalMediaDescription *md){
if (linphone_core_is_media_encryption_mandatory(lc) && linphone_core_get_media_encryption(lc)==LinphoneMediaEncryptionSRTP){
int i;
for(i=0;i<md->n_active_streams;i++){
SalStreamDescription *sd=&md->streams[i];
if (sd->proto!=SalProtoRtpSavp){
return TRUE;
}
bool_t linphone_core_media_description_has_srtp(const SalMediaDescription *md){
int i;
if (md->n_active_streams==0) return FALSE;
for(i=0;i<md->n_active_streams;i++){
const SalStreamDescription *sd=&md->streams[i];
if (sd->proto!=SalProtoRtpSavp){
return FALSE;
}
}
return FALSE;
return TRUE;
}
bool_t linphone_core_incompatible_security(LinphoneCore *lc, SalMediaDescription *md){
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){
@ -2899,7 +2903,7 @@ void linphone_core_notify_incoming_call(LinphoneCore *lc, LinphoneCall *call){
md=sal_call_get_final_media_description(call->op);
if (md){
if (sal_media_description_empty(md) || linphone_core_incompatible_security(lc,md)){
sal_call_decline(call->op,SalReasonMedia,NULL);
sal_call_decline(call->op,SalReasonNotAcceptable,NULL);
linphone_call_stop_media_streams(call);
linphone_core_del_call(lc,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");
new_md=sal_call_get_final_media_description(call->op);
linphone_core_update_streams(lc, call, new_md);
linphone_call_fix_call_parameters(call);
if (new_md){
linphone_call_set_state(call,LinphoneCallStreamsRunning,"Connected (streams running)");
}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){
return lp_config_get_int(lc->config,"rtp","video_dscp",0x2e);
return lp_config_get_int(lc->config,"rtp","video_dscp",0);
}

View file

@ -23,6 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "ortp/payloadtype.h"
#include "mediastreamer2/mscommon.h"
#include "mediastreamer2/msvideo.h"
#include "mediastreamer2/mediastream.h"
#ifdef IN_LINPHONE
#include "sipsetup.h"
@ -32,9 +33,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "lpconfig.h"
#include <belle-sip/object.h>
#include <belle-sip/dict.h>
#define LINPHONE_IPADDR_SIZE 64
#define LINPHONE_HOSTNAME_SIZE 128
@ -94,6 +92,7 @@ typedef struct _LCSipTransports{
/**
* Enum describing transport type for LinphoneAddress.
* @ingroup linphone_address
**/
enum _LinphoneTransportType{
LinphoneTransportUdp,
@ -103,6 +102,10 @@ enum _LinphoneTransportType{
};
/*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;
/**
@ -166,7 +169,7 @@ enum _LinphoneReason{
LinphoneReasonNotFound, /**<Destination of the calls was not found.*/
LinphoneReasonNotAnswered, /**<The call was not answered in time*/
LinphoneReasonBusy, /**<Phone line was busy */
LinphoneReasonMedia, /**<Incompatible media */
LinphoneReasonUnsupportedContent, /**<Unsupported content */
LinphoneReasonIOError, /**<Transport error: connection failures, disconnections etc...*/
LinphoneReasonDoNotDisturb, /**<Do not disturb reason*/
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*/
};
/*for compatibility*/
#define LinphoneReasonMedia LinphoneReasonUnsupportedContent
/**
* Enum describing failure reasons.
* @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_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 */
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_start_recording(LinphoneCall *call);
LINPHONE_PUBLIC void linphone_call_stop_recording(LinphoneCall *call);
/**
* Return TRUE if this call is currently part of a conference
* @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_delete_message(LinphoneChatRoom *cr, LinphoneChatMessage *msg);
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 LinphoneCore* linphone_chat_room_get_lc(LinphoneChatRoom *cr);
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);
/**
* 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.
* @param lc the linphone core
@ -1179,6 +1212,7 @@ typedef struct _LinphoneCoreVTable{
LinphoneCoreAuthInfoRequestedCb auth_info_requested; /**< Ask the application some authentication information */
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*/
LinphoneCoreIsComposingReceivedCb is_composing_received; /**< An is-composing notification has been received */
LinphoneCoreDtmfReceivedCb dtmf_received; /**< A dtmf has been received received */
LinphoneCoreReferReceivedCb refer_received; /**< An out of call refer was received */
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 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
*/

View file

@ -170,6 +170,7 @@ public:
vTable.call_encryption_changed = callEncryptionChange;
vTable.text_received = text_received;
vTable.message_received = message_received;
vTable.is_composing_received = is_composing_received;
vTable.dtmf_received = dtmf_received;
vTable.new_subscription_requested = new_subscription_requested;
vTable.notify_presence_received = notify_presence_received;
@ -225,6 +226,7 @@ public:
/*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");
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");
infoReceivedId = env->GetMethodID(listenerClass,"infoReceived",
"(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCall;Lorg/linphone/core/LinphoneInfoMessage;)V");
@ -307,6 +309,7 @@ public:
jmethodID notifyPresenceReceivedId;
jmethodID textReceivedId;
jmethodID messageReceivedId;
jmethodID isComposingReceivedId;
jmethodID dtmfReceivedId;
jmethodID callStatsUpdatedId;
jmethodID transferStateId;
@ -550,6 +553,19 @@ public:
,env->NewObject(lcData->chatRoomClass,lcData->chatRoomCtrId,(jlong)room)
,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) {
JNIEnv *env = 0;
jint result = jvm->AttachCurrentThread(&env,NULL);
@ -2311,6 +2327,12 @@ extern "C" void Java_org_linphone_core_LinphoneChatRoomImpl_deleteHistory(JNIEnv
,jlong 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
,jobject thiz
,jlong room

View file

@ -1239,16 +1239,16 @@ SalReason linphone_reason_to_sal(LinphoneReason reason){
return SalReasonTemporarilyUnavailable;
case LinphoneReasonBusy:
return SalReasonBusy;
case LinphoneReasonMedia:
return SalReasonMedia;
case LinphoneReasonNotAcceptable:
return SalReasonNotAcceptable;
case LinphoneReasonIOError:
return SalReasonServiceUnavailable;
case LinphoneReasonDoNotDisturb:
return SalReasonDoNotDisturb;
case LinphoneReasonUnauthorized:
return SalReasonUnauthorized;
case LinphoneReasonNotAcceptable:
return SalReasonNotAcceptable;
case LinphoneReasonUnsupportedContent:
return SalReasonUnsupportedContent;
case LinphoneReasonNoMatch:
return SalReasonNoMatch;
}
@ -1273,8 +1273,8 @@ LinphoneReason linphone_reason_from_sal(SalReason r){
case SalReasonForbidden:
ret=LinphoneReasonBadCredentials;
break;
case SalReasonMedia:
ret=LinphoneReasonMedia;
case SalReasonNotAcceptable:
ret=LinphoneReasonNotAcceptable;
break;
case SalReasonNotFound:
ret=LinphoneReasonNotFound;
@ -1294,8 +1294,8 @@ LinphoneReason linphone_reason_from_sal(SalReason r){
case SalReasonUnauthorized:
ret=LinphoneReasonUnauthorized;
break;
case SalReasonNotAcceptable:
ret=LinphoneReasonNotAcceptable;
case SalReasonUnsupportedContent:
ret=LinphoneReasonUnsupportedContent;
break;
case SalReasonNoMatch:
ret=LinphoneReasonNoMatch;

View file

@ -22,15 +22,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "lpconfig.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);
@ -83,13 +74,6 @@ struct _LinphonePresenceModel {
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";
@ -98,38 +82,6 @@ static const char *person_prefix = "/pidf:presence/dm:person";
* 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 * generate_presence_id(void) {
@ -1183,45 +1135,6 @@ void * linphone_presence_note_get_user_data(LinphonePresenceNote *note) {
* 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 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;
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)) {
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);
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;
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);
presence_service_add_note(service, note);
if (lang != NULL) free_xml_text_content(lang);
free_xml_text_content(note_str);
if (lang != NULL) linphone_free_xml_text_content(lang);
linphone_free_xml_text_content(note_str);
}
}
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;
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)) {
for (i = 1; i <= service_object->nodesetval->nodeNr; 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)
continue;
@ -1278,33 +1191,33 @@ static int process_pidf_xml_presence_services(xmlparsing_context_t *xml_ctx, Lin
basic_status = LinphonePresenceBasicStatusClosed;
} else {
/* Invalid value for basic status. */
free_xml_text_content(basic_status_str);
linphone_free_xml_text_content(basic_status_str);
return -1;
}
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);
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);
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);
if (service != NULL) {
if (timestamp_str != NULL) {
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) {
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);
linphone_presence_model_add_service(model, service);
}
free_xml_text_content(basic_status_str);
if (service_id_str != NULL) free_xml_text_content(service_id_str);
linphone_free_xml_text_content(basic_status_str);
if (service_id_str != NULL) linphone_free_xml_text_content(service_id_str);
}
}
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;
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)) {
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);
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)) {
for (j = 0; j < activities_object->nodesetval->nodeNr; 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;
description = (const char *)xmlNodeGetContent(activity_node);
if ((description != NULL) && (description[0] == '\0')) {
free_xml_text_content(description);
linphone_free_xml_text_content(description);
description = NULL;
}
err = activity_name_to_presence_activity_type((const char *)activity_node->name, &acttype);
if (err < 0) break;
activity = linphone_presence_activity_new(acttype, description);
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;
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)) {
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);
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;
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);
presence_person_add_activities_note(person, note);
if (lang != NULL) free_xml_text_content(lang);
free_xml_text_content(note_str);
if (lang != NULL) linphone_free_xml_text_content(lang);
linphone_free_xml_text_content(note_str);
}
}
if (note_object != NULL) xmlXPathFreeObject(note_object);
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)) {
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);
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;
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);
presence_person_add_note(person, note);
if (lang != NULL) free_xml_text_content(lang);
free_xml_text_content(note_str);
if (lang != NULL) linphone_free_xml_text_content(lang);
linphone_free_xml_text_content(note_str);
}
}
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 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)) {
for (i = 1; i <= person_object->nodesetval->nodeNr; 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);
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)
timestamp = time(NULL);
else
@ -1446,8 +1359,8 @@ static int process_pidf_xml_presence_persons(xmlparsing_context_t *xml_ctx, Linp
break;
}
}
if (person_id_str != NULL) free_xml_text_content(person_id_str);
if (person_timestamp_str != NULL) free_xml_text_content(person_timestamp_str);
if (person_id_str != NULL) linphone_free_xml_text_content(person_id_str);
if (person_timestamp_str != NULL) linphone_free_xml_text_content(person_timestamp_str);
}
}
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;
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)) {
for (i = 1; i <= note_object->nodesetval->nodeNr; 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;
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);
presence_model_add_note(model, note);
if (lang != NULL) free_xml_text_content(lang);
free_xml_text_content(note_str);
if (lang != NULL) linphone_free_xml_text_content(lang);
linphone_free_xml_text_content(note_str);
}
}
if (note_object != NULL) xmlXPathFreeObject(note_object);
@ -1491,7 +1404,7 @@ static LinphonePresenceModel * process_pidf_xml_presence_notification(xmlparsing
LinphonePresenceModel *model = NULL;
int err;
if (create_xml_xpath_context(xml_ctx) < 0)
if (linphone_create_xml_xpath_context(xml_ctx) < 0)
return NULL;
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) {
xml_ctx = xmlparsing_context_new();
xmlSetGenericErrorFunc(xml_ctx, xmlparsing_genericxml_error);
xml_ctx = linphone_xmlparsing_context_new();
xmlSetGenericErrorFunc(xml_ctx, linphone_xmlparsing_genericxml_error);
xml_ctx->doc = xmlReadDoc((const unsigned char*)body, 0, NULL, 0);
if (xml_ctx->doc != NULL) {
model = process_pidf_xml_presence_notification(xml_ctx);
} else {
ms_warning("Wrongly formatted presence XML: %s", xml_ctx->errorBuffer);
}
xmlparsing_context_destroy(xml_ctx);
linphone_xmlparsing_context_destroy(xml_ctx);
} else {
ms_error("Unknown content type '%s/%s' for presence", content_type, content_subtype);
}

View file

@ -34,6 +34,9 @@ extern "C" {
#include "sal/sal.h"
#include "sipsetup.h"
#include <belle-sip/object.h>
#include <belle-sip/dict.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@ -201,22 +204,22 @@ struct _LinphoneCall
LinphoneCall *referer; /*when this call is the result of a transfer, referer is set to the original call that caused the transfer*/
LinphoneCall *transfer_target;/*if this call received a transfer request, then transfer_target points to the new call created to the refer target */
int localdesc_changed;
bool_t refer_pending;
bool_t media_pending;
bool_t audio_muted;
bool_t camera_enabled;
bool_t all_muted; /*this flag is set during early medias*/
bool_t playing_ringbacktone;
bool_t owns_call_log;
bool_t ringing_beep; /* whether this call is ringing through an already existent current call*/
bool_t videostream_encrypted;
bool_t audiostream_encrypted;
bool_t auth_token_verified;
bool_t defer_update;
bool_t was_automatically_paused;
bool_t ping_replied;
bool_t record_active;
@ -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_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_has_srtp(const SalMediaDescription *md);
void linphone_core_send_initial_subscribes(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);
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);
@ -379,9 +384,9 @@ LinphoneProxyConfig * is_a_linphone_proxy_config(void *user_pointer);
static const int linphone_proxy_config_magic=0x7979;
/*chat*/
/*chat*/
void linphone_chat_message_destroy(LinphoneChatMessage* msg);
/**/
/**/
struct _LinphoneProxyConfig
{
@ -426,16 +431,26 @@ struct _LinphoneAuthInfo
bool_t works;
};
typedef enum _LinphoneIsComposingState {
LinphoneIsComposingIdle,
LinphoneIsComposingActive
} LinphoneIsComposingState;
struct _LinphoneChatRoom{
struct _LinphoneCore *lc;
char *peer;
LinphoneAddress *peer_url;
void * user_data;
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;
};
struct _LinphoneFriend{
LinphoneAddress *uri;
SalOp *insub;
@ -487,7 +502,7 @@ typedef struct rtp_config
int nortp_timeout;
int disable_upnp;
bool_t rtp_no_xmit_on_audio_mute;
/* stop rtp xmit when audio muted */
/* stop rtp xmit when audio muted */
bool_t audio_adaptive_jitt_comp_enabled;
bool_t video_adaptive_jitt_comp_enabled;
bool_t pad;
@ -633,12 +648,12 @@ struct _LinphoneCore
bool_t apply_nat_settings;
bool_t initial_subscribes_sent;
bool_t bl_refresh;
bool_t preview_finished;
bool_t auto_net_state_mon;
bool_t network_reachable;
bool_t use_preview_window;
time_t network_last_check;
bool_t network_last_status;
@ -788,6 +803,46 @@ LinphoneSubscriptionState linphone_subscription_state_from_sal(SalSubscribeStatu
const LinphoneContent *linphone_content_from_sal_body(LinphoneContent *obj, const SalBody *ref);
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
}
#endif

View file

@ -530,7 +530,7 @@ const char* sal_reason_to_string(const SalReason reason) {
case SalReasonTemporarilyUnavailable: return "SalReasonTemporarilyUnavailable";
case SalReasonNotFound: return "SalReasonNotFound";
case SalReasonDoNotDisturb: return "SalReasonDoNotDisturb";
case SalReasonMedia: return "SalReasonMedia";
case SalReasonUnsupportedContent: return "SalReasonUnsupportedContent";
case SalReasonForbidden: return "SalReasonForbidden";
case SalReasonUnknown: return "SalReasonUnknown";
case SalReasonServiceUnavailable: return "SalReasonServiceUnavailable";

98
coreapi/xml.c Normal file
View 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);
}

View file

@ -279,6 +279,16 @@ static void on_chat_state_changed(LinphoneChatMessage *msg, LinphoneChatMessageS
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(){
GtkWidget *main_window=linphone_gtk_get_main_window();
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_gtk_push_text(w,linphone_chat_message_get_from(msg),
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),"");
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);
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),"changed",(GCallback)linphone_gtk_compose_text,NULL);
g_signal_connect(G_OBJECT(notebook),"switch_page",(GCallback)linphone_gtk_notebook_tab_select,NULL);
ms_free(with_str);
return chat_view;
@ -417,7 +432,7 @@ GtkWidget* linphone_gtk_init_chatroom(LinphoneChatRoom *cr, const LinphoneAddres
LinphoneChatRoom * linphone_gtk_create_chatroom(const LinphoneAddress *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);
return cr;
}
@ -516,3 +531,7 @@ void linphone_gtk_text_received ( LinphoneCore *lc, LinphoneChatRoom *room,
linphone_gtk_show_friends();
}
void linphone_gtk_is_composing_received(LinphoneCore *lc, LinphoneChatRoom *room) {
linphone_gtk_friend_list_update_chat_picture();
}

View file

@ -87,6 +87,18 @@ static GdkPixbuf *create_chat_picture(){
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){
GtkTreeIter iter;
@ -227,15 +239,23 @@ void linphone_gtk_friend_list_update_chat_picture(){
GtkWidget *friendlist=linphone_gtk_get_widget(w,"contact_list");
GtkTreeModel *model=gtk_tree_view_get_model(GTK_TREE_VIEW(friendlist));
LinphoneChatRoom *cr=NULL;
bool_t is_composing;
int nbmsg=0;
if (gtk_tree_model_get_iter_first(model,&iter)) {
do{
gtk_tree_model_get (model, &iter,FRIEND_CHATROOM , &cr, -1);
nbmsg=linphone_chat_room_get_unread_messages_count(cr);
is_composing=linphone_chat_room_is_remote_composing(cr);
if(nbmsg != 0){
gtk_list_store_set(GTK_LIST_STORE(model),&iter,FRIEND_CHAT,create_unread_msg(),-1);
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);
} else {
gtk_list_store_set(GTK_LIST_STORE(model),&iter,FRIEND_CHAT,create_chat_picture(),-1);
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);
}
}while(gtk_tree_model_iter_next(model,&iter));
}

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk+" version="2.24"/>
<requires lib="gtk+" version="2.16"/>
<!-- interface-naming-policy project-wide -->
<object class="GtkWindow" id="ldap">
<property name="can_focus">False</property>

View file

@ -116,6 +116,7 @@ void linphone_gtk_send_text();
GtkWidget * linphone_gtk_init_chatroom(LinphoneChatRoom *cr, 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_is_composing_received(LinphoneCore *lc, LinphoneChatRoom *room);
void linphone_gtk_friend_list_update_chat_picture();
void linphone_gtk_friend_list_set_chat_conversation(const LinphoneAddress *la);

View file

@ -266,6 +266,7 @@ static void linphone_gtk_init_liblinphone(const char *config_file,
vtable.call_log_updated=linphone_gtk_call_log_updated;
//vtable.text_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.buddy_info_updated=linphone_gtk_buddy_info_updated;
vtable.call_encryption_changed=linphone_gtk_call_encryption_changed;
@ -846,7 +847,7 @@ static gboolean launch_contact_provider_search(void *userdata)
);
if(search)
belle_sip_object_ref(search);
linphone_contact_search_ref(search);
}
return FALSE;
}

View file

@ -32,6 +32,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "mediastreamer2/mscommon.h"
#include "ortp/ortp_srtp.h"
#include "belle-sip/belle-sip.h"
#ifndef LINPHONE_PUBLIC
#define LINPHONE_PUBLIC MS2_PUBLIC
@ -224,6 +225,11 @@ typedef struct SalMessage{
time_t time;
}SalMessage;
typedef struct SalIsComposing {
const char *from;
const char *text;
} SalIsComposing;
#define SAL_MEDIA_DESCRIPTION_MAX_MESSAGE_ATTRIBUTES 5
SalMediaDescription *sal_media_description_new();
@ -241,11 +247,7 @@ typedef struct SalOpBase{
Sal *root;
char *route; /*or request-uri for REGISTER*/
MSList* route_addresses; /*list of SalAddress* */
#ifndef USE_BELLESIP
char *contact;
#else
SalAddress* contact_address;
#endif
char *from;
SalAddress* from_address;
char *to;
@ -279,7 +281,7 @@ typedef enum SalReason{
SalReasonTemporarilyUnavailable,
SalReasonNotFound,
SalReasonDoNotDisturb,
SalReasonMedia,
SalReasonUnsupportedContent,
SalReasonForbidden,
SalReasonUnknown,
SalReasonServiceUnavailable,
@ -390,6 +392,7 @@ typedef void (*SalOnDtmfReceived)(SalOp *op, char dtmf);
typedef void (*SalOnRefer)(Sal *sal, SalOp *op, const char *referto);
typedef void (*SalOnTextReceived)(SalOp *op, const SalMessage *msg);
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 (*SalOnSubscribeResponse)(SalOp *op, SalSubscribeStatus status, SalError error, SalReason reason);
typedef void (*SalOnNotify)(SalOp *op, SalSubscribeStatus status, const char *event, const SalBody *body);
@ -425,6 +428,7 @@ typedef struct SalCallbacks{
SalOnRefer refer_received;
SalOnTextReceived text_received;
SalOnTextDeliveryUpdate text_delivery_update;
SalOnIsComposingReceived is_composing_received;
SalOnNotifyRefer notify_refer;
SalOnSubscribeReceived subscribe_received;
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 const char *sal_get_dns_user_hosts_file(const Sal *sal);
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);
/*this function parses a document with key=value pairs separated by new lines, and extracts the value for a given key*/

View file

@ -80,6 +80,17 @@ public interface LinphoneChatRoom {
* Deletes all the messages associated with the peer of this chat room
*/
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

View file

@ -91,6 +91,13 @@ public interface LinphoneCoreListener {
*/
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
* @param lc LinphoneCore

View file

@ -31,6 +31,8 @@ class LinphoneChatRoomImpl implements LinphoneChatRoom {
private native void destroy(long ptr);
private native int getUnreadMessagesCount(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 deleteMessage(long room, long message);
private native void updateUrl(long room, long message);
@ -87,6 +89,14 @@ class LinphoneChatRoomImpl implements LinphoneChatRoom {
public void deleteHistory() {
deleteHistory(nativePtr);
}
public void compose() {
compose(nativePtr);
}
public boolean isRemoteComposing() {
return isRemoteComposing(nativePtr);
}
public void markAsRead() {
markAsRead(nativePtr);

View file

@ -53,7 +53,7 @@ Libraries and headers required to develop software with linphone.
%if !%{video}
--disable-video \
%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}

@ -1 +1 @@
Subproject commit 4103f0b1d7757558d06e6e32b657308bb2556c9b
Subproject commit ce1127bbf74a1bc1113a048195db3cf2ed49c946

2
oRTP

@ -1 +1 @@
Subproject commit 37b81a118760caa22a5a89d56945acea9aa52523
Subproject commit d4241929983c8f0114f8de04dca6ecbc42b9607e

View file

@ -11,7 +11,7 @@ status-orange.png \
status-red.png \
status-offline.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\
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 \

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
pixmaps/composing_chat.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

View file

@ -27,6 +27,7 @@ gtk/loginframe.c
[type: gettext/glade]gtk/call_statistics.ui
[type: gettext/glade]gtk/tunnel_config.ui
[type: gettext/glade]gtk/keypad.ui
[type: gettext/glade]gtk/ldap.ui
coreapi/linphonecore.c
coreapi/misc.c
coreapi/presence.c

17
share/CMakeLists.txt Normal file
View 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)

View 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)

View file

@ -23,11 +23,11 @@ liblinphone_tester_SOURCES= liblinphone_tester.c liblinphone_tester.h\
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_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
./liblinphone_tester --config $(abs_srcdir)

View file

@ -331,9 +331,9 @@ static void call_failed_because_of_codecs(void) {
linphone_call_ref(out_call);
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_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);
linphone_call_unref(out_call);
@ -1387,6 +1387,41 @@ static void call_established_with_rejected_reinvite(void) {
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) {
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
@ -1399,8 +1434,8 @@ static void call_established_with_rejected_reinvite_with_error(void) {
sal_enable_unconditional_answer(marie->lc->sal,TRUE);
linphone_core_update_call( pauline->lc
,linphone_core_get_current_call(pauline->lc)
,linphone_call_get_current_params(linphone_core_get_current_call(pauline->lc)));
,linphone_core_get_current_call(pauline->lc)
,linphone_call_get_current_params(linphone_core_get_current_call(pauline->lc)));
CU_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&pauline->stat.number_of_LinphoneCallStreamsRunning,2));
@ -1460,6 +1495,7 @@ test_t call_tests[] = {
{ "Call with custom headers",call_with_custom_headers},
{ "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 incoming RE-INVITE", call_established_with_rejected_incoming_reinvite },
{ "Call established with rejected RE-INVITE in error", call_established_with_rejected_reinvite_with_error}
};

View file

@ -136,9 +136,11 @@ bool_t wait_for_until(LinphoneCore* lc_1, LinphoneCore* lc_2,int* counter,int va
ms_list_free(lcs);
return result;
}
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);
}
bool_t wait_for_list(MSList* lcs,int* counter,int value,int timeout_ms) {
int retry=0;
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.text_received=text_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.notify_presence_received=notify_presence_received;
mgr->v_table.transfer_state_changed=linphone_transfer_state_changed;

View file

@ -117,7 +117,8 @@ typedef struct _stats {
int number_of_LinphoneMessageInProgress;
int number_of_LinphoneMessageDelivered;
int number_of_LinphoneMessageNotDelivered;
int number_of_LinphoneIsComposingActiveReceived;
int number_of_LinphoneIsComposingIdleReceived;
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 text_message_received(LinphoneCore *lc, LinphoneChatRoom *room, const LinphoneAddress *from_address, const char *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 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);

View file

@ -5,6 +5,7 @@ sip_tls_port=5083
default_proxy=0
ping_with_options=0
register_only_when_network_is_up=0
composing_idle_timeout=1
[auth_info_0]
username=marie

View file

@ -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) {
LinphoneCore* lc=(LinphoneCore*)ud;
stats* counters = get_stats(lc);
@ -264,6 +273,24 @@ static void info_message_with_body(){
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[] = {
{ "Text message", text_message },
{ "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 external body", text_message_with_external_body },
{ "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 = {

View file

@ -5,6 +5,7 @@ sip_tls_port=5073
default_proxy=0
ping_with_options=0
register_only_when_network_is_up=0
composing_idle_timeout=1
[auth_info_0]
username=pauline