Merge remote-tracking branch 'linphone/master'
Conflicts: .gitignore Makefile.am mediastreamer2 oRTP
19
.cproject
|
|
@ -22,7 +22,7 @@
|
|||
<folderInfo id="0.2079208171." name="/" resourcePath="">
|
||||
<toolChain id="org.eclipse.cdt.build.core.prefbase.toolchain.2084203071" name="No ToolChain" resourceTypeBasedDiscovery="false" superClass="org.eclipse.cdt.build.core.prefbase.toolchain">
|
||||
<targetPlatform binaryParser="org.eclipse.cdt.core.MachO64;org.eclipse.cdt.core.ELF" id="org.eclipse.cdt.build.core.prefbase.toolchain.2084203071.81924294" name=""/>
|
||||
<builder arguments="CFLAGS="-g -Werror -Wall" CXXFLAGS="-g"" command="make" id="org.eclipse.cdt.build.core.settings.default.builder.731584538" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="org.eclipse.cdt.build.core.settings.default.builder"/>
|
||||
<builder arguments="-j4 CFLAGS="-g -Wall -Qunused-arguments" CXXFLAGS="-g"" command="make" id="org.eclipse.cdt.build.core.settings.default.builder.731584538" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="org.eclipse.cdt.build.core.settings.default.builder"/>
|
||||
<tool id="org.eclipse.cdt.build.core.settings.holder.libs.1252970003" name="holder for library settings" superClass="org.eclipse.cdt.build.core.settings.holder.libs"/>
|
||||
<tool id="org.eclipse.cdt.build.core.settings.holder.1371414073" name="GNU C++" superClass="org.eclipse.cdt.build.core.settings.holder">
|
||||
<inputType id="org.eclipse.cdt.build.core.settings.holder.inType.306286573" languageId="org.eclipse.cdt.core.g++" languageName="GNU C++" sourceContentType="org.eclipse.cdt.core.cxxSource,org.eclipse.cdt.core.cxxHeader" superClass="org.eclipse.cdt.build.core.settings.holder.inType"/>
|
||||
|
|
@ -35,9 +35,12 @@
|
|||
</tool>
|
||||
</toolChain>
|
||||
</folderInfo>
|
||||
<fileInfo id="0.2079208171.129489708" name="mediastreamer-config.h" rcbsApplicability="disable" resourcePath="mediastreamer2/mediastreamer-config.h" toolsToInvoke="org.eclipse.cdt.build.core.settings.holder.1371414073.1809017452">
|
||||
<tool id="org.eclipse.cdt.build.core.settings.holder.1371414073.1809017452" name="GNU C++" superClass="org.eclipse.cdt.build.core.settings.holder.1371414073"/>
|
||||
</fileInfo>
|
||||
<fileInfo id="0.2079208171.2090246372" name="ringback.wav" rcbsApplicability="disable" resourcePath="tester/sounds/ringback.wav" toolsToInvoke=""/>
|
||||
<sourceEntries>
|
||||
<entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="coreapi"/>
|
||||
<entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="gtk"/>
|
||||
<entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="tester"/>
|
||||
</sourceEntries>
|
||||
</configuration>
|
||||
</storageModule>
|
||||
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
|
||||
|
|
@ -48,8 +51,10 @@
|
|||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
<project id="linphone.null.1149313048" name="linphone"/>
|
||||
</storageModule>
|
||||
<storageModule moduleId="refreshScope" versionNumber="1">
|
||||
<resource resourceType="PROJECT" workspacePath="/linphone"/>
|
||||
<storageModule moduleId="refreshScope" versionNumber="2">
|
||||
<configuration configurationName="Default">
|
||||
<resource resourceType="PROJECT" workspacePath="/linphone"/>
|
||||
</configuration>
|
||||
</storageModule>
|
||||
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets">
|
||||
<buildTargets>
|
||||
|
|
@ -198,4 +203,6 @@
|
|||
</profile>
|
||||
</scannerConfigBuildInfo>
|
||||
</storageModule>
|
||||
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
|
||||
<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
|
||||
</cproject>
|
||||
|
|
|
|||
16
.gitignore
vendored
|
|
@ -52,14 +52,24 @@ coreapi/help/registration
|
|||
coreapi/test_ecc
|
||||
coreapi/test_lsd
|
||||
gtk/version_date.h
|
||||
|
||||
daemon/linphone-daemon
|
||||
daemon/linphone-daemon-pipetest
|
||||
tools/lpc2xml_test
|
||||
tools/xml2lpc_test
|
||||
*.la
|
||||
*.lo
|
||||
*.deps
|
||||
*.libs
|
||||
share/certdata.txt
|
||||
coreapi/test_numbers
|
||||
specs.c
|
||||
*.orig
|
||||
*.rej
|
||||
*.kdev4
|
||||
*.swp
|
||||
.deps
|
||||
.libs
|
||||
coreapi/help/notify
|
||||
share/fresh-rootca.pem
|
||||
tester/liblinphone_tester
|
||||
tools/lp-gen-wrappers
|
||||
tools/lpc2xml_test
|
||||
tools/xml2lpc_test
|
||||
2
.project
|
|
@ -23,7 +23,7 @@
|
|||
</dictionary>
|
||||
<dictionary>
|
||||
<key>org.eclipse.cdt.make.core.buildArguments</key>
|
||||
<value>CFLAGS="-g -Werror -Wall" CXXFLAGS="-g"</value>
|
||||
<value>CFLAGS="-g -Werror -Wall" CXXFLAGS="-g" V=1</value>
|
||||
</dictionary>
|
||||
<dictionary>
|
||||
<key>org.eclipse.cdt.make.core.buildCommand</key>
|
||||
|
|
|
|||
12
COPYING
|
|
@ -55,8 +55,8 @@ patent must be licensed for everyone's free use or not licensed at all.
|
|||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
|
|
@ -110,7 +110,7 @@ above, provided that you also meet all of these conditions:
|
|||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
|
|
@ -168,7 +168,7 @@ access to copy from a designated place, then offering equivalent
|
|||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
|
|
@ -225,7 +225,7 @@ impose that choice.
|
|||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
|
|
@ -278,7 +278,7 @@ PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
|||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
|
|
|
|||
33
Makefile.am
|
|
@ -4,8 +4,7 @@
|
|||
ACLOCAL_AMFLAGS = -I m4 $(ACLOCAL_MACOS_FLAGS)
|
||||
|
||||
SUBDIRS = build m4 pixmaps po @ORTP_DIR@ @MS2_DIR@ \
|
||||
coreapi console gtk share scripts tools daemon
|
||||
|
||||
coreapi console gtk share scripts tools daemon tester include
|
||||
|
||||
|
||||
ACLOCAL_FLAGS=-I$(top_srcdir)/m4
|
||||
|
|
@ -37,7 +36,7 @@ SDK_EXCLUDED= \
|
|||
|
||||
GTK_PREFIX=/
|
||||
GTK_THEME=Outcrop
|
||||
GTK_FILELIST=gtk+-2.22.1.filelist
|
||||
GTK_FILELIST=gtk+-2.24.8.filelist
|
||||
GTK_FILELIST_PATH=$(abs_top_srcdir)/$(GTK_FILELIST)
|
||||
LINPHONEDEPS_FILELIST=linphone-deps.filelist
|
||||
WINBINDIST_FILES=`cat $(abs_top_srcdir)/$(LINPHONEDEPS_FILELIST)`
|
||||
|
|
@ -101,31 +100,33 @@ endif
|
|||
other-cherrypick:
|
||||
cd $(GTK_PREFIX) && \
|
||||
for file in $(WINBINDIST_FILES) ; do \
|
||||
if test -d $$file; then \
|
||||
if test -d $(prefix)/$$file; then \
|
||||
$(MKDIR_P) $(INSTALLDIR_WITH_PREFIX)/$$file ;\
|
||||
else \
|
||||
cp $$file $(INSTALLDIR_WITH_PREFIX)/$$file ;\
|
||||
cp $(prefix)/$$file $(INSTALLDIR_WITH_PREFIX)/$$file ;\
|
||||
fi \
|
||||
done
|
||||
cp /mingw/bin/libgcc_s*.dll \
|
||||
/mingw/bin/libstdc++-6.dll \
|
||||
/mingw/bin/libintl-8.dll \
|
||||
/mingw/bin/libiconv-2.dll \
|
||||
/mingw/bin/pthreadGC2.dll \
|
||||
$(INSTALLDIR_WITH_PREFIX)/bin/.
|
||||
if test -d /mingw/bin ; then \
|
||||
cp /mingw/bin/libgcc_s*.dll \
|
||||
/mingw/bin/libstdc++-6.dll \
|
||||
/mingw/bin/libintl-8.dll \
|
||||
/mingw/bin/libiconv-2.dll \
|
||||
/mingw/bin/pthreadGC2.dll \
|
||||
$(INSTALLDIR_WITH_PREFIX)/bin/. ;\
|
||||
fi
|
||||
|
||||
|
||||
gtk-cherrypick:
|
||||
cd $(GTK_PREFIX) && \
|
||||
for file in `cat $(GTK_FILELIST_PATH)` ; do \
|
||||
if test -d $$file; then \
|
||||
if test -d $(prefix)/$$file; then \
|
||||
$(MKDIR_P) $(INSTALLDIR_WITH_PREFIX)/$$file ;\
|
||||
else \
|
||||
cp $$file $(INSTALLDIR_WITH_PREFIX)/$$file ;\
|
||||
cp $(prefix)/$$file $(INSTALLDIR_WITH_PREFIX)/$$file ;\
|
||||
fi \
|
||||
done && \
|
||||
$(MKDIR_P) $(INSTALLDIR_WITH_PREFIX)/share/themes && \
|
||||
cp -rf share/themes/$(GTK_THEME) $(INSTALLDIR_WITH_PREFIX)/share/themes/.
|
||||
cp -rf $(prefix)/share/themes/$(GTK_THEME) $(INSTALLDIR_WITH_PREFIX)/share/themes/.
|
||||
|
||||
zip:
|
||||
rm -f $(ZIPFILE)
|
||||
|
|
@ -230,6 +231,6 @@ bundle: $(LIBICONV_HACK)
|
|||
clean-local:
|
||||
rm -rf $(BUNDLEDIR)
|
||||
discovery:
|
||||
touch specs.cpp
|
||||
touch specs.c
|
||||
$(CC) --include $(top_builddir)/config.h \
|
||||
$(TUNNEL_CFLAGS) $(CFLAGS) $(MEDIASTREAMER2_CFLAGS) $(ORTP_CFLAGS) -E -P -v -dD specs.cpp
|
||||
$(TUNNEL_CFLAGS) $(CFLAGS) $(MEDIASTREAMER2_CFLAGS) $(ORTP_CFLAGS) $(SIPSTACK_CFLAGS) $(CUNIT_CFLAGS) -E -P -v -dD specs.c
|
||||
|
|
|
|||
14
NEWS
|
|
@ -1,3 +1,17 @@
|
|||
linphone-3.7...??
|
||||
Liblinphone level improvements thanks to belle-sip new SIP stack:
|
||||
* multiple SIP transports simualtaneously now allowed
|
||||
* IP dual stack: can use IPv6 and IPv4 simultaneously
|
||||
* fully asynchronous behavior: no more lengthly DNS or connections
|
||||
* +sip.instance parameter (RFC5626)
|
||||
* alias parameter (RFC5923)
|
||||
* better management of network disconnections
|
||||
* SIP/TLS handled through lightweighted polarssl library (instead of openssl)
|
||||
* SIP transaction state machines improved (RFC6026)
|
||||
* Privacy API (RFC3323, RFC3325)
|
||||
* Full support of rich presence in (RFC4480)
|
||||
|
||||
|
||||
linphone-3.6.1 -- June 17, 2013
|
||||
* fix memory leak with some video cameras on windows.
|
||||
|
||||
|
|
|
|||
10
README
|
|
@ -8,9 +8,9 @@ This is Linphone, a free (GPL) video softphone based on the SIP protocol.
|
|||
- intltool
|
||||
|
||||
- you need at least:
|
||||
- libosip2>=3.5.0
|
||||
- libeXosip2>=3.5.0
|
||||
- belle-sip>=1.0.0
|
||||
- speex>=1.2.0 (including libspeexdsp part)
|
||||
- libxml2
|
||||
|
||||
+ if you want the gtk/glade interface:
|
||||
- libgtk >=2.16.0
|
||||
|
|
@ -33,11 +33,11 @@ This is Linphone, a free (GPL) video softphone based on the SIP protocol.
|
|||
|
||||
Here is the command line to get these dependencies installed for Ubuntu && Debian
|
||||
|
||||
$ sudo apt-get install libtool intltool libgtk2.0-dev libosip2-dev libexosip2-dev libspeexdsp-dev libavcodec-dev libswscale-dev libx11-dev libvxl1-dev libgl1-mesa-dev libglew1.6-dev libv4l-dev
|
||||
$ sudo apt-get install libtool intltool libgtk2.0-dev libosip2-dev libexosip2-dev libspeexdsp-dev libavcodec-dev libswscale-dev libx11-dev libxv-dev libgl1-mesa-dev libglew1.6-dev libv4l-dev libxml2-dev
|
||||
|
||||
+ for optional library
|
||||
$ sudo apt-get install libreadline-dev libgsm1-dev libtheora-dev libsoup2.4-dev libsqlite3-dev libupnp4-dev
|
||||
|
||||
$ sudo apt-get install libreadline-dev libgsm1-dev libtheora-dev libsoup2.4-dev libsqlite3-dev libupnp4-dev
|
||||
|
||||
+ Install srtp (optional) for call encryption :
|
||||
$ git clone git://git.linphone.org/srtp.git
|
||||
$ cd srtp && autoconf && ./configure && make
|
||||
|
|
|
|||
28
README.macos
|
|
@ -7,17 +7,17 @@ You need:
|
|||
- Macports: http://www.macports.org/
|
||||
Download and install macports using its user friendly installer.
|
||||
|
||||
- In order to enable generation of bundle for multiple macos version it is recommended to edit /opt/local/etc/macports/macports.conf to add the
|
||||
following line:
|
||||
macosx_deployment_target 10.6
|
||||
- In order to enable generation of bundle for multiple macos version and 32 bit processors, it is recommended to:
|
||||
1) edit /opt/local/etc/macports/macports.conf to add the following line:
|
||||
macosx_deployment_target 10.6
|
||||
2) edit /opt/local/etc/macports/variants.conf to add the following line:
|
||||
+universal
|
||||
|
||||
- Install build time dependencies
|
||||
$ sudo port install automake autoconf libtool intltool
|
||||
|
||||
- Install some linphone dependencies with macports
|
||||
$ sudo port install speex
|
||||
$ sudo port install libosip2 # WARNING: currently outdated in macport
|
||||
$ sudo port install libeXosip2 #WARNING: currently outdated in macport
|
||||
$ sudo port install ffmpeg-devel -gpl2
|
||||
$ sudo port install libvpx
|
||||
$ sudo port install readline
|
||||
|
|
@ -36,6 +36,22 @@ You need:
|
|||
|
||||
The softwares below need to be compiled manually. To ensure compatibility with multiple mac os version it is recommended to do:
|
||||
$ export MACOSX_DEPLOYMENT_TARGET=10.6
|
||||
$ export CFLAGS="-arch i386 -arch x86_64 -mmacosx-version-min=10.5"
|
||||
$ export OBJCFLAGS="-arch i386 -arch x86_64 -mmacosx-version-min=10.5"
|
||||
$ export CXXFLAGS="-arch i386 -arch x86_64 -mmacosx-version-min=10.5"
|
||||
$ export LDFLAGS="-arch i386 -arch x86_64 -mmacosx-version-min=10.5"
|
||||
|
||||
- Install polarssl (encryption library used by belle-sip)
|
||||
$ git clone git://git.linphone.org/polarssl.git -b linphone
|
||||
$ cd polarssl
|
||||
$ ./autogen.sh && ./configure --prefix=/opt/local && make
|
||||
$ sudo make install
|
||||
|
||||
- Install belle-sip (sip stack)
|
||||
$ git clone git://git.linphone.org/belle-sip.git
|
||||
$ cd belle-sip
|
||||
$ ./autogen.sh && ./configure --prefix=/opt/local && make
|
||||
$ sudo make install
|
||||
|
||||
- Install srtp (optional) for call encryption
|
||||
$ sudo port install srtp
|
||||
|
|
@ -72,7 +88,7 @@ The softwares below need to be compiled manually. To ensure compatibility with m
|
|||
|
||||
Then or otherwise, do:
|
||||
|
||||
$ ./configure --prefix=/opt/local --with-readline=/opt/local --disable-x11 --with-srtp=/opt/local --with-gsm=/opt/local --enable-zrtp && make
|
||||
$ ./configure --prefix=/opt/local --with-readline=/opt/local --disable-x11 --with-srtp=/opt/local --with-gsm=/opt/local --enable-zrtp --disable-strict && make
|
||||
|
||||
Install to /opt/local
|
||||
|
||||
|
|
|
|||
61
README.mingw
|
|
@ -26,7 +26,7 @@ Download lastest linphone-deps-win32 zip from
|
|||
http://download.savannah.gnu.org/releases-noredirect/linphone/misc
|
||||
using your browser.
|
||||
|
||||
Download lastest gtk+2 win32 bundle from http://www.gtk.org
|
||||
Download lastest gtk+-2.24.10 win32 _bundle_ from http://www.gtk.org
|
||||
|
||||
Install all these three package in /:
|
||||
|
||||
|
|
@ -65,23 +65,19 @@ WARNING: During the build, windows might slow down suddenly. Using ctl+alt+del t
|
|||
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.
|
||||
|
||||
#Compile and install tunnel (optional, available under proprietary licensing)
|
||||
|
||||
cd tunnel && ./autogen.sh && ./configure --prefix=/usr --enable-shared --disable-static && make && make install
|
||||
|
||||
#Build linphone itself:
|
||||
#run autogen.sh after a git checkout or update
|
||||
|
||||
./autogen.sh
|
||||
|
||||
./configure --prefix=/opt/linphone --enable-shared --disable-static
|
||||
./configure --prefix=/usr --enable-shared --disable-static
|
||||
#note: in order to use the tunnel, append --enable-tunnel to the configure line above.
|
||||
|
||||
#compile:
|
||||
|
||||
make
|
||||
|
||||
#now install to /opt/linphone, required for compilation of plugins.
|
||||
#now install to /usr, required for compilation of plugins.
|
||||
|
||||
make install
|
||||
|
||||
|
|
@ -100,7 +96,7 @@ make setup.exe
|
|||
#build plugins
|
||||
cd mediastreamer2/plugins/msx264
|
||||
./autogen.sh
|
||||
PKG_CONFIG_PATH=/opt/linphone/lib/pkgconfig ./configure --prefix=/opt/linphone --enable-shared --disable-static
|
||||
PKG_CONFIG_PATH=/usr/lib/pkgconfig ./configure --prefix=/usr --enable-shared --disable-static
|
||||
#make a binary zip of this plugin
|
||||
make zip
|
||||
#or make an installer
|
||||
|
|
@ -109,7 +105,7 @@ 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=/opt/linphone/lib/pkgconfig ./configure --prefix=/opt/linphone --enable-shared --disable-static
|
||||
PKG_CONFIG_PATH=/usr/lib/pkgconfig ./configure --prefix=/usr --enable-shared --disable-static
|
||||
make
|
||||
#make a binary zip of this plugin
|
||||
make zip
|
||||
|
|
@ -125,13 +121,15 @@ These notes are useful if you want to upgrade part of the software that is inclu
|
|||
linphone-deps packages.
|
||||
|
||||
List of software included in linphone-deps:
|
||||
libosip2 (compiled)
|
||||
libeXosip2 (compiled)
|
||||
antlr3c (compiled)
|
||||
polarssl (compiled
|
||||
belle-sip (compiled)
|
||||
libsrtp (compiled)
|
||||
libavcodec, libavutil, libavformat, libavdevice, libswscale (compiled, all these from ffmpeg)
|
||||
libtheora (from the web)
|
||||
libx264 (compiled from the version distributed from linphone's web site)
|
||||
libogg (from the web)
|
||||
libspeex, libspeexdsp (compiled, statically to workaround a dll-related crash)
|
||||
libspeex, libspeexdsp (compiled)
|
||||
libgnutls (from the web)
|
||||
libgsm (from the web)
|
||||
libxml2 (compiled)
|
||||
|
|
@ -142,6 +140,45 @@ Remarks:
|
|||
For every package compiled that goes into linphone-deps, .la files (libtool files) must be removed to avoid libtool errors.
|
||||
When running "make install DESTDIR=<somepath>", somepath must be absolute and should not contain any ~ or space.
|
||||
|
||||
- building antlr3c
|
||||
* download the sources with:
|
||||
$ git clone -b linphone git://git.linphone.org/antlr3.git
|
||||
* compile and install
|
||||
$ cd runtime/C
|
||||
$ ./autogen.sh
|
||||
$ ./configure --prefix=/usr --enable-shared --disable-static
|
||||
$ make
|
||||
$ make install
|
||||
$ make install DESTDIR=/home/<myuser>/antlr3c-install
|
||||
$ cp
|
||||
|
||||
- building polarssl
|
||||
* download the sources with:
|
||||
$ git clone -b linphone git://git.linphone.org/polarssl.git
|
||||
* compile and install:
|
||||
$ cd polarssl
|
||||
$ make lib SHARED=1 WINDOWS=1
|
||||
$ 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
|
||||
* compile with
|
||||
$ autoconf
|
||||
$ ./configure --prefix=/usr
|
||||
$ make libsrtp.a
|
||||
$ make install
|
||||
$ make install DESTDIR=/home/<myuser>/libsrtp-install
|
||||
|
||||
- building sqlite3
|
||||
* download the sources on the following website:
|
||||
http://www.sqlite.org/download.html (choose the sqlite-autoconf-3XXX.tar.gz)
|
||||
|
|
|
|||
|
|
@ -1,50 +0,0 @@
|
|||
##
|
||||
## Android.mk -Android build script-
|
||||
##
|
||||
##
|
||||
## Copyright (C) 2010 Belledonne Communications, Grenoble, France
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; either version 2 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program; if not, write to the Free Software
|
||||
## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
##
|
||||
|
||||
LOCAL_PATH:= $(call my-dir)/../../coreapi
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
include $(linphone-root-dir)/submodules/linphone/build/android/common.mk
|
||||
|
||||
ifeq ($(LINPHONE_VIDEO),1)
|
||||
LOCAL_SHARED_LIBRARIES += \
|
||||
libavcodecnoneon \
|
||||
libswscale \
|
||||
libavcore \
|
||||
libavutil
|
||||
endif
|
||||
|
||||
LOCAL_MODULE := liblinphonenoneon
|
||||
ifeq ($(TARGET_ARCH_ABI),armeabi)
|
||||
LOCAL_MODULE_FILENAME := liblinphonearmv5noneon
|
||||
endif
|
||||
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
|
||||
LOCAL_MODULE_FILENAME := liblinphonearmv7noneon
|
||||
endif
|
||||
ifeq ($(TARGET_ARCH_ABI),x86)
|
||||
LOCAL_MODULE_FILENAME := liblinphonex86
|
||||
endif
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
||||
$(call import-module,android/cpufeatures)
|
||||
|
||||
|
|
@ -23,20 +23,215 @@ LOCAL_PATH:= $(call my-dir)/../../coreapi
|
|||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
include $(linphone-root-dir)/submodules/linphone/build/android/common.mk
|
||||
LOCAL_CPP_EXTENSION := .cc
|
||||
|
||||
ifeq ($(LINPHONE_VIDEO),1)
|
||||
LOCAL_SRC_FILES := \
|
||||
linphonecore.c \
|
||||
misc.c \
|
||||
enum.c \
|
||||
presence.c \
|
||||
proxy.c \
|
||||
friend.c \
|
||||
authentication.c \
|
||||
lpconfig.c \
|
||||
chat.c \
|
||||
sipsetup.c \
|
||||
siplogin.c \
|
||||
address.c \
|
||||
linphonecore_jni.cc \
|
||||
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_impl.c \
|
||||
bellesip_sal/sal_op_message.c \
|
||||
bellesip_sal/sal_op_presence.c \
|
||||
bellesip_sal/sal_op_registration.c \
|
||||
bellesip_sal/sal_op_publish.c \
|
||||
bellesip_sal/sal_op_info.c \
|
||||
bellesip_sal/sal_op_events.c \
|
||||
bellesip_sal/sal_sdp.c \
|
||||
sal.c \
|
||||
offeranswer.c \
|
||||
callbacks.c \
|
||||
linphonecall.c \
|
||||
conference.c \
|
||||
ec-calibrator.c \
|
||||
linphone_tunnel_config.c \
|
||||
message_storage.c \
|
||||
info.c \
|
||||
event.c
|
||||
|
||||
ifndef LINPHONE_VERSION
|
||||
LINPHONE_VERSION = "Devel"
|
||||
endif
|
||||
|
||||
LOCAL_CFLAGS += \
|
||||
-D_BYTE_ORDER=_LITTLE_ENDIAN \
|
||||
-DORTP_INET6 \
|
||||
-DINET6 \
|
||||
-DENABLE_TRACE \
|
||||
-DHAVE_CONFIG_H \
|
||||
-DLINPHONE_VERSION=\"$(LINPHONE_VERSION)\" \
|
||||
-DLINPHONE_PLUGINS_DIR=\"\\tmp\" \
|
||||
-DUSE_BELLESIP
|
||||
|
||||
LOCAL_CFLAGS += -DIN_LINPHONE
|
||||
|
||||
ifeq ($(_BUILD_VIDEO),1)
|
||||
LOCAL_CFLAGS += -DVIDEO_ENABLED
|
||||
ifeq ($(BUILD_X264),1)
|
||||
LOCAL_CFLAGS += -DHAVE_X264
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(BUILD_CONTACT_HEADER),1)
|
||||
LOCAL_CFLAGS += -DSAL_OP_CALL_FORCE_CONTACT_IN_RINGING
|
||||
endif
|
||||
|
||||
ifeq ($(USE_JAVAH),1)
|
||||
LOCAL_CFLAGS += -DUSE_JAVAH
|
||||
endif
|
||||
|
||||
LOCAL_C_INCLUDES += \
|
||||
$(LOCAL_PATH) \
|
||||
$(LOCAL_PATH)/../include \
|
||||
$(LOCAL_PATH)/../build/android \
|
||||
$(LOCAL_PATH)/../oRTP/include \
|
||||
$(LOCAL_PATH)/../mediastreamer2/include \
|
||||
$(LOCAL_PATH)/../../belle-sip/include \
|
||||
$(LOCAL_PATH)/../../../gen \
|
||||
$(LOCAL_PATH)/../../externals/libxml2/include \
|
||||
$(LOCAL_PATH)/../../externals/build/libxml2
|
||||
|
||||
LOCAL_LDLIBS += -llog -ldl
|
||||
|
||||
LOCAL_STATIC_LIBRARIES := \
|
||||
cpufeatures \
|
||||
libmediastreamer2 \
|
||||
libortp \
|
||||
libbellesip \
|
||||
libgsm \
|
||||
liblpxml2
|
||||
|
||||
|
||||
ifeq ($(BUILD_TUNNEL),1)
|
||||
LOCAL_CFLAGS +=-DTUNNEL_ENABLED
|
||||
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../tunnel/include $(LOCAL_PATH)/../../tunnel/src
|
||||
LOCAL_SRC_FILES += linphone_tunnel.cc TunnelManager.cc
|
||||
LOCAL_STATIC_LIBRARIES += libtunnelclient
|
||||
else
|
||||
LOCAL_SRC_FILES += linphone_tunnel_stubs.c
|
||||
endif
|
||||
|
||||
|
||||
_BUILD_AMR=0
|
||||
ifneq ($(BUILD_AMRNB), 0)
|
||||
_BUILD_AMR=1
|
||||
endif
|
||||
|
||||
ifneq ($(BUILD_AMRWB), 0)
|
||||
_BUILD_AMR=1
|
||||
endif
|
||||
|
||||
ifneq ($(_BUILD_AMR), 0)
|
||||
LOCAL_CFLAGS += -DHAVE_AMR
|
||||
LOCAL_STATIC_LIBRARIES += \
|
||||
libmsamr \
|
||||
libopencoreamr
|
||||
endif
|
||||
|
||||
ifneq ($(BUILD_AMRWB), 0)
|
||||
LOCAL_STATIC_LIBRARIES += \
|
||||
libvoamrwbenc
|
||||
endif
|
||||
|
||||
|
||||
ifeq ($(BUILD_SILK),1)
|
||||
LOCAL_CFLAGS += -DHAVE_SILK
|
||||
LOCAL_STATIC_LIBRARIES += libmssilk
|
||||
endif
|
||||
|
||||
ifeq ($(BUILD_WEBRTC_ISAC),1)
|
||||
LOCAL_CFLAGS += -DHAVE_ISAC
|
||||
LOCAL_STATIC_LIBRARIES += libwebrtc_isacfix_neon
|
||||
LOCAL_STATIC_LIBRARIES += libwebrtc_spl libwebrtc_isacfix libmsisac
|
||||
endif
|
||||
|
||||
ifeq ($(BUILD_G729),1)
|
||||
LOCAL_CFLAGS += -DHAVE_G729
|
||||
LOCAL_STATIC_LIBRARIES += libbcg729 libmsbcg729
|
||||
endif
|
||||
|
||||
ifeq ($(_BUILD_VIDEO),1)
|
||||
LOCAL_LDLIBS += -lGLESv2
|
||||
LOCAL_STATIC_LIBRARIES += libvpx
|
||||
ifeq ($(BUILD_X264),1)
|
||||
LOCAL_STATIC_LIBRARIES += \
|
||||
libmsx264 \
|
||||
libx264
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(BUILD_UPNP),1)
|
||||
LOCAL_CFLAGS += -DBUILD_UPNP
|
||||
LOCAL_SRC_FILES += upnp.c
|
||||
endif
|
||||
|
||||
LOCAL_STATIC_LIBRARIES += libspeex
|
||||
|
||||
ifeq ($(BUILD_SRTP), 1)
|
||||
LOCAL_C_INCLUDES += $(SRTP_C_INCLUDE)
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
|
||||
LOCAL_CFLAGS += -DHAVE_ILBC=1
|
||||
LOCAL_STATIC_LIBRARIES += libmsilbc
|
||||
endif
|
||||
|
||||
LOCAL_C_INCLUDES += $(LIBLINPHONE_EXTENDED_C_INCLUDES)
|
||||
LOCAL_WHOLE_STATIC_LIBRARIES += $(LIBLINPHONE_EXTENDED_STATIC_LIBS)
|
||||
LOCAL_SRC_FILES += $(LIBLINPHONE_EXTENDED_SRC_FILES)
|
||||
|
||||
ifeq ($(BUILD_GPLV3_ZRTP),1)
|
||||
LOCAL_SHARED_LIBRARIES += libssl-linphone libcrypto-linphone
|
||||
LOCAL_SHARED_LIBRARIES += libzrtpcpp
|
||||
endif
|
||||
|
||||
ifeq ($(BUILD_SRTP),1)
|
||||
LOCAL_SHARED_LIBRARIES += libsrtp
|
||||
endif
|
||||
|
||||
ifeq ($(BUILD_REMOTE_PROVISIONING),1)
|
||||
LOCAL_SRC_FILES += ../tools/xml2lpc.c \
|
||||
../tools/xml2lpc_jni.cc \
|
||||
../tools/lpc2xml.c \
|
||||
../tools/lpc2xml_jni.cc
|
||||
|
||||
endif
|
||||
|
||||
ifeq ($(BUILD_SQLITE),1)
|
||||
LOCAL_CFLAGS += -DMSG_STORAGE_ENABLED
|
||||
LOCAL_STATIC_LIBRARIES += liblinsqlite
|
||||
LOCAL_C_INCLUDES += \
|
||||
$(LOCAL_PATH)/../../externals/sqlite3/
|
||||
endif
|
||||
|
||||
ifeq ($(BUILD_OPUS),1)
|
||||
LOCAL_STATIC_LIBRARIES += libopus
|
||||
endif
|
||||
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_C_INCLUDES)
|
||||
LOCAL_EXPORT_CFLAGS := $(LOCAL_CFLAGS)
|
||||
|
||||
ifeq ($(_BUILD_VIDEO),1)
|
||||
LOCAL_SHARED_LIBRARIES += \
|
||||
libavcodec \
|
||||
libswscale \
|
||||
libavcore \
|
||||
libavutil
|
||||
libavcodec-linphone \
|
||||
libswscale-linphone \
|
||||
libavutil-linphone
|
||||
endif
|
||||
|
||||
LOCAL_MODULE := liblinphone
|
||||
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
|
||||
LOCAL_MODULE_FILENAME := liblinphonearmv7
|
||||
endif
|
||||
LOCAL_MODULE_FILENAME := liblinphone-$(TARGET_ARCH_ABI)
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,205 +0,0 @@
|
|||
##
|
||||
## Android.mk -Android build script-
|
||||
##
|
||||
##
|
||||
## Copyright (C) 2010 Belledonne Communications, Grenoble, France
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; either version 2 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program; if not, write to the Free Software
|
||||
## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
##
|
||||
|
||||
LOCAL_CPP_EXTENSION := .cc
|
||||
|
||||
LOCAL_SRC_FILES := \
|
||||
linphonecore.c \
|
||||
misc.c \
|
||||
enum.c \
|
||||
presence.c \
|
||||
proxy.c \
|
||||
friend.c \
|
||||
authentication.c \
|
||||
lpconfig.c \
|
||||
chat.c \
|
||||
sipsetup.c \
|
||||
siplogin.c \
|
||||
address.c \
|
||||
linphonecore_jni.cc \
|
||||
sal.c \
|
||||
sal_eXosip2.c \
|
||||
sal_eXosip2_presence.c \
|
||||
sal_eXosip2_sdp.c \
|
||||
offeranswer.c \
|
||||
callbacks.c \
|
||||
linphonecall.c \
|
||||
conference.c \
|
||||
ec-calibrator.c \
|
||||
linphone_tunnel_config.c \
|
||||
message_storage.c
|
||||
|
||||
ifndef LINPHONE_VERSION
|
||||
LINPHONE_VERSION = "Devel"
|
||||
endif
|
||||
|
||||
LOCAL_CFLAGS += \
|
||||
-D_BYTE_ORDER=_LITTLE_ENDIAN \
|
||||
-DORTP_INET6 \
|
||||
-DINET6 \
|
||||
-DOSIP_MT \
|
||||
-DENABLE_TRACE \
|
||||
-DHAVE_CONFIG_H \
|
||||
-DLINPHONE_VERSION=\"$(LINPHONE_VERSION)\" \
|
||||
-DLINPHONE_PLUGINS_DIR=\"\\tmp\" \
|
||||
|
||||
LOCAL_CFLAGS += -DIN_LINPHONE
|
||||
|
||||
ifeq ($(LINPHONE_VIDEO),1)
|
||||
LOCAL_CFLAGS += -DVIDEO_ENABLED
|
||||
ifeq ($(BUILD_X264),1)
|
||||
LOCAL_CFLAGS += -DHAVE_X264
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(USE_JAVAH),1)
|
||||
LOCAL_CFLAGS += -DUSE_JAVAH
|
||||
endif
|
||||
|
||||
LOCAL_C_INCLUDES += \
|
||||
$(LOCAL_PATH) \
|
||||
$(LOCAL_PATH)/include \
|
||||
$(LOCAL_PATH)/../build/android \
|
||||
$(LOCAL_PATH)/../oRTP/include \
|
||||
$(LOCAL_PATH)/../mediastreamer2/include \
|
||||
$(LOCAL_PATH)/../../externals/exosip/include \
|
||||
$(LOCAL_PATH)/../../externals/osip/include \
|
||||
$(LOCAL_PATH)/../../../gen
|
||||
|
||||
LOCAL_LDLIBS += -llog -ldl
|
||||
|
||||
|
||||
|
||||
LOCAL_STATIC_LIBRARIES := \
|
||||
cpufeatures \
|
||||
libmediastreamer2 \
|
||||
libortp \
|
||||
libeXosip2 \
|
||||
libosip2 \
|
||||
libgsm
|
||||
|
||||
ifeq ($(BUILD_REMOTE_PROVISIONING),1)
|
||||
LOCAL_STATIC_LIBRARIES += \
|
||||
libxml2lpc \
|
||||
liblpc2xml \
|
||||
liblpxml2
|
||||
endif
|
||||
|
||||
ifeq ($(BUILD_TUNNEL),1)
|
||||
LOCAL_CFLAGS +=-DTUNNEL_ENABLED
|
||||
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../tunnel/include $(LOCAL_PATH)/../../tunnel/src
|
||||
LOCAL_SRC_FILES += linphone_tunnel.cc TunnelManager.cc
|
||||
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
|
||||
LOCAL_SHARED_LIBRARIES += libtunnelclient
|
||||
else
|
||||
LOCAL_STATIC_LIBRARIES += libtunnelclient
|
||||
endif
|
||||
else
|
||||
LOCAL_SRC_FILES += linphone_tunnel_stubs.c
|
||||
endif
|
||||
|
||||
|
||||
_BUILD_AMR=0
|
||||
ifneq ($(BUILD_AMRNB), 0)
|
||||
_BUILD_AMR=1
|
||||
endif
|
||||
|
||||
ifneq ($(BUILD_AMRWB), 0)
|
||||
_BUILD_AMR=1
|
||||
endif
|
||||
|
||||
ifneq ($(_BUILD_AMR), 0)
|
||||
LOCAL_CFLAGS += -DHAVE_AMR
|
||||
LOCAL_STATIC_LIBRARIES += \
|
||||
libmsamr \
|
||||
libopencoreamr
|
||||
endif
|
||||
|
||||
ifneq ($(BUILD_AMRWB), 0)
|
||||
LOCAL_STATIC_LIBRARIES += \
|
||||
libvoamrwbenc
|
||||
endif
|
||||
|
||||
|
||||
ifeq ($(BUILD_SILK),1)
|
||||
LOCAL_CFLAGS += -DHAVE_SILK
|
||||
LOCAL_STATIC_LIBRARIES += libmssilk
|
||||
endif
|
||||
|
||||
ifeq ($(BUILD_G729),1)
|
||||
LOCAL_CFLAGS += -DHAVE_G729
|
||||
LOCAL_SHARED_LIBRARIES += libbcg729
|
||||
LOCAL_STATIC_LIBRARIES += libmsbcg729
|
||||
endif
|
||||
|
||||
ifeq ($(LINPHONE_VIDEO),1)
|
||||
LOCAL_LDLIBS += -lGLESv2
|
||||
LOCAL_STATIC_LIBRARIES += libvpx
|
||||
ifeq ($(BUILD_X264),1)
|
||||
LOCAL_STATIC_LIBRARIES += \
|
||||
libmsx264 \
|
||||
libx264
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(BUILD_UPNP),1)
|
||||
LOCAL_CFLAGS += -DBUILD_UPNP
|
||||
LOCAL_SRC_FILES += upnp.c
|
||||
endif
|
||||
|
||||
LOCAL_STATIC_LIBRARIES += libspeex
|
||||
|
||||
ifeq ($(BUILD_SRTP), 1)
|
||||
LOCAL_C_INCLUDES += $(SRTP_C_INCLUDE)
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
|
||||
LOCAL_CFLAGS += -DHAVE_ILBC=1
|
||||
LOCAL_STATIC_LIBRARIES += libmsilbc
|
||||
endif
|
||||
|
||||
LOCAL_C_INCLUDES += $(LIBLINPHONE_EXTENDED_C_INCLUDES)
|
||||
LOCAL_WHOLE_STATIC_LIBRARIES += $(LIBLINPHONE_EXTENDED_STATIC_LIBS)
|
||||
LOCAL_SRC_FILES += $(LIBLINPHONE_EXTENDED_SRC_FILES)
|
||||
|
||||
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
|
||||
LOCAL_SHARED_LIBRARIES += liblinssl liblincrypto
|
||||
ifeq ($(BUILD_GPLV3_ZRTP),1)
|
||||
LOCAL_SHARED_LIBRARIES += libzrtpcpp
|
||||
endif
|
||||
|
||||
ifeq ($(BUILD_SRTP),1)
|
||||
LOCAL_SHARED_LIBRARIES += libsrtp
|
||||
endif
|
||||
else
|
||||
LOCAL_LDLIBS += -lz
|
||||
#LOCAL_STATIC_LIBRARIES += libz libdl
|
||||
LOCAL_STATIC_LIBRARIES += \
|
||||
libssl-static libcrypto-static
|
||||
ifeq ($(BUILD_GPLV3_ZRTP),1)
|
||||
LOCAL_STATIC_LIBRARIES += libzrtpcpp-static
|
||||
endif
|
||||
|
||||
ifeq ($(BUILD_SRTP),1)
|
||||
LOCAL_STATIC_LIBRARIES += libsrtp-static
|
||||
endif
|
||||
endif
|
||||
|
||||
|
|
@ -38,19 +38,19 @@
|
|||
/* #def HAVE_EXOSIP_DSCP */
|
||||
|
||||
/* Defined when eXosip_get_version is available */
|
||||
#define HAVE_EXOSIP_GET_VERSION
|
||||
/* #undef HAVE_EXOSIP_GET_VERSION */
|
||||
|
||||
/* Defined when eXosip_reset_transports is available */
|
||||
#define HAVE_EXOSIP_RESET_TRANSPORTS
|
||||
/* #undef HAVE_EXOSIP_RESET_TRANSPORTS */
|
||||
|
||||
/* Defined when eXosip_tls_verify_certificate is available */
|
||||
#define HAVE_EXOSIP_TLS_VERIFY_CERTIFICATE
|
||||
/* #undef HAVE_EXOSIP_TLS_VERIFY_CERTIFICATE */
|
||||
|
||||
/* Defined when eXosip_tls_verify_certificate is available */
|
||||
/* #undef HAVE_EXOSIP_TLS_VERIFY_CN */
|
||||
|
||||
/* Defined when eXosip_get_socket is available */
|
||||
#define HAVE_EXOSIP_TRYLOCK
|
||||
/* #undef HAVE_EXOSIP_TRYLOCK */
|
||||
|
||||
/* If present, the getenv function allows fim to read environment variables.
|
||||
*/
|
||||
|
|
|
|||
33
build/android/liblinphone_tester.mk
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
LOCAL_PATH := $(call my-dir)/../../tester
|
||||
|
||||
common_SRC_FILES := \
|
||||
call_tester.c \
|
||||
liblinphone_tester.c \
|
||||
message_tester.c \
|
||||
presence_tester.c \
|
||||
register_tester.c \
|
||||
setup_tester.c \
|
||||
upnp_tester.c \
|
||||
eventapi_tester.c
|
||||
|
||||
common_C_INCLUDES += \
|
||||
$(LOCAL_PATH) \
|
||||
$(LOCAL_PATH)/../include \
|
||||
$(LOCAL_PATH)/../coreapi \
|
||||
$(LOCAL_PATH)/../oRTP/include \
|
||||
$(LOCAL_PATH)/../mediastreamer2/include
|
||||
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE := liblinphone_tester
|
||||
LOCAL_MODULE_FILENAME := liblinphone_tester-$(TARGET_ARCH_ABI)
|
||||
LOCAL_SRC_FILES += $(common_SRC_FILES)
|
||||
LOCAL_C_INCLUDES = $(common_C_INCLUDES)
|
||||
LOCAL_CFLAGS = -DIN_LINPHONE
|
||||
LOCAL_LDLIBS := -llog
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := cunit liblinphone
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
||||
#end
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
##
|
||||
## Android.mk -Android build script-
|
||||
##
|
||||
##
|
||||
## Copyright (C) 2013 Belledonne Communications, Grenoble, France
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; either version 2 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program; if not, write to the Free Software
|
||||
## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
##
|
||||
|
||||
LOCAL_PATH:= $(call my-dir)/../../tools
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_CPP_EXTENSION := .cc
|
||||
|
||||
LOCAL_SRC_FILES := \
|
||||
lpc2xml.c \
|
||||
lpc2xml_jni.cc \
|
||||
|
||||
LOCAL_CFLAGS += -DIN_LINPHONE
|
||||
|
||||
LOCAL_C_INCLUDES = \
|
||||
$(LOCAL_PATH)/../coreapi \
|
||||
$(LOCAL_PATH)/../oRTP/include \
|
||||
$(LOCAL_PATH)/../mediastreamer2/include \
|
||||
$(LOCAL_PATH)/../../externals/libxml2/include \
|
||||
$(LOCAL_PATH)/../../externals/build/libxml2 \
|
||||
|
||||
LOCAL_SHARED_LIBRARIES = \
|
||||
# liblinphonenoneon \
|
||||
# liblinphone \
|
||||
|
||||
LOCAL_MODULE := liblpc2xml
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
##
|
||||
## Android.mk -Android build script-
|
||||
##
|
||||
##
|
||||
## Copyright (C) 2013 Belledonne Communications, Grenoble, France
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; either version 2 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program; if not, write to the Free Software
|
||||
## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
##
|
||||
|
||||
LOCAL_PATH:= $(call my-dir)/../../tools
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_CPP_EXTENSION := .cc
|
||||
|
||||
LOCAL_SRC_FILES := \
|
||||
xml2lpc.c \
|
||||
xml2lpc_jni.cc \
|
||||
|
||||
LOCAL_CFLAGS += -DIN_LINPHONE
|
||||
|
||||
LOCAL_C_INCLUDES = \
|
||||
$(LOCAL_PATH)/../coreapi \
|
||||
$(LOCAL_PATH)/../oRTP/include \
|
||||
$(LOCAL_PATH)/../mediastreamer2/include \
|
||||
$(LOCAL_PATH)/../../externals/libxml2/include \
|
||||
$(LOCAL_PATH)/../../externals/build/libxml2 \
|
||||
|
||||
LOCAL_SHARED_LIBRARIES = \
|
||||
# liblinphonenoneon \
|
||||
# liblinphone \
|
||||
|
||||
LOCAL_MODULE := libxml2lpc
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
|
@ -15,7 +15,8 @@
|
|||
<prefix name="default">/opt/local</prefix>
|
||||
<prefix name="linphone">${env:LINPHONE_INSTALL_PREFIX}</prefix>
|
||||
<prefix name="ms2plugins">${env:MS2_PLUGINS_INSTALL_PREFIX}</prefix>
|
||||
<prefix name="macports">/opt/local</prefix>
|
||||
<!-- This prefix definition is necessary if some dependencies are to be taken from /usr/local/lib -->
|
||||
<prefix name="local">/usr/local</prefix>
|
||||
<!-- The project directory is the default location of the created
|
||||
app. If you leave out the path, the current directory is
|
||||
used. Note the usage of an environment variable here again.
|
||||
|
|
@ -55,11 +56,11 @@
|
|||
<main-binary>${prefix:linphone}/bin/linphone</main-binary>
|
||||
|
||||
<binary >
|
||||
${prefix:ms2plugins}/lib/mediastreamer/plugins/*.so
|
||||
${prefix:ms2plugins}/lib/mediastreamer/plugins/*.*.so
|
||||
</binary>
|
||||
|
||||
<binary >
|
||||
${prefix:linphone}/lib/*.dylib
|
||||
${prefix:linphone}/lib/*.*.dylib
|
||||
</binary>
|
||||
|
||||
<!-- Copy in GTK+ modules. Note the ${gtkdir} macro, which expands
|
||||
|
|
|
|||
274
build/vsx/LibLinphone/LibLinphone.vcxproj
Normal file
|
|
@ -0,0 +1,274 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|ARM">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>ARM</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|ARM">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>ARM</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{08dd0d38-d9b5-4626-b60d-b4d76b571142}</ProjectGuid>
|
||||
<RootNamespace>LibLinphone</RootNamespace>
|
||||
<DefaultLanguage>en-US</DefaultLanguage>
|
||||
<MinimumVisualStudioVersion>11.0</MinimumVisualStudioVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
<IgnoreImportLibrary>false</IgnoreImportLibrary>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v110_wp80</PlatformToolset>
|
||||
<IgnoreImportLibrary>false</IgnoreImportLibrary>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
<IgnoreImportLibrary>false</IgnoreImportLibrary>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<PlatformToolset>v110_wp80</PlatformToolset>
|
||||
<IgnoreImportLibrary>false</IgnoreImportLibrary>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)$(Platform)\$(Configuration)\$(TargetName)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<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>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<CompileAsWinRT>false</CompileAsWinRT>
|
||||
<AdditionalUsingDirectories>$(WindowsSDK_MetadataPath);$(AdditionalUsingDirectories)</AdditionalUsingDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>belle-sip_dll.lib;mediastreamer2_dll.lib;ws2_32.lib;ortp_dll.lib;gsm_dll.lib;speex_dll.lib;speexdsp_dll.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)$(Platform)\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<ImportLibrary>$(TargetDir)$(TargetName)_dll.lib</ImportLibrary>
|
||||
</Link>
|
||||
<CustomBuildStep>
|
||||
<Outputs>$(TargetDir)$(TargetName)_dll.lib;%(Outputs)</Outputs>
|
||||
</CustomBuildStep>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<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>
|
||||
<StringPooling>true</StringPooling>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<CompileAsWinRT>false</CompileAsWinRT>
|
||||
<AdditionalUsingDirectories>$(WindowsSDK_MetadataPath);$(AdditionalUsingDirectories)</AdditionalUsingDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
|
||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||
<AdditionalDependencies>belle-sip_dll.lib;mediastreamer2_dll.lib;ws2_32.lib;ortp_dll.lib;gsm_dll.lib;speex_dll.lib;speexdsp_dll.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)$(Platform)\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<ImportLibrary>$(TargetDir)$(TargetName)_dll.lib</ImportLibrary>
|
||||
</Link>
|
||||
<CustomBuildStep>
|
||||
<Outputs>$(TargetDir)$(TargetName)_dll.lib;%(Outputs)</Outputs>
|
||||
</CustomBuildStep>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
|
||||
<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>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<CompileAsWinRT>false</CompileAsWinRT>
|
||||
<AdditionalUsingDirectories>$(WindowsSDK_MetadataPath);$(AdditionalUsingDirectories)</AdditionalUsingDirectories>
|
||||
<PreprocessToFile>false</PreprocessToFile>
|
||||
<IgnoreStandardIncludePath>false</IgnoreStandardIncludePath>
|
||||
<ExceptionHandling>SyncCThrow</ExceptionHandling>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)$(Platform)\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<ImportLibrary>$(TargetDir)$(TargetName)_dll.lib</ImportLibrary>
|
||||
<IgnoreSpecificDefaultLibraries>ole32.lib;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
|
||||
<WindowsMetadataFile>
|
||||
</WindowsMetadataFile>
|
||||
</Link>
|
||||
<CustomBuildStep>
|
||||
<Outputs>$(TargetDir)$(TargetName)_dll.lib;%(Outputs)</Outputs>
|
||||
</CustomBuildStep>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
|
||||
<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>
|
||||
<StringPooling>true</StringPooling>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<CompileAsWinRT>false</CompileAsWinRT>
|
||||
<AdditionalUsingDirectories>$(WindowsSDK_MetadataPath);$(AdditionalUsingDirectories)</AdditionalUsingDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
|
||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||
<AdditionalDependencies>belle-sip_dll.lib;mediastreamer2_dll.lib;ws2_32.lib;ortp_dll.lib;gsm_dll.lib;speex_dll.lib;speexdsp_dll.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)$(Platform)\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<ImportLibrary>$(TargetDir)$(TargetName)_dll.lib</ImportLibrary>
|
||||
</Link>
|
||||
<CustomBuildStep>
|
||||
<Outputs>$(TargetDir)$(TargetName)_dll.lib;%(Outputs)</Outputs>
|
||||
</CustomBuildStep>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\..\coreapi\address.c" />
|
||||
<ClCompile Include="..\..\..\coreapi\authentication.c" />
|
||||
<ClCompile Include="..\..\..\coreapi\bellesip_sal\sal_address_impl.c" />
|
||||
<ClCompile Include="..\..\..\coreapi\bellesip_sal\sal_impl.c" />
|
||||
<ClCompile Include="..\..\..\coreapi\bellesip_sal\sal_op_call.c" />
|
||||
<ClCompile Include="..\..\..\coreapi\bellesip_sal\sal_op_call_transfer.c" />
|
||||
<ClCompile Include="..\..\..\coreapi\bellesip_sal\sal_op_events.c" />
|
||||
<ClCompile Include="..\..\..\coreapi\bellesip_sal\sal_op_impl.c" />
|
||||
<ClCompile Include="..\..\..\coreapi\bellesip_sal\sal_op_info.c" />
|
||||
<ClCompile Include="..\..\..\coreapi\bellesip_sal\sal_op_message.c" />
|
||||
<ClCompile Include="..\..\..\coreapi\bellesip_sal\sal_op_presence.c" />
|
||||
<ClCompile Include="..\..\..\coreapi\bellesip_sal\sal_op_publish.c" />
|
||||
<ClCompile Include="..\..\..\coreapi\bellesip_sal\sal_op_registration.c" />
|
||||
<ClCompile Include="..\..\..\coreapi\bellesip_sal\sal_sdp.c" />
|
||||
<ClCompile Include="..\..\..\coreapi\callbacks.c" />
|
||||
<ClCompile Include="..\..\..\coreapi\chat.c" />
|
||||
<ClCompile Include="..\..\..\coreapi\conference.c" />
|
||||
<ClCompile Include="..\..\..\coreapi\ec-calibrator.c" />
|
||||
<ClCompile Include="..\..\..\coreapi\enum.c" />
|
||||
<ClCompile Include="..\..\..\coreapi\event.c" />
|
||||
<ClCompile Include="..\..\..\coreapi\friend.c" />
|
||||
<ClCompile Include="..\..\..\coreapi\info.c" />
|
||||
<ClCompile Include="..\..\..\coreapi\linphonecall.c" />
|
||||
<ClCompile Include="..\..\..\coreapi\linphonecore.c" />
|
||||
<ClCompile Include="..\..\..\coreapi\linphone_tunnel.cc" />
|
||||
<ClCompile Include="..\..\..\coreapi\linphone_tunnel_config.c" />
|
||||
<ClCompile Include="..\..\..\coreapi\lpconfig.c" />
|
||||
<ClCompile Include="..\..\..\coreapi\lsd.c" />
|
||||
<ClCompile Include="..\..\..\coreapi\message_storage.c" />
|
||||
<ClCompile Include="..\..\..\coreapi\misc.c" />
|
||||
<ClCompile Include="..\..\..\coreapi\offeranswer.c" />
|
||||
<ClCompile Include="..\..\..\coreapi\presence.c" />
|
||||
<ClCompile Include="..\..\..\coreapi\proxy.c" />
|
||||
<ClCompile Include="..\..\..\coreapi\sal.c" />
|
||||
<ClCompile Include="..\..\..\coreapi\siplogin.c" />
|
||||
<ClCompile Include="..\..\..\coreapi\sipsetup.c" />
|
||||
<ClCompile Include="..\..\..\coreapi\TunnelManager.cc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\..\coreapi\bellesip_sal\sal_impl.h" />
|
||||
<ClInclude Include="..\..\..\coreapi\enum.h" />
|
||||
<ClInclude Include="..\..\..\coreapi\event.h" />
|
||||
<ClInclude Include="..\..\..\coreapi\linphonecore.h" />
|
||||
<ClInclude Include="..\..\..\coreapi\linphonecore_utils.h" />
|
||||
<ClInclude Include="..\..\..\coreapi\linphonefriend.h" />
|
||||
<ClInclude Include="..\..\..\coreapi\linphone_tunnel.h" />
|
||||
<ClInclude Include="..\..\..\coreapi\lpconfig.h" />
|
||||
<ClInclude Include="..\..\..\coreapi\offeranswer.h" />
|
||||
<ClInclude Include="..\..\..\coreapi\private.h" />
|
||||
<ClInclude Include="..\..\..\coreapi\sipsetup.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\belle-sip\build\windows\belle-sip\belle-sip.vcxproj">
|
||||
<Project>{4c225a82-800b-427b-ba7b-61686a9b347f}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\..\mediastreamer2\build\vsx\mediastreamer2\mediastreamer2\mediastreamer2.vcxproj">
|
||||
<Project>{027bad0e-9179-48c1-9733-7aa7e2c2ec70}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\..\msamr\build\windows\msamr\msamr\msamr.vcxproj">
|
||||
<Project>{9924ac72-f96c-4e56-94d9-2b025da43c6b}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\..\msilbc\build\windows\msilbc\msilbc\msilbc.vcxproj">
|
||||
<Project>{072fad20-7007-4da2-b2e7-16ce2b219f67}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\..\mssilk\build\windows\mssilk\mssilk\mssilk.vcxproj">
|
||||
<Project>{36b528f9-fb79-4078-a16b-0a7442581bb7}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\..\mswasapi\mswasapi\mswasapi\mswasapi.vcxproj">
|
||||
<Project>{d22bd217-d0f8-4274-9b3a-f3f35f46482c}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\..\oRTP\build\vsx\oRTP\oRTP\oRTP.vcxproj">
|
||||
<Project>{ffc7b532-0502-4d88-ac98-9e89071cbc97}</Project>
|
||||
<Private>false</Private>
|
||||
<ReferenceOutputAssembly>true</ReferenceOutputAssembly>
|
||||
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
|
||||
<LinkLibraryDependencies>true</LinkLibraryDependencies>
|
||||
<UseLibraryDependencyInputs>false</UseLibraryDependencyInputs>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\..\tunnel\build\windows\tunnel\tunnel\tunnel.vcxproj">
|
||||
<Project>{59500dd1-b192-4ddf-a402-8a8e3739e032}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\libxml2\libxml2\libxml2.vcxproj">
|
||||
<Project>{5dfa07b4-0be9-46a9-ba32-fdf5a55c580b}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="'$(Platform)'=='ARM'">
|
||||
<Reference Include="Windows">
|
||||
<IsWinMDFile>true</IsWinMDFile>
|
||||
</Reference>
|
||||
<Reference Include="platform.winmd">
|
||||
<IsWinMDFile>true</IsWinMDFile>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\..\coreapi\TunnelManager.hh" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsPhone\v$(TargetPlatformVersion)\Microsoft.Cpp.WindowsPhone.$(TargetPlatformVersion).targets" Condition="'$(Platform)'=='ARM'" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
522
build/vsx/LibLinphoneTester-wp8/LibLinphoneTester-wp8.sln
Normal file
|
|
@ -0,0 +1,522 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Express 2012 for Windows Phone
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LibLinphoneTester-wp8", "LibLinphoneTester-wp8\LibLinphoneTester-wp8.csproj", "{34D6878F-6CAB-4AE3-9CCC-25E8D6734C90}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{5E94A00B-B14A-4E42-8284-8CB0EF099534} = {5E94A00B-B14A-4E42-8284-8CB0EF099534}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LibLinphone", "..\LibLinphone\LibLinphone.vcxproj", "{08DD0D38-D9B5-4626-B60D-B4D76B571142}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{D22BD217-D0F8-4274-9B3A-F3F35F46482C} = {D22BD217-D0F8-4274-9B3A-F3F35F46482C}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LibLinphoneTester", "..\LibLinphoneTester\LibLinphoneTester.vcxproj", "{5E94A00B-B14A-4E42-8284-8CB0EF099534}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{902DAF1D-EBF1-4D03-B598-143500A50AB4} = {902DAF1D-EBF1-4D03-B598-143500A50AB4}
|
||||
{08DD0D38-D9B5-4626-B60D-B4D76B571142} = {08DD0D38-D9B5-4626-B60D-B4D76B571142}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "belle-sip", "..\..\..\..\belle-sip\build\windows\belle-sip\belle-sip.vcxproj", "{4C225A82-800B-427B-BA7B-61686A9B347F}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mediastreamer2", "..\..\..\..\mediastreamer2\build\vsx\mediastreamer2\mediastreamer2\mediastreamer2.vcxproj", "{027BAD0E-9179-48C1-9733-7AA7E2C2EC70}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "oRTP", "..\..\..\..\oRTP\build\vsx\oRTP\oRTP\oRTP.vcxproj", "{FFC7B532-0502-4D88-AC98-9E89071CBC97}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libantlr3c", "..\..\..\..\antlr3\runtime\C\build\vsx\libantlr3c\libantlr3c.vcxproj", "{8FA74260-151B-429B-83EF-3CF3EAC8CFD9}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gsm", "..\..\..\..\gsm\build\windows\gsm\gsm\gsm.vcxproj", "{746EA080-5BA9-42C5-9E52-EA421C3F3AFD}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "speex", "..\..\..\..\speex\build\windows\speex\speex\speex.vcxproj", "{D5EC8C11-C1D9-47E3-BB82-A93C300FD902}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "speexdsp", "..\..\..\..\speex\build\windows\speex\speexdsp\speexdsp.vcxproj", "{6BD78980-9C71-4341-8775-AD19E9EC7305}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cunit", "..\..\..\..\cunit\build\windows\cunit\cunit.vcxproj", "{902DAF1D-EBF1-4D03-B598-143500A50AB4}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libmswasapi", "..\..\..\..\mswasapi\mswasapi\mswasapi\mswasapi.vcxproj", "{D22BD217-D0F8-4274-9B3A-F3F35F46482C}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{027BAD0E-9179-48C1-9733-7AA7E2C2EC70} = {027BAD0E-9179-48C1-9733-7AA7E2C2EC70}
|
||||
{FFC7B532-0502-4D88-AC98-9E89071CBC97} = {FFC7B532-0502-4D88-AC98-9E89071CBC97}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "webrtcaecm", "..\..\..\..\webrtc\build\windows\webrtcaecm\webrtcaecm\webrtcaecm.vcxproj", "{1C4E6DA0-B8C7-4A05-A58E-54A6ED07C8DF}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libilbc-rfc3951", "..\..\..\..\libilbc-rfc3951\build\windows\libilbc-rfc3951\libilbc-rfc3951\libilbc-rfc3951.vcxproj", "{8E216BF3-2DD8-4794-8E97-B1AED301ED4D}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libmsilbc", "..\..\..\..\msilbc\build\windows\msilbc\msilbc\msilbc.vcxproj", "{072FAD20-7007-4DA2-B2E7-16CE2B219F67}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{027BAD0E-9179-48C1-9733-7AA7E2C2EC70} = {027BAD0E-9179-48C1-9733-7AA7E2C2EC70}
|
||||
{FFC7B532-0502-4D88-AC98-9E89071CBC97} = {FFC7B532-0502-4D88-AC98-9E89071CBC97}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libmssilk", "..\..\..\..\mssilk\build\windows\mssilk\mssilk\mssilk.vcxproj", "{36B528F9-FB79-4078-A16B-0A7442581BB7}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{027BAD0E-9179-48C1-9733-7AA7E2C2EC70} = {027BAD0E-9179-48C1-9733-7AA7E2C2EC70}
|
||||
{FFC7B532-0502-4D88-AC98-9E89071CBC97} = {FFC7B532-0502-4D88-AC98-9E89071CBC97}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libmsamr", "..\..\..\..\msamr\build\windows\msamr\msamr\msamr.vcxproj", "{9924AC72-F96C-4E56-94D9-2B025DA43C6B}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{027BAD0E-9179-48C1-9733-7AA7E2C2EC70} = {027BAD0E-9179-48C1-9733-7AA7E2C2EC70}
|
||||
{018A4428-535C-4566-9AE0-E93AFF0D3ED2} = {018A4428-535C-4566-9AE0-E93AFF0D3ED2}
|
||||
{7AC65D2A-6981-4D17-856D-C37A522739D8} = {7AC65D2A-6981-4D17-856D-C37A522739D8}
|
||||
{88191E75-2993-48D7-AA76-652F274EF0FE} = {88191E75-2993-48D7-AA76-652F274EF0FE}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vo-amrwbenc", "..\..\..\..\msamr\build\windows\msamr\vo-amrwbenc\vo-amrwbenc.vcxproj", "{018A4428-535C-4566-9AE0-E93AFF0D3ED2}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "opencore_amrnb", "..\..\..\..\msamr\build\windows\msamr\opencore_amrnb\opencore_amrnb.vcxproj", "{88191E75-2993-48D7-AA76-652F274EF0FE}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "opencore_amrwb", "..\..\..\..\msamr\build\windows\msamr\opencore_amrwb\opencore_amrwb.vcxproj", "{7AC65D2A-6981-4D17-856D-C37A522739D8}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "polarssl", "..\..\..\..\polarssl\build\windows\polarssl\polarssl\polarssl.vcxproj", "{E9F8C5D1-13A2-46B6-A9BC-878030D4BE09}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tunnel", "..\..\..\..\tunnel\build\windows\tunnel\tunnel\tunnel.vcxproj", "{59500DD1-B192-4DDF-A402-8A8E3739E032}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libxml2", "..\libxml2\libxml2\libxml2.vcxproj", "{5DFA07B4-0BE9-46A9-BA32-FDF5A55C580B}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|ARM = Debug|ARM
|
||||
Debug|Mixed Platforms = Debug|Mixed Platforms
|
||||
Debug|Win32 = Debug|Win32
|
||||
Debug|x86 = Debug|x86
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|ARM = Release|ARM
|
||||
Release|Mixed Platforms = Release|Mixed Platforms
|
||||
Release|Win32 = Release|Win32
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{34D6878F-6CAB-4AE3-9CCC-25E8D6734C90}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{34D6878F-6CAB-4AE3-9CCC-25E8D6734C90}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{34D6878F-6CAB-4AE3-9CCC-25E8D6734C90}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
|
||||
{34D6878F-6CAB-4AE3-9CCC-25E8D6734C90}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{34D6878F-6CAB-4AE3-9CCC-25E8D6734C90}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{34D6878F-6CAB-4AE3-9CCC-25E8D6734C90}.Debug|ARM.Deploy.0 = Debug|ARM
|
||||
{34D6878F-6CAB-4AE3-9CCC-25E8D6734C90}.Debug|Mixed Platforms.ActiveCfg = Debug|ARM
|
||||
{34D6878F-6CAB-4AE3-9CCC-25E8D6734C90}.Debug|Mixed Platforms.Build.0 = Debug|ARM
|
||||
{34D6878F-6CAB-4AE3-9CCC-25E8D6734C90}.Debug|Mixed Platforms.Deploy.0 = Debug|ARM
|
||||
{34D6878F-6CAB-4AE3-9CCC-25E8D6734C90}.Debug|Win32.ActiveCfg = Debug|x86
|
||||
{34D6878F-6CAB-4AE3-9CCC-25E8D6734C90}.Debug|Win32.Build.0 = Debug|x86
|
||||
{34D6878F-6CAB-4AE3-9CCC-25E8D6734C90}.Debug|Win32.Deploy.0 = Debug|x86
|
||||
{34D6878F-6CAB-4AE3-9CCC-25E8D6734C90}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{34D6878F-6CAB-4AE3-9CCC-25E8D6734C90}.Debug|x86.Build.0 = Debug|x86
|
||||
{34D6878F-6CAB-4AE3-9CCC-25E8D6734C90}.Debug|x86.Deploy.0 = Debug|x86
|
||||
{34D6878F-6CAB-4AE3-9CCC-25E8D6734C90}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{34D6878F-6CAB-4AE3-9CCC-25E8D6734C90}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{34D6878F-6CAB-4AE3-9CCC-25E8D6734C90}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||
{34D6878F-6CAB-4AE3-9CCC-25E8D6734C90}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{34D6878F-6CAB-4AE3-9CCC-25E8D6734C90}.Release|ARM.Build.0 = Release|ARM
|
||||
{34D6878F-6CAB-4AE3-9CCC-25E8D6734C90}.Release|ARM.Deploy.0 = Release|ARM
|
||||
{34D6878F-6CAB-4AE3-9CCC-25E8D6734C90}.Release|Mixed Platforms.ActiveCfg = Release|x86
|
||||
{34D6878F-6CAB-4AE3-9CCC-25E8D6734C90}.Release|Mixed Platforms.Build.0 = Release|x86
|
||||
{34D6878F-6CAB-4AE3-9CCC-25E8D6734C90}.Release|Mixed Platforms.Deploy.0 = Release|x86
|
||||
{34D6878F-6CAB-4AE3-9CCC-25E8D6734C90}.Release|Win32.ActiveCfg = Release|x86
|
||||
{34D6878F-6CAB-4AE3-9CCC-25E8D6734C90}.Release|Win32.Build.0 = Release|x86
|
||||
{34D6878F-6CAB-4AE3-9CCC-25E8D6734C90}.Release|Win32.Deploy.0 = Release|x86
|
||||
{34D6878F-6CAB-4AE3-9CCC-25E8D6734C90}.Release|x86.ActiveCfg = Release|x86
|
||||
{34D6878F-6CAB-4AE3-9CCC-25E8D6734C90}.Release|x86.Build.0 = Release|x86
|
||||
{34D6878F-6CAB-4AE3-9CCC-25E8D6734C90}.Release|x86.Deploy.0 = Release|x86
|
||||
{08DD0D38-D9B5-4626-B60D-B4D76B571142}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{08DD0D38-D9B5-4626-B60D-B4D76B571142}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{08DD0D38-D9B5-4626-B60D-B4D76B571142}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{08DD0D38-D9B5-4626-B60D-B4D76B571142}.Debug|Mixed Platforms.ActiveCfg = Debug|ARM
|
||||
{08DD0D38-D9B5-4626-B60D-B4D76B571142}.Debug|Mixed Platforms.Build.0 = Debug|ARM
|
||||
{08DD0D38-D9B5-4626-B60D-B4D76B571142}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{08DD0D38-D9B5-4626-B60D-B4D76B571142}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{08DD0D38-D9B5-4626-B60D-B4D76B571142}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{08DD0D38-D9B5-4626-B60D-B4D76B571142}.Debug|x86.Build.0 = Debug|Win32
|
||||
{08DD0D38-D9B5-4626-B60D-B4D76B571142}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{08DD0D38-D9B5-4626-B60D-B4D76B571142}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{08DD0D38-D9B5-4626-B60D-B4D76B571142}.Release|ARM.Build.0 = Release|ARM
|
||||
{08DD0D38-D9B5-4626-B60D-B4D76B571142}.Release|Mixed Platforms.ActiveCfg = Release|Win32
|
||||
{08DD0D38-D9B5-4626-B60D-B4D76B571142}.Release|Mixed Platforms.Build.0 = Release|Win32
|
||||
{08DD0D38-D9B5-4626-B60D-B4D76B571142}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{08DD0D38-D9B5-4626-B60D-B4D76B571142}.Release|Win32.Build.0 = Release|Win32
|
||||
{08DD0D38-D9B5-4626-B60D-B4D76B571142}.Release|x86.ActiveCfg = Release|Win32
|
||||
{08DD0D38-D9B5-4626-B60D-B4D76B571142}.Release|x86.Build.0 = Release|Win32
|
||||
{5E94A00B-B14A-4E42-8284-8CB0EF099534}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{5E94A00B-B14A-4E42-8284-8CB0EF099534}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{5E94A00B-B14A-4E42-8284-8CB0EF099534}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{5E94A00B-B14A-4E42-8284-8CB0EF099534}.Debug|Mixed Platforms.ActiveCfg = Debug|ARM
|
||||
{5E94A00B-B14A-4E42-8284-8CB0EF099534}.Debug|Mixed Platforms.Build.0 = Debug|ARM
|
||||
{5E94A00B-B14A-4E42-8284-8CB0EF099534}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{5E94A00B-B14A-4E42-8284-8CB0EF099534}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{5E94A00B-B14A-4E42-8284-8CB0EF099534}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{5E94A00B-B14A-4E42-8284-8CB0EF099534}.Debug|x86.Build.0 = Debug|Win32
|
||||
{5E94A00B-B14A-4E42-8284-8CB0EF099534}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{5E94A00B-B14A-4E42-8284-8CB0EF099534}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{5E94A00B-B14A-4E42-8284-8CB0EF099534}.Release|ARM.Build.0 = Release|ARM
|
||||
{5E94A00B-B14A-4E42-8284-8CB0EF099534}.Release|Mixed Platforms.ActiveCfg = Release|Win32
|
||||
{5E94A00B-B14A-4E42-8284-8CB0EF099534}.Release|Mixed Platforms.Build.0 = Release|Win32
|
||||
{5E94A00B-B14A-4E42-8284-8CB0EF099534}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{5E94A00B-B14A-4E42-8284-8CB0EF099534}.Release|Win32.Build.0 = Release|Win32
|
||||
{5E94A00B-B14A-4E42-8284-8CB0EF099534}.Release|x86.ActiveCfg = Release|Win32
|
||||
{5E94A00B-B14A-4E42-8284-8CB0EF099534}.Release|x86.Build.0 = Release|Win32
|
||||
{4C225A82-800B-427B-BA7B-61686A9B347F}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{4C225A82-800B-427B-BA7B-61686A9B347F}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{4C225A82-800B-427B-BA7B-61686A9B347F}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{4C225A82-800B-427B-BA7B-61686A9B347F}.Debug|Mixed Platforms.ActiveCfg = Debug|ARM
|
||||
{4C225A82-800B-427B-BA7B-61686A9B347F}.Debug|Mixed Platforms.Build.0 = Debug|ARM
|
||||
{4C225A82-800B-427B-BA7B-61686A9B347F}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{4C225A82-800B-427B-BA7B-61686A9B347F}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{4C225A82-800B-427B-BA7B-61686A9B347F}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{4C225A82-800B-427B-BA7B-61686A9B347F}.Debug|x86.Build.0 = Debug|Win32
|
||||
{4C225A82-800B-427B-BA7B-61686A9B347F}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{4C225A82-800B-427B-BA7B-61686A9B347F}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{4C225A82-800B-427B-BA7B-61686A9B347F}.Release|ARM.Build.0 = Release|ARM
|
||||
{4C225A82-800B-427B-BA7B-61686A9B347F}.Release|Mixed Platforms.ActiveCfg = Release|Win32
|
||||
{4C225A82-800B-427B-BA7B-61686A9B347F}.Release|Mixed Platforms.Build.0 = Release|Win32
|
||||
{4C225A82-800B-427B-BA7B-61686A9B347F}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{4C225A82-800B-427B-BA7B-61686A9B347F}.Release|Win32.Build.0 = Release|Win32
|
||||
{4C225A82-800B-427B-BA7B-61686A9B347F}.Release|x86.ActiveCfg = Release|Win32
|
||||
{4C225A82-800B-427B-BA7B-61686A9B347F}.Release|x86.Build.0 = Release|Win32
|
||||
{027BAD0E-9179-48C1-9733-7AA7E2C2EC70}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{027BAD0E-9179-48C1-9733-7AA7E2C2EC70}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{027BAD0E-9179-48C1-9733-7AA7E2C2EC70}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{027BAD0E-9179-48C1-9733-7AA7E2C2EC70}.Debug|Mixed Platforms.ActiveCfg = Debug|ARM
|
||||
{027BAD0E-9179-48C1-9733-7AA7E2C2EC70}.Debug|Mixed Platforms.Build.0 = Debug|ARM
|
||||
{027BAD0E-9179-48C1-9733-7AA7E2C2EC70}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{027BAD0E-9179-48C1-9733-7AA7E2C2EC70}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{027BAD0E-9179-48C1-9733-7AA7E2C2EC70}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{027BAD0E-9179-48C1-9733-7AA7E2C2EC70}.Debug|x86.Build.0 = Debug|Win32
|
||||
{027BAD0E-9179-48C1-9733-7AA7E2C2EC70}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{027BAD0E-9179-48C1-9733-7AA7E2C2EC70}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{027BAD0E-9179-48C1-9733-7AA7E2C2EC70}.Release|ARM.Build.0 = Release|ARM
|
||||
{027BAD0E-9179-48C1-9733-7AA7E2C2EC70}.Release|Mixed Platforms.ActiveCfg = Release|Win32
|
||||
{027BAD0E-9179-48C1-9733-7AA7E2C2EC70}.Release|Mixed Platforms.Build.0 = Release|Win32
|
||||
{027BAD0E-9179-48C1-9733-7AA7E2C2EC70}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{027BAD0E-9179-48C1-9733-7AA7E2C2EC70}.Release|Win32.Build.0 = Release|Win32
|
||||
{027BAD0E-9179-48C1-9733-7AA7E2C2EC70}.Release|x86.ActiveCfg = Release|Win32
|
||||
{027BAD0E-9179-48C1-9733-7AA7E2C2EC70}.Release|x86.Build.0 = Release|Win32
|
||||
{FFC7B532-0502-4D88-AC98-9E89071CBC97}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{FFC7B532-0502-4D88-AC98-9E89071CBC97}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{FFC7B532-0502-4D88-AC98-9E89071CBC97}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{FFC7B532-0502-4D88-AC98-9E89071CBC97}.Debug|Mixed Platforms.ActiveCfg = Debug|ARM
|
||||
{FFC7B532-0502-4D88-AC98-9E89071CBC97}.Debug|Mixed Platforms.Build.0 = Debug|ARM
|
||||
{FFC7B532-0502-4D88-AC98-9E89071CBC97}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{FFC7B532-0502-4D88-AC98-9E89071CBC97}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{FFC7B532-0502-4D88-AC98-9E89071CBC97}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{FFC7B532-0502-4D88-AC98-9E89071CBC97}.Debug|x86.Build.0 = Debug|Win32
|
||||
{FFC7B532-0502-4D88-AC98-9E89071CBC97}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{FFC7B532-0502-4D88-AC98-9E89071CBC97}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{FFC7B532-0502-4D88-AC98-9E89071CBC97}.Release|ARM.Build.0 = Release|ARM
|
||||
{FFC7B532-0502-4D88-AC98-9E89071CBC97}.Release|Mixed Platforms.ActiveCfg = Release|Win32
|
||||
{FFC7B532-0502-4D88-AC98-9E89071CBC97}.Release|Mixed Platforms.Build.0 = Release|Win32
|
||||
{FFC7B532-0502-4D88-AC98-9E89071CBC97}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{FFC7B532-0502-4D88-AC98-9E89071CBC97}.Release|Win32.Build.0 = Release|Win32
|
||||
{FFC7B532-0502-4D88-AC98-9E89071CBC97}.Release|x86.ActiveCfg = Release|Win32
|
||||
{FFC7B532-0502-4D88-AC98-9E89071CBC97}.Release|x86.Build.0 = Release|Win32
|
||||
{8FA74260-151B-429B-83EF-3CF3EAC8CFD9}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{8FA74260-151B-429B-83EF-3CF3EAC8CFD9}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{8FA74260-151B-429B-83EF-3CF3EAC8CFD9}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{8FA74260-151B-429B-83EF-3CF3EAC8CFD9}.Debug|Mixed Platforms.ActiveCfg = Debug|ARM
|
||||
{8FA74260-151B-429B-83EF-3CF3EAC8CFD9}.Debug|Mixed Platforms.Build.0 = Debug|ARM
|
||||
{8FA74260-151B-429B-83EF-3CF3EAC8CFD9}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{8FA74260-151B-429B-83EF-3CF3EAC8CFD9}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{8FA74260-151B-429B-83EF-3CF3EAC8CFD9}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{8FA74260-151B-429B-83EF-3CF3EAC8CFD9}.Debug|x86.Build.0 = Debug|Win32
|
||||
{8FA74260-151B-429B-83EF-3CF3EAC8CFD9}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{8FA74260-151B-429B-83EF-3CF3EAC8CFD9}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{8FA74260-151B-429B-83EF-3CF3EAC8CFD9}.Release|ARM.Build.0 = Release|ARM
|
||||
{8FA74260-151B-429B-83EF-3CF3EAC8CFD9}.Release|Mixed Platforms.ActiveCfg = Release|Win32
|
||||
{8FA74260-151B-429B-83EF-3CF3EAC8CFD9}.Release|Mixed Platforms.Build.0 = Release|Win32
|
||||
{8FA74260-151B-429B-83EF-3CF3EAC8CFD9}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{8FA74260-151B-429B-83EF-3CF3EAC8CFD9}.Release|Win32.Build.0 = Release|Win32
|
||||
{8FA74260-151B-429B-83EF-3CF3EAC8CFD9}.Release|x86.ActiveCfg = Release|Win32
|
||||
{8FA74260-151B-429B-83EF-3CF3EAC8CFD9}.Release|x86.Build.0 = Release|Win32
|
||||
{746EA080-5BA9-42C5-9E52-EA421C3F3AFD}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{746EA080-5BA9-42C5-9E52-EA421C3F3AFD}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{746EA080-5BA9-42C5-9E52-EA421C3F3AFD}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{746EA080-5BA9-42C5-9E52-EA421C3F3AFD}.Debug|Mixed Platforms.ActiveCfg = Debug|ARM
|
||||
{746EA080-5BA9-42C5-9E52-EA421C3F3AFD}.Debug|Mixed Platforms.Build.0 = Debug|ARM
|
||||
{746EA080-5BA9-42C5-9E52-EA421C3F3AFD}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{746EA080-5BA9-42C5-9E52-EA421C3F3AFD}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{746EA080-5BA9-42C5-9E52-EA421C3F3AFD}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{746EA080-5BA9-42C5-9E52-EA421C3F3AFD}.Debug|x86.Build.0 = Debug|Win32
|
||||
{746EA080-5BA9-42C5-9E52-EA421C3F3AFD}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{746EA080-5BA9-42C5-9E52-EA421C3F3AFD}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{746EA080-5BA9-42C5-9E52-EA421C3F3AFD}.Release|ARM.Build.0 = Release|ARM
|
||||
{746EA080-5BA9-42C5-9E52-EA421C3F3AFD}.Release|Mixed Platforms.ActiveCfg = Release|Win32
|
||||
{746EA080-5BA9-42C5-9E52-EA421C3F3AFD}.Release|Mixed Platforms.Build.0 = Release|Win32
|
||||
{746EA080-5BA9-42C5-9E52-EA421C3F3AFD}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{746EA080-5BA9-42C5-9E52-EA421C3F3AFD}.Release|Win32.Build.0 = Release|Win32
|
||||
{746EA080-5BA9-42C5-9E52-EA421C3F3AFD}.Release|x86.ActiveCfg = Release|Win32
|
||||
{746EA080-5BA9-42C5-9E52-EA421C3F3AFD}.Release|x86.Build.0 = Release|Win32
|
||||
{D5EC8C11-C1D9-47E3-BB82-A93C300FD902}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{D5EC8C11-C1D9-47E3-BB82-A93C300FD902}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{D5EC8C11-C1D9-47E3-BB82-A93C300FD902}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{D5EC8C11-C1D9-47E3-BB82-A93C300FD902}.Debug|Mixed Platforms.ActiveCfg = Debug|ARM
|
||||
{D5EC8C11-C1D9-47E3-BB82-A93C300FD902}.Debug|Mixed Platforms.Build.0 = Debug|ARM
|
||||
{D5EC8C11-C1D9-47E3-BB82-A93C300FD902}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{D5EC8C11-C1D9-47E3-BB82-A93C300FD902}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{D5EC8C11-C1D9-47E3-BB82-A93C300FD902}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{D5EC8C11-C1D9-47E3-BB82-A93C300FD902}.Debug|x86.Build.0 = Debug|Win32
|
||||
{D5EC8C11-C1D9-47E3-BB82-A93C300FD902}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{D5EC8C11-C1D9-47E3-BB82-A93C300FD902}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{D5EC8C11-C1D9-47E3-BB82-A93C300FD902}.Release|ARM.Build.0 = Release|ARM
|
||||
{D5EC8C11-C1D9-47E3-BB82-A93C300FD902}.Release|Mixed Platforms.ActiveCfg = Release|Win32
|
||||
{D5EC8C11-C1D9-47E3-BB82-A93C300FD902}.Release|Mixed Platforms.Build.0 = Release|Win32
|
||||
{D5EC8C11-C1D9-47E3-BB82-A93C300FD902}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{D5EC8C11-C1D9-47E3-BB82-A93C300FD902}.Release|Win32.Build.0 = Release|Win32
|
||||
{D5EC8C11-C1D9-47E3-BB82-A93C300FD902}.Release|x86.ActiveCfg = Release|Win32
|
||||
{D5EC8C11-C1D9-47E3-BB82-A93C300FD902}.Release|x86.Build.0 = Release|Win32
|
||||
{6BD78980-9C71-4341-8775-AD19E9EC7305}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{6BD78980-9C71-4341-8775-AD19E9EC7305}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{6BD78980-9C71-4341-8775-AD19E9EC7305}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{6BD78980-9C71-4341-8775-AD19E9EC7305}.Debug|Mixed Platforms.ActiveCfg = Debug|ARM
|
||||
{6BD78980-9C71-4341-8775-AD19E9EC7305}.Debug|Mixed Platforms.Build.0 = Debug|ARM
|
||||
{6BD78980-9C71-4341-8775-AD19E9EC7305}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{6BD78980-9C71-4341-8775-AD19E9EC7305}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{6BD78980-9C71-4341-8775-AD19E9EC7305}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{6BD78980-9C71-4341-8775-AD19E9EC7305}.Debug|x86.Build.0 = Debug|Win32
|
||||
{6BD78980-9C71-4341-8775-AD19E9EC7305}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{6BD78980-9C71-4341-8775-AD19E9EC7305}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{6BD78980-9C71-4341-8775-AD19E9EC7305}.Release|ARM.Build.0 = Release|ARM
|
||||
{6BD78980-9C71-4341-8775-AD19E9EC7305}.Release|Mixed Platforms.ActiveCfg = Release|Win32
|
||||
{6BD78980-9C71-4341-8775-AD19E9EC7305}.Release|Mixed Platforms.Build.0 = Release|Win32
|
||||
{6BD78980-9C71-4341-8775-AD19E9EC7305}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{6BD78980-9C71-4341-8775-AD19E9EC7305}.Release|Win32.Build.0 = Release|Win32
|
||||
{6BD78980-9C71-4341-8775-AD19E9EC7305}.Release|x86.ActiveCfg = Release|Win32
|
||||
{6BD78980-9C71-4341-8775-AD19E9EC7305}.Release|x86.Build.0 = Release|Win32
|
||||
{902DAF1D-EBF1-4D03-B598-143500A50AB4}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{902DAF1D-EBF1-4D03-B598-143500A50AB4}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{902DAF1D-EBF1-4D03-B598-143500A50AB4}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{902DAF1D-EBF1-4D03-B598-143500A50AB4}.Debug|Mixed Platforms.ActiveCfg = Debug|ARM
|
||||
{902DAF1D-EBF1-4D03-B598-143500A50AB4}.Debug|Mixed Platforms.Build.0 = Debug|ARM
|
||||
{902DAF1D-EBF1-4D03-B598-143500A50AB4}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{902DAF1D-EBF1-4D03-B598-143500A50AB4}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{902DAF1D-EBF1-4D03-B598-143500A50AB4}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{902DAF1D-EBF1-4D03-B598-143500A50AB4}.Debug|x86.Build.0 = Debug|Win32
|
||||
{902DAF1D-EBF1-4D03-B598-143500A50AB4}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{902DAF1D-EBF1-4D03-B598-143500A50AB4}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{902DAF1D-EBF1-4D03-B598-143500A50AB4}.Release|ARM.Build.0 = Release|ARM
|
||||
{902DAF1D-EBF1-4D03-B598-143500A50AB4}.Release|Mixed Platforms.ActiveCfg = Release|Win32
|
||||
{902DAF1D-EBF1-4D03-B598-143500A50AB4}.Release|Mixed Platforms.Build.0 = Release|Win32
|
||||
{902DAF1D-EBF1-4D03-B598-143500A50AB4}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{902DAF1D-EBF1-4D03-B598-143500A50AB4}.Release|Win32.Build.0 = Release|Win32
|
||||
{902DAF1D-EBF1-4D03-B598-143500A50AB4}.Release|x86.ActiveCfg = Release|Win32
|
||||
{902DAF1D-EBF1-4D03-B598-143500A50AB4}.Release|x86.Build.0 = Release|Win32
|
||||
{D22BD217-D0F8-4274-9B3A-F3F35F46482C}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{D22BD217-D0F8-4274-9B3A-F3F35F46482C}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{D22BD217-D0F8-4274-9B3A-F3F35F46482C}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{D22BD217-D0F8-4274-9B3A-F3F35F46482C}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
|
||||
{D22BD217-D0F8-4274-9B3A-F3F35F46482C}.Debug|Mixed Platforms.Build.0 = Debug|Win32
|
||||
{D22BD217-D0F8-4274-9B3A-F3F35F46482C}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{D22BD217-D0F8-4274-9B3A-F3F35F46482C}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{D22BD217-D0F8-4274-9B3A-F3F35F46482C}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{D22BD217-D0F8-4274-9B3A-F3F35F46482C}.Debug|x86.Build.0 = Debug|Win32
|
||||
{D22BD217-D0F8-4274-9B3A-F3F35F46482C}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{D22BD217-D0F8-4274-9B3A-F3F35F46482C}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{D22BD217-D0F8-4274-9B3A-F3F35F46482C}.Release|ARM.Build.0 = Release|ARM
|
||||
{D22BD217-D0F8-4274-9B3A-F3F35F46482C}.Release|Mixed Platforms.ActiveCfg = Release|Win32
|
||||
{D22BD217-D0F8-4274-9B3A-F3F35F46482C}.Release|Mixed Platforms.Build.0 = Release|Win32
|
||||
{D22BD217-D0F8-4274-9B3A-F3F35F46482C}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{D22BD217-D0F8-4274-9B3A-F3F35F46482C}.Release|Win32.Build.0 = Release|Win32
|
||||
{D22BD217-D0F8-4274-9B3A-F3F35F46482C}.Release|x86.ActiveCfg = Release|Win32
|
||||
{D22BD217-D0F8-4274-9B3A-F3F35F46482C}.Release|x86.Build.0 = Release|Win32
|
||||
{1C4E6DA0-B8C7-4A05-A58E-54A6ED07C8DF}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{1C4E6DA0-B8C7-4A05-A58E-54A6ED07C8DF}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{1C4E6DA0-B8C7-4A05-A58E-54A6ED07C8DF}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{1C4E6DA0-B8C7-4A05-A58E-54A6ED07C8DF}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
|
||||
{1C4E6DA0-B8C7-4A05-A58E-54A6ED07C8DF}.Debug|Mixed Platforms.Build.0 = Debug|Win32
|
||||
{1C4E6DA0-B8C7-4A05-A58E-54A6ED07C8DF}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{1C4E6DA0-B8C7-4A05-A58E-54A6ED07C8DF}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{1C4E6DA0-B8C7-4A05-A58E-54A6ED07C8DF}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{1C4E6DA0-B8C7-4A05-A58E-54A6ED07C8DF}.Debug|x86.Build.0 = Debug|Win32
|
||||
{1C4E6DA0-B8C7-4A05-A58E-54A6ED07C8DF}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{1C4E6DA0-B8C7-4A05-A58E-54A6ED07C8DF}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{1C4E6DA0-B8C7-4A05-A58E-54A6ED07C8DF}.Release|ARM.Build.0 = Release|ARM
|
||||
{1C4E6DA0-B8C7-4A05-A58E-54A6ED07C8DF}.Release|Mixed Platforms.ActiveCfg = Release|Win32
|
||||
{1C4E6DA0-B8C7-4A05-A58E-54A6ED07C8DF}.Release|Mixed Platforms.Build.0 = Release|Win32
|
||||
{1C4E6DA0-B8C7-4A05-A58E-54A6ED07C8DF}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{1C4E6DA0-B8C7-4A05-A58E-54A6ED07C8DF}.Release|Win32.Build.0 = Release|Win32
|
||||
{1C4E6DA0-B8C7-4A05-A58E-54A6ED07C8DF}.Release|x86.ActiveCfg = Release|Win32
|
||||
{1C4E6DA0-B8C7-4A05-A58E-54A6ED07C8DF}.Release|x86.Build.0 = Release|Win32
|
||||
{8E216BF3-2DD8-4794-8E97-B1AED301ED4D}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{8E216BF3-2DD8-4794-8E97-B1AED301ED4D}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{8E216BF3-2DD8-4794-8E97-B1AED301ED4D}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{8E216BF3-2DD8-4794-8E97-B1AED301ED4D}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
|
||||
{8E216BF3-2DD8-4794-8E97-B1AED301ED4D}.Debug|Mixed Platforms.Build.0 = Debug|Win32
|
||||
{8E216BF3-2DD8-4794-8E97-B1AED301ED4D}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{8E216BF3-2DD8-4794-8E97-B1AED301ED4D}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{8E216BF3-2DD8-4794-8E97-B1AED301ED4D}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{8E216BF3-2DD8-4794-8E97-B1AED301ED4D}.Debug|x86.Build.0 = Debug|Win32
|
||||
{8E216BF3-2DD8-4794-8E97-B1AED301ED4D}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{8E216BF3-2DD8-4794-8E97-B1AED301ED4D}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{8E216BF3-2DD8-4794-8E97-B1AED301ED4D}.Release|ARM.Build.0 = Release|ARM
|
||||
{8E216BF3-2DD8-4794-8E97-B1AED301ED4D}.Release|Mixed Platforms.ActiveCfg = Release|Win32
|
||||
{8E216BF3-2DD8-4794-8E97-B1AED301ED4D}.Release|Mixed Platforms.Build.0 = Release|Win32
|
||||
{8E216BF3-2DD8-4794-8E97-B1AED301ED4D}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{8E216BF3-2DD8-4794-8E97-B1AED301ED4D}.Release|Win32.Build.0 = Release|Win32
|
||||
{8E216BF3-2DD8-4794-8E97-B1AED301ED4D}.Release|x86.ActiveCfg = Release|Win32
|
||||
{8E216BF3-2DD8-4794-8E97-B1AED301ED4D}.Release|x86.Build.0 = Release|Win32
|
||||
{072FAD20-7007-4DA2-B2E7-16CE2B219F67}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{072FAD20-7007-4DA2-B2E7-16CE2B219F67}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{072FAD20-7007-4DA2-B2E7-16CE2B219F67}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{072FAD20-7007-4DA2-B2E7-16CE2B219F67}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
|
||||
{072FAD20-7007-4DA2-B2E7-16CE2B219F67}.Debug|Mixed Platforms.Build.0 = Debug|Win32
|
||||
{072FAD20-7007-4DA2-B2E7-16CE2B219F67}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{072FAD20-7007-4DA2-B2E7-16CE2B219F67}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{072FAD20-7007-4DA2-B2E7-16CE2B219F67}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{072FAD20-7007-4DA2-B2E7-16CE2B219F67}.Debug|x86.Build.0 = Debug|Win32
|
||||
{072FAD20-7007-4DA2-B2E7-16CE2B219F67}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{072FAD20-7007-4DA2-B2E7-16CE2B219F67}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{072FAD20-7007-4DA2-B2E7-16CE2B219F67}.Release|ARM.Build.0 = Release|ARM
|
||||
{072FAD20-7007-4DA2-B2E7-16CE2B219F67}.Release|Mixed Platforms.ActiveCfg = Release|Win32
|
||||
{072FAD20-7007-4DA2-B2E7-16CE2B219F67}.Release|Mixed Platforms.Build.0 = Release|Win32
|
||||
{072FAD20-7007-4DA2-B2E7-16CE2B219F67}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{072FAD20-7007-4DA2-B2E7-16CE2B219F67}.Release|Win32.Build.0 = Release|Win32
|
||||
{072FAD20-7007-4DA2-B2E7-16CE2B219F67}.Release|x86.ActiveCfg = Release|Win32
|
||||
{072FAD20-7007-4DA2-B2E7-16CE2B219F67}.Release|x86.Build.0 = Release|Win32
|
||||
{36B528F9-FB79-4078-A16B-0A7442581BB7}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{36B528F9-FB79-4078-A16B-0A7442581BB7}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{36B528F9-FB79-4078-A16B-0A7442581BB7}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{36B528F9-FB79-4078-A16B-0A7442581BB7}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
|
||||
{36B528F9-FB79-4078-A16B-0A7442581BB7}.Debug|Mixed Platforms.Build.0 = Debug|Win32
|
||||
{36B528F9-FB79-4078-A16B-0A7442581BB7}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{36B528F9-FB79-4078-A16B-0A7442581BB7}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{36B528F9-FB79-4078-A16B-0A7442581BB7}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{36B528F9-FB79-4078-A16B-0A7442581BB7}.Debug|x86.Build.0 = Debug|Win32
|
||||
{36B528F9-FB79-4078-A16B-0A7442581BB7}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{36B528F9-FB79-4078-A16B-0A7442581BB7}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{36B528F9-FB79-4078-A16B-0A7442581BB7}.Release|ARM.Build.0 = Release|ARM
|
||||
{36B528F9-FB79-4078-A16B-0A7442581BB7}.Release|Mixed Platforms.ActiveCfg = Release|Win32
|
||||
{36B528F9-FB79-4078-A16B-0A7442581BB7}.Release|Mixed Platforms.Build.0 = Release|Win32
|
||||
{36B528F9-FB79-4078-A16B-0A7442581BB7}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{36B528F9-FB79-4078-A16B-0A7442581BB7}.Release|Win32.Build.0 = Release|Win32
|
||||
{36B528F9-FB79-4078-A16B-0A7442581BB7}.Release|x86.ActiveCfg = Release|Win32
|
||||
{36B528F9-FB79-4078-A16B-0A7442581BB7}.Release|x86.Build.0 = Release|Win32
|
||||
{9924AC72-F96C-4E56-94D9-2B025DA43C6B}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{9924AC72-F96C-4E56-94D9-2B025DA43C6B}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{9924AC72-F96C-4E56-94D9-2B025DA43C6B}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{9924AC72-F96C-4E56-94D9-2B025DA43C6B}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
|
||||
{9924AC72-F96C-4E56-94D9-2B025DA43C6B}.Debug|Mixed Platforms.Build.0 = Debug|Win32
|
||||
{9924AC72-F96C-4E56-94D9-2B025DA43C6B}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{9924AC72-F96C-4E56-94D9-2B025DA43C6B}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{9924AC72-F96C-4E56-94D9-2B025DA43C6B}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{9924AC72-F96C-4E56-94D9-2B025DA43C6B}.Debug|x86.Build.0 = Debug|Win32
|
||||
{9924AC72-F96C-4E56-94D9-2B025DA43C6B}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{9924AC72-F96C-4E56-94D9-2B025DA43C6B}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{9924AC72-F96C-4E56-94D9-2B025DA43C6B}.Release|ARM.Build.0 = Release|ARM
|
||||
{9924AC72-F96C-4E56-94D9-2B025DA43C6B}.Release|Mixed Platforms.ActiveCfg = Release|Win32
|
||||
{9924AC72-F96C-4E56-94D9-2B025DA43C6B}.Release|Mixed Platforms.Build.0 = Release|Win32
|
||||
{9924AC72-F96C-4E56-94D9-2B025DA43C6B}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{9924AC72-F96C-4E56-94D9-2B025DA43C6B}.Release|Win32.Build.0 = Release|Win32
|
||||
{9924AC72-F96C-4E56-94D9-2B025DA43C6B}.Release|x86.ActiveCfg = Release|Win32
|
||||
{9924AC72-F96C-4E56-94D9-2B025DA43C6B}.Release|x86.Build.0 = Release|Win32
|
||||
{018A4428-535C-4566-9AE0-E93AFF0D3ED2}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{018A4428-535C-4566-9AE0-E93AFF0D3ED2}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{018A4428-535C-4566-9AE0-E93AFF0D3ED2}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{018A4428-535C-4566-9AE0-E93AFF0D3ED2}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
|
||||
{018A4428-535C-4566-9AE0-E93AFF0D3ED2}.Debug|Mixed Platforms.Build.0 = Debug|Win32
|
||||
{018A4428-535C-4566-9AE0-E93AFF0D3ED2}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{018A4428-535C-4566-9AE0-E93AFF0D3ED2}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{018A4428-535C-4566-9AE0-E93AFF0D3ED2}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{018A4428-535C-4566-9AE0-E93AFF0D3ED2}.Debug|x86.Build.0 = Debug|Win32
|
||||
{018A4428-535C-4566-9AE0-E93AFF0D3ED2}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{018A4428-535C-4566-9AE0-E93AFF0D3ED2}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{018A4428-535C-4566-9AE0-E93AFF0D3ED2}.Release|ARM.Build.0 = Release|ARM
|
||||
{018A4428-535C-4566-9AE0-E93AFF0D3ED2}.Release|Mixed Platforms.ActiveCfg = Release|Win32
|
||||
{018A4428-535C-4566-9AE0-E93AFF0D3ED2}.Release|Mixed Platforms.Build.0 = Release|Win32
|
||||
{018A4428-535C-4566-9AE0-E93AFF0D3ED2}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{018A4428-535C-4566-9AE0-E93AFF0D3ED2}.Release|Win32.Build.0 = Release|Win32
|
||||
{018A4428-535C-4566-9AE0-E93AFF0D3ED2}.Release|x86.ActiveCfg = Release|Win32
|
||||
{018A4428-535C-4566-9AE0-E93AFF0D3ED2}.Release|x86.Build.0 = Release|Win32
|
||||
{88191E75-2993-48D7-AA76-652F274EF0FE}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{88191E75-2993-48D7-AA76-652F274EF0FE}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{88191E75-2993-48D7-AA76-652F274EF0FE}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{88191E75-2993-48D7-AA76-652F274EF0FE}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
|
||||
{88191E75-2993-48D7-AA76-652F274EF0FE}.Debug|Mixed Platforms.Build.0 = Debug|Win32
|
||||
{88191E75-2993-48D7-AA76-652F274EF0FE}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{88191E75-2993-48D7-AA76-652F274EF0FE}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{88191E75-2993-48D7-AA76-652F274EF0FE}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{88191E75-2993-48D7-AA76-652F274EF0FE}.Debug|x86.Build.0 = Debug|Win32
|
||||
{88191E75-2993-48D7-AA76-652F274EF0FE}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{88191E75-2993-48D7-AA76-652F274EF0FE}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{88191E75-2993-48D7-AA76-652F274EF0FE}.Release|ARM.Build.0 = Release|ARM
|
||||
{88191E75-2993-48D7-AA76-652F274EF0FE}.Release|Mixed Platforms.ActiveCfg = Release|Win32
|
||||
{88191E75-2993-48D7-AA76-652F274EF0FE}.Release|Mixed Platforms.Build.0 = Release|Win32
|
||||
{88191E75-2993-48D7-AA76-652F274EF0FE}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{88191E75-2993-48D7-AA76-652F274EF0FE}.Release|Win32.Build.0 = Release|Win32
|
||||
{88191E75-2993-48D7-AA76-652F274EF0FE}.Release|x86.ActiveCfg = Release|Win32
|
||||
{88191E75-2993-48D7-AA76-652F274EF0FE}.Release|x86.Build.0 = Release|Win32
|
||||
{7AC65D2A-6981-4D17-856D-C37A522739D8}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{7AC65D2A-6981-4D17-856D-C37A522739D8}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{7AC65D2A-6981-4D17-856D-C37A522739D8}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{7AC65D2A-6981-4D17-856D-C37A522739D8}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
|
||||
{7AC65D2A-6981-4D17-856D-C37A522739D8}.Debug|Mixed Platforms.Build.0 = Debug|Win32
|
||||
{7AC65D2A-6981-4D17-856D-C37A522739D8}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{7AC65D2A-6981-4D17-856D-C37A522739D8}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{7AC65D2A-6981-4D17-856D-C37A522739D8}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{7AC65D2A-6981-4D17-856D-C37A522739D8}.Debug|x86.Build.0 = Debug|Win32
|
||||
{7AC65D2A-6981-4D17-856D-C37A522739D8}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{7AC65D2A-6981-4D17-856D-C37A522739D8}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{7AC65D2A-6981-4D17-856D-C37A522739D8}.Release|ARM.Build.0 = Release|ARM
|
||||
{7AC65D2A-6981-4D17-856D-C37A522739D8}.Release|Mixed Platforms.ActiveCfg = Release|Win32
|
||||
{7AC65D2A-6981-4D17-856D-C37A522739D8}.Release|Mixed Platforms.Build.0 = Release|Win32
|
||||
{7AC65D2A-6981-4D17-856D-C37A522739D8}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{7AC65D2A-6981-4D17-856D-C37A522739D8}.Release|Win32.Build.0 = Release|Win32
|
||||
{7AC65D2A-6981-4D17-856D-C37A522739D8}.Release|x86.ActiveCfg = Release|Win32
|
||||
{7AC65D2A-6981-4D17-856D-C37A522739D8}.Release|x86.Build.0 = Release|Win32
|
||||
{E9F8C5D1-13A2-46B6-A9BC-878030D4BE09}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{E9F8C5D1-13A2-46B6-A9BC-878030D4BE09}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{E9F8C5D1-13A2-46B6-A9BC-878030D4BE09}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{E9F8C5D1-13A2-46B6-A9BC-878030D4BE09}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
|
||||
{E9F8C5D1-13A2-46B6-A9BC-878030D4BE09}.Debug|Mixed Platforms.Build.0 = Debug|Win32
|
||||
{E9F8C5D1-13A2-46B6-A9BC-878030D4BE09}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{E9F8C5D1-13A2-46B6-A9BC-878030D4BE09}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{E9F8C5D1-13A2-46B6-A9BC-878030D4BE09}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{E9F8C5D1-13A2-46B6-A9BC-878030D4BE09}.Debug|x86.Build.0 = Debug|Win32
|
||||
{E9F8C5D1-13A2-46B6-A9BC-878030D4BE09}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{E9F8C5D1-13A2-46B6-A9BC-878030D4BE09}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{E9F8C5D1-13A2-46B6-A9BC-878030D4BE09}.Release|ARM.Build.0 = Release|ARM
|
||||
{E9F8C5D1-13A2-46B6-A9BC-878030D4BE09}.Release|Mixed Platforms.ActiveCfg = Release|Win32
|
||||
{E9F8C5D1-13A2-46B6-A9BC-878030D4BE09}.Release|Mixed Platforms.Build.0 = Release|Win32
|
||||
{E9F8C5D1-13A2-46B6-A9BC-878030D4BE09}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{E9F8C5D1-13A2-46B6-A9BC-878030D4BE09}.Release|Win32.Build.0 = Release|Win32
|
||||
{E9F8C5D1-13A2-46B6-A9BC-878030D4BE09}.Release|x86.ActiveCfg = Release|Win32
|
||||
{E9F8C5D1-13A2-46B6-A9BC-878030D4BE09}.Release|x86.Build.0 = Release|Win32
|
||||
{59500DD1-B192-4DDF-A402-8A8E3739E032}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{59500DD1-B192-4DDF-A402-8A8E3739E032}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{59500DD1-B192-4DDF-A402-8A8E3739E032}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{59500DD1-B192-4DDF-A402-8A8E3739E032}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
|
||||
{59500DD1-B192-4DDF-A402-8A8E3739E032}.Debug|Mixed Platforms.Build.0 = Debug|Win32
|
||||
{59500DD1-B192-4DDF-A402-8A8E3739E032}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{59500DD1-B192-4DDF-A402-8A8E3739E032}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{59500DD1-B192-4DDF-A402-8A8E3739E032}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{59500DD1-B192-4DDF-A402-8A8E3739E032}.Debug|x86.Build.0 = Debug|Win32
|
||||
{59500DD1-B192-4DDF-A402-8A8E3739E032}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{59500DD1-B192-4DDF-A402-8A8E3739E032}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{59500DD1-B192-4DDF-A402-8A8E3739E032}.Release|ARM.Build.0 = Release|ARM
|
||||
{59500DD1-B192-4DDF-A402-8A8E3739E032}.Release|Mixed Platforms.ActiveCfg = Release|Win32
|
||||
{59500DD1-B192-4DDF-A402-8A8E3739E032}.Release|Mixed Platforms.Build.0 = Release|Win32
|
||||
{59500DD1-B192-4DDF-A402-8A8E3739E032}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{59500DD1-B192-4DDF-A402-8A8E3739E032}.Release|Win32.Build.0 = Release|Win32
|
||||
{59500DD1-B192-4DDF-A402-8A8E3739E032}.Release|x86.ActiveCfg = Release|Win32
|
||||
{59500DD1-B192-4DDF-A402-8A8E3739E032}.Release|x86.Build.0 = Release|Win32
|
||||
{5DFA07B4-0BE9-46A9-BA32-FDF5A55C580B}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{5DFA07B4-0BE9-46A9-BA32-FDF5A55C580B}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{5DFA07B4-0BE9-46A9-BA32-FDF5A55C580B}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{5DFA07B4-0BE9-46A9-BA32-FDF5A55C580B}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
|
||||
{5DFA07B4-0BE9-46A9-BA32-FDF5A55C580B}.Debug|Mixed Platforms.Build.0 = Debug|Win32
|
||||
{5DFA07B4-0BE9-46A9-BA32-FDF5A55C580B}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{5DFA07B4-0BE9-46A9-BA32-FDF5A55C580B}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{5DFA07B4-0BE9-46A9-BA32-FDF5A55C580B}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{5DFA07B4-0BE9-46A9-BA32-FDF5A55C580B}.Debug|x86.Build.0 = Debug|Win32
|
||||
{5DFA07B4-0BE9-46A9-BA32-FDF5A55C580B}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{5DFA07B4-0BE9-46A9-BA32-FDF5A55C580B}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{5DFA07B4-0BE9-46A9-BA32-FDF5A55C580B}.Release|ARM.Build.0 = Release|ARM
|
||||
{5DFA07B4-0BE9-46A9-BA32-FDF5A55C580B}.Release|Mixed Platforms.ActiveCfg = Release|Win32
|
||||
{5DFA07B4-0BE9-46A9-BA32-FDF5A55C580B}.Release|Mixed Platforms.Build.0 = Release|Win32
|
||||
{5DFA07B4-0BE9-46A9-BA32-FDF5A55C580B}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{5DFA07B4-0BE9-46A9-BA32-FDF5A55C580B}.Release|Win32.Build.0 = Release|Win32
|
||||
{5DFA07B4-0BE9-46A9-BA32-FDF5A55C580B}.Release|x86.ActiveCfg = Release|Win32
|
||||
{5DFA07B4-0BE9-46A9-BA32-FDF5A55C580B}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
<Application
|
||||
x:Class="LibLinphoneTester_wp8.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
|
||||
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone">
|
||||
|
||||
<!--Application Resources-->
|
||||
<Application.Resources>
|
||||
<local:LocalizedStrings xmlns:local="clr-namespace:LibLinphoneTester_wp8" x:Key="LocalizedStrings"/>
|
||||
</Application.Resources>
|
||||
|
||||
<Application.ApplicationLifetimeObjects>
|
||||
<!--Required object that handles lifetime events for the application-->
|
||||
<shell:PhoneApplicationService
|
||||
Launching="Application_Launching" Closing="Application_Closing"
|
||||
Activated="Application_Activated" Deactivated="Application_Deactivated"/>
|
||||
</Application.ApplicationLifetimeObjects>
|
||||
|
||||
</Application>
|
||||
|
|
@ -0,0 +1,234 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Resources;
|
||||
using System.Windows;
|
||||
using System.Windows.Markup;
|
||||
using System.Windows.Navigation;
|
||||
using Microsoft.Phone.Controls;
|
||||
using Microsoft.Phone.Shell;
|
||||
using LibLinphoneTester_wp8.Resources;
|
||||
using linphone_tester_native;
|
||||
|
||||
namespace LibLinphoneTester_wp8
|
||||
{
|
||||
public partial class App : Application
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides easy access to the root frame of the Phone Application.
|
||||
/// </summary>
|
||||
/// <returns>The root frame of the Phone Application.</returns>
|
||||
public static PhoneApplicationFrame RootFrame { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for the Application object.
|
||||
/// </summary>
|
||||
public App()
|
||||
{
|
||||
// Global handler for uncaught exceptions.
|
||||
UnhandledException += Application_UnhandledException;
|
||||
|
||||
// Standard XAML initialization
|
||||
InitializeComponent();
|
||||
|
||||
// Phone-specific initialization
|
||||
InitializePhoneApplication();
|
||||
|
||||
// Language display initialization
|
||||
InitializeLanguage();
|
||||
|
||||
// Show graphics profiling information while debugging.
|
||||
if (Debugger.IsAttached)
|
||||
{
|
||||
// Display the current frame rate counters.
|
||||
Application.Current.Host.Settings.EnableFrameRateCounter = true;
|
||||
|
||||
// Show the areas of the app that are being redrawn in each frame.
|
||||
//Application.Current.Host.Settings.EnableRedrawRegions = true;
|
||||
|
||||
// Enable non-production analysis visualization mode,
|
||||
// which shows areas of a page that are handed off to GPU with a colored overlay.
|
||||
//Application.Current.Host.Settings.EnableCacheVisualization = true;
|
||||
|
||||
// Prevent the screen from turning off while under the debugger by disabling
|
||||
// the application's idle detection.
|
||||
// Caution:- Use this under debug mode only. Application that disables user idle detection will continue to run
|
||||
// and consume battery power when the user is not using the phone.
|
||||
PhoneApplicationService.Current.UserIdleDetectionMode = IdleDetectionMode.Disabled;
|
||||
}
|
||||
|
||||
tester = new LinphoneTesterNative();
|
||||
suite = null;
|
||||
}
|
||||
|
||||
// Code to execute when the application is launching (eg, from Start)
|
||||
// This code will not execute when the application is reactivated
|
||||
private void Application_Launching(object sender, LaunchingEventArgs e)
|
||||
{
|
||||
}
|
||||
|
||||
// Code to execute when the application is activated (brought to foreground)
|
||||
// This code will not execute when the application is first launched
|
||||
private void Application_Activated(object sender, ActivatedEventArgs e)
|
||||
{
|
||||
}
|
||||
|
||||
// Code to execute when the application is deactivated (sent to background)
|
||||
// This code will not execute when the application is closing
|
||||
private void Application_Deactivated(object sender, DeactivatedEventArgs e)
|
||||
{
|
||||
}
|
||||
|
||||
// Code to execute when the application is closing (eg, user hit Back)
|
||||
// This code will not execute when the application is deactivated
|
||||
private void Application_Closing(object sender, ClosingEventArgs e)
|
||||
{
|
||||
}
|
||||
|
||||
// Code to execute if a navigation fails
|
||||
private void RootFrame_NavigationFailed(object sender, NavigationFailedEventArgs e)
|
||||
{
|
||||
if (Debugger.IsAttached)
|
||||
{
|
||||
// A navigation has failed; break into the debugger
|
||||
Debugger.Break();
|
||||
}
|
||||
}
|
||||
|
||||
// Code to execute on Unhandled Exceptions
|
||||
private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
|
||||
{
|
||||
if (Debugger.IsAttached)
|
||||
{
|
||||
// An unhandled exception has occurred; break into the debugger
|
||||
Debugger.Break();
|
||||
}
|
||||
}
|
||||
|
||||
#region Phone application initialization
|
||||
|
||||
// Avoid double-initialization
|
||||
private bool phoneApplicationInitialized = false;
|
||||
|
||||
// Do not add any additional code to this method
|
||||
private void InitializePhoneApplication()
|
||||
{
|
||||
if (phoneApplicationInitialized)
|
||||
return;
|
||||
|
||||
// Create the frame but don't set it as RootVisual yet; this allows the splash
|
||||
// screen to remain active until the application is ready to render.
|
||||
RootFrame = new PhoneApplicationFrame();
|
||||
RootFrame.Navigated += CompleteInitializePhoneApplication;
|
||||
|
||||
// Handle navigation failures
|
||||
RootFrame.NavigationFailed += RootFrame_NavigationFailed;
|
||||
|
||||
// Handle reset requests for clearing the backstack
|
||||
RootFrame.Navigated += CheckForResetNavigation;
|
||||
|
||||
// Ensure we don't initialize again
|
||||
phoneApplicationInitialized = true;
|
||||
}
|
||||
|
||||
// Do not add any additional code to this method
|
||||
private void CompleteInitializePhoneApplication(object sender, NavigationEventArgs e)
|
||||
{
|
||||
// Set the root visual to allow the application to render
|
||||
if (RootVisual != RootFrame)
|
||||
RootVisual = RootFrame;
|
||||
|
||||
// Remove this handler since it is no longer needed
|
||||
RootFrame.Navigated -= CompleteInitializePhoneApplication;
|
||||
}
|
||||
|
||||
private void CheckForResetNavigation(object sender, NavigationEventArgs e)
|
||||
{
|
||||
// If the app has received a 'reset' navigation, then we need to check
|
||||
// on the next navigation to see if the page stack should be reset
|
||||
if (e.NavigationMode == NavigationMode.Reset)
|
||||
RootFrame.Navigated += ClearBackStackAfterReset;
|
||||
}
|
||||
|
||||
private void ClearBackStackAfterReset(object sender, NavigationEventArgs e)
|
||||
{
|
||||
// Unregister the event so it doesn't get called again
|
||||
RootFrame.Navigated -= ClearBackStackAfterReset;
|
||||
|
||||
// Only clear the stack for 'new' (forward) and 'refresh' navigations
|
||||
if (e.NavigationMode != NavigationMode.New && e.NavigationMode != NavigationMode.Refresh)
|
||||
return;
|
||||
|
||||
// For UI consistency, clear the entire page stack
|
||||
while (RootFrame.RemoveBackEntry() != null)
|
||||
{
|
||||
; // do nothing
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// Initialize the app's font and flow direction as defined in its localized resource strings.
|
||||
//
|
||||
// To ensure that the font of your application is aligned with its supported languages and that the
|
||||
// FlowDirection for each of those languages follows its traditional direction, ResourceLanguage
|
||||
// and ResourceFlowDirection should be initialized in each resx file to match these values with that
|
||||
// file's culture. For example:
|
||||
//
|
||||
// AppResources.es-ES.resx
|
||||
// ResourceLanguage's value should be "es-ES"
|
||||
// ResourceFlowDirection's value should be "LeftToRight"
|
||||
//
|
||||
// AppResources.ar-SA.resx
|
||||
// ResourceLanguage's value should be "ar-SA"
|
||||
// ResourceFlowDirection's value should be "RightToLeft"
|
||||
//
|
||||
// For more info on localizing Windows Phone apps see http://go.microsoft.com/fwlink/?LinkId=262072.
|
||||
//
|
||||
private void InitializeLanguage()
|
||||
{
|
||||
try
|
||||
{
|
||||
// Set the font to match the display language defined by the
|
||||
// ResourceLanguage resource string for each supported language.
|
||||
//
|
||||
// Fall back to the font of the neutral language if the Display
|
||||
// language of the phone is not supported.
|
||||
//
|
||||
// If a compiler error is hit then ResourceLanguage is missing from
|
||||
// the resource file.
|
||||
RootFrame.Language = XmlLanguage.GetLanguage(AppResources.ResourceLanguage);
|
||||
|
||||
// Set the FlowDirection of all elements under the root frame based
|
||||
// on the ResourceFlowDirection resource string for each
|
||||
// supported language.
|
||||
//
|
||||
// If a compiler error is hit then ResourceFlowDirection is missing from
|
||||
// the resource file.
|
||||
FlowDirection flow = (FlowDirection)Enum.Parse(typeof(FlowDirection), AppResources.ResourceFlowDirection);
|
||||
RootFrame.FlowDirection = flow;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// If an exception is caught here it is most likely due to either
|
||||
// ResourceLangauge not being correctly set to a supported language
|
||||
// code or ResourceFlowDirection is set to a value other than LeftToRight
|
||||
// or RightToLeft.
|
||||
|
||||
if (Debugger.IsAttached)
|
||||
{
|
||||
Debugger.Break();
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public bool suiteRunning()
|
||||
{
|
||||
return (suite != null) && (suite.running);
|
||||
}
|
||||
|
||||
public LinphoneTesterNative tester { get; set; }
|
||||
public UnitTestSuite suite { get; set; }
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 8.8 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 9.7 KiB |
|
After Width: | Height: | Size: 8.9 KiB |
|
After Width: | Height: | Size: 3.6 KiB |
|
After Width: | Height: | Size: 4.8 KiB |
|
After Width: | Height: | Size: 3.6 KiB |
|
|
@ -0,0 +1,6 @@
|
|||
[net]
|
||||
mtu=1300
|
||||
|
||||
[sip]
|
||||
ping_with_options=0
|
||||
sip_random_port=1
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
[sip]
|
||||
sip_port=5092
|
||||
sip_tcp_port=5092
|
||||
sip_tls_port=5093
|
||||
default_proxy=0
|
||||
ping_with_options=0
|
||||
register_only_when_network_is_up=0
|
||||
|
||||
[auth_info_0]
|
||||
username=laure
|
||||
userid=laure
|
||||
passwd=secret
|
||||
realm="sip.example.org"
|
||||
|
||||
|
||||
[proxy_0]
|
||||
reg_proxy=sip.example.org
|
||||
reg_identity=sip:laure@sip.example.org
|
||||
reg_expires=3600
|
||||
reg_sendregister=1
|
||||
publish=0
|
||||
dial_escape_plus=0
|
||||
|
||||
|
||||
[rtp]
|
||||
audio_rtp_port=9010
|
||||
video_rtp_port=9012
|
||||
|
||||
[video]
|
||||
display=0
|
||||
capture=0
|
||||
show_local=0
|
||||
size=vga
|
||||
enabled=0
|
||||
self_view=0
|
||||
automatically_initiate=0
|
||||
automatically_accept=0
|
||||
device=StaticImage: Static picture
|
||||
|
||||
[sound]
|
||||
echocancellation=0 #to not overload cpu in case of VG
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
[sip]
|
||||
sip_port=5082
|
||||
sip_tcp_port=5082
|
||||
sip_tls_port=5083
|
||||
default_proxy=0
|
||||
ping_with_options=0
|
||||
register_only_when_network_is_up=0
|
||||
incoming_calls_early_media=1
|
||||
|
||||
[auth_info_0]
|
||||
username=marie
|
||||
userid=marie
|
||||
passwd=secret
|
||||
realm="sip.example.org"
|
||||
|
||||
|
||||
[proxy_0]
|
||||
reg_proxy=sip.example.org;transport=tcp
|
||||
reg_route=sip.example.org;transport=tcp;lr
|
||||
reg_identity=sip:marie@sip.example.org
|
||||
reg_expires=3600
|
||||
reg_sendregister=1
|
||||
publish=0
|
||||
dial_escape_plus=0
|
||||
|
||||
[friend_0]
|
||||
url="Paupoche" <sip:pauline@sip.example.org>
|
||||
pol=accept
|
||||
subscribe=0
|
||||
|
||||
|
||||
[rtp]
|
||||
audio_rtp_port=8070
|
||||
video_rtp_port=8072
|
||||
|
||||
[video]
|
||||
display=0
|
||||
capture=0
|
||||
show_local=0
|
||||
size=vga
|
||||
enabled=0
|
||||
self_view=0
|
||||
automatically_initiate=0
|
||||
automatically_accept=0
|
||||
device=StaticImage: Static picture
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
[sip]
|
||||
sip_port=5082
|
||||
sip_tcp_port=5082
|
||||
sip_tls_port=5083
|
||||
default_proxy=0
|
||||
ping_with_options=0
|
||||
register_only_when_network_is_up=0
|
||||
|
||||
[auth_info_0]
|
||||
username=marie
|
||||
userid=marie
|
||||
passwd=secret
|
||||
realm="sip.example.org"
|
||||
|
||||
|
||||
[proxy_0]
|
||||
reg_proxy=sip.example.org;transport=tcp
|
||||
reg_route=sip.example.org;transport=tcp;lr
|
||||
reg_identity=sip:marie@sip.example.org
|
||||
reg_expires=3600
|
||||
reg_sendregister=1
|
||||
publish=0
|
||||
dial_escape_plus=0
|
||||
|
||||
[friend_0]
|
||||
url="Paupoche" <sip:pauline@sip.example.org>
|
||||
pol=accept
|
||||
subscribe=0
|
||||
|
||||
|
||||
[rtp]
|
||||
audio_rtp_port=8070
|
||||
video_rtp_port=8072
|
||||
|
||||
[video]
|
||||
display=0
|
||||
capture=0
|
||||
show_local=0
|
||||
size=vga
|
||||
enabled=0
|
||||
self_view=0
|
||||
automatically_initiate=0
|
||||
automatically_accept=0
|
||||
device=StaticImage: Static picture
|
||||
|
||||
[sound]
|
||||
echocancellation=0 #to not overload cpu in case of VG
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
[sip]
|
||||
sip_port=5072
|
||||
sip_tcp_port=5072
|
||||
sip_tls_port=5073
|
||||
default_proxy=0
|
||||
|
||||
[auth_info_0]
|
||||
username=liblinphone_tester
|
||||
userid=liblinphone_tester
|
||||
passwd=secret
|
||||
realm="auth.example.org"
|
||||
|
||||
[auth_info_1]
|
||||
username=pauline
|
||||
userid=pauline
|
||||
passwd=secret
|
||||
realm="sip.example.org"
|
||||
|
||||
[auth_info_2]
|
||||
username=liblinphone_tester
|
||||
userid=liblinphone_tester
|
||||
passwd=secret
|
||||
realm="auth1.example.org"
|
||||
|
||||
[auth_info_3]
|
||||
username=marie
|
||||
userid=marie
|
||||
passwd=secret
|
||||
realm="sip.example.org"
|
||||
|
||||
[proxy_0]
|
||||
reg_proxy=sip2.linphone.org;transport=tls
|
||||
reg_identity=sip:pauline@sip.example.org
|
||||
reg_expires=3600
|
||||
reg_sendregister=1
|
||||
publish=0
|
||||
dial_escape_plus=0
|
||||
|
||||
[proxy_1]
|
||||
reg_proxy=sip.example.org;transport=tcp
|
||||
reg_identity=sip:marie@sip.example.org
|
||||
reg_expires=3600
|
||||
reg_sendregister=1
|
||||
publish=0
|
||||
dial_escape_plus=0
|
||||
|
||||
[proxy_2]
|
||||
reg_proxy=auth1.example.org
|
||||
reg_identity=sip:liblinphone_tester@auth1.example.org
|
||||
reg_expires=3600
|
||||
reg_sendregister=1
|
||||
publish=0
|
||||
dial_escape_plus=0
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
[sip]
|
||||
sip_port=5072
|
||||
sip_tcp_port=5072
|
||||
sip_tls_port=5073
|
||||
default_proxy=0
|
||||
ping_with_options=0
|
||||
register_only_when_network_is_up=0
|
||||
|
||||
[auth_info_0]
|
||||
username=pauline
|
||||
userid=pauline
|
||||
passwd=secret
|
||||
realm="sip.example.org"
|
||||
|
||||
|
||||
[proxy_0]
|
||||
reg_proxy=sip2.linphone.org;transport=tls
|
||||
reg_route=sip2.linphone.org;transport=tls
|
||||
reg_identity=sip:pauline@sip.example.org
|
||||
reg_expires=3600
|
||||
reg_sendregister=1
|
||||
publish=0
|
||||
dial_escape_plus=0
|
||||
|
||||
#[friend_0]
|
||||
#url="Mariette" <sip:marie@sip.example.org>
|
||||
#pol=accept
|
||||
#subscribe=0
|
||||
|
||||
[rtp]
|
||||
audio_rtp_port=8090
|
||||
video_rtp_port=8092
|
||||
|
||||
[video]
|
||||
display=0
|
||||
capture=0
|
||||
show_local=0
|
||||
size=vga
|
||||
enabled=0
|
||||
self_view=0
|
||||
automatically_initiate=0
|
||||
automatically_accept=0
|
||||
device=StaticImage: Static picture
|
||||
|
||||
[sound]
|
||||
echocancellation=0 #to not overload cpu in case of VG
|
||||
|
|
@ -0,0 +1,193 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>10.0.20506</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{34D6878F-6CAB-4AE3-9CCC-25E8D6734C90}</ProjectGuid>
|
||||
<ProjectTypeGuids>{C089C8C0-30E0-4E22-80C0-CE093F111A43};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>LibLinphoneTester_wp8</RootNamespace>
|
||||
<AssemblyName>LibLinphoneTester_wp8</AssemblyName>
|
||||
<TargetFrameworkIdentifier>WindowsPhone</TargetFrameworkIdentifier>
|
||||
<TargetFrameworkVersion>v8.0</TargetFrameworkVersion>
|
||||
<SilverlightVersion>$(TargetFrameworkVersion)</SilverlightVersion>
|
||||
<SilverlightApplication>true</SilverlightApplication>
|
||||
<SupportedCultures>
|
||||
</SupportedCultures>
|
||||
<XapOutputs>true</XapOutputs>
|
||||
<GenerateSilverlightManifest>true</GenerateSilverlightManifest>
|
||||
<XapFilename>LibLinphoneTester_wp8_$(Configuration)_$(Platform).xap</XapFilename>
|
||||
<SilverlightManifestTemplate>Properties\AppManifest.xml</SilverlightManifestTemplate>
|
||||
<SilverlightAppEntry>LibLinphoneTester_wp8.App</SilverlightAppEntry>
|
||||
<ValidateXaml>true</ValidateXaml>
|
||||
<MinimumVisualStudioVersion>11.0</MinimumVisualStudioVersion>
|
||||
<ThrowErrorsInValidation>true</ThrowErrorsInValidation>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>Bin\Debug</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE</DefineConstants>
|
||||
<NoStdLib>true</NoStdLib>
|
||||
<NoConfig>true</NoConfig>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>Bin\Release</OutputPath>
|
||||
<DefineConstants>TRACE;SILVERLIGHT;WINDOWS_PHONE</DefineConstants>
|
||||
<NoStdLib>true</NoStdLib>
|
||||
<NoConfig>true</NoConfig>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>Bin\x86\Debug</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE</DefineConstants>
|
||||
<NoStdLib>true</NoStdLib>
|
||||
<NoConfig>true</NoConfig>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>Bin\x86\Release</OutputPath>
|
||||
<DefineConstants>TRACE;SILVERLIGHT;WINDOWS_PHONE</DefineConstants>
|
||||
<NoStdLib>true</NoStdLib>
|
||||
<NoConfig>true</NoConfig>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|ARM' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>Bin\ARM\Debug</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE</DefineConstants>
|
||||
<NoStdLib>true</NoStdLib>
|
||||
<NoConfig>true</NoConfig>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|ARM' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>Bin\ARM\Release</OutputPath>
|
||||
<DefineConstants>TRACE;SILVERLIGHT;WINDOWS_PHONE</DefineConstants>
|
||||
<NoStdLib>true</NoStdLib>
|
||||
<NoConfig>true</NoConfig>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="App.xaml.cs">
|
||||
<DependentUpon>App.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="LocalizedStrings.cs" />
|
||||
<Compile Include="MainPage.xaml.cs">
|
||||
<DependentUpon>MainPage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Resources\AppResources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>AppResources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="TestCasePage.xaml.cs">
|
||||
<DependentUpon>TestCasePage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="TestResultPage.xaml.cs">
|
||||
<DependentUpon>TestResultPage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ApplicationDefinition Include="App.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</ApplicationDefinition>
|
||||
<Page Include="MainPage.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="TestCasePage.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="TestResultPage.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Assets\empty_rc" />
|
||||
<Content Include="Assets\laure_rc" />
|
||||
<Content Include="Assets\marie_rc" />
|
||||
<Content Include="Assets\oldphone.wav" />
|
||||
<Content Include="Assets\pauline_rc" />
|
||||
<Content Include="Assets\multi_account_lrc" />
|
||||
<Content Include="log.html" />
|
||||
<Content Include="Assets\marie_early_rc" />
|
||||
<None Include="Properties\AppManifest.xml" />
|
||||
<None Include="Properties\WMAppManifest.xml">
|
||||
<SubType>Designer</SubType>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Assets\AlignmentGrid.png" />
|
||||
<Content Include="Assets\ApplicationIcon.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Assets\ringback.wav" />
|
||||
<Content Include="Assets\Tiles\FlipCycleTileLarge.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Assets\Tiles\FlipCycleTileMedium.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Assets\Tiles\FlipCycleTileSmall.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Assets\Tiles\IconicTileMediumLarge.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Assets\Tiles\IconicTileSmall.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Resources\AppResources.resx">
|
||||
<Generator>PublicResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>AppResources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\LibLinphoneTester\LibLinphoneTester.vcxproj">
|
||||
<Project>{5E94A00B-B14A-4E42-8284-8CB0EF099534}</Project>
|
||||
<Name>LibLinphoneTester</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildExtensionsPath)\Microsoft\$(TargetFrameworkIdentifier)\$(TargetFrameworkVersion)\Microsoft.$(TargetFrameworkIdentifier).$(TargetFrameworkVersion).Overrides.targets" />
|
||||
<Import Project="$(MSBuildExtensionsPath)\Microsoft\$(TargetFrameworkIdentifier)\$(TargetFrameworkVersion)\Microsoft.$(TargetFrameworkIdentifier).CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
<ProjectExtensions />
|
||||
<PropertyGroup>
|
||||
<PreBuildEvent>Xcopy /I /Y $(ProjectDir)..\..\..\..\tester\*rc $(ProjectDir)Assets\</PreBuildEvent>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
using LibLinphoneTester_wp8.Resources;
|
||||
|
||||
namespace LibLinphoneTester_wp8
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides access to string resources.
|
||||
/// </summary>
|
||||
public class LocalizedStrings
|
||||
{
|
||||
private static AppResources _localizedResources = new AppResources();
|
||||
|
||||
public AppResources LocalizedResources { get { return _localizedResources; } }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
<phone:PhoneApplicationPage
|
||||
x:Class="LibLinphoneTester_wp8.MainPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
|
||||
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
FontFamily="{StaticResource PhoneFontFamilyNormal}"
|
||||
FontSize="{StaticResource PhoneFontSizeNormal}"
|
||||
Foreground="{StaticResource PhoneForegroundBrush}"
|
||||
SupportedOrientations="Portrait" Orientation="Portrait"
|
||||
mc:Ignorable="d"
|
||||
shell:SystemTray.IsVisible="True">
|
||||
|
||||
<phone:PhoneApplicationPage.Resources>
|
||||
<DataTemplate x:Key="UnitTestItemTemplate">
|
||||
<TextBlock Style="{StaticResource PhoneTextTitle2Style}" Text="{Binding Name}"/>
|
||||
</DataTemplate>
|
||||
</phone:PhoneApplicationPage.Resources>
|
||||
<!--LayoutRoot is the root grid where all page content is placed-->
|
||||
<Grid x:Name="LayoutRoot" Background="Transparent">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!--TitlePanel contains the name of the application and page title-->
|
||||
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
|
||||
<TextBlock Text="LINPHONE TESTER" Style="{StaticResource PhoneTextNormalStyle}" Margin="12,0"/>
|
||||
<TextBlock Text="Test Suite" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
|
||||
</StackPanel>
|
||||
|
||||
<!--ContentPanel - place additional content here-->
|
||||
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
|
||||
<CheckBox x:Name="Verbose" Content="Verbose" HorizontalAlignment="Right" Margin="0,0,0,537" IsChecked="True"/>
|
||||
<phone:LongListSelector x:Name="Tests" HorizontalAlignment="Left" Height="510" VerticalAlignment="Top" Width="456" ItemTemplate="{StaticResource UnitTestItemTemplate}" LayoutMode="List" Margin="0,70,0,-10" Tap="Tests_Tap"/>
|
||||
</Grid>
|
||||
|
||||
</Grid>
|
||||
|
||||
</phone:PhoneApplicationPage>
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Navigation;
|
||||
using Microsoft.Phone.Controls;
|
||||
using Microsoft.Phone.Shell;
|
||||
|
||||
namespace LibLinphoneTester_wp8
|
||||
{
|
||||
public partial class MainPage : PhoneApplicationPage
|
||||
{
|
||||
public MainPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
var tester = (Application.Current as App).tester;
|
||||
List<UnitTestSuiteName> source = new List<UnitTestSuiteName>();
|
||||
source.Add(new UnitTestSuiteName("ALL"));
|
||||
for (int i = 0; i < tester.nbTestSuites(); i++)
|
||||
{
|
||||
source.Add(new UnitTestSuiteName(tester.testSuiteName(i)));
|
||||
}
|
||||
|
||||
Tests.ItemsSource = source;
|
||||
}
|
||||
|
||||
private void Tests_Tap(object sender, System.Windows.Input.GestureEventArgs e)
|
||||
{
|
||||
UnitTestSuiteName test = (sender as LongListSelector).SelectedItem as UnitTestSuiteName;
|
||||
if (test == null) return;
|
||||
if (test.Name == "ALL")
|
||||
{
|
||||
NavigationService.Navigate(new Uri("/TestResultPage.xaml?SuiteName=" + test.Name + "&Verbose=" + Verbose.IsChecked.GetValueOrDefault(), UriKind.Relative));
|
||||
}
|
||||
else
|
||||
{
|
||||
NavigationService.Navigate(new Uri("/TestCasePage.xaml?SuiteName=" + test.Name + "&Verbose=" + Verbose.IsChecked.GetValueOrDefault(), UriKind.Relative));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class UnitTestSuiteName
|
||||
{
|
||||
public string Name
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public UnitTestSuiteName(string name)
|
||||
{
|
||||
this.Name = name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
<Deployment xmlns="http://schemas.microsoft.com/client/2007/deployment"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
>
|
||||
<Deployment.Parts>
|
||||
</Deployment.Parts>
|
||||
</Deployment>
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Resources;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("LibLinphoneTester_wp8")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("LibLinphoneTester_wp8")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2013")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("f1aad7a9-2083-4726-ab28-f57b1dd5891e")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Revision and Build Numbers
|
||||
// by using the '*' as shown below:
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
[assembly: NeutralResourcesLanguageAttribute("en-US")]
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Deployment xmlns="http://schemas.microsoft.com/windowsphone/2012/deployment" AppPlatformVersion="8.0">
|
||||
<DefaultLanguage xmlns="" code="en-US" />
|
||||
<App xmlns="" ProductID="{34d6878f-6cab-4ae3-9ccc-25e8d6734c90}" Title="LibLinphoneTester_wp8" RuntimeType="Silverlight" Version="1.0.0.0" Genre="apps.normal" Author="Belledonne Communications" Description="Sample description" Publisher="Belledonne Communications" PublisherID="{975afaec-3620-4b48-9a95-98c6d06539a6}">
|
||||
<IconPath IsRelative="true" IsResource="false">Assets\ApplicationIcon.png</IconPath>
|
||||
<Capabilities>
|
||||
<Capability Name="ID_CAP_NETWORKING" />
|
||||
<Capability Name="ID_CAP_MEDIALIB_AUDIO" />
|
||||
<Capability Name="ID_CAP_MEDIALIB_PLAYBACK" />
|
||||
<Capability Name="ID_CAP_SENSORS" />
|
||||
<Capability Name="ID_CAP_WEBBROWSERCOMPONENT" />
|
||||
</Capabilities>
|
||||
<Tasks>
|
||||
<DefaultTask Name="_default" NavigationPage="MainPage.xaml" />
|
||||
</Tasks>
|
||||
<Tokens>
|
||||
<PrimaryToken TokenID="LibLinphoneTester_wp8Token" TaskName="_default">
|
||||
<TemplateFlip>
|
||||
<SmallImageURI IsRelative="true" IsResource="false">Assets\Tiles\FlipCycleTileSmall.png</SmallImageURI>
|
||||
<Count>0</Count>
|
||||
<BackgroundImageURI IsRelative="true" IsResource="false">Assets\Tiles\FlipCycleTileMedium.png</BackgroundImageURI>
|
||||
<Title>LibLinphoneTester_wp8</Title>
|
||||
<BackContent>
|
||||
</BackContent>
|
||||
<BackBackgroundImageURI>
|
||||
</BackBackgroundImageURI>
|
||||
<BackTitle>
|
||||
</BackTitle>
|
||||
<LargeBackgroundImageURI>
|
||||
</LargeBackgroundImageURI>
|
||||
<LargeBackContent>
|
||||
</LargeBackContent>
|
||||
<LargeBackBackgroundImageURI>
|
||||
</LargeBackBackgroundImageURI>
|
||||
<DeviceLockImageURI>
|
||||
</DeviceLockImageURI>
|
||||
<HasLarge>
|
||||
</HasLarge>
|
||||
</TemplateFlip>
|
||||
</PrimaryToken>
|
||||
</Tokens>
|
||||
<ScreenResolutions>
|
||||
<ScreenResolution Name="ID_RESOLUTION_WVGA" />
|
||||
<ScreenResolution Name="ID_RESOLUTION_WXGA" />
|
||||
<ScreenResolution Name="ID_RESOLUTION_HD720P" />
|
||||
</ScreenResolutions>
|
||||
</App>
|
||||
</Deployment>
|
||||
127
build/vsx/LibLinphoneTester-wp8/LibLinphoneTester-wp8/Resources/AppResources.Designer.cs
generated
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.17626
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace LibLinphoneTester_wp8.Resources
|
||||
{
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
public class AppResources
|
||||
{
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal AppResources()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
public static global::System.Resources.ResourceManager ResourceManager
|
||||
{
|
||||
get
|
||||
{
|
||||
if (object.ReferenceEquals(resourceMan, null))
|
||||
{
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("LibLinphoneTester_wp8.Resources.AppResources", typeof(AppResources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
public static global::System.Globalization.CultureInfo Culture
|
||||
{
|
||||
get
|
||||
{
|
||||
return resourceCulture;
|
||||
}
|
||||
set
|
||||
{
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to LeftToRight.
|
||||
/// </summary>
|
||||
public static string ResourceFlowDirection
|
||||
{
|
||||
get
|
||||
{
|
||||
return ResourceManager.GetString("ResourceFlowDirection", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to us-EN.
|
||||
/// </summary>
|
||||
public static string ResourceLanguage
|
||||
{
|
||||
get
|
||||
{
|
||||
return ResourceManager.GetString("ResourceLanguage", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to MY APPLICATION.
|
||||
/// </summary>
|
||||
public static string ApplicationTitle
|
||||
{
|
||||
get
|
||||
{
|
||||
return ResourceManager.GetString("ApplicationTitle", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to button.
|
||||
/// </summary>
|
||||
public static string AppBarButtonText
|
||||
{
|
||||
get
|
||||
{
|
||||
return ResourceManager.GetString("AppBarButtonText", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to menu item.
|
||||
/// </summary>
|
||||
public static string AppBarMenuItemText
|
||||
{
|
||||
get
|
||||
{
|
||||
return ResourceManager.GetString("AppBarMenuItemText", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,137 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="ResourceFlowDirection" xml:space="preserve">
|
||||
<value>LeftToRight</value>
|
||||
<comment>Controls the FlowDirection for all elements in the RootFrame. Set to the traditional direction of this resource file's language</comment>
|
||||
</data>
|
||||
<data name="ResourceLanguage" xml:space="preserve">
|
||||
<value>en-US</value>
|
||||
<comment>Controls the Language and ensures that the font for all elements in the RootFrame aligns with the app's language. Set to the language code of this resource file's language.</comment>
|
||||
</data>
|
||||
<data name="ApplicationTitle" xml:space="preserve">
|
||||
<value>MY APPLICATION</value>
|
||||
</data>
|
||||
<data name="AppBarButtonText" xml:space="preserve">
|
||||
<value>add</value>
|
||||
</data>
|
||||
<data name="AppBarMenuItemText" xml:space="preserve">
|
||||
<value>Menu Item</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
<phone:PhoneApplicationPage
|
||||
x:Class="LibLinphoneTester_wp8.TestCasePage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
|
||||
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
FontFamily="{StaticResource PhoneFontFamilyNormal}"
|
||||
FontSize="{StaticResource PhoneFontSizeNormal}"
|
||||
Foreground="{StaticResource PhoneForegroundBrush}"
|
||||
SupportedOrientations="Portrait" Orientation="Portrait"
|
||||
mc:Ignorable="d"
|
||||
shell:SystemTray.IsVisible="True">
|
||||
|
||||
<phone:PhoneApplicationPage.Resources>
|
||||
<DataTemplate x:Key="UnitTestItemTemplate">
|
||||
<TextBlock Style="{StaticResource PhoneTextTitle2Style}" Text="{Binding Name}"/>
|
||||
</DataTemplate>
|
||||
</phone:PhoneApplicationPage.Resources>
|
||||
<!--LayoutRoot is the root grid where all page content is placed-->
|
||||
<Grid x:Name="LayoutRoot" Background="Transparent">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!--TitlePanel contains the name of the application and page title-->
|
||||
<StackPanel Grid.Row="0" Margin="12,17,0,28">
|
||||
<TextBlock Text="LINPHONETESTER" Style="{StaticResource PhoneTextNormalStyle}"/>
|
||||
<TextBlock Text="Test Case" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
|
||||
</StackPanel>
|
||||
|
||||
<!--ContentPanel - place additional content here-->
|
||||
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
|
||||
<phone:LongListSelector x:Name="Tests" HorizontalAlignment="Left" Height="510" VerticalAlignment="Top" Width="456" ItemTemplate="{StaticResource UnitTestItemTemplate}" LayoutMode="List" Margin="0,70,0,-10" Tap="Tests_Tap" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
</phone:PhoneApplicationPage>
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Navigation;
|
||||
using Microsoft.Phone.Controls;
|
||||
using Microsoft.Phone.Shell;
|
||||
|
||||
namespace LibLinphoneTester_wp8
|
||||
{
|
||||
public partial class TestCasePage : PhoneApplicationPage
|
||||
{
|
||||
public TestCasePage()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
protected override void OnNavigatedTo(NavigationEventArgs e)
|
||||
{
|
||||
base.OnNavigatedTo(e);
|
||||
suiteName = NavigationContext.QueryString["SuiteName"];
|
||||
verbose = Convert.ToBoolean(NavigationContext.QueryString["Verbose"]);
|
||||
var tester = (Application.Current as App).tester;
|
||||
List<UnitTestCaseName> source = new List<UnitTestCaseName>();
|
||||
source.Add(new UnitTestCaseName("ALL"));
|
||||
for (int i = 0; i < tester.nbTests(suiteName); i++)
|
||||
{
|
||||
source.Add(new UnitTestCaseName(tester.testName(suiteName, i)));
|
||||
}
|
||||
|
||||
Tests.ItemsSource = source;
|
||||
}
|
||||
|
||||
private void Tests_Tap(object sender, System.Windows.Input.GestureEventArgs e)
|
||||
{
|
||||
UnitTestCaseName test = (sender as LongListSelector).SelectedItem as UnitTestCaseName;
|
||||
if (test == null) return;
|
||||
if (!(Application.Current as App).suiteRunning())
|
||||
{
|
||||
NavigationService.Navigate(new Uri("/TestResultPage.xaml?SuiteName=" + suiteName + "&CaseName=" + test.Name + "&Verbose=" + verbose, UriKind.Relative));
|
||||
}
|
||||
}
|
||||
|
||||
private string suiteName;
|
||||
private bool verbose;
|
||||
}
|
||||
|
||||
public class UnitTestCaseName
|
||||
{
|
||||
public string Name
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public UnitTestCaseName(string name)
|
||||
{
|
||||
this.Name = name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
<phone:PhoneApplicationPage
|
||||
x:Class="LibLinphoneTester_wp8.TestResultPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
|
||||
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
FontFamily="{StaticResource PhoneFontFamilyNormal}"
|
||||
FontSize="{StaticResource PhoneFontSizeNormal}"
|
||||
Foreground="{StaticResource PhoneForegroundBrush}"
|
||||
SupportedOrientations="Portrait" Orientation="Portrait"
|
||||
mc:Ignorable="d"
|
||||
shell:SystemTray.IsVisible="True">
|
||||
|
||||
<!--LayoutRoot is the root grid where all page content is placed-->
|
||||
<Grid x:Name="LayoutRoot" Background="Transparent">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!--TitlePanel contains the name of the application and page title-->
|
||||
<StackPanel Grid.Row="0" Margin="12,17,0,28">
|
||||
<TextBlock Style="{StaticResource PhoneTextNormalStyle}">
|
||||
<Run Text="LINPHONE TESTER"/>
|
||||
<LineBreak/>
|
||||
<Run/>
|
||||
</TextBlock>
|
||||
<TextBlock Text="Test Results" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
|
||||
</StackPanel>
|
||||
|
||||
<!--ContentPanel - place additional content here-->
|
||||
<Grid x:Name="ContentPanel" Grid.Row="2" Margin="12,0,12,0">
|
||||
<phone:WebBrowser x:Name="Browser" IsScriptEnabled="True" LoadCompleted="Browser_LoadCompleted" Background="{StaticResource PhoneBackgroundBrush}"/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
</phone:PhoneApplicationPage>
|
||||
|
|
@ -0,0 +1,136 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Navigation;
|
||||
using Microsoft.Phone.Controls;
|
||||
using Microsoft.Phone.Shell;
|
||||
using System.Threading.Tasks;
|
||||
using linphone_tester_native;
|
||||
|
||||
namespace LibLinphoneTester_wp8
|
||||
{
|
||||
public delegate void OutputDisplayDelegate(int level, String msg);
|
||||
|
||||
public partial class TestResultPage : PhoneApplicationPage
|
||||
{
|
||||
public TestResultPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
Browser.Navigate(new Uri("log.html", UriKind.Relative));
|
||||
}
|
||||
|
||||
private void Browser_LoadCompleted(object sender, NavigationEventArgs e)
|
||||
{
|
||||
string suiteName = NavigationContext.QueryString["SuiteName"];
|
||||
string caseName;
|
||||
if (NavigationContext.QueryString.ContainsKey("CaseName"))
|
||||
{
|
||||
caseName = NavigationContext.QueryString["CaseName"];
|
||||
}
|
||||
else
|
||||
{
|
||||
caseName = "ALL";
|
||||
}
|
||||
bool verbose = Convert.ToBoolean(NavigationContext.QueryString["Verbose"]);
|
||||
var app = (Application.Current as App);
|
||||
app.suite = new UnitTestSuite(suiteName, caseName, verbose, new OutputDisplayDelegate(OutputDisplay));
|
||||
app.suite.run();
|
||||
}
|
||||
|
||||
public void OutputDisplay(int level, String msg)
|
||||
{
|
||||
this.Dispatcher.BeginInvoke(() =>
|
||||
{
|
||||
msg = msg.Replace("\r\n", "\n");
|
||||
string[] lines = msg.Split('\n');
|
||||
bool insertNewLine = false;
|
||||
foreach (string line in lines)
|
||||
{
|
||||
if (line.Length == 0)
|
||||
{
|
||||
insertNewLine = false;
|
||||
Browser.InvokeScript("append_nl");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (insertNewLine == true)
|
||||
{
|
||||
Browser.InvokeScript("append_nl");
|
||||
}
|
||||
if (level == 0)
|
||||
{
|
||||
Browser.InvokeScript("append_trace", line, "debug");
|
||||
}
|
||||
else if (level == 1)
|
||||
{
|
||||
Browser.InvokeScript("append_trace", line, "message");
|
||||
}
|
||||
else if (level == 2)
|
||||
{
|
||||
Browser.InvokeScript("append_trace", line, "warning");
|
||||
}
|
||||
else if (level == 3)
|
||||
{
|
||||
Browser.InvokeScript("append_trace", line, "error");
|
||||
}
|
||||
else
|
||||
{
|
||||
Browser.InvokeScript("append_text", line);
|
||||
}
|
||||
insertNewLine = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public class UnitTestSuite : OutputTraceListener
|
||||
{
|
||||
public UnitTestSuite(string SuiteName, string CaseName, bool Verbose, OutputDisplayDelegate OutputDisplay)
|
||||
{
|
||||
this.SuiteName = SuiteName;
|
||||
this.CaseName = CaseName;
|
||||
this.Verbose = Verbose;
|
||||
this.Running = false;
|
||||
this.OutputDisplay = OutputDisplay;
|
||||
}
|
||||
|
||||
async public void run()
|
||||
{
|
||||
Running = true;
|
||||
var tup = new Tuple<string, string, bool>(SuiteName, CaseName, Verbose);
|
||||
var t = Task.Factory.StartNew((object parameters) =>
|
||||
{
|
||||
var tester = (Application.Current as App).tester;
|
||||
tester.setOutputTraceListener(this);
|
||||
var p = parameters as Tuple<string, string, bool>;
|
||||
tester.run(p.Item1, p.Item2, p.Item3);
|
||||
}, tup);
|
||||
await t;
|
||||
Running = false;
|
||||
}
|
||||
|
||||
public void outputTrace(int level, String msg)
|
||||
{
|
||||
if (OutputDisplay != null)
|
||||
{
|
||||
OutputDisplay(level, msg);
|
||||
}
|
||||
System.Diagnostics.Debug.WriteLine(msg);
|
||||
}
|
||||
|
||||
public bool running {
|
||||
get { return Running; }
|
||||
protected set { Running = value; }
|
||||
}
|
||||
|
||||
private string SuiteName;
|
||||
private string CaseName;
|
||||
private bool Verbose;
|
||||
private bool Running;
|
||||
private OutputDisplayDelegate OutputDisplay;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
<html>
|
||||
<head>
|
||||
<style>
|
||||
html { background-color: black; font-family:'Courier New'; font-size: 16pt; color: white; }
|
||||
.debug { color: light-grey; }
|
||||
.message { color: white; }
|
||||
.warning { color: orange; }
|
||||
.error { color: red; }
|
||||
</style>
|
||||
<script>
|
||||
function append_text(msg) {
|
||||
var content = document.getElementById("content");
|
||||
var new_text = document.createTextNode(msg);
|
||||
content.appendChild(new_text);
|
||||
}
|
||||
function append_trace(msg, level) {
|
||||
var content = document.getElementById("content");
|
||||
var span_elem = document.createElement('span');
|
||||
span_elem.className = level;
|
||||
var new_text = document.createTextNode(msg);
|
||||
span_elem.appendChild(new_text);
|
||||
content.appendChild(span_elem);
|
||||
}
|
||||
function append_nl() {
|
||||
var content = document.getElementById("content");
|
||||
var element = document.createElement('br');
|
||||
content.appendChild(element);
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<p><pre id="content"></pre></p>
|
||||
</body>
|
||||
</html>
|
||||
166
build/vsx/LibLinphoneTester/LibLinphoneTester.vcxproj
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|ARM">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>ARM</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|ARM">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>ARM</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{5e94a00b-b14a-4e42-8284-8cb0ef099534}</ProjectGuid>
|
||||
<RootNamespace>linphone_tester_native</RootNamespace>
|
||||
<DefaultLanguage>en-US</DefaultLanguage>
|
||||
<MinimumVisualStudioVersion>11.0</MinimumVisualStudioVersion>
|
||||
<WinMDAssembly>true</WinMDAssembly>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v110_wp80</PlatformToolset>
|
||||
<IgnoreImportLibrary>false</IgnoreImportLibrary>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v110_wp80</PlatformToolset>
|
||||
<IgnoreImportLibrary>true</IgnoreImportLibrary>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<PlatformToolset>v110_wp80</PlatformToolset>
|
||||
<IgnoreImportLibrary>false</IgnoreImportLibrary>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<PlatformToolset>v110_wp80</PlatformToolset>
|
||||
<IgnoreImportLibrary>false</IgnoreImportLibrary>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<CompileAsWinRT>false</CompileAsWinRT>
|
||||
<AdditionalUsingDirectories>$(WindowsSDK_MetadataPath);$(AdditionalUsingDirectories)</AdditionalUsingDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>_USRDLL;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<CompileAsWinRT>false</CompileAsWinRT>
|
||||
<AdditionalUsingDirectories>$(WindowsSDK_MetadataPath);$(AdditionalUsingDirectories)</AdditionalUsingDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
|
||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_WINRT_DLL;_CRT_SECURE_NO_WARNINGS;HAVE_CU_GET_SUITE;IN_LINPHONE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\..\..\..\belle-sip\include;$(ProjectDir)..\..\..\..\oRTP\include;$(ProjectDir)..\..\..\..\mediastreamer2\include;$(ProjectDir)..\..\..\tester;$(ProjectDir)..\..\..\coreapi;$(ProjectDir)..\..\..\include;$(ProjectDir)..\..\..\..\cunit\build\windows\cunit\$(Platform)\$(Configuration);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<AdditionalUsingDirectories>$(WindowsSDK_MetadataPath);$(AdditionalUsingDirectories)</AdditionalUsingDirectories>
|
||||
<CompileAsWinRT>false</CompileAsWinRT>
|
||||
<ExceptionHandling>Async</ExceptionHandling>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<IgnoreSpecificDefaultLibraries>ole32.lib;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
|
||||
<GenerateWindowsMetadata>true</GenerateWindowsMetadata>
|
||||
<AdditionalDependencies>WindowsPhoneCore.lib;RuntimeObject.lib;PhoneAppModelHost.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)$(Platform)\$(Configuration)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>_USRDLL;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<CompileAsWinRT>false</CompileAsWinRT>
|
||||
<AdditionalUsingDirectories>$(WindowsSDK_MetadataPath);$(AdditionalUsingDirectories)</AdditionalUsingDirectories>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\..\..\..\belle-sip\include;$(ProjectDir)..\..\..\..\oRTP\include;$(ProjectDir)..\..\..\..\mediastreamer2\include;$(ProjectDir)..\..\..\tester;$(ProjectDir)..\..\..\coreapi;$(ProjectDir)..\..\..\include;$(ProjectDir)..\..\..\..\cunit\build\windows\cunit\$(Platform)\$(Configuration);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
|
||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="platform.winmd">
|
||||
<IsWinMDFile>true</IsWinMDFile>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\..\tester\call_tester.c" />
|
||||
<ClCompile Include="..\..\..\tester\eventapi_tester.c" />
|
||||
<ClCompile Include="..\..\..\tester\liblinphone_tester.c" />
|
||||
<ClCompile Include="..\..\..\tester\message_tester.c" />
|
||||
<ClCompile Include="..\..\..\tester\presence_tester.c" />
|
||||
<ClCompile Include="..\..\..\tester\register_tester.c" />
|
||||
<ClCompile Include="..\..\..\tester\setup_tester.c" />
|
||||
<ClCompile Include="linphone-tester-native.cpp">
|
||||
<CompileAsWinRT Condition="'$(Platform)'=='ARM'">true</CompileAsWinRT>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\..\tester\liblinphone_tester.h" />
|
||||
<ClInclude Include="linphone-tester-native.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\cunit\build\windows\cunit\cunit.vcxproj">
|
||||
<Project>{902daf1d-ebf1-4d03-b598-143500a50ab4}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\..\mediastreamer2\build\vsx\mediastreamer2\mediastreamer2\mediastreamer2.vcxproj">
|
||||
<Project>{027bad0e-9179-48c1-9733-7aa7e2c2ec70}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\..\oRTP\build\vsx\oRTP\oRTP\oRTP.vcxproj">
|
||||
<Project>{ffc7b532-0502-4d88-ac98-9e89071cbc97}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\LibLinphone\LibLinphone.vcxproj">
|
||||
<Project>{08dd0d38-d9b5-4626-b60d-b4d76b571142}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsPhone\v$(TargetPlatformVersion)\Microsoft.Cpp.WindowsPhone.$(TargetPlatformVersion).targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
125
build/vsx/LibLinphoneTester/linphone-tester-native.cpp
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
#include <string>
|
||||
|
||||
#include "linphone-tester-native.h"
|
||||
#include "ortp/logging.h"
|
||||
#include "cunit/Util.h"
|
||||
|
||||
|
||||
using namespace linphone_tester_native;
|
||||
using namespace Platform;
|
||||
|
||||
#define MAX_TRACE_SIZE 512
|
||||
#define MAX_SUITE_NAME_SIZE 128
|
||||
|
||||
static OutputTraceListener^ sTraceListener;
|
||||
|
||||
static void nativeOutputTraceHandler(OutputTraceLevel lev, const char *fmt, va_list args)
|
||||
{
|
||||
if (sTraceListener) {
|
||||
wchar_t wstr[MAX_TRACE_SIZE];
|
||||
std::string str;
|
||||
str.resize(MAX_TRACE_SIZE);
|
||||
vsnprintf((char *)str.c_str(), MAX_TRACE_SIZE, fmt, args);
|
||||
mbstowcs(wstr, str.c_str(), sizeof(wstr));
|
||||
String^ msg = ref new String(wstr);
|
||||
sTraceListener->outputTrace(lev, msg);
|
||||
}
|
||||
}
|
||||
|
||||
static void LinphoneNativeGenericOutputTraceHandler(OrtpLogLevel lev, const char *fmt, va_list args)
|
||||
{
|
||||
OutputTraceLevel level = Message;
|
||||
char fmt2[MAX_TRACE_SIZE];
|
||||
snprintf(fmt2, MAX_TRACE_SIZE, "%s\n", fmt);
|
||||
if (lev == ORTP_DEBUG) level = Debug;
|
||||
else if (lev == ORTP_MESSAGE) level = Message;
|
||||
else if (lev == ORTP_TRACE) level = Message;
|
||||
else if (lev == ORTP_WARNING) level = Warning;
|
||||
else if (lev == ORTP_ERROR) level = Error;
|
||||
else if (lev == ORTP_FATAL) level = Error;
|
||||
nativeOutputTraceHandler(level, fmt2, args);
|
||||
}
|
||||
|
||||
static void LinphoneNativeOutputTraceHandler(OrtpLogLevel lev, const char *fmt, va_list args)
|
||||
{
|
||||
if (lev >= ORTP_WARNING) {
|
||||
LinphoneNativeGenericOutputTraceHandler(lev, fmt, args);
|
||||
}
|
||||
}
|
||||
|
||||
static void LinphoneNativeVerboseOutputTraceHandler(OrtpLogLevel lev, const char *fmt, va_list args)
|
||||
{
|
||||
LinphoneNativeGenericOutputTraceHandler(lev, fmt, args);
|
||||
}
|
||||
|
||||
static void CUnitNativeOutputTraceHandler(int lev, const char *fmt, va_list args)
|
||||
{
|
||||
nativeOutputTraceHandler(Raw, fmt, args);
|
||||
}
|
||||
|
||||
LinphoneTesterNative::LinphoneTesterNative()
|
||||
{
|
||||
liblinphone_tester_init();
|
||||
}
|
||||
|
||||
LinphoneTesterNative::~LinphoneTesterNative()
|
||||
{
|
||||
liblinphone_tester_uninit();
|
||||
}
|
||||
|
||||
void LinphoneTesterNative::setOutputTraceListener(OutputTraceListener^ traceListener)
|
||||
{
|
||||
sTraceListener = traceListener;
|
||||
}
|
||||
|
||||
void LinphoneTesterNative::run(Platform::String^ suiteName, Platform::String^ caseName, Platform::Boolean verbose)
|
||||
{
|
||||
std::wstring all(L"ALL");
|
||||
std::wstring wssuitename = suiteName->Data();
|
||||
std::wstring wscasename = caseName->Data();
|
||||
char csuitename[MAX_SUITE_NAME_SIZE] = { 0 };
|
||||
char ccasename[MAX_SUITE_NAME_SIZE] = { 0 };
|
||||
wcstombs(csuitename, wssuitename.c_str(), sizeof(csuitename));
|
||||
wcstombs(ccasename, wscasename.c_str(), sizeof(ccasename));
|
||||
|
||||
if (verbose) {
|
||||
linphone_core_enable_logs_with_cb(LinphoneNativeVerboseOutputTraceHandler);
|
||||
} else {
|
||||
linphone_core_enable_logs_with_cb(LinphoneNativeOutputTraceHandler);
|
||||
}
|
||||
CU_set_trace_handler(CUnitNativeOutputTraceHandler);
|
||||
|
||||
liblinphone_tester_run_tests(wssuitename == all ? 0 : csuitename, wscasename == all ? 0 : ccasename);
|
||||
}
|
||||
|
||||
unsigned int LinphoneTesterNative::nbTestSuites()
|
||||
{
|
||||
return liblinphone_tester_nb_test_suites();
|
||||
}
|
||||
|
||||
unsigned int LinphoneTesterNative::nbTests(Platform::String^ suiteName)
|
||||
{
|
||||
std::wstring suitename = suiteName->Data();
|
||||
char cname[MAX_SUITE_NAME_SIZE] = { 0 };
|
||||
wcstombs(cname, suitename.c_str(), sizeof(cname));
|
||||
return liblinphone_tester_nb_tests(cname);
|
||||
}
|
||||
|
||||
Platform::String^ LinphoneTesterNative::testSuiteName(int index)
|
||||
{
|
||||
const char *cname = liblinphone_tester_test_suite_name(index);
|
||||
wchar_t wcname[MAX_SUITE_NAME_SIZE];
|
||||
mbstowcs(wcname, cname, sizeof(wcname));
|
||||
return ref new String(wcname);
|
||||
}
|
||||
|
||||
Platform::String^ LinphoneTesterNative::testName(Platform::String^ suiteName, int testIndex)
|
||||
{
|
||||
std::wstring suitename = suiteName->Data();
|
||||
char csuitename[MAX_SUITE_NAME_SIZE] = { 0 };
|
||||
wcstombs(csuitename, suitename.c_str(), sizeof(csuitename));
|
||||
const char *cname = liblinphone_tester_test_name(csuitename, testIndex);
|
||||
wchar_t wcname[MAX_SUITE_NAME_SIZE];
|
||||
mbstowcs(wcname, cname, sizeof(wcname));
|
||||
return ref new String(wcname);
|
||||
}
|
||||
33
build/vsx/LibLinphoneTester/linphone-tester-native.h
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
#pragma once
|
||||
|
||||
#include "liblinphone_tester.h"
|
||||
|
||||
namespace linphone_tester_native
|
||||
{
|
||||
enum OutputTraceLevel {
|
||||
Debug,
|
||||
Message,
|
||||
Warning,
|
||||
Error,
|
||||
Raw
|
||||
};
|
||||
|
||||
public interface class OutputTraceListener
|
||||
{
|
||||
public:
|
||||
void outputTrace(int level, Platform::String^ msg);
|
||||
};
|
||||
|
||||
public ref class LinphoneTesterNative sealed
|
||||
{
|
||||
public:
|
||||
LinphoneTesterNative();
|
||||
virtual ~LinphoneTesterNative();
|
||||
void setOutputTraceListener(OutputTraceListener^ traceListener);
|
||||
unsigned int nbTestSuites();
|
||||
unsigned int nbTests(Platform::String^ suiteName);
|
||||
Platform::String^ testSuiteName(int index);
|
||||
Platform::String^ testName(Platform::String^ suiteName, int testIndex);
|
||||
void run(Platform::String^ suiteName, Platform::String^ caseName, Platform::Boolean verbose);
|
||||
};
|
||||
}
|
||||
26
build/vsx/libxml2/libxml2.sln
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Express 2012 for Windows Phone
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libxml2", "libxml2\libxml2.vcxproj", "{5DFA07B4-0BE9-46A9-BA32-FDF5A55C580B}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|ARM = Debug|ARM
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release|ARM = Release|ARM
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{5DFA07B4-0BE9-46A9-BA32-FDF5A55C580B}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{5DFA07B4-0BE9-46A9-BA32-FDF5A55C580B}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{5DFA07B4-0BE9-46A9-BA32-FDF5A55C580B}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{5DFA07B4-0BE9-46A9-BA32-FDF5A55C580B}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{5DFA07B4-0BE9-46A9-BA32-FDF5A55C580B}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{5DFA07B4-0BE9-46A9-BA32-FDF5A55C580B}.Release|ARM.Build.0 = Release|ARM
|
||||
{5DFA07B4-0BE9-46A9-BA32-FDF5A55C580B}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{5DFA07B4-0BE9-46A9-BA32-FDF5A55C580B}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
6
build/vsx/libxml2/libxml2/install_headers.bat
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
SET curdir=%CD%
|
||||
SET incdir=..\..\..\..\..\libxml2\include\libxml
|
||||
SET installdir=%1\libxml
|
||||
|
||||
Xcopy /I /Y %incdir%\*.h %installdir%\
|
||||
Xcopy /I /Y xmlversion.h %installdir%\
|
||||
249
build/vsx/libxml2/libxml2/libxml2.vcxproj
Normal file
|
|
@ -0,0 +1,249 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|ARM">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>ARM</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|ARM">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>ARM</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{5dfa07b4-0be9-46a9-ba32-fdf5a55c580b}</ProjectGuid>
|
||||
<RootNamespace>libxml2</RootNamespace>
|
||||
<DefaultLanguage>en-US</DefaultLanguage>
|
||||
<MinimumVisualStudioVersion>11.0</MinimumVisualStudioVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
<IgnoreImportLibrary>false</IgnoreImportLibrary>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v110_wp80</PlatformToolset>
|
||||
<IgnoreImportLibrary>false</IgnoreImportLibrary>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
<IgnoreImportLibrary>false</IgnoreImportLibrary>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<PlatformToolset>v110_wp80</PlatformToolset>
|
||||
<IgnoreImportLibrary>false</IgnoreImportLibrary>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)$(Platform)\$(Configuration)\$(TargetName)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)$(Platform)\$(Configuration)\include;$(ProjectDir)..\..\..\..\..\libxml2\include;$(ProjectDir)..\..\..\..\..\libxml2\win32\VC10;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_WIN32;_WINDLL;_USRDLL;_CRT_SECURE_NO_WARNINGS;HAVE_WIN32_THREADS;HAVE_COMPILER_TLS;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<UndefinePreprocessorDefinitions>LIBXML_MODULES_ENABLED</UndefinePreprocessorDefinitions>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<CompileAsWinRT>false</CompileAsWinRT>
|
||||
<AdditionalUsingDirectories>$(WindowsSDK_MetadataPath);$(AdditionalUsingDirectories)</AdditionalUsingDirectories>
|
||||
<ForcedIncludeFiles>$(ProjectDir)libxml2_port.h</ForcedIncludeFiles>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ImportLibrary>$(TargetDir)$(TargetName)_dll.lib</ImportLibrary>
|
||||
<AdditionalDependencies>Ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
<PreBuildEvent>
|
||||
<Command>install_headers.bat $(SolutionDir)$(Platform)\$(Configuration)\include</Command>
|
||||
</PreBuildEvent>
|
||||
<CustomBuildStep>
|
||||
<Outputs>$(TargetDir)$(TargetName)_dll.lib;%(Outputs)</Outputs>
|
||||
</CustomBuildStep>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)$(Platform)\$(Configuration)\include;$(ProjectDir)..\..\..\..\..\libxml2\include;$(ProjectDir)..\..\..\..\..\libxml2\win32\VC10;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_WIN32;_WINDLL;_USRDLL;NDEBUG;_CRT_SECURE_NO_WARNINGS;HAVE_WIN32_THREADS;HAVE_COMPILER_TLS;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<UndefinePreprocessorDefinitions>LIBXML_MODULES_ENABLED</UndefinePreprocessorDefinitions>
|
||||
<StringPooling>true</StringPooling>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<CompileAsWinRT>false</CompileAsWinRT>
|
||||
<AdditionalUsingDirectories>$(WindowsSDK_MetadataPath);$(AdditionalUsingDirectories)</AdditionalUsingDirectories>
|
||||
<ForcedIncludeFiles>$(ProjectDir)libxml2_port.h</ForcedIncludeFiles>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
|
||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||
<ImportLibrary>$(TargetDir)$(TargetName)_dll.lib</ImportLibrary>
|
||||
<AdditionalDependencies>Ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
<PreBuildEvent>
|
||||
<Command>install_headers.bat $(SolutionDir)$(Platform)\$(Configuration)\include</Command>
|
||||
</PreBuildEvent>
|
||||
<CustomBuildStep>
|
||||
<Outputs>$(TargetDir)$(TargetName)_dll.lib;%(Outputs)</Outputs>
|
||||
</CustomBuildStep>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)$(Platform)\$(Configuration)\include;$(ProjectDir)..\..\..\..\..\libxml2\include;$(ProjectDir)..\..\..\..\..\libxml2\win32\VC10;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_WIN32;WIN32;_WINDLL;_USRDLL;_CRT_SECURE_NO_WARNINGS;HAVE_WIN32_THREADS;HAVE_COMPILER_TLS;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<UndefinePreprocessorDefinitions>LIBXML_MODULES_ENABLED</UndefinePreprocessorDefinitions>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<CompileAsWinRT>false</CompileAsWinRT>
|
||||
<AdditionalUsingDirectories>$(WindowsSDK_MetadataPath);$(AdditionalUsingDirectories)</AdditionalUsingDirectories>
|
||||
<ForcedIncludeFiles>$(ProjectDir)libxml2_port.h</ForcedIncludeFiles>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ImportLibrary>$(TargetDir)$(TargetName)_dll.lib</ImportLibrary>
|
||||
<AdditionalDependencies>Ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
<PreBuildEvent>
|
||||
<Command>install_headers.bat $(SolutionDir)$(Platform)\$(Configuration)\include</Command>
|
||||
</PreBuildEvent>
|
||||
<CustomBuildStep>
|
||||
<Outputs>$(TargetDir)$(TargetName)_dll.lib;%(Outputs)</Outputs>
|
||||
</CustomBuildStep>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)$(Platform)\$(Configuration)\include;$(ProjectDir)..\..\..\..\..\libxml2\include;$(ProjectDir)..\..\..\..\..\libxml2\win32\VC10;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_WIN32;_WINDLL;_USRDLL;NDEBUG;_CRT_SECURE_NO_WARNINGS;HAVE_WIN32_THREADS;HAVE_COMPILER_TLS;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<UndefinePreprocessorDefinitions>LIBXML_MODULES_ENABLED</UndefinePreprocessorDefinitions>
|
||||
<StringPooling>true</StringPooling>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<CompileAsWinRT>false</CompileAsWinRT>
|
||||
<AdditionalUsingDirectories>$(WindowsSDK_MetadataPath);$(AdditionalUsingDirectories)</AdditionalUsingDirectories>
|
||||
<ForcedIncludeFiles>$(ProjectDir)libxml2_port.h</ForcedIncludeFiles>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
|
||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||
<ImportLibrary>$(TargetDir)$(TargetName)_dll.lib</ImportLibrary>
|
||||
<AdditionalDependencies>Ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
<PreBuildEvent>
|
||||
<Command>install_headers.bat $(SolutionDir)$(Platform)\$(Configuration)\include</Command>
|
||||
</PreBuildEvent>
|
||||
<CustomBuildStep>
|
||||
<Outputs>$(TargetDir)$(TargetName)_dll.lib;%(Outputs)</Outputs>
|
||||
</CustomBuildStep>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Windows" Condition="'$(Platform)'=='ARM'">
|
||||
<IsWinMDFile>true</IsWinMDFile>
|
||||
</Reference>
|
||||
<Reference Include="platform.winmd">
|
||||
<IsWinMDFile>true</IsWinMDFile>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\..\..\..\libxml2\c14n.c" />
|
||||
<ClCompile Include="..\..\..\..\..\libxml2\catalog.c" />
|
||||
<ClCompile Include="..\..\..\..\..\libxml2\chvalid.c" />
|
||||
<ClCompile Include="..\..\..\..\..\libxml2\debugXML.c" />
|
||||
<ClCompile Include="..\..\..\..\..\libxml2\dict.c" />
|
||||
<ClCompile Include="..\..\..\..\..\libxml2\DOCBparser.c" />
|
||||
<ClCompile Include="..\..\..\..\..\libxml2\encoding.c" />
|
||||
<ClCompile Include="..\..\..\..\..\libxml2\entities.c" />
|
||||
<ClCompile Include="..\..\..\..\..\libxml2\error.c" />
|
||||
<ClCompile Include="..\..\..\..\..\libxml2\globals.c" />
|
||||
<ClCompile Include="..\..\..\..\..\libxml2\hash.c" />
|
||||
<ClCompile Include="..\..\..\..\..\libxml2\HTMLparser.c" />
|
||||
<ClCompile Include="..\..\..\..\..\libxml2\HTMLtree.c" />
|
||||
<ClCompile Include="..\..\..\..\..\libxml2\legacy.c" />
|
||||
<ClCompile Include="..\..\..\..\..\libxml2\list.c" />
|
||||
<ClCompile Include="..\..\..\..\..\libxml2\nanoftp.c" />
|
||||
<ClCompile Include="..\..\..\..\..\libxml2\nanohttp.c" />
|
||||
<ClCompile Include="..\..\..\..\..\libxml2\parser.c" />
|
||||
<ClCompile Include="..\..\..\..\..\libxml2\parserInternals.c" />
|
||||
<ClCompile Include="..\..\..\..\..\libxml2\pattern.c" />
|
||||
<ClCompile Include="..\..\..\..\..\libxml2\relaxng.c" />
|
||||
<ClCompile Include="..\..\..\..\..\libxml2\SAX.c" />
|
||||
<ClCompile Include="..\..\..\..\..\libxml2\SAX2.c" />
|
||||
<ClCompile Include="..\..\..\..\..\libxml2\schematron.c" />
|
||||
<ClCompile Include="..\..\..\..\..\libxml2\threads.c" />
|
||||
<ClCompile Include="..\..\..\..\..\libxml2\tree.c" />
|
||||
<ClCompile Include="..\..\..\..\..\libxml2\uri.c" />
|
||||
<ClCompile Include="..\..\..\..\..\libxml2\valid.c" />
|
||||
<ClCompile Include="..\..\..\..\..\libxml2\xinclude.c" />
|
||||
<ClCompile Include="..\..\..\..\..\libxml2\xlink.c" />
|
||||
<ClCompile Include="..\..\..\..\..\libxml2\xmlcatalog.c" />
|
||||
<ClCompile Include="..\..\..\..\..\libxml2\xmlIO.c" />
|
||||
<ClCompile Include="..\..\..\..\..\libxml2\xmlmemory.c" />
|
||||
<ClCompile Include="..\..\..\..\..\libxml2\xmlmodule.c" />
|
||||
<ClCompile Include="..\..\..\..\..\libxml2\xmlreader.c" />
|
||||
<ClCompile Include="..\..\..\..\..\libxml2\xmlregexp.c" />
|
||||
<ClCompile Include="..\..\..\..\..\libxml2\xmlsave.c" />
|
||||
<ClCompile Include="..\..\..\..\..\libxml2\xmlschemas.c" />
|
||||
<ClCompile Include="..\..\..\..\..\libxml2\xmlschemastypes.c" />
|
||||
<ClCompile Include="..\..\..\..\..\libxml2\xmlstring.c" />
|
||||
<ClCompile Include="..\..\..\..\..\libxml2\xmlunicode.c" />
|
||||
<ClCompile Include="..\..\..\..\..\libxml2\xmlwriter.c" />
|
||||
<ClCompile Include="..\..\..\..\..\libxml2\xpath.c" />
|
||||
<ClCompile Include="..\..\..\..\..\libxml2\xpointer.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\..\..\..\libxml2\elfgcchack.h" />
|
||||
<ClInclude Include="..\..\..\..\..\libxml2\libxml.h" />
|
||||
<ClInclude Include="..\..\..\..\..\libxml2\win32\VC10\config.h" />
|
||||
<ClInclude Include="libxml2_port.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsPhone\v$(TargetPlatformVersion)\Microsoft.Cpp.WindowsPhone.$(TargetPlatformVersion).targets" Condition="'$(Platform)'=='ARM'" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
19
build/vsx/libxml2/libxml2/libxml2_port.h
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
|
||||
#ifndef LIBXML2_PORT_H
|
||||
#define LIBXML2_PORT_H
|
||||
|
||||
#define CreateMutex(a, b, c) CreateMutexExW(a, c, ((b) ? CREATE_MUTEX_INITIAL_OWNER : 0), 0)
|
||||
|
||||
#define GetVersionEx(osvi) (((osvi)->dwPlatformId = 0) != 0)
|
||||
|
||||
#define InitializeCriticalSection(cs) InitializeCriticalSectionEx(cs, 0, 0)
|
||||
|
||||
#define WaitForSingleObject(hHandle, dwMilliseconds) WaitForSingleObjectEx(hHandle, dwMilliseconds, 0)
|
||||
|
||||
#define Sleep(ms) { \
|
||||
HANDLE sleepEvent = CreateEventEx(NULL, NULL, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS); \
|
||||
if (!sleepEvent) return; \
|
||||
WaitForSingleObjectEx(sleepEvent, ms, FALSE); \
|
||||
}
|
||||
|
||||
#endif /* LIBXML2_PORT_H */
|
||||
476
build/vsx/libxml2/libxml2/xmlversion.h
Normal file
|
|
@ -0,0 +1,476 @@
|
|||
/*
|
||||
* Summary: compile-time version informations
|
||||
* Description: compile-time version informations for the XML library
|
||||
*
|
||||
* Copy: See Copyright for the status of this software.
|
||||
*
|
||||
* Author: Daniel Veillard
|
||||
*/
|
||||
|
||||
#ifndef __XML_VERSION_H__
|
||||
#define __XML_VERSION_H__
|
||||
|
||||
#include <libxml/xmlexports.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* use those to be sure nothing nasty will happen if
|
||||
* your library and includes mismatch
|
||||
*/
|
||||
#ifndef LIBXML2_COMPILING_MSCCDEF
|
||||
XMLPUBFUN void XMLCALL xmlCheckVersion(int version);
|
||||
#endif /* LIBXML2_COMPILING_MSCCDEF */
|
||||
|
||||
/**
|
||||
* LIBXML_DOTTED_VERSION:
|
||||
*
|
||||
* the version string like "1.2.3"
|
||||
*/
|
||||
#define LIBXML_DOTTED_VERSION "2.8.0"
|
||||
|
||||
/**
|
||||
* LIBXML_VERSION:
|
||||
*
|
||||
* the version number: 1.2.3 value is 10203
|
||||
*/
|
||||
#define LIBXML_VERSION 20800
|
||||
|
||||
/**
|
||||
* LIBXML_VERSION_STRING:
|
||||
*
|
||||
* the version number string, 1.2.3 value is "10203"
|
||||
*/
|
||||
#define LIBXML_VERSION_STRING "20800"
|
||||
|
||||
/**
|
||||
* LIBXML_VERSION_EXTRA:
|
||||
*
|
||||
* extra version information, used to show a CVS compilation
|
||||
*/
|
||||
#define LIBXML_VERSION_EXTRA ""
|
||||
|
||||
/**
|
||||
* LIBXML_TEST_VERSION:
|
||||
*
|
||||
* Macro to check that the libxml version in use is compatible with
|
||||
* the version the software has been compiled against
|
||||
*/
|
||||
#define LIBXML_TEST_VERSION xmlCheckVersion(20800);
|
||||
|
||||
#ifndef VMS
|
||||
#if 0
|
||||
/**
|
||||
* WITH_TRIO:
|
||||
*
|
||||
* defined if the trio support need to be configured in
|
||||
*/
|
||||
#define WITH_TRIO
|
||||
#else
|
||||
/**
|
||||
* WITHOUT_TRIO:
|
||||
*
|
||||
* defined if the trio support should not be configured in
|
||||
*/
|
||||
#define WITHOUT_TRIO
|
||||
#endif
|
||||
#else /* VMS */
|
||||
/**
|
||||
* WITH_TRIO:
|
||||
*
|
||||
* defined if the trio support need to be configured in
|
||||
*/
|
||||
#define WITH_TRIO 1
|
||||
#endif /* VMS */
|
||||
|
||||
/**
|
||||
* LIBXML_THREAD_ENABLED:
|
||||
*
|
||||
* Whether the thread support is configured in
|
||||
*/
|
||||
#if 1
|
||||
#if defined(_REENTRANT) || defined(__MT__) || \
|
||||
(defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE - 0 >= 199506L))
|
||||
#define LIBXML_THREAD_ENABLED
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LIBXML_TREE_ENABLED:
|
||||
*
|
||||
* Whether the DOM like tree manipulation API support is configured in
|
||||
*/
|
||||
#if 1
|
||||
#define LIBXML_TREE_ENABLED
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LIBXML_OUTPUT_ENABLED:
|
||||
*
|
||||
* Whether the serialization/saving support is configured in
|
||||
*/
|
||||
#if 1
|
||||
#define LIBXML_OUTPUT_ENABLED
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LIBXML_PUSH_ENABLED:
|
||||
*
|
||||
* Whether the push parsing interfaces are configured in
|
||||
*/
|
||||
#if 1
|
||||
#define LIBXML_PUSH_ENABLED
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LIBXML_READER_ENABLED:
|
||||
*
|
||||
* Whether the xmlReader parsing interface is configured in
|
||||
*/
|
||||
#if 1
|
||||
#define LIBXML_READER_ENABLED
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LIBXML_PATTERN_ENABLED:
|
||||
*
|
||||
* Whether the xmlPattern node selection interface is configured in
|
||||
*/
|
||||
#if 1
|
||||
#define LIBXML_PATTERN_ENABLED
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LIBXML_WRITER_ENABLED:
|
||||
*
|
||||
* Whether the xmlWriter saving interface is configured in
|
||||
*/
|
||||
#if 1
|
||||
#define LIBXML_WRITER_ENABLED
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LIBXML_SAX1_ENABLED:
|
||||
*
|
||||
* Whether the older SAX1 interface is configured in
|
||||
*/
|
||||
#if 1
|
||||
#define LIBXML_SAX1_ENABLED
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LIBXML_FTP_ENABLED:
|
||||
*
|
||||
* Whether the FTP support is configured in
|
||||
*/
|
||||
#if 1
|
||||
#define LIBXML_FTP_ENABLED
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LIBXML_HTTP_ENABLED:
|
||||
*
|
||||
* Whether the HTTP support is configured in
|
||||
*/
|
||||
#if 1
|
||||
#define LIBXML_HTTP_ENABLED
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LIBXML_VALID_ENABLED:
|
||||
*
|
||||
* Whether the DTD validation support is configured in
|
||||
*/
|
||||
#if 1
|
||||
#define LIBXML_VALID_ENABLED
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LIBXML_HTML_ENABLED:
|
||||
*
|
||||
* Whether the HTML support is configured in
|
||||
*/
|
||||
#if 1
|
||||
#define LIBXML_HTML_ENABLED
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LIBXML_LEGACY_ENABLED:
|
||||
*
|
||||
* Whether the deprecated APIs are compiled in for compatibility
|
||||
*/
|
||||
#if 1
|
||||
#define LIBXML_LEGACY_ENABLED
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LIBXML_C14N_ENABLED:
|
||||
*
|
||||
* Whether the Canonicalization support is configured in
|
||||
*/
|
||||
#if 1
|
||||
#define LIBXML_C14N_ENABLED
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LIBXML_CATALOG_ENABLED:
|
||||
*
|
||||
* Whether the Catalog support is configured in
|
||||
*/
|
||||
#if 0
|
||||
#define LIBXML_CATALOG_ENABLED
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LIBXML_DOCB_ENABLED:
|
||||
*
|
||||
* Whether the SGML Docbook support is configured in
|
||||
*/
|
||||
#if 1
|
||||
#define LIBXML_DOCB_ENABLED
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LIBXML_XPATH_ENABLED:
|
||||
*
|
||||
* Whether XPath is configured in
|
||||
*/
|
||||
#if 1
|
||||
#define LIBXML_XPATH_ENABLED
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LIBXML_XPTR_ENABLED:
|
||||
*
|
||||
* Whether XPointer is configured in
|
||||
*/
|
||||
#if 1
|
||||
#define LIBXML_XPTR_ENABLED
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LIBXML_XINCLUDE_ENABLED:
|
||||
*
|
||||
* Whether XInclude is configured in
|
||||
*/
|
||||
#if 1
|
||||
#define LIBXML_XINCLUDE_ENABLED
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LIBXML_ICONV_ENABLED:
|
||||
*
|
||||
* Whether iconv support is available
|
||||
*/
|
||||
#if 0
|
||||
#define LIBXML_ICONV_ENABLED
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LIBXML_ICU_ENABLED:
|
||||
*
|
||||
* Whether icu support is available
|
||||
*/
|
||||
#if 0
|
||||
#define LIBXML_ICU_ENABLED
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LIBXML_ISO8859X_ENABLED:
|
||||
*
|
||||
* Whether ISO-8859-* support is made available in case iconv is not
|
||||
*/
|
||||
#if 0
|
||||
#define LIBXML_ISO8859X_ENABLED
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LIBXML_DEBUG_ENABLED:
|
||||
*
|
||||
* Whether Debugging module is configured in
|
||||
*/
|
||||
#if 1
|
||||
#define LIBXML_DEBUG_ENABLED
|
||||
#endif
|
||||
|
||||
/**
|
||||
* DEBUG_MEMORY_LOCATION:
|
||||
*
|
||||
* Whether the memory debugging is configured in
|
||||
*/
|
||||
#if 0
|
||||
#define DEBUG_MEMORY_LOCATION
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LIBXML_DEBUG_RUNTIME:
|
||||
*
|
||||
* Whether the runtime debugging is configured in
|
||||
*/
|
||||
#if 0
|
||||
#define LIBXML_DEBUG_RUNTIME
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LIBXML_UNICODE_ENABLED:
|
||||
*
|
||||
* Whether the Unicode related interfaces are compiled in
|
||||
*/
|
||||
#if 1
|
||||
#define LIBXML_UNICODE_ENABLED
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LIBXML_REGEXP_ENABLED:
|
||||
*
|
||||
* Whether the regular expressions interfaces are compiled in
|
||||
*/
|
||||
#if 1
|
||||
#define LIBXML_REGEXP_ENABLED
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LIBXML_AUTOMATA_ENABLED:
|
||||
*
|
||||
* Whether the automata interfaces are compiled in
|
||||
*/
|
||||
#if 1
|
||||
#define LIBXML_AUTOMATA_ENABLED
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LIBXML_EXPR_ENABLED:
|
||||
*
|
||||
* Whether the formal expressions interfaces are compiled in
|
||||
*/
|
||||
#if 1
|
||||
#define LIBXML_EXPR_ENABLED
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LIBXML_SCHEMAS_ENABLED:
|
||||
*
|
||||
* Whether the Schemas validation interfaces are compiled in
|
||||
*/
|
||||
#if 1
|
||||
#define LIBXML_SCHEMAS_ENABLED
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LIBXML_SCHEMATRON_ENABLED:
|
||||
*
|
||||
* Whether the Schematron validation interfaces are compiled in
|
||||
*/
|
||||
#if 1
|
||||
#define LIBXML_SCHEMATRON_ENABLED
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LIBXML_MODULES_ENABLED:
|
||||
*
|
||||
* Whether the module interfaces are compiled in
|
||||
*/
|
||||
#if 0
|
||||
#define LIBXML_MODULES_ENABLED
|
||||
/**
|
||||
* LIBXML_MODULE_EXTENSION:
|
||||
*
|
||||
* the string suffix used by dynamic modules (usually shared libraries)
|
||||
*/
|
||||
#define LIBXML_MODULE_EXTENSION ".dll"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LIBXML_ZLIB_ENABLED:
|
||||
*
|
||||
* Whether the Zlib support is compiled in
|
||||
*/
|
||||
#if 0
|
||||
#define LIBXML_ZLIB_ENABLED
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LIBXML_LZMA_ENABLED:
|
||||
*
|
||||
* Whether the Lzma support is compiled in
|
||||
*/
|
||||
#if 0
|
||||
#define LIBXML_LZMA_ENABLED
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
#ifdef HAVE_ANSIDECL_H
|
||||
#include <ansidecl.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* ATTRIBUTE_UNUSED:
|
||||
*
|
||||
* Macro used to signal to GCC unused function parameters
|
||||
*/
|
||||
|
||||
#ifndef ATTRIBUTE_UNUSED
|
||||
#define ATTRIBUTE_UNUSED __attribute__((unused))
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LIBXML_ATTR_ALLOC_SIZE:
|
||||
*
|
||||
* Macro used to indicate to GCC this is an allocator function
|
||||
*/
|
||||
|
||||
#ifndef LIBXML_ATTR_ALLOC_SIZE
|
||||
# if ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3)))
|
||||
# define LIBXML_ATTR_ALLOC_SIZE(x) __attribute__((alloc_size(x)))
|
||||
# else
|
||||
# define LIBXML_ATTR_ALLOC_SIZE(x)
|
||||
# endif
|
||||
#else
|
||||
# define LIBXML_ATTR_ALLOC_SIZE(x)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LIBXML_ATTR_FORMAT:
|
||||
*
|
||||
* Macro used to indicate to GCC the parameter are printf like
|
||||
*/
|
||||
|
||||
#ifndef LIBXML_ATTR_FORMAT
|
||||
# if ((__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)))
|
||||
# define LIBXML_ATTR_FORMAT(fmt,args) __attribute__((__format__(__printf__,fmt,args)))
|
||||
# else
|
||||
# define LIBXML_ATTR_FORMAT(fmt,args)
|
||||
# endif
|
||||
#else
|
||||
# define LIBXML_ATTR_FORMAT(fmt,args)
|
||||
#endif
|
||||
|
||||
#else /* ! __GNUC__ */
|
||||
/**
|
||||
* ATTRIBUTE_UNUSED:
|
||||
*
|
||||
* Macro used to signal to GCC unused function parameters
|
||||
*/
|
||||
#define ATTRIBUTE_UNUSED
|
||||
/**
|
||||
* LIBXML_ATTR_ALLOC_SIZE:
|
||||
*
|
||||
* Macro used to indicate to GCC this is an allocator function
|
||||
*/
|
||||
#define LIBXML_ATTR_ALLOC_SIZE(x)
|
||||
/**
|
||||
* LIBXML_ATTR_FORMAT:
|
||||
*
|
||||
* Macro used to indicate to GCC the parameter are printf like
|
||||
*/
|
||||
#define LIBXML_ATTR_FORMAT(fmt,args)
|
||||
#endif /* __GNUC__ */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif
|
||||
|
||||
|
||||
174
configure.ac
|
|
@ -1,6 +1,6 @@
|
|||
dnl Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_INIT([linphone],[3.6.1],[linphone-developers@nongnu.org])
|
||||
AC_INIT([linphone],[3.6.99],[linphone-developers@nongnu.org])
|
||||
AC_CANONICAL_SYSTEM
|
||||
AC_CONFIG_SRCDIR([coreapi/linphonecore.c])
|
||||
|
||||
|
|
@ -23,6 +23,7 @@ LIBLINPHONE_SO_AGE=0 dnl increment this number when you add an interface, set to
|
|||
|
||||
LIBLINPHONE_SO_VERSION=$LIBLINPHONE_SO_CURRENT:$LIBLINPHONE_SO_REVISION:$LIBLINPHONE_SO_AGE
|
||||
|
||||
AC_SUBST(LIBLINPHONE_SO_CURRENT, $LIBLINPHONE_SO_CURRENT)
|
||||
AC_SUBST(LIBLINPHONE_SO_VERSION, $LIBLINPHONE_SO_VERSION)
|
||||
AC_SUBST(LINPHONE_VERSION)
|
||||
|
||||
|
|
@ -35,9 +36,13 @@ m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])],)
|
|||
AC_SUBST([docdir], [${datadir}/doc])
|
||||
AC_CONFIG_HEADERS(config.h)
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
dnl don't put anythingelse before AC_PROG_CC unless checking if macro still work for clang
|
||||
AC_PROG_CXX(["xcrun clang++" g++])
|
||||
AC_PROG_CC(["xcrun clang" gcc])
|
||||
|
||||
gl_LD_OUTPUT_DEF
|
||||
|
||||
AC_ISC_POSIX
|
||||
AC_PROG_CC
|
||||
AC_PROG_CXX
|
||||
AC_C_INLINE
|
||||
AC_HEADER_STDC
|
||||
AM_PROG_CC_C_O
|
||||
|
|
@ -59,10 +64,10 @@ case $target in
|
|||
GUI_FLAGS="-mwindows"
|
||||
CONSOLE_FLAGS="-mconsole"
|
||||
mingw_found=yes
|
||||
AC_CHECK_TOOL(WINDRES, windres)
|
||||
;;
|
||||
armv6-apple-darwin|armv7-apple-darwin|i386-apple-darwin|armv7s-apple-darwin)
|
||||
CFLAGS="$CFLAGS -DTARGET_OS_IPHONE "
|
||||
build_tests=no
|
||||
CFLAGS="$CFLAGS -DTARGET_OS_IPHONE=1 "
|
||||
ios_found=yes
|
||||
;;
|
||||
x86_64-apple-darwin*|i686-apple-darwin*)
|
||||
|
|
@ -74,15 +79,24 @@ case $target in
|
|||
|
||||
esac
|
||||
|
||||
|
||||
|
||||
|
||||
AC_SUBST(ACLOCAL_MACOS_FLAGS)
|
||||
AC_SUBST(CONSOLE_FLAGS)
|
||||
AC_SUBST(GUI_FLAGS)
|
||||
|
||||
case "$build_os" in
|
||||
*darwin*)
|
||||
HTTPS_CA_DIR=`openssl version -d | sed "s/OPENSSLDIR: \"\(.*\)\"/\1/"`
|
||||
;;
|
||||
esac
|
||||
|
||||
AC_SUBST(HTTPS_CA_DIR)
|
||||
|
||||
dnl localization tools
|
||||
IT_PROG_INTLTOOL([0.40], [no-xml])
|
||||
|
||||
AM_CONDITIONAL(BUILD_TESTS,test x$build_tests != xno)
|
||||
|
||||
dnl Initialize libtool
|
||||
LT_INIT([win32-dll shared disable-static])
|
||||
|
||||
|
|
@ -127,13 +141,15 @@ if test "$mingw_found" != "yes" ; then
|
|||
CPPFLAGS=$CPPFLAGS_save
|
||||
LIBS="$LIBS $LIBINTL"
|
||||
else
|
||||
AC_DEFINE(ENABLE_NLS,1,[Tells whether localisation is possible])
|
||||
AC_DEFINE(HAVE_GETTEXT,1,[Tells wheter localisation is possible])
|
||||
LIBS="$LIBS -lintl"
|
||||
if test "$USE_NLS" = "yes" ; then
|
||||
AC_DEFINE(ENABLE_NLS,1,[Tells whether localisation is possible])
|
||||
AC_DEFINE(HAVE_GETTEXT,1,[Tells wheter localisation is possible])
|
||||
LIBS="$LIBS -lintl"
|
||||
fi
|
||||
fi
|
||||
|
||||
GETTEXT_PACKAGE=linphone
|
||||
AC_SUBST(GETTEXT_PACKAGE)
|
||||
AC_SUBST([GETTEXT_PACKAGE])
|
||||
AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE",[The name of the gettext package name])
|
||||
dnl AC_CHECK_LIB(intl,libintl_gettext)
|
||||
|
||||
|
|
@ -203,15 +219,10 @@ if test "$build_upnp" != "false" ; then
|
|||
AC_DEFINE(BUILD_UPNP, 1, [Define if upnp enabled])
|
||||
fi
|
||||
|
||||
dnl check libxml2 (needed for tools)
|
||||
if test "$build_tools" != "false" ; then
|
||||
PKG_CHECK_MODULES(LIBXML2, [libxml-2.0],[],
|
||||
[if test "$build_tools" = "true" ; then
|
||||
AC_MSG_ERROR([Could not found libxml2, tools cannot be compiled.])
|
||||
else
|
||||
build_tools=false
|
||||
fi]
|
||||
)
|
||||
dnl check libxml2
|
||||
PKG_CHECK_MODULES(LIBXML2, [libxml-2.0],[libxml2_found=yes],foo=bar)
|
||||
if test "$libxml2_found" != "yes" ; then
|
||||
AC_MSG_ERROR([libxml2 not found. Install it and try again (the package is usually named libxml2-dev in the Linux distributions)])
|
||||
fi
|
||||
|
||||
AM_CONDITIONAL(BUILD_TOOLS, test x$build_tools != xfalse)
|
||||
|
|
@ -356,6 +367,25 @@ AC_ARG_ENABLE(debug,
|
|||
esac],
|
||||
[debug_enabled=no]
|
||||
)
|
||||
AS_CASE([$debug_enabled],
|
||||
[yes],[
|
||||
CFLAGS="$CFLAGS -g -DDEBUG"
|
||||
CXXFLAGS="$CXXFLAGS -g -DDEBUG"
|
||||
OBJCFLAGS="$OBJCFLAGS -g -DDEBUG"
|
||||
],
|
||||
[no],
|
||||
[
|
||||
case "$CFLAGS" in
|
||||
*-O*)
|
||||
;;
|
||||
*)
|
||||
CFLAGS="$CFLAGS -O2 -g"
|
||||
CXXFLAGS="$CXXFLAGS -O2 -g"
|
||||
OBJCFLAGS="$OBJCFLAGS -O2 -g"
|
||||
;;
|
||||
esac
|
||||
],
|
||||
[AC_MSG_ERROR([Bad value ($debug_enabled) for --enable-debug. Valid values are yes or no.])])
|
||||
|
||||
dnl enable truespeech codec support
|
||||
AC_ARG_ENABLE(truespeech,
|
||||
|
|
@ -387,13 +417,6 @@ AC_ARG_ENABLE(nonstandard-gsm,
|
|||
[exotic_gsm=no]
|
||||
)
|
||||
|
||||
|
||||
dnl support for RSVP (by Vincent Maury)
|
||||
AC_ARG_ENABLE(rsvp,
|
||||
[AS_HELP_STRING([--enable-rsvp], [Enable support for QoS reservations.])],
|
||||
AC_DEFINE(VINCENT_MAURY_RSVP,1,[Tell whether RSVP support should be compiled.])
|
||||
)
|
||||
|
||||
if test "x${prefix}" = "xNONE"; then
|
||||
package_prefix=${ac_default_prefix}
|
||||
else
|
||||
|
|
@ -424,26 +447,6 @@ AC_DEFINE_UNQUOTED(PACKAGE_SOUND_DIR, "${package_prefix}/${DATADIRNAME}/sounds/l
|
|||
dnl check if we have the getifaddrs() sytem call
|
||||
AC_CHECK_FUNCS(getifaddrs)
|
||||
|
||||
dnl check for osip2
|
||||
LP_CHECK_OSIP2
|
||||
|
||||
dnl conditionnal build for ssl
|
||||
AC_ARG_ENABLE(ssl,
|
||||
[AS_HELP_STRING([--enable-ssl], [Turn on ssl support compiling. Required for sip tls. (default=false)])],
|
||||
[case "${enableval}" in
|
||||
yes) build_ssl=true ;;
|
||||
no) build_ssl=false ;;
|
||||
*) AC_MSG_ERROR(bad value ${enableval} for --enable-ssl) ;;
|
||||
esac],
|
||||
[build_ssl=false]
|
||||
)
|
||||
|
||||
if test "$build_ssl" = "true"; then
|
||||
PKG_CHECK_MODULES(OPENSSL, libssl >= 0.9.8)
|
||||
fi
|
||||
dnl setup flags for exosip library
|
||||
LP_SETUP_EXOSIP
|
||||
|
||||
if test "$console_ui" = "true" ; then
|
||||
dnl check gnu readline
|
||||
LP_CHECK_READLINE
|
||||
|
|
@ -604,7 +607,15 @@ AC_ARG_ENABLE(strict,
|
|||
[strictness=yes]
|
||||
)
|
||||
|
||||
STRICT_OPTIONS="-Wall "
|
||||
STRICT_OPTIONS="-Wall"
|
||||
|
||||
#for clang
|
||||
|
||||
case $CC in
|
||||
*clang*)
|
||||
STRICT_OPTIONS="$STRICT_OPTIONS -Qunused-arguments"
|
||||
;;
|
||||
esac
|
||||
|
||||
if test "$strictness" = "yes" ; then
|
||||
STRICT_OPTIONS="$STRICT_OPTIONS -Werror"
|
||||
|
|
@ -686,6 +697,15 @@ if test x$enable_msg_storage != xfalse; then
|
|||
|
||||
fi
|
||||
|
||||
|
||||
PKG_CHECK_MODULES(BELLESIP, [belle-sip >= 1.2.0])
|
||||
|
||||
SIPSTACK_CFLAGS="$BELLESIP_CFLAGS"
|
||||
SIPSTACK_LIBS="$BELLESIP_LIBS"
|
||||
|
||||
|
||||
AC_SUBST(SIPSTACK_CFLAGS)
|
||||
AC_SUBST(SIPSTACK_LIBS)
|
||||
|
||||
dnl check for db2html (docbook) to generate html user manual
|
||||
AC_CHECK_PROG(have_sgmltools, sgmltools, yes, no)
|
||||
|
|
@ -693,11 +713,8 @@ AM_CONDITIONAL(ENABLE_MANUAL, test x$have_sgmltools$build_manual = xyesyes )
|
|||
|
||||
dnl for external use of linphone libs
|
||||
LINPHONE_CFLAGS="-I${includedir} -I${includedir}/linphone"
|
||||
LINPHONE_LIBS="-L${libdir} -llinphone"
|
||||
LINPHONE_LIBS="-L${libdir} -llinphone -llpc2xml -lxml2lpc"
|
||||
|
||||
if test x$mingw_found = xyes ; then
|
||||
LINPHONE_LIBS="$LINPHONE_LIBS $OSIP_LIBS"
|
||||
fi
|
||||
AC_SUBST(LINPHONE_CFLAGS)
|
||||
AC_SUBST(LINPHONE_LIBS)
|
||||
|
||||
|
|
@ -740,18 +757,62 @@ AC_SUBST(ORTP_LIBS)
|
|||
AC_SUBST([ORTP_VERSION])
|
||||
AC_SUBST([ORTP_DIR])
|
||||
|
||||
AC_ARG_ENABLE(tests_enabled,
|
||||
AC_ARG_ENABLE(tutorials,
|
||||
[AS_HELP_STRING([--disable-tutorials], [Disable compilation of tutorials])],
|
||||
[case "${enableval}" in
|
||||
yes) tutorials_enabled=true ;;
|
||||
no) tutorials_enabled=false ;;
|
||||
*) AC_MSG_ERROR(bad value ${enableval} for --disable-tutorials) ;;
|
||||
esac],
|
||||
[tutorials_enabled=yes]
|
||||
)
|
||||
AM_CONDITIONAL(ENABLE_TUTORIALS, test x$tutorials_enabled = xyes)
|
||||
|
||||
AC_ARG_ENABLE(tests,
|
||||
[AS_HELP_STRING([--disable-tests], [Disable compilation of tests])],
|
||||
[case "${enableval}" in
|
||||
yes) tests_enabled=true ;;
|
||||
no) tests_enabled=false ;;
|
||||
*) AC_MSG_ERROR(bad value ${enableval} for --disable-tests) ;;
|
||||
esac],
|
||||
[tests_enabled=false]
|
||||
[tests_enabled=yes]
|
||||
)
|
||||
AM_CONDITIONAL(ENABLE_TESTS, test x$tests_enabled = xyes)
|
||||
|
||||
PKG_CHECK_MODULES(CUNIT, cunit, [found_cunit=yes],[found_cunit=no])
|
||||
|
||||
if test "$found_cunit" = "no" ; then
|
||||
AC_CHECK_HEADERS(CUnit/CUnit.h,
|
||||
[
|
||||
AC_CHECK_LIB(cunit,CU_add_suite,[
|
||||
found_cunit=yes
|
||||
CUNIT_LIBS+=" -lcunit"
|
||||
])
|
||||
|
||||
])
|
||||
fi
|
||||
|
||||
case "$target_os" in
|
||||
*darwin*)
|
||||
#hack for macport
|
||||
CUNIT_LIBS+=" -lncurses"
|
||||
;;
|
||||
esac
|
||||
AM_CONDITIONAL([BUILD_CUNIT_TESTS], [test x$found_cunit = xyes && test x$tests_enabled != xfalse])
|
||||
if test "$found_cunit" = "no" ; then
|
||||
AC_MSG_WARN([Could not find cunit framework, tests are not compiled.])
|
||||
else
|
||||
AC_CHECK_LIB(cunit,CU_curses_run_tests,[
|
||||
AC_DEFINE(HAVE_CU_CURSES,1,[defined when CU_curses_run_tests is available])
|
||||
],[foo=bar],[$CUNIT_LIBS])
|
||||
fi
|
||||
|
||||
case "$target_os" in
|
||||
*linux*)
|
||||
# Eliminate -lstdc++ addition to postdeps for cross compiles.
|
||||
postdeps_CXX=`echo " $postdeps_CXX " | sed 's, -lstdc++ ,,g'`
|
||||
;;
|
||||
esac
|
||||
|
||||
dnl ##################################################
|
||||
dnl # Check for doxygen
|
||||
|
|
@ -769,9 +830,11 @@ AC_CONFIG_FILES([
|
|||
m4/Makefile
|
||||
po/Makefile.in
|
||||
pixmaps/Makefile
|
||||
include/Makefile
|
||||
coreapi/Makefile
|
||||
coreapi/help/Makefile
|
||||
coreapi/help/Doxyfile
|
||||
tester/Makefile
|
||||
gtk/Makefile
|
||||
console/Makefile
|
||||
daemon/Makefile
|
||||
|
|
@ -804,7 +867,8 @@ printf "* %-30s %s\n" "zRTP encryption (GPLv3)" $zrtp
|
|||
printf "* %-30s %s\n" "uPnP support" $build_upnp
|
||||
|
||||
if test "$enable_tunnel" = "true" ; then
|
||||
printf "* Tunnel support\t\ttrue\n"
|
||||
printf "* %-30s %s\n" "Tunnel support" "true"
|
||||
fi
|
||||
|
||||
|
||||
echo "Now type 'make' to compile, and then 'make install' as root to install it."
|
||||
|
|
|
|||
|
|
@ -3,19 +3,17 @@
|
|||
AM_CPPFLAGS=\
|
||||
-I$(top_srcdir) \
|
||||
-I$(top_srcdir)/coreapi \
|
||||
-I$(top_srcdir)/exosip
|
||||
-I$(top_srcdir)/include
|
||||
|
||||
COMMON_CFLAGS=\
|
||||
-DIN_LINPHONE \
|
||||
-DENABLE_TRACE \
|
||||
-D_ORTP_SOURCE \
|
||||
$(STRICT_OPTIONS) \
|
||||
$(ORTP_CFLAGS) \
|
||||
$(MEDIASTREAMER_CFLAGS) \
|
||||
$(VIDEO_CFLAGS) \
|
||||
$(READLINE_CFLAGS) \
|
||||
$(OSIP_CFLAGS) \
|
||||
$(ORTP_CFLAGS) \
|
||||
$(SQLITE3_CFLAGS) \
|
||||
$(MEDIASTREAMER_CFLAGS)
|
||||
$(SQLITE3_CFLAGS)
|
||||
|
||||
if BUILD_CONSOLE
|
||||
|
||||
|
|
|
|||
|
|
@ -1022,7 +1022,7 @@ lpc_cmd_friend(LinphoneCore *lc, char *args)
|
|||
linphonec_friend_add(lc, name, addr);
|
||||
#else
|
||||
LinphoneFriend *new_friend;
|
||||
new_friend = linphone_friend_new_with_addr(args);
|
||||
new_friend = linphone_friend_new_with_address(args);
|
||||
linphone_core_add_friend(lc, new_friend);
|
||||
#endif
|
||||
return 1;
|
||||
|
|
@ -1082,6 +1082,7 @@ lpc_cmd_proxy(LinphoneCore *lc, char *args)
|
|||
}
|
||||
else if (strcmp(arg1,"remove")==0)
|
||||
{
|
||||
if (arg2==NULL) return 0;
|
||||
linphonec_proxy_remove(lc,atoi(arg2));
|
||||
}
|
||||
else if (strcmp(arg1,"use")==0)
|
||||
|
|
@ -1109,16 +1110,16 @@ lpc_cmd_proxy(LinphoneCore *lc, char *args)
|
|||
{
|
||||
if (strstr(arg2,"default"))
|
||||
{
|
||||
proxynum=linphone_core_get_default_proxy(lc, NULL);
|
||||
if ( proxynum < 0 ) {
|
||||
linphonec_out("No default proxy defined\n");
|
||||
return 1;
|
||||
}
|
||||
linphonec_proxy_show(lc,proxynum);
|
||||
proxynum=linphone_core_get_default_proxy(lc, NULL);
|
||||
if ( proxynum < 0 ) {
|
||||
linphonec_out("No default proxy defined\n");
|
||||
return 1;
|
||||
}
|
||||
linphonec_proxy_show(lc,proxynum);
|
||||
}
|
||||
else
|
||||
{
|
||||
linphonec_proxy_show(lc, atoi(arg2));
|
||||
linphonec_proxy_show(lc, atoi(arg2));
|
||||
}
|
||||
}
|
||||
else return 0; /* syntax error */
|
||||
|
|
@ -1615,7 +1616,7 @@ linphonec_proxy_add(LinphoneCore *lc)
|
|||
continue;
|
||||
}
|
||||
|
||||
linphone_proxy_config_expires(cfg, expires);
|
||||
linphone_proxy_config_set_expires(cfg, expires);
|
||||
linphonec_out("Expiration: %d seconds\n", linphone_proxy_config_get_expires (cfg));
|
||||
|
||||
free(input);
|
||||
|
|
@ -1852,7 +1853,7 @@ linphonec_friend_add(LinphoneCore *lc, const char *name, const char *addr)
|
|||
char url[PATH_MAX];
|
||||
|
||||
snprintf(url, PATH_MAX, "%s <%s>", name, addr);
|
||||
newFriend = linphone_friend_new_with_addr(url);
|
||||
newFriend = linphone_friend_new_with_address(url);
|
||||
linphone_core_add_friend(lc, newFriend);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1929,9 +1930,7 @@ static int lpc_cmd_register(LinphoneCore *lc, char *args){
|
|||
LinphoneAddress *from;
|
||||
LinphoneAuthInfo *info;
|
||||
if ((from=linphone_address_new(identity))!=NULL){
|
||||
char realm[128];
|
||||
snprintf(realm,sizeof(realm)-1,"\"%s\"",linphone_address_get_domain(from));
|
||||
info=linphone_auth_info_new(linphone_address_get_username(from),NULL,passwd,NULL,NULL);
|
||||
info=linphone_auth_info_new(NULL,NULL,passwd,NULL,NULL,linphone_address_get_username(from));
|
||||
linphone_core_add_auth_info(lc,info);
|
||||
linphone_address_destroy(from);
|
||||
linphone_auth_info_destroy(info);
|
||||
|
|
@ -1942,7 +1941,7 @@ static int lpc_cmd_register(LinphoneCore *lc, char *args){
|
|||
cfg=(LinphoneProxyConfig*)elem->data;
|
||||
linphone_proxy_config_edit(cfg);
|
||||
}
|
||||
else cfg=linphone_proxy_config_new();
|
||||
else cfg=linphone_core_create_proxy_config(lc);
|
||||
linphone_proxy_config_set_identity(cfg,identity);
|
||||
linphone_proxy_config_set_server_addr(cfg,proxy);
|
||||
linphone_proxy_config_enable_register(cfg,TRUE);
|
||||
|
|
@ -2030,7 +2029,7 @@ static int lpc_cmd_status(LinphoneCore *lc, char *args)
|
|||
if (linphone_call_get_dir(call)==LinphoneCallOutgoing){
|
||||
linphonec_out("Call out, hook=%s duration=%i, muted=%s rtp-xmit-muted=%s\n", linphonec_get_callee(),
|
||||
linphone_core_get_current_call_duration(lc),
|
||||
linphone_core_is_mic_muted (lc) ? "yes" : "no",
|
||||
linphone_core_mic_enabled(lc) ? "no" : "yes",
|
||||
linphone_core_is_rtp_muted(lc) ? "yes" : "no");
|
||||
}else{
|
||||
linphonec_out("hook=answered duration=%i %s\n" ,
|
||||
|
|
@ -2110,7 +2109,13 @@ static int lpc_cmd_speak(LinphoneCore *lc, char *args){
|
|||
memset(voice,0,sizeof(voice));
|
||||
sscanf(args,"%63s",voice);
|
||||
sentence=args+strlen(voice);
|
||||
|
||||
#ifdef __APPLE__
|
||||
wavfile=mktemp("/tmp/linphonec-espeak-XXXXXX");
|
||||
#else
|
||||
wavfile=tempnam("/tmp/","linphonec-espeak-");
|
||||
#endif
|
||||
|
||||
snprintf(cl,sizeof(cl),"espeak -v %s -s 100 -w %s --stdin",voice,wavfile);
|
||||
file=popen(cl,"w");
|
||||
if (file==NULL){
|
||||
|
|
|
|||
|
|
@ -117,13 +117,12 @@ static char **linephonec_readline_completion(const char *text,
|
|||
#endif
|
||||
|
||||
/* These are callback for linphone core */
|
||||
static void linphonec_prompt_for_auth(LinphoneCore *lc, const char *realm,
|
||||
const char *username);
|
||||
static void linphonec_prompt_for_auth(LinphoneCore *lc, const char *realm, const char *username, const char *domain);
|
||||
static void linphonec_display_refer (LinphoneCore * lc, const char *refer_to);
|
||||
static void linphonec_display_something (LinphoneCore * lc, const char *something);
|
||||
static void linphonec_display_url (LinphoneCore * lc, const char *something, const char *url);
|
||||
static void linphonec_display_warning (LinphoneCore * lc, const char *something);
|
||||
static void linphonec_notify_received(LinphoneCore *lc, LinphoneCall *call, const char *from,const char *event);
|
||||
static void linphonec_transfer_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState new_call_state);
|
||||
|
||||
static void linphonec_notify_presence_received(LinphoneCore *lc,LinphoneFriend *fid);
|
||||
static void linphonec_new_unknown_subscriber(LinphoneCore *lc,
|
||||
|
|
@ -256,7 +255,7 @@ linphonec_display_url (LinphoneCore * lc, const char *something, const char *url
|
|||
* Linphone core callback
|
||||
*/
|
||||
static void
|
||||
linphonec_prompt_for_auth(LinphoneCore *lc, const char *realm, const char *username)
|
||||
linphonec_prompt_for_auth(LinphoneCore *lc, const char *realm, const char *username, const char *domain)
|
||||
{
|
||||
/* no prompt possible when using pipes or tcp mode*/
|
||||
if (unix_socket){
|
||||
|
|
@ -272,7 +271,7 @@ linphonec_prompt_for_auth(LinphoneCore *lc, const char *realm, const char *usern
|
|||
return;
|
||||
}
|
||||
|
||||
pending_auth=linphone_auth_info_new(username,NULL,NULL,NULL,realm);
|
||||
pending_auth=linphone_auth_info_new(username,NULL,NULL,NULL,realm,domain);
|
||||
auth_stack.elem[auth_stack.nitems++]=pending_auth;
|
||||
}
|
||||
}
|
||||
|
|
@ -281,13 +280,14 @@ linphonec_prompt_for_auth(LinphoneCore *lc, const char *realm, const char *usern
|
|||
* Linphone core callback
|
||||
*/
|
||||
static void
|
||||
linphonec_notify_received(LinphoneCore *lc, LinphoneCall *call, const char *from,const char *event)
|
||||
linphonec_transfer_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState new_call_state)
|
||||
{
|
||||
if(!strcmp(event,"refer"))
|
||||
{
|
||||
linphonec_out("The distand endpoint %s of call %li has been transfered, you can safely close the call.\n",
|
||||
from,(long)linphone_call_get_user_pointer (call));
|
||||
char *remote=linphone_call_get_remote_address_as_string(call);
|
||||
if (new_call_state==LinphoneCallConnected){
|
||||
linphonec_out("The distant endpoint %s of call %li has been transfered, you can safely close the call.\n",
|
||||
remote,(long)linphone_call_get_user_pointer (call));
|
||||
}
|
||||
ms_free(remote);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -628,8 +628,8 @@ int
|
|||
main (int argc, char *argv[]) {
|
||||
#endif
|
||||
linphonec_vtable.call_state_changed=linphonec_call_state_changed;
|
||||
linphonec_vtable.notify_presence_recv = linphonec_notify_presence_received;
|
||||
linphonec_vtable.new_subscription_request = linphonec_new_unknown_subscriber;
|
||||
linphonec_vtable.notify_presence_received = linphonec_notify_presence_received;
|
||||
linphonec_vtable.new_subscription_requested = linphonec_new_unknown_subscriber;
|
||||
linphonec_vtable.auth_info_requested = linphonec_prompt_for_auth;
|
||||
linphonec_vtable.display_status = linphonec_display_status;
|
||||
linphonec_vtable.display_message=linphonec_display_something;
|
||||
|
|
@ -638,7 +638,7 @@ main (int argc, char *argv[]) {
|
|||
linphonec_vtable.text_received=linphonec_text_received;
|
||||
linphonec_vtable.dtmf_received=linphonec_dtmf_received;
|
||||
linphonec_vtable.refer_received=linphonec_display_refer;
|
||||
linphonec_vtable.notify_recv=linphonec_notify_received;
|
||||
linphonec_vtable.transfer_state_changed=linphonec_transfer_state_changed;
|
||||
linphonec_vtable.call_encryption_changed=linphonec_call_encryption_changed;
|
||||
|
||||
if (! linphonec_init(argc, argv) ) exit(EXIT_FAILURE);
|
||||
|
|
@ -734,7 +734,8 @@ linphonec_init(int argc, char **argv)
|
|||
*/
|
||||
linphonec=linphone_core_new (&linphonec_vtable, configfile_name, factory_configfile_name, NULL);
|
||||
linphone_core_set_zrtp_secrets_file(linphonec,zrtpsecrets);
|
||||
linphone_core_enable_video(linphonec,vcap_enabled,display_enabled);
|
||||
linphone_core_enable_video_capture(linphonec, vcap_enabled);
|
||||
linphone_core_enable_video_display(linphonec, display_enabled);
|
||||
if (display_enabled && window_id != 0)
|
||||
{
|
||||
printf ("Setting window_id: 0x%x\n", window_id);
|
||||
|
|
@ -1074,7 +1075,7 @@ linphonec_initialize_readline()
|
|||
rl_attempted_completion_function = linephonec_readline_completion;
|
||||
|
||||
/* printf("Readline initialized.\n"); */
|
||||
setlinebuf(stdout);
|
||||
setlinebuf(stdout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,9 +25,9 @@
|
|||
|
||||
|
||||
#ifdef WIN32
|
||||
#include <ws2tcpip.h>
|
||||
#include <windows.h>
|
||||
#include <winbase.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <ctype.h>
|
||||
#include <conio.h>
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
GITVERSION_FILE=liblinphone_gitversion.h
|
||||
GITVERSION_FILE_TMP=liblinphone_gitversion.h.tmp
|
||||
GITDESCRIBE=`git describe --always`
|
||||
GITREVISION=`git rev-parse HEAD`
|
||||
GITDESCRIBE=`cd $(top_srcdir) && git describe --always`
|
||||
GIT_TAG=`cd $(top_srcdir) && git describe --abbrev=0`
|
||||
GITREVISION=`cd $(top_srcdir) && git rev-parse HEAD`
|
||||
|
||||
ECHO=/bin/echo
|
||||
|
||||
|
|
@ -16,7 +17,7 @@ CLEANFILES=$(GITVERSION_FILE)
|
|||
## Process this file with automake to produce Makefile.in
|
||||
linphone_includedir=$(includedir)/linphone
|
||||
|
||||
linphone_include_HEADERS=linphonecore.h linphonefriend.h linphonecore_utils.h lpconfig.h sipsetup.h
|
||||
linphone_include_HEADERS=linphonecore.h linphonefriend.h linphonepresence.h linphonecore_utils.h lpconfig.h sipsetup.h event.h
|
||||
|
||||
if BUILD_TUNNEL
|
||||
linphone_include_HEADERS+=linphone_tunnel.h
|
||||
|
|
@ -27,10 +28,7 @@ lib_LTLIBRARIES=liblinphone.la
|
|||
liblinphone_la_SOURCES=\
|
||||
linphonecore.c linphonecore.h private.h\
|
||||
offeranswer.c offeranswer.h\
|
||||
sal.c sal.h \
|
||||
sal_eXosip2.c sal_eXosip2.h\
|
||||
sal_eXosip2_sdp.c \
|
||||
sal_eXosip2_presence.c \
|
||||
sal.c \
|
||||
callbacks.c \
|
||||
misc.c \
|
||||
address.c \
|
||||
|
|
@ -48,12 +46,27 @@ liblinphone_la_SOURCES=\
|
|||
ec-calibrator.c \
|
||||
conference.c \
|
||||
message_storage.c \
|
||||
info.c \
|
||||
event.c event.h \
|
||||
$(GITVERSION_FILE)
|
||||
|
||||
if BUILD_UPNP
|
||||
liblinphone_la_SOURCES+=upnp.c upnp.h
|
||||
endif
|
||||
|
||||
liblinphone_la_SOURCES+= bellesip_sal/sal_address_impl.c \
|
||||
bellesip_sal/sal_impl.c bellesip_sal/sal_impl.h \
|
||||
bellesip_sal/sal_op_impl.c \
|
||||
bellesip_sal/sal_op_call.c \
|
||||
bellesip_sal/sal_op_registration.c \
|
||||
bellesip_sal/sal_sdp.c \
|
||||
bellesip_sal/sal_op_message.c \
|
||||
bellesip_sal/sal_op_presence.c \
|
||||
bellesip_sal/sal_op_publish.c \
|
||||
bellesip_sal/sal_op_call_transfer.c \
|
||||
bellesip_sal/sal_op_info.c \
|
||||
bellesip_sal/sal_op_events.c
|
||||
|
||||
if BUILD_WIZARD
|
||||
liblinphone_la_SOURCES+=sipwizard.c
|
||||
endif
|
||||
|
|
@ -69,16 +82,32 @@ endif
|
|||
|
||||
liblinphone_la_LDFLAGS= -version-info $(LIBLINPHONE_SO_VERSION) -no-undefined
|
||||
|
||||
if HAVE_LD_OUTPUT_DEF
|
||||
liblinphone_la_LDFLAGS += -Wl,--output-def,liblinphone-$(LIBLINPHONE_SO_CURRENT).def
|
||||
defexecdir = $(libdir)
|
||||
defexec_DATA = liblinphone-$(LIBLINPHONE_SO_CURRENT).def
|
||||
CLEANFILES = $(defexec_DATA)
|
||||
|
||||
liblinphone-$(LIBLINPHONE_SO_CURRENT).def: liblinphone.la
|
||||
|
||||
if BUILD_WIN32
|
||||
defexec_DATA += liblinphone-$(LIBLINPHONE_SO_CURRENT).lib
|
||||
liblinphone-$(LIBLINPHONE_SO_CURRENT).lib: liblinphone-$(LIBLINPHONE_SO_CURRENT).def liblinphone.la
|
||||
$(DLLTOOL) --dllname liblinphone-$(LIBLINPHONE_SO_CURRENT).dll --input-def liblinphone-$(LIBLINPHONE_SO_CURRENT).def --output-lib $@ liblinphone.la
|
||||
endif
|
||||
endif
|
||||
|
||||
liblinphone_la_LIBADD= \
|
||||
$(EXOSIP_LIBS) \
|
||||
$(SIPSTACK_LIBS) \
|
||||
$(MEDIASTREAMER_LIBS) \
|
||||
$(ORTP_LIBS) $(OPENSSL_LIBS) \
|
||||
$(TUNNEL_LIBS) \
|
||||
$(LIBSOUP_LIBS) \
|
||||
$(SQLITE3_LIBS)
|
||||
$(SQLITE3_LIBS) \
|
||||
$(LIBXML2_LIBS)
|
||||
|
||||
|
||||
if BUILD_TESTS
|
||||
if ENABLE_TESTS
|
||||
noinst_PROGRAMS=test_lsd test_ecc test_numbers
|
||||
|
||||
test_lsd_SOURCES=test_lsd.c
|
||||
|
|
@ -95,14 +124,13 @@ test_numbers_LDADD=liblinphone.la $(liblinphone_la_LIBADD)
|
|||
endif
|
||||
|
||||
AM_CPPFLAGS=\
|
||||
-I$(top_srcdir)
|
||||
-I$(top_srcdir) -I$(top_srcdir)/include
|
||||
|
||||
AM_CFLAGS=\
|
||||
$(STRICT_OPTIONS) -DIN_LINPHONE \
|
||||
$(ORTP_CFLAGS) \
|
||||
$(MEDIASTREAMER_CFLAGS) \
|
||||
$(OSIP_CFLAGS) \
|
||||
$(EXOSIP_CFLAGS) \
|
||||
$(SIPSTACK_CFLAGS) \
|
||||
$(LIBSOUP_CFLAGS) \
|
||||
-DENABLE_TRACE \
|
||||
-DLOG_DOMAIN=\"LinphoneCore\" \
|
||||
|
|
@ -110,16 +138,23 @@ AM_CFLAGS=\
|
|||
-DORTP_INET6 \
|
||||
$(VIDEO_CFLAGS) \
|
||||
$(TUNNEL_CFLAGS) \
|
||||
$(SQLITE3_CFLAGS)
|
||||
$(SQLITE3_CFLAGS) \
|
||||
$(LIBXML2_CFLAGS)
|
||||
|
||||
if BUILD_WIZARD
|
||||
AM_CFLAGS+= -DBUILD_WIZARD
|
||||
endif
|
||||
|
||||
AM_CFLAGS+= -DUSE_BELLESIP
|
||||
|
||||
AM_CXXFLAGS=$(AM_CFLAGS)
|
||||
|
||||
make_gitversion_h:
|
||||
if test "$(GITDESCRIBE)" != "" ; then \
|
||||
if test "$(GIT_TAG)" != "$(PACKAGE_VERSION)" ; then \
|
||||
echo "*** PACKAGE_VERSION and git tag differ. Please put them identical."; \
|
||||
exit 1; \
|
||||
fi ; \
|
||||
$(ECHO) -n "#define LIBLINPHONE_GIT_VERSION \"$(GITDESCRIBE)\"" > $(GITVERSION_FILE_TMP) ; \
|
||||
elif test "$(GITREVISION)" != "" ; then \
|
||||
$(ECHO) -n "#define LIBLINPHONE_GIT_VERSION \"$(LINPHONE_VERSION)_$(GITREVISION)\"" > $(GITVERSION_FILE_TMP) ; \
|
||||
|
|
|
|||
|
|
@ -16,8 +16,11 @@
|
|||
#include "ortp/rtpsession.h"
|
||||
#include "linphonecore.h"
|
||||
#include "linphonecore_utils.h"
|
||||
#ifndef USE_BELLESIP
|
||||
#include "eXosip2/eXosip_transport_hook.h"
|
||||
#endif
|
||||
#include "tunnel/udp_mirror.hh"
|
||||
#include "private.h"
|
||||
|
||||
#ifdef ANDROID
|
||||
#include <android/log.h>
|
||||
|
|
@ -27,6 +30,8 @@
|
|||
using namespace belledonnecomm;
|
||||
using namespace ::std;
|
||||
|
||||
#ifndef USE_BELLESIP
|
||||
|
||||
Mutex TunnelManager::sMutex;
|
||||
|
||||
int TunnelManager::eXosipSendto(int fd,const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen,void* userdata){
|
||||
|
|
@ -99,6 +104,7 @@ int TunnelManager::eXosipSelect(int max_fds, fd_set *s1, fd_set *s2, fd_set *s3,
|
|||
return select(max_fds,s1,s2,s3,tv);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void TunnelManager::addServer(const char *ip, int port,unsigned int udpMirrorPort,unsigned int delay) {
|
||||
|
|
@ -181,7 +187,9 @@ void TunnelManager::start() {
|
|||
}
|
||||
mTunnelClient->start();
|
||||
|
||||
#ifndef USE_BELLESIP
|
||||
if (mSipSocket == NULL) mSipSocket =mTunnelClient->createSocket(5060);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool TunnelManager::isStarted() {
|
||||
|
|
@ -209,7 +217,9 @@ int TunnelManager::customRecvfrom(struct _RtpTransport *t, mblk_t *msg, int flag
|
|||
|
||||
TunnelManager::TunnelManager(LinphoneCore* lc) :TunnelClientController()
|
||||
,mCore(lc)
|
||||
#ifndef USE_BELLESIP
|
||||
,mSipSocket(NULL)
|
||||
#endif
|
||||
,mCallback(NULL)
|
||||
,mEnabled(false)
|
||||
,mTunnelClient(NULL)
|
||||
|
|
@ -217,10 +227,12 @@ TunnelManager::TunnelManager(LinphoneCore* lc) :TunnelClientController()
|
|||
,mReady(false)
|
||||
,mHttpProxyPort(0){
|
||||
|
||||
#ifndef USE_BELLESIP
|
||||
mExosipTransport.data=this;
|
||||
mExosipTransport.recvfrom=eXosipRecvfrom;
|
||||
mExosipTransport.sendto=eXosipSendto;
|
||||
mExosipTransport.select=eXosipSelect;
|
||||
#endif
|
||||
linphone_core_add_iterate_hook(mCore,(LinphoneCoreIterateHook)sOnIterate,this);
|
||||
mTransportFactories.audio_rtcp_func=sCreateRtpTransport;
|
||||
mTransportFactories.audio_rtcp_func_data=this;
|
||||
|
|
@ -237,6 +249,9 @@ TunnelManager::~TunnelManager(){
|
|||
}
|
||||
|
||||
void TunnelManager::stopClient(){
|
||||
#ifdef USE_BELLESIP
|
||||
sal_disable_tunnel(mCore->sal);
|
||||
#else
|
||||
eXosip_transport_hook_register(NULL);
|
||||
if (mSipSocket != NULL){
|
||||
sMutex.lock();
|
||||
|
|
@ -244,6 +259,7 @@ void TunnelManager::stopClient(){
|
|||
mSipSocket = NULL;
|
||||
sMutex.unlock();
|
||||
}
|
||||
#endif
|
||||
if (mTunnelClient){
|
||||
delete mTunnelClient;
|
||||
mTunnelClient=NULL;
|
||||
|
|
@ -258,16 +274,9 @@ void TunnelManager::processTunnelEvent(const Event &ev){
|
|||
ms_message("Tunnel is up, registering now");
|
||||
linphone_core_set_firewall_policy(mCore,LinphonePolicyNoFirewall);
|
||||
linphone_core_set_rtp_transport_factories(mCore,&mTransportFactories);
|
||||
eXosip_transport_hook_register(&mExosipTransport);
|
||||
//force transport to udp
|
||||
LCSipTransports lTransport;
|
||||
|
||||
lTransport.udp_port=(0xDFFF&random())+1024;
|
||||
lTransport.tcp_port=0;
|
||||
lTransport.tls_port=0;
|
||||
lTransport.dtls_port=0;
|
||||
|
||||
linphone_core_set_sip_transports(mCore, &lTransport);
|
||||
|
||||
sal_enable_tunnel(mCore->sal, mTunnelClient);
|
||||
|
||||
//register
|
||||
if (lProxy) {
|
||||
linphone_proxy_config_done(lProxy);
|
||||
|
|
@ -323,7 +332,15 @@ void TunnelManager::enable(bool isEnable) {
|
|||
mReady=false;
|
||||
linphone_core_set_rtp_transport_factories(mCore,NULL);
|
||||
|
||||
eXosip_transport_hook_register(NULL);
|
||||
sal_disable_tunnel(mCore->sal);
|
||||
// Set empty transports to force the setting of regular transport, otherwise it is not applied
|
||||
LCSipTransports lTransport;
|
||||
lTransport.udp_port = 0;
|
||||
lTransport.tcp_port = 0;
|
||||
lTransport.tls_port = 0;
|
||||
lTransport.dtls_port = 0;
|
||||
linphone_core_set_sip_transports(mCore, &lTransport);
|
||||
|
||||
//Restore transport and firewall policy
|
||||
linphone_core_set_sip_transports(mCore, &mRegularTransport);
|
||||
linphone_core_set_firewall_policy(mCore, mPreviousFirewallPolicy);
|
||||
|
|
@ -366,8 +383,12 @@ void TunnelManager::sOnIterate(TunnelManager *zis){
|
|||
}
|
||||
|
||||
#ifdef ANDROID
|
||||
extern void linphone_android_log_handler(int prio, const char *fmt, va_list args);
|
||||
extern void linphone_android_log_handler(int prio, char *str);
|
||||
static void linphone_android_tunnel_log_handler(int lev, const char *fmt, va_list args) {
|
||||
char str[4096];
|
||||
vsnprintf(str, sizeof(str) - 1, fmt, args);
|
||||
str[sizeof(str) - 1] = '\0';
|
||||
|
||||
int prio;
|
||||
switch(lev){
|
||||
case TUNNEL_DEBUG: prio = ANDROID_LOG_DEBUG; break;
|
||||
|
|
@ -377,7 +398,7 @@ static void linphone_android_tunnel_log_handler(int lev, const char *fmt, va_lis
|
|||
case TUNNEL_ERROR: prio = ANDROID_LOG_ERROR; break;
|
||||
default: prio = ANDROID_LOG_DEFAULT; break;
|
||||
}
|
||||
linphone_android_log_handler(prio, fmt, args);
|
||||
linphone_android_log_handler(prio, str);
|
||||
}
|
||||
#endif /*ANDROID*/
|
||||
|
||||
|
|
@ -390,7 +411,7 @@ void TunnelManager::enableLogs(bool isEnabled,LogHandler logHandler) {
|
|||
#ifdef ANDROID
|
||||
else SetLogHandler(linphone_android_tunnel_log_handler);
|
||||
#else
|
||||
else SetLogHandler(default_log_handler);
|
||||
else SetLogHandler(tunnel_default_log_handler);
|
||||
#endif
|
||||
|
||||
if (isEnabled) {
|
||||
|
|
|
|||
|
|
@ -15,9 +15,12 @@
|
|||
#include "tunnel/client.hh"
|
||||
#include "linphonecore.h"
|
||||
|
||||
#ifndef USE_BELLESIP
|
||||
extern "C" {
|
||||
#include "eXosip2/eXosip_transport_hook.h"
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace belledonnecomm {
|
||||
class TunnelClient;
|
||||
class UdpMirrorClient;
|
||||
|
|
@ -159,8 +162,10 @@ class UdpMirrorClient;
|
|||
void postEvent(const Event &ev);
|
||||
LinphoneCore* mCore;
|
||||
LCSipTransports mRegularTransport;
|
||||
#ifndef USE_BELLESIP
|
||||
TunnelSocket *mSipSocket;
|
||||
eXosip_transport_hooks_t mExosipTransport;
|
||||
#endif
|
||||
StateCallback mCallback;
|
||||
void * mCallbackData;
|
||||
bool mEnabled;
|
||||
|
|
|
|||
|
|
@ -32,7 +32,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
**/
|
||||
LinphoneAddress * linphone_address_new(const char *addr){
|
||||
SalAddress *saddr=sal_address_new(addr);
|
||||
if (saddr==NULL) ms_error("Cannot create LinphoneAddress, bad uri [%s]",addr);
|
||||
if (saddr==NULL)
|
||||
ms_error("Cannot create LinphoneAddress, bad uri [%s]",addr);
|
||||
return saddr;
|
||||
}
|
||||
|
||||
|
|
@ -43,6 +44,20 @@ LinphoneAddress * linphone_address_clone(const LinphoneAddress *addr){
|
|||
return sal_address_clone(addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment reference count of LinphoneAddress object.
|
||||
**/
|
||||
LinphoneAddress * linphone_address_ref(LinphoneAddress *addr){
|
||||
return sal_address_ref(addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrement reference count of LinphoneAddress object. When dropped to zero, memory is freed.
|
||||
**/
|
||||
void linphone_address_unref(LinphoneAddress *addr){
|
||||
sal_address_unref(addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the address scheme, normally "sip".
|
||||
**/
|
||||
|
|
@ -92,18 +107,26 @@ void linphone_address_set_domain(LinphoneAddress *uri, const char *host){
|
|||
sal_address_set_domain(uri,host);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the port number.
|
||||
**/
|
||||
void linphone_address_set_port(LinphoneAddress *uri, const char *port){
|
||||
sal_address_set_port(uri,port);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the port number.
|
||||
**/
|
||||
void linphone_address_set_port_int(LinphoneAddress *uri, int port){
|
||||
sal_address_set_port_int(uri,port);
|
||||
void linphone_address_set_port(LinphoneAddress *uri, int port){
|
||||
sal_address_set_port(uri,port);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a transport.
|
||||
**/
|
||||
void linphone_address_set_transport(LinphoneAddress *uri, LinphoneTransportType tp){
|
||||
sal_address_set_transport(uri,(SalTransport)tp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the transport.
|
||||
**/
|
||||
LinphoneTransportType linphone_address_get_transport(const LinphoneAddress *uri){
|
||||
return (LinphoneTransportType)sal_address_get_transport(uri);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -129,6 +152,13 @@ char *linphone_address_as_string_uri_only(const LinphoneAddress *u){
|
|||
return sal_address_as_string_uri_only(u);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if address refers to a secure location (sips)
|
||||
**/
|
||||
bool_t linphone_address_is_secure(const LinphoneAddress *uri){
|
||||
return sal_address_is_secure(uri);
|
||||
}
|
||||
|
||||
static bool_t strings_equals(const char *s1, const char *s2){
|
||||
if (s1==NULL && s2==NULL) return TRUE;
|
||||
if (s1!=NULL && s2!=NULL && strcmp(s1,s2)==0) return TRUE;
|
||||
|
|
@ -145,26 +175,33 @@ bool_t linphone_address_weak_equal(const LinphoneAddress *a1, const LinphoneAddr
|
|||
int p1,p2;
|
||||
u1=linphone_address_get_username(a1);
|
||||
u2=linphone_address_get_username(a2);
|
||||
p1=linphone_address_get_port_int(a1);
|
||||
p2=linphone_address_get_port_int(a2);
|
||||
p1=linphone_address_get_port(a1);
|
||||
p2=linphone_address_get_port(a2);
|
||||
h1=linphone_address_get_domain(a1);
|
||||
h2=linphone_address_get_domain(a2);
|
||||
return strings_equals(u1,u2) && strings_equals(h1,h2) && p1==p2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys a LinphoneAddress object.
|
||||
* Destroys a LinphoneAddress object (actually calls linphone_address_unref()).
|
||||
**/
|
||||
void linphone_address_destroy(LinphoneAddress *u){
|
||||
sal_address_destroy(u);
|
||||
sal_address_unref(u);
|
||||
}
|
||||
|
||||
int linphone_address_get_port_int(const LinphoneAddress *u) {
|
||||
return sal_address_get_port_int(u);
|
||||
}
|
||||
/**
|
||||
* Get port number as an integer value.
|
||||
*/
|
||||
|
||||
const char* linphone_address_get_port(const LinphoneAddress *u) {
|
||||
/**
|
||||
* Get port number, 0 if not present.
|
||||
*/
|
||||
int linphone_address_get_port(const LinphoneAddress *u) {
|
||||
return sal_address_get_port(u);
|
||||
}
|
||||
|
||||
LinphoneAddress * linphone_core_create_address(LinphoneCore *lc, const char *address) {
|
||||
return linphone_address_new(address);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
|
|
|||
|
|
@ -33,19 +33,26 @@
|
|||
|
||||
/**
|
||||
* Create a LinphoneAuthInfo object with supplied information.
|
||||
*
|
||||
* The object can be created empty, that is with all arguments set to NULL.
|
||||
* Username, userid, password and realm can be set later using specific methods.
|
||||
* Username, userid, password, realm and domain can be set later using specific methods.
|
||||
* At the end, username and passwd (or ha1) are required.
|
||||
* @param username the username that needs to be authenticated
|
||||
* @param userid the userid used for authenticating (use NULL if you don't know what it is)
|
||||
* @param passwd the password in clear text
|
||||
* @param ha1 the ha1-encrypted password if password is not given in clear text.
|
||||
* @param realm the authentication domain (which can be larger than the sip domain. Unfortunately many SIP servers don't use this parameter.
|
||||
* @param domain the SIP domain for which this authentication information is valid, if it has to be restricted for a single SIP domain.
|
||||
* @return a #LinphoneAuthInfo. linphone_auth_info_destroy() must be used to destroy it when no longer needed. The LinphoneCore makes a copy of LinphoneAuthInfo
|
||||
* passed through linphone_core_add_auth_info().
|
||||
**/
|
||||
LinphoneAuthInfo *linphone_auth_info_new(const char *username, const char *userid,
|
||||
const char *passwd, const char *ha1,const char *realm)
|
||||
{
|
||||
LinphoneAuthInfo *linphone_auth_info_new(const char *username, const char *userid, const char *passwd, const char *ha1, const char *realm, const char *domain){
|
||||
LinphoneAuthInfo *obj=ms_new0(LinphoneAuthInfo,1);
|
||||
if (username!=NULL && (strlen(username)>0) ) obj->username=ms_strdup(username);
|
||||
if (userid!=NULL && (strlen(userid)>0)) obj->userid=ms_strdup(userid);
|
||||
if (passwd!=NULL && (strlen(passwd)>0)) obj->passwd=ms_strdup(passwd);
|
||||
if (ha1!=NULL && (strlen(ha1)>0)) obj->ha1=ms_strdup(ha1);
|
||||
if (realm!=NULL && (strlen(realm)>0)) obj->realm=ms_strdup(realm);
|
||||
if (domain!=NULL && (strlen(domain)>0)) obj->domain=ms_strdup(domain);
|
||||
obj->works=FALSE;
|
||||
return obj;
|
||||
}
|
||||
|
|
@ -57,6 +64,7 @@ static LinphoneAuthInfo *linphone_auth_info_clone(const LinphoneAuthInfo *ai){
|
|||
if (ai->passwd) obj->passwd=ms_strdup(ai->passwd);
|
||||
if (ai->ha1) obj->ha1=ms_strdup(ai->ha1);
|
||||
if (ai->realm) obj->realm=ms_strdup(ai->realm);
|
||||
if (ai->domain) obj->domain=ms_strdup(ai->domain);
|
||||
obj->works=FALSE;
|
||||
obj->usecount=0;
|
||||
return obj;
|
||||
|
|
@ -83,6 +91,11 @@ const char *linphone_auth_info_get_userid(const LinphoneAuthInfo *i){
|
|||
const char *linphone_auth_info_get_realm(const LinphoneAuthInfo *i){
|
||||
return i->realm;
|
||||
}
|
||||
|
||||
const char *linphone_auth_info_get_domain(const LinphoneAuthInfo *i){
|
||||
return i->domain;
|
||||
}
|
||||
|
||||
const char *linphone_auth_info_get_ha1(const LinphoneAuthInfo *i){
|
||||
return i->ha1;
|
||||
}
|
||||
|
|
@ -121,7 +134,7 @@ void linphone_auth_info_set_userid(LinphoneAuthInfo *info, const char *userid){
|
|||
}
|
||||
|
||||
/**
|
||||
* Sets realm.
|
||||
* Set realm.
|
||||
**/
|
||||
void linphone_auth_info_set_realm(LinphoneAuthInfo *info, const char *realm){
|
||||
if (info->realm){
|
||||
|
|
@ -130,6 +143,19 @@ void linphone_auth_info_set_realm(LinphoneAuthInfo *info, const char *realm){
|
|||
}
|
||||
if (realm && strlen(realm)>0) info->realm=ms_strdup(realm);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set domain for which this authentication is valid. This should not be necessary because realm is supposed to be unique and sufficient.
|
||||
* However, many SIP servers don't set realm correctly, then domain has to be used to distinguish between several SIP account bearing the same username.
|
||||
**/
|
||||
void linphone_auth_info_set_domain(LinphoneAuthInfo *info, const char *domain){
|
||||
if (info->domain){
|
||||
ms_free(info->domain);
|
||||
info->domain=NULL;
|
||||
}
|
||||
if (domain && strlen(domain)>0) info->domain=ms_strdup(domain);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets ha1.
|
||||
**/
|
||||
|
|
@ -150,6 +176,7 @@ void linphone_auth_info_destroy(LinphoneAuthInfo *obj){
|
|||
if (obj->passwd!=NULL) ms_free(obj->passwd);
|
||||
if (obj->ha1!=NULL) ms_free(obj->ha1);
|
||||
if (obj->realm!=NULL) ms_free(obj->realm);
|
||||
if (obj->domain!=NULL) ms_free(obj->domain);
|
||||
ms_free(obj);
|
||||
}
|
||||
|
||||
|
|
@ -161,28 +188,36 @@ void linphone_auth_info_write_config(LpConfig *config, LinphoneAuthInfo *obj, in
|
|||
|
||||
if (obj==NULL || lp_config_get_int(config, "sip", "store_auth_info", 1) == 0){
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!obj->ha1 && obj->realm && obj->passwd && (obj->username||obj->userid) && lp_config_get_int(config, "sip", "store_ha1_passwd", 1) == 1) {
|
||||
/*compute ha1 to avoid storing clear text password*/
|
||||
obj->ha1=ms_malloc(33);
|
||||
sal_auth_compute_ha1(obj->userid?obj->userid:obj->username,obj->realm,obj->passwd,obj->ha1);
|
||||
}
|
||||
if (obj->username!=NULL){
|
||||
lp_config_set_string(config,key,"username",obj->username);
|
||||
}
|
||||
if (obj->userid!=NULL){
|
||||
lp_config_set_string(config,key,"userid",obj->userid);
|
||||
}
|
||||
if (obj->passwd!=NULL){
|
||||
lp_config_set_string(config,key,"passwd",obj->passwd);
|
||||
}
|
||||
if (obj->ha1!=NULL){
|
||||
lp_config_set_string(config,key,"ha1",obj->ha1);
|
||||
} else if (obj->passwd!=NULL){ /*only write passwd if no ha1*/
|
||||
lp_config_set_string(config,key,"passwd",obj->passwd);
|
||||
}
|
||||
if (obj->realm!=NULL){
|
||||
lp_config_set_string(config,key,"realm",obj->realm);
|
||||
}
|
||||
if (obj->domain!=NULL){
|
||||
lp_config_set_string(config,key,"domain",obj->domain);
|
||||
}
|
||||
}
|
||||
|
||||
LinphoneAuthInfo *linphone_auth_info_new_from_config_file(LpConfig * config, int pos)
|
||||
{
|
||||
char key[50];
|
||||
const char *username,*userid,*passwd,*ha1,*realm;
|
||||
const char *username,*userid,*passwd,*ha1,*realm,*domain;
|
||||
LinphoneAuthInfo *ret;
|
||||
|
||||
sprintf(key,"auth_info_%i",pos);
|
||||
if (!lp_config_has_section(config,key)){
|
||||
|
|
@ -194,14 +229,9 @@ LinphoneAuthInfo *linphone_auth_info_new_from_config_file(LpConfig * config, int
|
|||
passwd=lp_config_get_string(config,key,"passwd",NULL);
|
||||
ha1=lp_config_get_string(config,key,"ha1",NULL);
|
||||
realm=lp_config_get_string(config,key,"realm",NULL);
|
||||
return linphone_auth_info_new(username,userid,passwd,ha1,realm);
|
||||
}
|
||||
|
||||
static bool_t key_match(const char *tmp1, const char *tmp2){
|
||||
if (tmp1==NULL && tmp2==NULL) return TRUE;
|
||||
if (tmp1!=NULL && tmp2!=NULL && strcmp(tmp1,tmp2)==0) return TRUE;
|
||||
return FALSE;
|
||||
|
||||
domain=lp_config_get_string(config,key,"domain",NULL);
|
||||
ret=linphone_auth_info_new(username,userid,passwd,ha1,realm,domain);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static char * remove_quotes(char * input){
|
||||
|
|
@ -230,41 +260,62 @@ static int realm_match(const char *realm1, const char *realm2){
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a LinphoneAuthInfo previously entered into the LinphoneCore.
|
||||
**/
|
||||
const LinphoneAuthInfo *linphone_core_find_auth_info(LinphoneCore *lc, const char *realm, const char *username)
|
||||
{
|
||||
static const LinphoneAuthInfo *find_auth_info(LinphoneCore *lc, const char *username, const char *realm, const char *domain){
|
||||
MSList *elem;
|
||||
LinphoneAuthInfo *ret=NULL,*candidate=NULL;
|
||||
for (elem=lc->auth_info;elem!=NULL;elem=elem->next){
|
||||
LinphoneAuthInfo *pinfo=(LinphoneAuthInfo*)elem->data;
|
||||
if (realm==NULL){
|
||||
/*return the authinfo for any realm provided that there is only one for that username*/
|
||||
if (key_match(pinfo->username,username)){
|
||||
if (ret!=NULL){
|
||||
ms_warning("There are several auth info for username '%s'",username);
|
||||
return NULL;
|
||||
const LinphoneAuthInfo *ret=NULL;
|
||||
|
||||
for (elem=lc->auth_info;elem!=NULL;elem=elem->next) {
|
||||
LinphoneAuthInfo *pinfo = (LinphoneAuthInfo*)elem->data;
|
||||
if (username && pinfo->username && strcmp(username,pinfo->username)==0) {
|
||||
if (realm && domain){
|
||||
if (pinfo->realm && strcmp(realm,pinfo->realm)==0
|
||||
&& pinfo->domain && strcmp(domain,pinfo->domain)==0) {
|
||||
return pinfo;
|
||||
}
|
||||
ret=pinfo;
|
||||
}
|
||||
}else{
|
||||
/*return the exact authinfo, or an authinfo for which realm was not supplied yet*/
|
||||
if (pinfo->realm!=NULL){
|
||||
if (realm_match(pinfo->realm,realm)
|
||||
&& key_match(pinfo->username,username))
|
||||
} else if (realm) {
|
||||
if (pinfo->realm && realm_match(realm,pinfo->realm)) {
|
||||
if (ret!=NULL) {
|
||||
ms_warning("Non unique realm found for %s",username);
|
||||
return NULL;
|
||||
}
|
||||
ret=pinfo;
|
||||
}else{
|
||||
if (key_match(pinfo->username,username))
|
||||
candidate=pinfo;
|
||||
}
|
||||
} else if (domain && pinfo->domain && strcmp(domain,pinfo->domain)==0) {
|
||||
return pinfo;
|
||||
} else if (!domain) {
|
||||
return pinfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ret==NULL && candidate!=NULL)
|
||||
ret=candidate;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find authentication info matching realm, username, domain criterias.
|
||||
* First of all, (realm,username) pair are searched. If multiple results (which should not happen because realm are supposed to be unique), then domain is added to the search.
|
||||
* @param lc the LinphoneCore
|
||||
* @param realm the authentication 'realm' (optional)
|
||||
* @param username the SIP username to be authenticated (mandatory)
|
||||
* @param domain the SIP domain name (optional)
|
||||
* @return a #LinphoneAuthInfo
|
||||
**/
|
||||
const LinphoneAuthInfo *linphone_core_find_auth_info(LinphoneCore *lc, const char *realm, const char *username, const char *domain){
|
||||
const LinphoneAuthInfo *ai=NULL;
|
||||
if (realm){
|
||||
ai=find_auth_info(lc,username,realm,NULL);
|
||||
if (ai==NULL && domain){
|
||||
ai=find_auth_info(lc,username,realm,domain);
|
||||
}
|
||||
}
|
||||
if (ai == NULL && domain != NULL) {
|
||||
ai=find_auth_info(lc,username,NULL,domain);
|
||||
}
|
||||
if (ai==NULL){
|
||||
ai=find_auth_info(lc,username,NULL,NULL);
|
||||
}
|
||||
return ai;
|
||||
}
|
||||
|
||||
static void write_auth_infos(LinphoneCore *lc){
|
||||
MSList *elem;
|
||||
int i;
|
||||
|
|
@ -277,6 +328,10 @@ static void write_auth_infos(LinphoneCore *lc){
|
|||
linphone_auth_info_write_config(lc->config,NULL,i); /* mark the end */
|
||||
}
|
||||
|
||||
LinphoneAuthInfo * linphone_core_create_auth_info(LinphoneCore *lc, const char *username, const char *userid, const char *passwd, const char *ha1, const char *realm, const char *domain) {
|
||||
return linphone_auth_info_new(username, userid, passwd, ha1, realm, domain);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds authentication information to the LinphoneCore.
|
||||
*
|
||||
|
|
@ -289,25 +344,33 @@ void linphone_core_add_auth_info(LinphoneCore *lc, const LinphoneAuthInfo *info)
|
|||
MSList *l;
|
||||
|
||||
/* find if we are attempting to modify an existing auth info */
|
||||
ai=(LinphoneAuthInfo*)linphone_core_find_auth_info(lc,info->realm,info->username);
|
||||
if (ai!=NULL){
|
||||
ai=(LinphoneAuthInfo*)linphone_core_find_auth_info(lc,info->realm,info->username,info->domain);
|
||||
if (ai!=NULL && ai->domain && info->domain && strcmp(ai->domain, info->domain)==0){
|
||||
lc->auth_info=ms_list_remove(lc->auth_info,ai);
|
||||
linphone_auth_info_destroy(ai);
|
||||
}
|
||||
lc->auth_info=ms_list_append(lc->auth_info,linphone_auth_info_clone(info));
|
||||
/* retry pending authentication operations */
|
||||
for(l=elem=sal_get_pending_auths(lc->sal);elem!=NULL;elem=elem->next){
|
||||
const char *username,*realm;
|
||||
SalOp *op=(SalOp*)elem->data;
|
||||
LinphoneAuthInfo *ai;
|
||||
sal_op_get_auth_requested(op,&realm,&username);
|
||||
ai=(LinphoneAuthInfo*)linphone_core_find_auth_info(lc,realm,username);
|
||||
const SalAuthInfo *req_sai=sal_op_get_auth_requested(op);
|
||||
ai=(LinphoneAuthInfo*)linphone_core_find_auth_info(lc,req_sai->realm,req_sai->username,req_sai->domain);
|
||||
if (ai){
|
||||
SalAuthInfo sai;
|
||||
MSList* proxy;
|
||||
sai.username=ai->username;
|
||||
sai.userid=ai->userid;
|
||||
sai.realm=ai->realm;
|
||||
sai.password=ai->passwd;
|
||||
sai.ha1=ai->ha1;
|
||||
/*proxy case*/
|
||||
for (proxy=(MSList*)linphone_core_get_proxy_config_list(lc);proxy!=NULL;proxy=proxy->next) {
|
||||
if (proxy->data == sal_op_get_user_pointer(op)) {
|
||||
linphone_proxy_config_set_state((LinphoneProxyConfig*)(proxy->data),LinphoneRegistrationProgress,"Authentication...");
|
||||
break;
|
||||
}
|
||||
}
|
||||
sal_op_authenticate(op,&sai);
|
||||
ai->usecount++;
|
||||
}
|
||||
|
|
@ -329,7 +392,7 @@ void linphone_core_abort_authentication(LinphoneCore *lc, LinphoneAuthInfo *inf
|
|||
**/
|
||||
void linphone_core_remove_auth_info(LinphoneCore *lc, const LinphoneAuthInfo *info){
|
||||
LinphoneAuthInfo *r;
|
||||
r=(LinphoneAuthInfo*)linphone_core_find_auth_info(lc,info->realm,info->username);
|
||||
r=(LinphoneAuthInfo*)linphone_core_find_auth_info(lc,info->realm,info->username,info->domain);
|
||||
if (r){
|
||||
lc->auth_info=ms_list_remove(lc->auth_info,r);
|
||||
/*printf("len=%i newlen=%i\n",len,newlen);*/
|
||||
|
|
|
|||
174
coreapi/bellesip_sal/sal_address_impl.c
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
/*
|
||||
linphone
|
||||
Copyright (C) 2012 Belledonne Communications, Grenoble, France
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#include "sal_impl.h"
|
||||
/**/
|
||||
/* Address manipulation API*/
|
||||
SalAddress * sal_address_new(const char *uri){
|
||||
belle_sip_header_address_t* result;
|
||||
if (uri) {
|
||||
result=belle_sip_header_address_parse (uri);
|
||||
/*may return NULL*/
|
||||
} else {
|
||||
result = belle_sip_header_address_new();
|
||||
belle_sip_header_address_set_uri(result,belle_sip_uri_new());
|
||||
}
|
||||
if (result) belle_sip_object_ref(result);
|
||||
return (SalAddress *)result;
|
||||
}
|
||||
SalAddress * sal_address_clone(const SalAddress *addr){
|
||||
return (SalAddress *) belle_sip_object_ref(belle_sip_object_clone(BELLE_SIP_OBJECT(addr)));
|
||||
}
|
||||
const char *sal_address_get_scheme(const SalAddress *addr){
|
||||
belle_sip_header_address_t* header_addr = BELLE_SIP_HEADER_ADDRESS(addr);
|
||||
belle_sip_uri_t* uri = belle_sip_header_address_get_uri(header_addr);
|
||||
if (uri) {
|
||||
if (belle_sip_uri_is_secure(uri)) return "sips";
|
||||
else return "sip";
|
||||
} else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool_t sal_address_is_secure(const SalAddress *addr){
|
||||
belle_sip_header_address_t* header_addr = BELLE_SIP_HEADER_ADDRESS(addr);
|
||||
belle_sip_uri_t* uri = belle_sip_header_address_get_uri(header_addr);
|
||||
if (uri) return belle_sip_uri_is_secure(uri);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
const char *sal_address_get_display_name(const SalAddress* addr){
|
||||
belle_sip_header_address_t* header_addr = BELLE_SIP_HEADER_ADDRESS(addr);
|
||||
return belle_sip_header_address_get_displayname(header_addr);
|
||||
|
||||
}
|
||||
const char *sal_address_get_display_name_unquoted(const SalAddress *addr){
|
||||
return sal_address_get_display_name(addr);
|
||||
}
|
||||
#define SAL_ADDRESS_GET(addr,param) \
|
||||
{belle_sip_header_address_t* header_addr = BELLE_SIP_HEADER_ADDRESS(addr);\
|
||||
belle_sip_uri_t* uri = belle_sip_header_address_get_uri(header_addr);\
|
||||
if (uri) {\
|
||||
return belle_sip_uri_get_##param(uri);\
|
||||
} else\
|
||||
return NULL;}
|
||||
|
||||
#define SAL_ADDRESS_SET(addr,param,value) {\
|
||||
belle_sip_header_address_t* header_addr = BELLE_SIP_HEADER_ADDRESS(addr);\
|
||||
belle_sip_uri_t* uri = belle_sip_header_address_get_uri(header_addr);\
|
||||
belle_sip_uri_set_##param(uri,value);}
|
||||
|
||||
const char *sal_address_get_username(const SalAddress *addr){
|
||||
SAL_ADDRESS_GET(addr,user)
|
||||
}
|
||||
const char *sal_address_get_domain(const SalAddress *addr){
|
||||
SAL_ADDRESS_GET(addr,host)
|
||||
}
|
||||
int sal_address_get_port(const SalAddress *addr){
|
||||
belle_sip_header_address_t* header_addr = BELLE_SIP_HEADER_ADDRESS(addr);
|
||||
belle_sip_uri_t* uri = belle_sip_header_address_get_uri(header_addr);
|
||||
if (uri) {
|
||||
return belle_sip_uri_get_port(uri);
|
||||
} else
|
||||
return -1;
|
||||
}
|
||||
SalTransport sal_address_get_transport(const SalAddress* addr){
|
||||
const char *transport=sal_address_get_transport_name(addr);
|
||||
if (transport)
|
||||
return sal_transport_parse(transport);
|
||||
else
|
||||
return SalTransportUDP;
|
||||
};
|
||||
|
||||
const char* sal_address_get_transport_name(const SalAddress* addr){
|
||||
belle_sip_header_address_t* header_addr = BELLE_SIP_HEADER_ADDRESS(addr);
|
||||
belle_sip_uri_t* uri = belle_sip_header_address_get_uri(header_addr);
|
||||
if (uri) {
|
||||
return belle_sip_uri_get_transport_param(uri);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void sal_address_set_display_name(SalAddress *addr, const char *display_name){
|
||||
belle_sip_header_address_t* header_addr = BELLE_SIP_HEADER_ADDRESS(addr);
|
||||
belle_sip_header_address_set_displayname(header_addr,display_name);
|
||||
}
|
||||
|
||||
void sal_address_set_username(SalAddress *addr, const char *username){
|
||||
SAL_ADDRESS_SET(addr,user,username);
|
||||
}
|
||||
|
||||
void sal_address_set_domain(SalAddress *addr, const char *host){
|
||||
SAL_ADDRESS_SET(addr,host,host);
|
||||
}
|
||||
|
||||
void sal_address_set_port(SalAddress *addr, int port){
|
||||
SAL_ADDRESS_SET(addr,port,port);
|
||||
}
|
||||
|
||||
void sal_address_clean(SalAddress *addr){
|
||||
belle_sip_header_address_t* header_addr = BELLE_SIP_HEADER_ADDRESS(addr);
|
||||
belle_sip_uri_t* uri=belle_sip_header_address_get_uri(header_addr);
|
||||
if (uri) belle_sip_parameters_clean(BELLE_SIP_PARAMETERS(uri));
|
||||
belle_sip_parameters_clean(BELLE_SIP_PARAMETERS(header_addr));
|
||||
return ;
|
||||
}
|
||||
|
||||
char *sal_address_as_string(const SalAddress *addr){
|
||||
char tmp[1024]={0};
|
||||
size_t off=0;
|
||||
belle_sip_object_marshal((belle_sip_object_t*)addr,tmp,sizeof(tmp),&off);
|
||||
return ms_strdup(tmp);
|
||||
}
|
||||
|
||||
char *sal_address_as_string_uri_only(const SalAddress *addr){
|
||||
belle_sip_header_address_t* header_addr = BELLE_SIP_HEADER_ADDRESS(addr);
|
||||
belle_sip_uri_t* uri = belle_sip_header_address_get_uri(header_addr);
|
||||
char tmp[1024]={0};
|
||||
size_t off=0;
|
||||
belle_sip_object_marshal((belle_sip_object_t*)uri,tmp,sizeof(tmp),&off);
|
||||
return ms_strdup(tmp);
|
||||
}
|
||||
|
||||
void sal_address_set_param(SalAddress *addr,const char* name,const char* value){
|
||||
belle_sip_parameters_t* parameters = BELLE_SIP_PARAMETERS(addr);
|
||||
belle_sip_parameters_set_parameter(parameters,name,value);
|
||||
return ;
|
||||
}
|
||||
|
||||
void sal_address_set_transport(SalAddress* addr,SalTransport transport){
|
||||
if (!sal_address_is_secure(addr)){
|
||||
SAL_ADDRESS_SET(addr,transport_param,sal_transport_to_string(transport));
|
||||
}
|
||||
}
|
||||
|
||||
void sal_address_set_transport_name(SalAddress* addr,const char *transport){
|
||||
SAL_ADDRESS_SET(addr,transport_param,transport);
|
||||
}
|
||||
|
||||
SalAddress *sal_address_ref(SalAddress *addr){
|
||||
return (SalAddress*)belle_sip_object_ref(BELLE_SIP_HEADER_ADDRESS(addr));
|
||||
}
|
||||
|
||||
void sal_address_unref(SalAddress *addr){
|
||||
belle_sip_object_unref(BELLE_SIP_HEADER_ADDRESS(addr));
|
||||
}
|
||||
|
||||
void sal_address_destroy(SalAddress *addr){
|
||||
sal_address_unref(addr);
|
||||
}
|
||||
|
||||
919
coreapi/bellesip_sal/sal_impl.c
Normal file
|
|
@ -0,0 +1,919 @@
|
|||
/*
|
||||
linphone
|
||||
Copyright (C) 2012 Belledonne Communications, Grenoble, France
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "sal_impl.h"
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
typedef struct belle_sip_certificates_chain_t _SalCertificatesChain;
|
||||
typedef struct belle_sip_signing_key_t _SalSigningKey;
|
||||
|
||||
/*
|
||||
rfc3323
|
||||
4.2 Expressing Privacy Preferences
|
||||
When a Privacy header is constructed, it MUST consist of either the
|
||||
value 'none', or one or more of the values 'user', 'header' and
|
||||
'session' (each of which MUST appear at most once) which MAY in turn
|
||||
be followed by the 'critical' indicator.
|
||||
*/
|
||||
void sal_op_set_privacy_from_message(SalOp* op,belle_sip_message_t* msg) {
|
||||
belle_sip_header_privacy_t* privacy = belle_sip_message_get_header_by_type(msg,belle_sip_header_privacy_t);
|
||||
if (!privacy) {
|
||||
sal_op_set_privacy(op,SalPrivacyNone);
|
||||
} else {
|
||||
belle_sip_list_t* privacy_list=belle_sip_header_privacy_get_privacy(privacy);
|
||||
sal_op_set_privacy(op,0);
|
||||
for (;privacy_list!=NULL;privacy_list=privacy_list->next) {
|
||||
char* privacy_value=(char*)privacy_list->data;
|
||||
if(strcmp(sal_privacy_to_string(SalPrivacyCritical),privacy_value) == 0)
|
||||
sal_op_set_privacy(op,sal_op_get_privacy(op)|SalPrivacyCritical);
|
||||
if(strcmp(sal_privacy_to_string(SalPrivacyHeader),privacy_value) == 0)
|
||||
sal_op_set_privacy(op,sal_op_get_privacy(op)|SalPrivacyHeader);
|
||||
if(strcmp(sal_privacy_to_string(SalPrivacyId),privacy_value) == 0)
|
||||
sal_op_set_privacy(op,sal_op_get_privacy(op)|SalPrivacyId);
|
||||
if(strcmp(sal_privacy_to_string(SalPrivacyNone),privacy_value) == 0) {
|
||||
sal_op_set_privacy(op,SalPrivacyNone);
|
||||
break;
|
||||
}
|
||||
if(strcmp(sal_privacy_to_string(SalPrivacySession),privacy_value) == 0)
|
||||
sal_op_set_privacy(op,sal_op_get_privacy(op)|SalPrivacySession);
|
||||
if(strcmp(sal_privacy_to_string(SalPrivacyUser),privacy_value) == 0)
|
||||
sal_op_set_privacy(op,sal_op_get_privacy(op)|SalPrivacyUser);
|
||||
}
|
||||
}
|
||||
}
|
||||
static void set_tls_properties(Sal *ctx);
|
||||
|
||||
void _belle_sip_log(belle_sip_log_level lev, const char *fmt, va_list args) {
|
||||
int ortp_level;
|
||||
switch(lev) {
|
||||
case BELLE_SIP_LOG_FATAL:
|
||||
ortp_level=ORTP_FATAL;
|
||||
break;
|
||||
case BELLE_SIP_LOG_ERROR:
|
||||
ortp_level=ORTP_ERROR;
|
||||
break;
|
||||
case BELLE_SIP_LOG_WARNING:
|
||||
ortp_level=ORTP_WARNING;
|
||||
break;
|
||||
case BELLE_SIP_LOG_MESSAGE:
|
||||
ortp_level=ORTP_MESSAGE;
|
||||
break;
|
||||
case BELLE_SIP_LOG_DEBUG:
|
||||
default:
|
||||
ortp_level=ORTP_DEBUG;
|
||||
break;
|
||||
}
|
||||
if (ortp_log_level_enabled(ortp_level)){
|
||||
ortp_logv(ortp_level,fmt,args);
|
||||
}
|
||||
}
|
||||
|
||||
void sal_enable_logs(){
|
||||
belle_sip_set_log_level(BELLE_SIP_LOG_MESSAGE);
|
||||
}
|
||||
|
||||
void sal_disable_logs() {
|
||||
belle_sip_set_log_level(BELLE_SIP_LOG_ERROR);
|
||||
}
|
||||
|
||||
void sal_add_pending_auth(Sal *sal, SalOp *op){
|
||||
if (ms_list_find(sal->pending_auths,op)==NULL){
|
||||
sal->pending_auths=ms_list_append(sal->pending_auths,sal_op_ref(op));
|
||||
}
|
||||
}
|
||||
|
||||
void sal_remove_pending_auth(Sal *sal, SalOp *op){
|
||||
if (ms_list_find(sal->pending_auths,op)){
|
||||
sal->pending_auths=ms_list_remove(sal->pending_auths,op);
|
||||
sal_op_unref(op);
|
||||
}
|
||||
}
|
||||
|
||||
void sal_process_authentication(SalOp *op) {
|
||||
belle_sip_request_t* initial_request=belle_sip_transaction_get_request((belle_sip_transaction_t*)op->pending_auth_transaction);
|
||||
belle_sip_request_t* new_request;
|
||||
bool_t is_within_dialog=FALSE;
|
||||
belle_sip_list_t* auth_list=NULL;
|
||||
belle_sip_auth_event_t* auth_event;
|
||||
belle_sip_response_t *response=belle_sip_transaction_get_response((belle_sip_transaction_t*)op->pending_auth_transaction);
|
||||
|
||||
sal_add_pending_auth(op->base.root,op);
|
||||
|
||||
if (op->dialog && belle_sip_dialog_get_state(op->dialog)==BELLE_SIP_DIALOG_CONFIRMED) {
|
||||
new_request = belle_sip_dialog_create_request_from(op->dialog,initial_request);
|
||||
if (!new_request)
|
||||
new_request = belle_sip_dialog_create_queued_request_from(op->dialog,initial_request);
|
||||
is_within_dialog=TRUE;
|
||||
} else {
|
||||
new_request=initial_request;
|
||||
belle_sip_message_remove_header(BELLE_SIP_MESSAGE(new_request),BELLE_SIP_AUTHORIZATION);
|
||||
belle_sip_message_remove_header(BELLE_SIP_MESSAGE(new_request),BELLE_SIP_PROXY_AUTHORIZATION);
|
||||
}
|
||||
if (new_request==NULL) {
|
||||
ms_error("sal_process_authentication() op=[%p] cannot obtain new request from dialog.",op);
|
||||
return;
|
||||
}
|
||||
|
||||
if (belle_sip_provider_add_authorization(op->base.root->prov,new_request,response,&auth_list)) {
|
||||
if (is_within_dialog) {
|
||||
sal_op_send_request(op,new_request);
|
||||
} else {
|
||||
sal_op_resend_request(op,new_request);
|
||||
}
|
||||
sal_remove_pending_auth(op->base.root,op);
|
||||
}else {
|
||||
ms_message("No auth info found for [%s]",sal_op_get_from(op));
|
||||
if (is_within_dialog) {
|
||||
belle_sip_object_unref(new_request);
|
||||
}
|
||||
if (op->auth_info) sal_auth_info_delete(op->auth_info);
|
||||
auth_event=(belle_sip_auth_event_t*)(auth_list->data);
|
||||
op->auth_info=sal_auth_info_create(auth_event);
|
||||
belle_sip_list_free_with_data(auth_list,(void (*)(void*))belle_sip_auth_event_destroy);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void process_dialog_terminated(void *sal, const belle_sip_dialog_terminated_event_t *event){
|
||||
belle_sip_dialog_t* dialog = belle_sip_dialog_terminated_event_get_dialog(event);
|
||||
SalOp* op = belle_sip_dialog_get_application_data(dialog);
|
||||
if (op && op->callbacks.process_dialog_terminated) {
|
||||
op->callbacks.process_dialog_terminated(op,event);
|
||||
} else {
|
||||
ms_error("sal process_dialog_terminated no op found for this dialog [%p], ignoring",dialog);
|
||||
}
|
||||
}
|
||||
|
||||
static void process_io_error(void *user_ctx, const belle_sip_io_error_event_t *event){
|
||||
belle_sip_client_transaction_t*client_transaction;
|
||||
SalOp* op;
|
||||
if (BELLE_SIP_OBJECT_IS_INSTANCE_OF(belle_sip_io_error_event_get_source(event),belle_sip_client_transaction_t)) {
|
||||
client_transaction=BELLE_SIP_CLIENT_TRANSACTION(belle_sip_io_error_event_get_source(event));
|
||||
op = (SalOp*)belle_sip_transaction_get_application_data(BELLE_SIP_TRANSACTION(client_transaction));
|
||||
if (op->callbacks.process_io_error) {
|
||||
op->callbacks.process_io_error(op,event);
|
||||
}
|
||||
} else {
|
||||
/*ms_error("sal process_io_error not implemented yet for non transaction");*/
|
||||
/*nop, because already handle at transaction layer*/
|
||||
}
|
||||
}
|
||||
|
||||
static void process_request_event(void *ud, const belle_sip_request_event_t *event) {
|
||||
Sal *sal=(Sal*)ud;
|
||||
SalOp* op=NULL;
|
||||
belle_sip_request_t* req = belle_sip_request_event_get_request(event);
|
||||
belle_sip_dialog_t* dialog=belle_sip_request_event_get_dialog(event);
|
||||
belle_sip_header_address_t* origin_address;
|
||||
belle_sip_header_address_t* address;
|
||||
belle_sip_header_from_t* from_header;
|
||||
belle_sip_header_to_t* to;
|
||||
belle_sip_response_t* resp;
|
||||
belle_sip_header_t *evh;
|
||||
const char *method=belle_sip_request_get_method(req);
|
||||
|
||||
from_header=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_from_t);
|
||||
|
||||
if (dialog) {
|
||||
op=(SalOp*)belle_sip_dialog_get_application_data(dialog);
|
||||
if (op==NULL || op->state==SalOpStateTerminated){
|
||||
ms_warning("Receiving request for null or terminated op [%p], ignored",op);
|
||||
return;
|
||||
}
|
||||
}else if (strcmp("INVITE",method)==0) {
|
||||
op=sal_op_new(sal);
|
||||
op->dir=SalOpDirIncoming;
|
||||
sal_op_call_fill_cbs(op);
|
||||
}else if ((strcmp("SUBSCRIBE",method)==0 || strcmp("NOTIFY",method)==0) && (evh=belle_sip_message_get_header(BELLE_SIP_MESSAGE(req),"Event"))!=NULL) {
|
||||
op=sal_op_new(sal);
|
||||
op->dir=SalOpDirIncoming;
|
||||
if (strncmp(belle_sip_header_get_unparsed_value(evh),"presence",strlen("presence"))==0){
|
||||
sal_op_presence_fill_cbs(op);
|
||||
}else
|
||||
sal_op_subscribe_fill_cbs(op);
|
||||
}else if (strcmp("MESSAGE",method)==0) {
|
||||
op=sal_op_new(sal);
|
||||
op->dir=SalOpDirIncoming;
|
||||
sal_op_message_fill_cbs(op);
|
||||
}else if (strcmp("OPTIONS",method)==0) {
|
||||
resp=belle_sip_response_create_from_request(req,200);
|
||||
belle_sip_provider_send_response(sal->prov,resp);
|
||||
return;
|
||||
}else if (strcmp("INFO",method)==0) {
|
||||
resp=belle_sip_response_create_from_request(req,481);/*INFO out of call dialogs are not allowed*/
|
||||
belle_sip_provider_send_response(sal->prov,resp);
|
||||
return;
|
||||
}else if (strcmp("BYE",method)==0) {
|
||||
resp=belle_sip_response_create_from_request(req,481);/*out of dialog BYE */
|
||||
belle_sip_provider_send_response(sal->prov,resp);
|
||||
return;
|
||||
}else if (strcmp("CANCEL",method)==0) {
|
||||
resp=belle_sip_response_create_from_request(req,481);/*out of dialog CANCEL */
|
||||
belle_sip_provider_send_response(sal->prov,resp);
|
||||
return;
|
||||
}else if (sal->enable_test_features && strcmp("PUBLISH",method)==0) {
|
||||
resp=belle_sip_response_create_from_request(req,200);/*out of dialog BYE */
|
||||
belle_sip_message_add_header((belle_sip_message_t*)resp,belle_sip_header_create("SIP-Etag","4441929FFFZQOA"));
|
||||
belle_sip_provider_send_response(sal->prov,resp);
|
||||
return;
|
||||
}else {
|
||||
ms_error("sal process_request_event not implemented yet for method [%s]",belle_sip_request_get_method(req));
|
||||
resp=belle_sip_response_create_from_request(req,501);
|
||||
belle_sip_provider_send_response(sal->prov,resp);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!op->base.from_address) {
|
||||
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)));
|
||||
sal_op_set_from_address(op,(SalAddress*)address);
|
||||
belle_sip_object_unref(address);
|
||||
}
|
||||
|
||||
|
||||
if (!op->base.to_address) {
|
||||
to=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_to_t);
|
||||
address=belle_sip_header_address_create(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(to))
|
||||
,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(to)));
|
||||
sal_op_set_to_address(op,(SalAddress*)address);
|
||||
belle_sip_object_unref(address);
|
||||
}
|
||||
|
||||
if (!op->base.origin) {
|
||||
/*set origin uri*/
|
||||
origin_address=belle_sip_header_address_create(NULL,belle_sip_request_extract_origin(req));
|
||||
__sal_op_set_network_origin_address(op,(SalAddress*)origin_address);
|
||||
belle_sip_object_unref(origin_address);
|
||||
}
|
||||
if (!op->base.remote_ua) {
|
||||
sal_op_set_remote_ua(op,BELLE_SIP_MESSAGE(req));
|
||||
}
|
||||
|
||||
if (!op->base.call_id) {
|
||||
op->base.call_id=ms_strdup(belle_sip_header_call_id_get_call_id(BELLE_SIP_HEADER_CALL_ID(belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req), belle_sip_header_call_id_t))));
|
||||
}
|
||||
/*It is worth noting that proxies can (and
|
||||
will) remove this header field*/
|
||||
sal_op_set_privacy_from_message(op,(belle_sip_message_t*)req);
|
||||
|
||||
sal_op_assign_recv_headers(op,(belle_sip_message_t*)req);
|
||||
if (op->callbacks.process_request_event) {
|
||||
op->callbacks.process_request_event(op,event);
|
||||
} else {
|
||||
ms_error("sal process_request_event not implemented yet");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void process_response_event(void *user_ctx, const belle_sip_response_event_t *event){
|
||||
belle_sip_client_transaction_t* client_transaction = belle_sip_response_event_get_client_transaction(event);
|
||||
belle_sip_response_t* response = belle_sip_response_event_get_response(event);
|
||||
int response_code = belle_sip_response_get_status_code(response);
|
||||
|
||||
if (!client_transaction) {
|
||||
ms_warning("Discarding stateless response [%i]",response_code);
|
||||
return;
|
||||
} else {
|
||||
SalOp* op = (SalOp*)belle_sip_transaction_get_application_data(BELLE_SIP_TRANSACTION(client_transaction));
|
||||
belle_sip_request_t* request=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction));
|
||||
|
||||
if (op->state == SalOpStateTerminated) {
|
||||
belle_sip_message("Op is terminated, nothing to do with this [%i]",response_code);
|
||||
return;
|
||||
}
|
||||
if (!op->base.remote_ua) {
|
||||
sal_op_set_remote_ua(op,BELLE_SIP_MESSAGE(response));
|
||||
}
|
||||
if (!op->base.call_id) {
|
||||
op->base.call_id=ms_strdup(belle_sip_header_call_id_get_call_id(BELLE_SIP_HEADER_CALL_ID(belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(response), belle_sip_header_call_id_t))));
|
||||
}
|
||||
|
||||
sal_op_assign_recv_headers(op,(belle_sip_message_t*)response);
|
||||
|
||||
if (op->callbacks.process_response_event) {
|
||||
/*handle authorization*/
|
||||
switch (response_code) {
|
||||
case 200:
|
||||
break;
|
||||
case 401:
|
||||
case 407:
|
||||
/*belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(client_transaction),NULL);*//*remove op from trans*/
|
||||
if (op->state == SalOpStateTerminating && strcmp("BYE",belle_sip_request_get_method(request))!=0) {
|
||||
/*only bye are completed*/
|
||||
belle_sip_message("Op is in state terminating, nothing else to do ");
|
||||
} else {
|
||||
if (op->pending_auth_transaction){
|
||||
belle_sip_object_unref(op->pending_auth_transaction);
|
||||
op->pending_auth_transaction=NULL;
|
||||
}
|
||||
op->pending_auth_transaction=(belle_sip_client_transaction_t*)belle_sip_object_ref(client_transaction);
|
||||
sal_process_authentication(op);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 403:
|
||||
if (op->auth_info) op->base.root->callbacks.auth_failure(op,op->auth_info);
|
||||
break;
|
||||
}
|
||||
op->callbacks.process_response_event(op,event);
|
||||
} else {
|
||||
ms_error("Unhandled event response [%p]",event);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
static void process_timeout(void *user_ctx, const belle_sip_timeout_event_t *event) {
|
||||
belle_sip_client_transaction_t* client_transaction = belle_sip_timeout_event_get_client_transaction(event);
|
||||
SalOp* op = (SalOp*)belle_sip_transaction_get_application_data(BELLE_SIP_TRANSACTION(client_transaction));
|
||||
if (op && op->callbacks.process_timeout) {
|
||||
op->callbacks.process_timeout(op,event);
|
||||
} else {
|
||||
ms_error("Unhandled event timeout [%p]",event);
|
||||
}
|
||||
}
|
||||
static void process_transaction_terminated(void *user_ctx, const belle_sip_transaction_terminated_event_t *event) {
|
||||
belle_sip_client_transaction_t* client_transaction = belle_sip_transaction_terminated_event_get_client_transaction(event);
|
||||
belle_sip_server_transaction_t* server_transaction = belle_sip_transaction_terminated_event_get_server_transaction(event);
|
||||
belle_sip_transaction_t* trans;
|
||||
SalOp* op;
|
||||
|
||||
if(client_transaction)
|
||||
trans=BELLE_SIP_TRANSACTION(client_transaction);
|
||||
else
|
||||
trans=BELLE_SIP_TRANSACTION(server_transaction);
|
||||
|
||||
op = (SalOp*)belle_sip_transaction_get_application_data(trans);
|
||||
if (op && op->callbacks.process_transaction_terminated) {
|
||||
op->callbacks.process_transaction_terminated(op,event);
|
||||
} else {
|
||||
ms_message("Unhandled transaction terminated [%p]",trans);
|
||||
}
|
||||
if (op && client_transaction) sal_op_unref(op); /*because every client transaction ref op*/
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void process_auth_requested(void *sal, belle_sip_auth_event_t *event) {
|
||||
SalAuthInfo* auth_info = sal_auth_info_create(event);
|
||||
((Sal*)sal)->callbacks.auth_requested(sal,auth_info);
|
||||
belle_sip_auth_event_set_passwd(event,(const char*)auth_info->password);
|
||||
belle_sip_auth_event_set_ha1(event,(const char*)auth_info->ha1);
|
||||
belle_sip_auth_event_set_userid(event,(const char*)auth_info->userid);
|
||||
belle_sip_auth_event_set_signing_key(event,(belle_sip_signing_key_t *)auth_info->key);
|
||||
belle_sip_auth_event_set_client_certificates_chain(event,(belle_sip_certificates_chain_t* )auth_info->certificates);
|
||||
sal_auth_info_delete(auth_info);
|
||||
}
|
||||
|
||||
Sal * sal_init(){
|
||||
belle_sip_listener_callbacks_t listener_callbacks;
|
||||
Sal * sal=ms_new0(Sal,1);
|
||||
sal->auto_contacts=TRUE;
|
||||
sal->user_agent=belle_sip_header_user_agent_new();
|
||||
#if defined(PACKAGE_NAME) && defined(LINPHONE_VERSION)
|
||||
belle_sip_header_user_agent_add_product(sal->user_agent, PACKAGE_NAME "/" LINPHONE_VERSION);
|
||||
#endif
|
||||
sal_append_stack_string_to_user_agent(sal);
|
||||
belle_sip_object_ref(sal->user_agent);
|
||||
belle_sip_set_log_handler(_belle_sip_log);
|
||||
sal->stack = belle_sip_stack_new(NULL);
|
||||
sal->prov = belle_sip_stack_create_provider(sal->stack,NULL);
|
||||
sal_nat_helper_enable(sal,TRUE);
|
||||
memset(&listener_callbacks,0,sizeof(listener_callbacks));
|
||||
listener_callbacks.process_dialog_terminated=process_dialog_terminated;
|
||||
listener_callbacks.process_io_error=process_io_error;
|
||||
listener_callbacks.process_request_event=process_request_event;
|
||||
listener_callbacks.process_response_event=process_response_event;
|
||||
listener_callbacks.process_timeout=process_timeout;
|
||||
listener_callbacks.process_transaction_terminated=process_transaction_terminated;
|
||||
listener_callbacks.process_auth_requested=process_auth_requested;
|
||||
sal->listener=belle_sip_listener_create_from_callbacks(&listener_callbacks,sal);
|
||||
belle_sip_provider_add_sip_listener(sal->prov,sal->listener);
|
||||
sal->tls_verify=TRUE;
|
||||
sal->tls_verify_cn=TRUE;
|
||||
sal->refresher_retry_after=60000; /*default value in ms*/
|
||||
return sal;
|
||||
}
|
||||
void sal_set_user_pointer(Sal *sal, void *user_data){
|
||||
sal->up=user_data;
|
||||
}
|
||||
|
||||
void *sal_get_user_pointer(const Sal *sal){
|
||||
return sal->up;
|
||||
}
|
||||
|
||||
static void unimplemented_stub(){
|
||||
ms_warning("Unimplemented SAL callback");
|
||||
}
|
||||
|
||||
void sal_set_callbacks(Sal *ctx, const SalCallbacks *cbs){
|
||||
memcpy(&ctx->callbacks,cbs,sizeof(*cbs));
|
||||
if (ctx->callbacks.call_received==NULL)
|
||||
ctx->callbacks.call_received=(SalOnCallReceived)unimplemented_stub;
|
||||
if (ctx->callbacks.call_ringing==NULL)
|
||||
ctx->callbacks.call_ringing=(SalOnCallRinging)unimplemented_stub;
|
||||
if (ctx->callbacks.call_accepted==NULL)
|
||||
ctx->callbacks.call_accepted=(SalOnCallAccepted)unimplemented_stub;
|
||||
if (ctx->callbacks.call_failure==NULL)
|
||||
ctx->callbacks.call_failure=(SalOnCallFailure)unimplemented_stub;
|
||||
if (ctx->callbacks.call_terminated==NULL)
|
||||
ctx->callbacks.call_terminated=(SalOnCallTerminated)unimplemented_stub;
|
||||
if (ctx->callbacks.call_released==NULL)
|
||||
ctx->callbacks.call_released=(SalOnCallReleased)unimplemented_stub;
|
||||
if (ctx->callbacks.call_updating==NULL)
|
||||
ctx->callbacks.call_updating=(SalOnCallUpdating)unimplemented_stub;
|
||||
if (ctx->callbacks.auth_failure==NULL)
|
||||
ctx->callbacks.auth_failure=(SalOnAuthFailure)unimplemented_stub;
|
||||
if (ctx->callbacks.register_success==NULL)
|
||||
ctx->callbacks.register_success=(SalOnRegisterSuccess)unimplemented_stub;
|
||||
if (ctx->callbacks.register_failure==NULL)
|
||||
ctx->callbacks.register_failure=(SalOnRegisterFailure)unimplemented_stub;
|
||||
if (ctx->callbacks.dtmf_received==NULL)
|
||||
ctx->callbacks.dtmf_received=(SalOnDtmfReceived)unimplemented_stub;
|
||||
if (ctx->callbacks.notify==NULL)
|
||||
ctx->callbacks.notify=(SalOnNotify)unimplemented_stub;
|
||||
if (ctx->callbacks.subscribe_received==NULL)
|
||||
ctx->callbacks.subscribe_received=(SalOnSubscribeReceived)unimplemented_stub;
|
||||
if (ctx->callbacks.subscribe_closed==NULL)
|
||||
ctx->callbacks.subscribe_closed=(SalOnSubscribeClosed)unimplemented_stub;
|
||||
if (ctx->callbacks.parse_presence_requested==NULL)
|
||||
ctx->callbacks.parse_presence_requested=(SalOnParsePresenceRequested)unimplemented_stub;
|
||||
if (ctx->callbacks.convert_presence_to_xml_requested==NULL)
|
||||
ctx->callbacks.convert_presence_to_xml_requested=(SalOnConvertPresenceToXMLRequested)unimplemented_stub;
|
||||
if (ctx->callbacks.notify_presence==NULL)
|
||||
ctx->callbacks.notify_presence=(SalOnNotifyPresence)unimplemented_stub;
|
||||
if (ctx->callbacks.subscribe_presence_received==NULL)
|
||||
ctx->callbacks.subscribe_presence_received=(SalOnSubscribePresenceReceived)unimplemented_stub;
|
||||
if (ctx->callbacks.text_received==NULL)
|
||||
ctx->callbacks.text_received=(SalOnTextReceived)unimplemented_stub;
|
||||
if (ctx->callbacks.ping_reply==NULL)
|
||||
ctx->callbacks.ping_reply=(SalOnPingReply)unimplemented_stub;
|
||||
if (ctx->callbacks.auth_requested==NULL)
|
||||
ctx->callbacks.auth_requested=(SalOnAuthRequested)unimplemented_stub;
|
||||
if (ctx->callbacks.info_received==NULL)
|
||||
ctx->callbacks.info_received=(SalOnInfoReceived)unimplemented_stub;
|
||||
if (ctx->callbacks.on_publish_response==NULL)
|
||||
ctx->callbacks.on_publish_response=(SalOnPublishResponse)unimplemented_stub;
|
||||
if (ctx->callbacks.on_expire==NULL)
|
||||
ctx->callbacks.on_expire=(SalOnExpire)unimplemented_stub;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void sal_uninit(Sal* sal){
|
||||
belle_sip_object_unref(sal->user_agent);
|
||||
belle_sip_object_unref(sal->prov);
|
||||
belle_sip_object_unref(sal->stack);
|
||||
belle_sip_object_unref(sal->listener);
|
||||
if (sal->uuid) ms_free(sal->uuid);
|
||||
if (sal->root_ca) ms_free(sal->root_ca);
|
||||
ms_free(sal);
|
||||
};
|
||||
|
||||
int sal_transport_available(Sal *sal, SalTransport t){
|
||||
switch(t){
|
||||
case SalTransportUDP:
|
||||
case SalTransportTCP:
|
||||
return TRUE;
|
||||
case SalTransportTLS:
|
||||
return belle_sip_stack_tls_available(sal->stack);
|
||||
case SalTransportDTLS:
|
||||
return FALSE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int sal_add_listen_port(Sal *ctx, SalAddress* addr){
|
||||
int result;
|
||||
belle_sip_listening_point_t* lp = belle_sip_stack_create_listening_point(ctx->stack
|
||||
,sal_address_get_domain(addr)
|
||||
,sal_address_get_port(addr)
|
||||
,sal_transport_to_string(sal_address_get_transport(addr)));
|
||||
if (lp) {
|
||||
belle_sip_listening_point_set_keep_alive(lp,ctx->keep_alive);
|
||||
result = belle_sip_provider_add_listening_point(ctx->prov,lp);
|
||||
set_tls_properties(ctx);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int sal_listen_port(Sal *ctx, const char *addr, int port, SalTransport tr, int is_secure) {
|
||||
SalAddress* sal_addr = sal_address_new(NULL);
|
||||
int result;
|
||||
sal_address_set_domain(sal_addr,addr);
|
||||
sal_address_set_port(sal_addr,port);
|
||||
sal_address_set_transport(sal_addr,tr);
|
||||
result = sal_add_listen_port(ctx,sal_addr);
|
||||
sal_address_destroy(sal_addr);
|
||||
return result;
|
||||
}
|
||||
static void remove_listening_point(belle_sip_listening_point_t* lp,belle_sip_provider_t* prov) {
|
||||
belle_sip_provider_remove_listening_point(prov,lp);
|
||||
}
|
||||
int sal_unlisten_ports(Sal *ctx){
|
||||
const belle_sip_list_t * lps = belle_sip_provider_get_listening_points(ctx->prov);
|
||||
belle_sip_list_t * tmp_list = belle_sip_list_copy(lps);
|
||||
belle_sip_list_for_each2 (tmp_list,(void (*)(void*,void*))remove_listening_point,ctx->prov);
|
||||
belle_sip_list_free(tmp_list);
|
||||
|
||||
ms_message("sal_unlisten_ports done");
|
||||
return 0;
|
||||
}
|
||||
ortp_socket_t sal_get_socket(Sal *ctx){
|
||||
ms_warning("sal_get_socket is deprecated");
|
||||
return -1;
|
||||
}
|
||||
void sal_set_user_agent(Sal *ctx, const char *user_agent){
|
||||
belle_sip_header_user_agent_set_products(ctx->user_agent,NULL);
|
||||
belle_sip_header_user_agent_add_product(ctx->user_agent,user_agent);
|
||||
return ;
|
||||
}
|
||||
|
||||
void sal_append_stack_string_to_user_agent(Sal *ctx) {
|
||||
char stack_string[64];
|
||||
snprintf(stack_string, sizeof(stack_string) - 1, "(belle-sip/%s)", belle_sip_version_to_string());
|
||||
belle_sip_header_user_agent_add_product(ctx->user_agent, stack_string);
|
||||
}
|
||||
|
||||
/*keepalive period in ms*/
|
||||
void sal_set_keepalive_period(Sal *ctx,unsigned int value){
|
||||
const belle_sip_list_t* iterator;
|
||||
belle_sip_listening_point_t* lp;
|
||||
ctx->keep_alive=value;
|
||||
for (iterator=belle_sip_provider_get_listening_points(ctx->prov);iterator!=NULL;iterator=iterator->next) {
|
||||
lp=(belle_sip_listening_point_t*)iterator->data;
|
||||
if (ctx->use_tcp_tls_keep_alive || strcasecmp(belle_sip_listening_point_get_transport(lp),"udp")==0) {
|
||||
belle_sip_listening_point_set_keep_alive(lp,ctx->keep_alive);
|
||||
}
|
||||
}
|
||||
return ;
|
||||
}
|
||||
int sal_enable_tunnel(Sal *ctx, void *tunnelclient) {
|
||||
#ifdef TUNNEL_ENABLED
|
||||
belle_sip_listening_point_t *lp;
|
||||
int result;
|
||||
|
||||
sal_unlisten_ports(ctx);
|
||||
lp = belle_sip_tunnel_listening_point_new(ctx->stack, tunnelclient);
|
||||
if (lp == NULL) return -1;
|
||||
|
||||
belle_sip_listening_point_set_keep_alive(lp, ctx->keep_alive);
|
||||
result = belle_sip_provider_add_listening_point(ctx->prov, lp);
|
||||
set_tls_properties(ctx);
|
||||
return result;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
void sal_disable_tunnel(Sal *ctx) {
|
||||
#ifdef TUNNEL_ENABLED
|
||||
sal_unlisten_ports(ctx);
|
||||
#endif
|
||||
}
|
||||
/**
|
||||
* returns keepalive period in ms
|
||||
* 0 desactiaved
|
||||
* */
|
||||
unsigned int sal_get_keepalive_period(Sal *ctx){
|
||||
return ctx->keep_alive;
|
||||
}
|
||||
void sal_use_session_timers(Sal *ctx, int expires){
|
||||
ctx->session_expires=expires;
|
||||
return ;
|
||||
}
|
||||
|
||||
void sal_use_one_matching_codec_policy(Sal *ctx, bool_t one_matching_codec){
|
||||
ctx->one_matching_codec=one_matching_codec;
|
||||
}
|
||||
|
||||
void sal_use_rport(Sal *ctx, bool_t use_rports){
|
||||
belle_sip_provider_enable_rport(ctx->prov,use_rports);
|
||||
ms_message("Sal use rport [%s]",use_rports?"enabled":"disabled");
|
||||
return ;
|
||||
}
|
||||
|
||||
static void set_tls_properties(Sal *ctx){
|
||||
belle_sip_listening_point_t *lp=belle_sip_provider_get_listening_point(ctx->prov,"TLS");
|
||||
if (lp){
|
||||
belle_sip_tls_listening_point_t *tlp=BELLE_SIP_TLS_LISTENING_POINT(lp);
|
||||
int verify_exceptions=0;
|
||||
|
||||
if (!ctx->tls_verify) verify_exceptions=BELLE_SIP_TLS_LISTENING_POINT_BADCERT_ANY_REASON;
|
||||
else if (!ctx->tls_verify_cn) verify_exceptions=BELLE_SIP_TLS_LISTENING_POINT_BADCERT_CN_MISMATCH;
|
||||
|
||||
belle_sip_tls_listening_point_set_root_ca(tlp,ctx->root_ca); /*root_ca might be NULL */
|
||||
belle_sip_tls_listening_point_set_verify_exceptions(tlp,verify_exceptions);
|
||||
}
|
||||
}
|
||||
|
||||
void sal_set_root_ca(Sal* ctx, const char* rootCa){
|
||||
if (ctx->root_ca){
|
||||
ms_free(ctx->root_ca);
|
||||
ctx->root_ca=NULL;
|
||||
}
|
||||
if (rootCa)
|
||||
ctx->root_ca=ms_strdup(rootCa);
|
||||
set_tls_properties(ctx);
|
||||
return ;
|
||||
}
|
||||
|
||||
void sal_verify_server_certificates(Sal *ctx, bool_t verify){
|
||||
ctx->tls_verify=verify;
|
||||
set_tls_properties(ctx);
|
||||
return ;
|
||||
}
|
||||
|
||||
void sal_verify_server_cn(Sal *ctx, bool_t verify){
|
||||
ctx->tls_verify_cn=verify;
|
||||
set_tls_properties(ctx);
|
||||
return ;
|
||||
}
|
||||
|
||||
void sal_use_tcp_tls_keepalive(Sal *ctx, bool_t enabled) {
|
||||
ctx->use_tcp_tls_keep_alive=enabled;
|
||||
}
|
||||
|
||||
int sal_iterate(Sal *sal){
|
||||
belle_sip_stack_sleep(sal->stack,0);
|
||||
return 0;
|
||||
}
|
||||
MSList * sal_get_pending_auths(Sal *sal){
|
||||
return ms_list_copy(sal->pending_auths);
|
||||
}
|
||||
|
||||
#define payload_type_set_number(pt,n) (pt)->user_data=(void*)((long)n);
|
||||
#define payload_type_get_number(pt) ((int)(long)(pt)->user_data)
|
||||
|
||||
/*misc*/
|
||||
void sal_get_default_local_ip(Sal *sal, int address_family, char *ip, size_t iplen){
|
||||
strncpy(ip,address_family==AF_INET6 ? "::1" : "127.0.0.1",iplen);
|
||||
ms_error("sal_get_default_local_ip() is deprecated.");
|
||||
}
|
||||
|
||||
const char *sal_get_root_ca(Sal* ctx) {
|
||||
return ctx->root_ca;
|
||||
}
|
||||
|
||||
int sal_reset_transports(Sal *ctx){
|
||||
ms_message("Reseting transports");
|
||||
belle_sip_provider_clean_channels(ctx->prov);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sal_set_dscp(Sal *ctx, int dscp){
|
||||
belle_sip_stack_set_default_dscp(ctx->stack,dscp);
|
||||
}
|
||||
|
||||
void sal_set_send_error(Sal *sal,int value) {
|
||||
belle_sip_stack_set_send_error(sal->stack,value);
|
||||
}
|
||||
void sal_set_recv_error(Sal *sal,int value) {
|
||||
belle_sip_provider_set_recv_error(sal->prov,value);
|
||||
}
|
||||
void sal_nat_helper_enable(Sal *sal,bool_t enable) {
|
||||
sal->nat_helper_enabled=enable;
|
||||
belle_sip_provider_enable_nat_helper(sal->prov,enable);
|
||||
ms_message("Sal nat helper [%s]",enable?"enabled":"disabled");
|
||||
}
|
||||
bool_t sal_nat_helper_enabled(Sal *sal) {
|
||||
return sal->nat_helper_enabled;
|
||||
}
|
||||
void sal_set_dns_timeout(Sal* sal,int timeout) {
|
||||
belle_sip_stack_set_dns_timeout(sal->stack, timeout);
|
||||
}
|
||||
int sal_get_dns_timeout(const Sal* sal) {
|
||||
return belle_sip_stack_get_dns_timeout(sal->stack);
|
||||
}
|
||||
void sal_enable_dns_srv(Sal *sal, bool_t enable) {
|
||||
belle_sip_stack_enable_dns_srv(sal->stack, (unsigned char)enable);
|
||||
}
|
||||
bool_t sal_dns_srv_enabled(const Sal *sal) {
|
||||
return (bool_t)belle_sip_stack_dns_srv_enabled(sal->stack);
|
||||
}
|
||||
|
||||
void sal_set_dns_user_hosts_file(Sal *sal, const char *hosts_file) {
|
||||
belle_sip_stack_set_dns_user_hosts_file(sal->stack, hosts_file);
|
||||
}
|
||||
|
||||
const char * sal_get_dns_user_hosts_file(const Sal *sal) {
|
||||
return belle_sip_stack_get_dns_user_hosts_file(sal->stack);
|
||||
}
|
||||
|
||||
SalAuthInfo* sal_auth_info_create(belle_sip_auth_event_t* event) {
|
||||
SalAuthInfo* auth_info = sal_auth_info_new();
|
||||
auth_info->realm = ms_strdup(belle_sip_auth_event_get_realm(event));
|
||||
auth_info->username = ms_strdup(belle_sip_auth_event_get_username(event));
|
||||
auth_info->domain = ms_strdup(belle_sip_auth_event_get_domain(event));
|
||||
auth_info->mode = (SalAuthMode)belle_sip_auth_event_get_mode(event);
|
||||
return auth_info;
|
||||
}
|
||||
|
||||
SalAuthMode sal_auth_info_get_mode(const SalAuthInfo* auth_info) { return auth_info->mode; }
|
||||
SalSigningKey *sal_auth_info_get_signing_key(const SalAuthInfo* auth_info) { return auth_info->key; }
|
||||
SalCertificatesChain *sal_auth_info_get_certificates_chain(const SalAuthInfo* auth_info) { return auth_info->certificates; }
|
||||
void sal_auth_info_set_mode(SalAuthInfo* auth_info, SalAuthMode mode) { auth_info->mode = mode; }
|
||||
void sal_certificates_chain_delete(SalCertificatesChain *chain) {
|
||||
belle_sip_object_unref((belle_sip_object_t *)chain);
|
||||
}
|
||||
void sal_signing_key_delete(SalSigningKey *key) {
|
||||
belle_sip_object_unref((belle_sip_object_t *)key);
|
||||
}
|
||||
|
||||
const char* sal_op_type_to_string(const SalOpType type) {
|
||||
switch(type) {
|
||||
case SalOpRegister: return "SalOpRegister";
|
||||
case SalOpCall: return "SalOpCall";
|
||||
case SalOpMessage: return "SalOpMessage";
|
||||
case SalOpPresence: return "SalOpPresence";
|
||||
default:
|
||||
return "SalOpUnknown";
|
||||
}
|
||||
}
|
||||
|
||||
void sal_use_dates(Sal *ctx, bool_t enabled){
|
||||
ctx->use_dates=enabled;
|
||||
}
|
||||
|
||||
int sal_auth_compute_ha1(const char* userid,const char* realm,const char* password, char ha1[33]) {
|
||||
return belle_sip_auth_helper_compute_ha1(userid, realm, password, ha1);
|
||||
}
|
||||
|
||||
|
||||
SalCustomHeader *sal_custom_header_append(SalCustomHeader *ch, const char *name, const char *value){
|
||||
belle_sip_message_t *msg=(belle_sip_message_t*)ch;
|
||||
belle_sip_header_t *h;
|
||||
char *tmp=ms_strdup_printf("%s: %s\r\n",name,value);
|
||||
|
||||
if (msg==NULL){
|
||||
msg=(belle_sip_message_t*)belle_sip_request_new();
|
||||
belle_sip_object_ref(msg);
|
||||
}
|
||||
h=BELLE_SIP_HEADER(belle_sip_header_extension_parse(tmp));
|
||||
ms_free(tmp);
|
||||
if (h==NULL){
|
||||
belle_sip_error("Fail to parse extension header.");
|
||||
return (SalCustomHeader*)msg;
|
||||
}
|
||||
belle_sip_message_add_header(msg,h);
|
||||
return (SalCustomHeader*)msg;
|
||||
}
|
||||
|
||||
const char *sal_custom_header_find(const SalCustomHeader *ch, const char *name){
|
||||
if (ch){
|
||||
belle_sip_header_t *h=belle_sip_message_get_header((belle_sip_message_t*)ch,name);
|
||||
|
||||
if (h){
|
||||
if (BELLE_SIP_OBJECT_IS_INSTANCE_OF(h,belle_sip_header_extension_t)){
|
||||
return belle_sip_header_extension_get_value(BELLE_SIP_HEADER_EXTENSION(h));
|
||||
}else{
|
||||
return belle_sip_header_get_unparsed_value(h);
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void sal_custom_header_free(SalCustomHeader *ch){
|
||||
if (ch==NULL) return;
|
||||
belle_sip_object_unref((belle_sip_message_t*)ch);
|
||||
}
|
||||
|
||||
SalCustomHeader *sal_custom_header_clone(const SalCustomHeader *ch){
|
||||
if (ch==NULL) return NULL;
|
||||
return (SalCustomHeader*)belle_sip_object_ref((belle_sip_message_t*)ch);
|
||||
}
|
||||
|
||||
const SalCustomHeader *sal_op_get_recv_custom_header(SalOp *op){
|
||||
SalOpBase *b=(SalOpBase *)op;
|
||||
return b->recv_custom_headers;
|
||||
}
|
||||
|
||||
void sal_set_uuid(Sal *sal, const char *uuid){
|
||||
if (sal->uuid){
|
||||
belle_sip_free(sal->uuid);
|
||||
sal->uuid=NULL;
|
||||
}
|
||||
if (uuid)
|
||||
sal->uuid=belle_sip_strdup(uuid);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
unsigned int time_low;
|
||||
unsigned short time_mid;
|
||||
unsigned short time_hi_and_version;
|
||||
unsigned char clock_seq_hi_and_reserved;
|
||||
unsigned char clock_seq_low;
|
||||
unsigned char node[6];
|
||||
} sal_uuid_t;
|
||||
|
||||
|
||||
int sal_create_uuid(Sal*ctx, char *uuid, size_t len){
|
||||
sal_uuid_t uuid_struct;
|
||||
int i;
|
||||
int written;
|
||||
|
||||
if (len==0) return -1;
|
||||
/*create an UUID as described in RFC4122, 4.4 */
|
||||
belle_sip_random_bytes((unsigned char*)&uuid_struct, sizeof(sal_uuid_t));
|
||||
uuid_struct.clock_seq_hi_and_reserved&=~(1<<6);
|
||||
uuid_struct.clock_seq_hi_and_reserved|=1<<7;
|
||||
uuid_struct.time_hi_and_version&=~(0xf<<12);
|
||||
uuid_struct.time_hi_and_version|=4<<12;
|
||||
|
||||
written=snprintf(uuid,len,"%8.8x-%4.4x-%4.4x-%2.2x%2.2x-", uuid_struct.time_low, uuid_struct.time_mid,
|
||||
uuid_struct.time_hi_and_version, uuid_struct.clock_seq_hi_and_reserved,
|
||||
uuid_struct.clock_seq_low);
|
||||
if (written>len+13){
|
||||
ms_error("sal_create_uuid(): buffer is too short !");
|
||||
return -1;
|
||||
}
|
||||
for (i = 0; i < 6; i++)
|
||||
written+=snprintf(uuid+written,len-written,"%2.2x", uuid_struct.node[i]);
|
||||
uuid[len-1]='\0';
|
||||
sal_set_uuid(ctx,uuid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
belle_sip_response_t* sal_create_response_from_request ( Sal* sal, belle_sip_request_t* req, int code ) {
|
||||
belle_sip_response_t *resp=belle_sip_response_create_from_request(req,code);
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(resp),BELLE_SIP_HEADER(sal->user_agent));
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(resp),sal_make_supported_header(sal));
|
||||
return resp;
|
||||
}
|
||||
|
||||
void sal_set_refresher_retry_after(Sal *sal,int value) {
|
||||
sal->refresher_retry_after=value;
|
||||
}
|
||||
|
||||
int sal_get_refresher_retry_after(const Sal *sal) {
|
||||
return sal->refresher_retry_after;
|
||||
}
|
||||
|
||||
void sal_enable_auto_contacts(Sal *ctx, bool_t enabled){
|
||||
ctx->auto_contacts=enabled;
|
||||
}
|
||||
|
||||
void sal_enable_test_features(Sal*ctx, bool_t enabled){
|
||||
ctx->enable_test_features=enabled;
|
||||
}
|
||||
|
||||
SalResolverContext * sal_resolve_a(Sal* sal, const char *name, int port, int family, SalResolverCallback cb, void *data){
|
||||
return (SalResolverContext*)belle_sip_stack_resolve_a(sal->stack,name,port,family,(belle_sip_resolver_callback_t)cb,data);
|
||||
}
|
||||
|
||||
/*
|
||||
void sal_resolve_cancel(Sal *sal, SalResolverContext* ctx){
|
||||
belle_sip_stack_resolve_cancel(sal->stack,ctx);
|
||||
}
|
||||
*/
|
||||
|
||||
void sal_enable_unconditional_answer(Sal *sal,int value) {
|
||||
belle_sip_provider_enable_unconditional_answer(sal->prov,value);
|
||||
}
|
||||
|
||||
/** Parse a file containing either a certificate chain order in PEM format or a single DER cert
|
||||
* @param auth_info structure where to store the result of parsing
|
||||
* @param path path to certificate chain file
|
||||
* @param format either PEM or DER
|
||||
*/
|
||||
void sal_certificates_chain_parse_file(SalAuthInfo* auth_info, const char* path, SalCertificateRawFormat format) {
|
||||
auth_info->certificates = (SalCertificatesChain*) belle_sip_certificates_chain_parse_file(path, (belle_sip_certificate_raw_format_t)format); //
|
||||
if (auth_info->certificates) belle_sip_object_ref((belle_sip_object_t *) auth_info->certificates);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a file containing either a private or public rsa key
|
||||
* @param auth_info structure where to store the result of parsing
|
||||
* @param passwd password (optionnal)
|
||||
*/
|
||||
void sal_signing_key_parse_file(SalAuthInfo* auth_info, const char* path, const char *passwd) {
|
||||
auth_info->key = (SalSigningKey *) belle_sip_signing_key_parse_file(path, passwd);
|
||||
if (auth_info->key) belle_sip_object_ref((belle_sip_object_t *) auth_info->key);
|
||||
}
|
||||
|
||||
unsigned char * sal_get_random_bytes(unsigned char *ret, size_t size){
|
||||
return belle_sip_random_bytes(ret,size);
|
||||
}
|
||||
|
||||
|
||||
|
||||
162
coreapi/bellesip_sal/sal_impl.h
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
/*
|
||||
linphone
|
||||
Copyright (C) 2012 Belledonne Communications, Grenoble, France
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef SAL_IMPL_H_
|
||||
#define SAL_IMPL_H_
|
||||
|
||||
#include "sal/sal.h"
|
||||
#include "belle-sip/belle-sip.h"
|
||||
#include "belle-sip/belle-sdp.h"
|
||||
|
||||
|
||||
|
||||
struct Sal{
|
||||
SalCallbacks callbacks;
|
||||
MSList *pending_auths;/*MSList of SalOp */
|
||||
belle_sip_stack_t* stack;
|
||||
belle_sip_provider_t *prov;
|
||||
belle_sip_header_user_agent_t* user_agent;
|
||||
belle_sip_listener_t *listener;
|
||||
void *up; /*user pointer*/
|
||||
int session_expires;
|
||||
unsigned int keep_alive;
|
||||
char *root_ca;
|
||||
char *uuid;
|
||||
int refresher_retry_after; /*retry after value for refresher*/
|
||||
bool_t one_matching_codec;
|
||||
bool_t use_tcp_tls_keep_alive;
|
||||
bool_t nat_helper_enabled;
|
||||
bool_t tls_verify;
|
||||
bool_t tls_verify_cn;
|
||||
bool_t use_dates;
|
||||
bool_t auto_contacts;
|
||||
bool_t enable_test_features;
|
||||
};
|
||||
|
||||
typedef enum SalOpState {
|
||||
SalOpStateEarly=0
|
||||
,SalOpStateActive
|
||||
,SalOpStateTerminating /*this state is used to wait until a proceeding state, so we can send the cancel*/
|
||||
,SalOpStateTerminated
|
||||
}SalOpState;
|
||||
|
||||
const char* sal_op_state_to_string(SalOpState value);
|
||||
|
||||
typedef enum SalOpDir {
|
||||
SalOpDirIncoming=0
|
||||
,SalOpDirOutgoing
|
||||
}SalOpDir;
|
||||
typedef enum SalOpType {
|
||||
SalOpUnknown,
|
||||
SalOpRegister,
|
||||
SalOpCall,
|
||||
SalOpMessage,
|
||||
SalOpPresence,
|
||||
SalOpPublish,
|
||||
SalOpSubscribe
|
||||
}SalOpType;
|
||||
|
||||
const char* sal_op_type_to_string(SalOpType type);
|
||||
|
||||
struct SalOp{
|
||||
SalOpBase base;
|
||||
belle_sip_listener_callbacks_t callbacks;
|
||||
belle_sip_client_transaction_t *pending_auth_transaction;
|
||||
belle_sip_server_transaction_t* pending_server_trans;
|
||||
belle_sip_client_transaction_t* pending_client_trans;
|
||||
SalAuthInfo* auth_info;
|
||||
belle_sip_dialog_t* dialog;
|
||||
belle_sip_header_replaces_t *replaces;
|
||||
belle_sip_header_referred_by_t *referred_by;
|
||||
SalMediaDescription *result;
|
||||
belle_sdp_session_description_t *sdp_answer;
|
||||
bool_t supports_session_timers;
|
||||
SalOpState state;
|
||||
SalOpDir dir;
|
||||
belle_sip_refresher_t* refresher;
|
||||
int ref;
|
||||
SalOpType type;
|
||||
SalPrivacyMask privacy;
|
||||
belle_sip_header_t *event; /*used by SalOpSubscribe kinds*/
|
||||
bool_t auto_answer_asked;
|
||||
bool_t sdp_offering;
|
||||
bool_t call_released;
|
||||
bool_t manual_refresher;
|
||||
};
|
||||
|
||||
|
||||
belle_sdp_session_description_t * media_description_to_sdp(const SalMediaDescription *sal);
|
||||
int sdp_to_media_description(belle_sdp_session_description_t *sdp, SalMediaDescription *desc);
|
||||
belle_sip_request_t* sal_op_build_request(SalOp *op,const char* method);
|
||||
|
||||
|
||||
void sal_op_call_fill_cbs(SalOp*op);
|
||||
void set_or_update_dialog(SalOp* op, belle_sip_dialog_t* dialog);
|
||||
|
||||
/*return reffed op*/
|
||||
SalOp* sal_op_ref(SalOp* op);
|
||||
/*return null, destroy op if ref count =0*/
|
||||
void* sal_op_unref(SalOp* op);
|
||||
void sal_op_release_impl(SalOp *op);
|
||||
|
||||
void sal_op_set_remote_ua(SalOp*op,belle_sip_message_t* message);
|
||||
int sal_op_send_request(SalOp* op, belle_sip_request_t* request);
|
||||
int sal_op_send_request_with_expires(SalOp* op, belle_sip_request_t* request,int expires);
|
||||
void sal_op_resend_request(SalOp* op, belle_sip_request_t* request);
|
||||
int sal_op_send_and_create_refresher(SalOp* op,belle_sip_request_t* req, int expires,belle_sip_refresher_listener_t listener );
|
||||
belle_sip_response_t *sal_op_create_response_from_request(SalOp *op, belle_sip_request_t *req, int code);
|
||||
|
||||
/*
|
||||
* return true if both from and to uri are sips
|
||||
* */
|
||||
bool_t sal_op_is_secure(const SalOp* op);
|
||||
|
||||
void sal_process_authentication(SalOp *op);
|
||||
belle_sip_header_contact_t* sal_op_create_contact(SalOp *op) ;
|
||||
|
||||
bool_t sal_compute_sal_errors(belle_sip_response_t* response,SalError* sal_err,SalReason* sal_reason,char* reason, size_t reason_size);
|
||||
void sal_compute_sal_errors_from_code(int code ,SalError* sal_err,SalReason* sal_reason) ;
|
||||
/*presence*/
|
||||
void sal_op_presence_fill_cbs(SalOp*op);
|
||||
/*messaging*/
|
||||
void sal_op_message_fill_cbs(SalOp*op);
|
||||
|
||||
void sal_op_subscribe_fill_cbs(SalOp*op);
|
||||
|
||||
/*call transfer*/
|
||||
void sal_op_process_refer(SalOp *op, const belle_sip_request_event_t *event, belle_sip_server_transaction_t *tr);
|
||||
void sal_op_call_process_notify(SalOp *op, const belle_sip_request_event_t *event, belle_sip_server_transaction_t *tr);
|
||||
/*create SalAuthInfo by copying username and realm from suth event*/
|
||||
SalAuthInfo* sal_auth_info_create(belle_sip_auth_event_t* event) ;
|
||||
void sal_add_pending_auth(Sal *sal, SalOp *op);
|
||||
void sal_remove_pending_auth(Sal *sal, SalOp *op);
|
||||
void sal_add_presence_info(SalOp *op, belle_sip_message_t *notify, SalPresenceModel *presence);
|
||||
|
||||
belle_sip_response_t *sal_create_response_from_request(Sal *sal, belle_sip_request_t *req, int code);
|
||||
|
||||
void sal_op_assign_recv_headers(SalOp *op, belle_sip_message_t *incoming);
|
||||
|
||||
void sal_op_add_body(SalOp *op, belle_sip_message_t *req, const SalBody *body);
|
||||
bool_t sal_op_get_body(SalOp *op, belle_sip_message_t *msg, SalBody *salbody);
|
||||
|
||||
SalReason sal_reason_to_sip_code(SalReason r);
|
||||
|
||||
belle_sip_header_t * sal_make_supported_header(Sal *sal);
|
||||
|
||||
#endif /* SAL_IMPL_H_ */
|
||||
813
coreapi/bellesip_sal/sal_op_call.c
Normal file
|
|
@ -0,0 +1,813 @@
|
|||
/*
|
||||
linphone
|
||||
Copyright (C) 2012 Belledonne Communications, Grenoble, France
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#include "sal_impl.h"
|
||||
#include "offeranswer.h"
|
||||
|
||||
/*used for calls terminated before creation of a dialog*/
|
||||
static void call_set_released(SalOp* op){
|
||||
if (!op->call_released){
|
||||
op->state=SalOpStateTerminated;
|
||||
op->base.root->callbacks.call_released(op);
|
||||
op->call_released=TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/*used when the SalOp was ref'd by the dialog, in which case we rely only on the dialog terminated notification*/
|
||||
static void call_set_released_and_unref(SalOp* op) {
|
||||
call_set_released(op);
|
||||
sal_op_unref(op);
|
||||
}
|
||||
|
||||
|
||||
static void call_set_error(SalOp* op,belle_sip_response_t* response){
|
||||
SalError error=SalErrorUnknown;
|
||||
SalReason sr=SalReasonUnknown;
|
||||
belle_sip_header_t* reason_header = belle_sip_message_get_header(BELLE_SIP_MESSAGE(response),"Reason");
|
||||
char* reason=(char*)belle_sip_response_get_reason_phrase(response);
|
||||
int code = belle_sip_response_get_status_code(response);
|
||||
if (reason_header){
|
||||
reason = ms_strdup_printf("%s %s",reason,belle_sip_header_extension_get_value(BELLE_SIP_HEADER_EXTENSION(reason_header)));
|
||||
}
|
||||
sal_compute_sal_errors_from_code(code,&error,&sr);
|
||||
op->base.root->callbacks.call_failure(op,error,sr,reason,code);
|
||||
if (reason_header != NULL){
|
||||
ms_free(reason);
|
||||
}
|
||||
}
|
||||
|
||||
static void sdp_process(SalOp *h){
|
||||
ms_message("Doing SDP offer/answer process of type %s",h->sdp_offering ? "outgoing" : "incoming");
|
||||
if (h->result){
|
||||
sal_media_description_unref(h->result);
|
||||
}
|
||||
h->result=sal_media_description_new();
|
||||
if (h->sdp_offering){
|
||||
offer_answer_initiate_outgoing(h->base.local_media,h->base.remote_media,h->result);
|
||||
}else{
|
||||
int i;
|
||||
if (h->sdp_answer){
|
||||
belle_sip_object_unref(h->sdp_answer);
|
||||
}
|
||||
offer_answer_initiate_incoming(h->base.local_media,h->base.remote_media,h->result,h->base.root->one_matching_codec);
|
||||
h->sdp_answer=(belle_sdp_session_description_t *)belle_sip_object_ref(media_description_to_sdp(h->result));
|
||||
/*once we have generated the SDP answer, we modify the result description for processing by the upper layer.
|
||||
It should contains media parameters constraint from the remote offer, not our response*/
|
||||
strcpy(h->result->addr,h->base.remote_media->addr);
|
||||
h->result->bandwidth=h->base.remote_media->bandwidth;
|
||||
|
||||
for(i=0;i<h->result->n_active_streams;++i){
|
||||
strcpy(h->result->streams[i].rtp_addr,h->base.remote_media->streams[i].rtp_addr);
|
||||
h->result->streams[i].ptime=h->base.remote_media->streams[i].ptime;
|
||||
h->result->streams[i].bandwidth=h->base.remote_media->streams[i].bandwidth;
|
||||
h->result->streams[i].rtp_port=h->base.remote_media->streams[i].rtp_port;
|
||||
strcpy(h->result->streams[i].rtcp_addr,h->base.remote_media->streams[i].rtcp_addr);
|
||||
h->result->streams[i].rtcp_port=h->base.remote_media->streams[i].rtcp_port;
|
||||
|
||||
if (h->result->streams[i].proto == SalProtoRtpSavp) {
|
||||
h->result->streams[i].crypto[0] = h->base.remote_media->streams[i].crypto[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
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;
|
||||
belle_sip_error_code error = BELLE_SIP_OK;
|
||||
size_t length = 0;
|
||||
char buff[2048];
|
||||
|
||||
if (session_desc) {
|
||||
content_type = belle_sip_header_content_type_create("application","sdp");
|
||||
error = belle_sip_object_marshal(BELLE_SIP_OBJECT(session_desc),buff,sizeof(buff),&length);
|
||||
if (error != BELLE_SIP_OK) {
|
||||
ms_error("Buffer too small or sdp too big");
|
||||
return -1;
|
||||
}
|
||||
|
||||
content_length= belle_sip_header_content_length_create(length);
|
||||
belle_sip_message_add_header(msg,BELLE_SIP_HEADER(content_type));
|
||||
belle_sip_message_add_header(msg,BELLE_SIP_HEADER(content_length));
|
||||
belle_sip_message_set_body(msg,buff,length);
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
static int set_sdp_from_desc(belle_sip_message_t *msg, const SalMediaDescription *desc){
|
||||
int err;
|
||||
belle_sdp_session_description_t *sdp=media_description_to_sdp(desc);
|
||||
err=set_sdp(msg,sdp);
|
||||
belle_sip_object_unref(sdp);
|
||||
return err;
|
||||
|
||||
}
|
||||
static void call_process_io_error(void *user_ctx, const belle_sip_io_error_event_t *event){
|
||||
SalOp* op=(SalOp*)user_ctx;
|
||||
|
||||
if (op->state==SalOpStateTerminated) return;
|
||||
|
||||
if (!op->dialog) {
|
||||
/*call terminated very early*/
|
||||
op->base.root->callbacks.call_failure(op,SalErrorNoResponse,SalReasonUnknown,"Service Unavailable",503);
|
||||
call_set_released(op);
|
||||
} else {
|
||||
/*dialog will terminated shortly, nothing to do*/
|
||||
}
|
||||
}
|
||||
static void process_dialog_terminated(void *ctx, const belle_sip_dialog_terminated_event_t *event) {
|
||||
SalOp* op=(SalOp*)ctx;
|
||||
|
||||
if (op->dialog && op->dialog==belle_sip_dialog_terminated_event_get_dialog(event)) {
|
||||
/*belle_sip_transaction_t* trans=belle_sip_dialog_get_last_transaction(op->dialog);*/
|
||||
ms_message("Dialog [%p] terminated for op [%p]",belle_sip_dialog_terminated_event_get_dialog(event),op);
|
||||
|
||||
switch(belle_sip_dialog_get_previous_state(op->dialog)) {
|
||||
case BELLE_SIP_DIALOG_CONFIRMED:
|
||||
if (op->state!=SalOpStateTerminated && op->state!=SalOpStateTerminating) {
|
||||
/*this is probably a normal termination from a BYE*/
|
||||
op->base.root->callbacks.call_terminated(op,op->dir==SalOpDirIncoming?sal_op_get_from(op):sal_op_get_to(op));
|
||||
op->state=SalOpStateTerminating;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
belle_sip_main_loop_do_later(belle_sip_stack_get_main_loop(op->base.root->stack)
|
||||
,(belle_sip_callback_t) call_set_released_and_unref
|
||||
, op);
|
||||
} else {
|
||||
ms_error("dialog unknown for op ");
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
static void cancelling_invite(SalOp* op ){
|
||||
belle_sip_request_t* cancel;
|
||||
ms_message("Cancelling INVITE request from [%s] to [%s] ",sal_op_get_from(op), sal_op_get_to(op));
|
||||
cancel = belle_sip_client_transaction_create_cancel(op->pending_client_trans);
|
||||
sal_op_send_request(op,cancel);
|
||||
op->state=SalOpStateTerminating;
|
||||
}
|
||||
|
||||
static void call_process_response(void *op_base, const belle_sip_response_event_t *event){
|
||||
SalOp* op = (SalOp*)op_base;
|
||||
belle_sip_request_t* ack;
|
||||
belle_sip_dialog_state_t dialog_state;
|
||||
belle_sip_client_transaction_t* client_transaction = belle_sip_response_event_get_client_transaction(event);
|
||||
belle_sip_request_t* req;
|
||||
belle_sip_response_t* response=belle_sip_response_event_get_response(event);
|
||||
int code = belle_sip_response_get_status_code(response);
|
||||
|
||||
|
||||
if (!client_transaction) {
|
||||
ms_warning("Discarding stateless response [%i] on op [%p]",code,op);
|
||||
return;
|
||||
}
|
||||
req=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction));
|
||||
set_or_update_dialog(op,belle_sip_response_event_get_dialog(event));
|
||||
dialog_state=op->dialog?belle_sip_dialog_get_state(op->dialog):BELLE_SIP_DIALOG_NULL;
|
||||
|
||||
ms_message("Op [%p] receiving call response [%i], dialog is [%p] in state [%s]",op,code,op->dialog,belle_sip_dialog_state_to_string(dialog_state));
|
||||
|
||||
switch(dialog_state) {
|
||||
case BELLE_SIP_DIALOG_NULL:
|
||||
case BELLE_SIP_DIALOG_EARLY: {
|
||||
if (strcmp("INVITE",belle_sip_request_get_method(req))==0 ) {
|
||||
if (op->state == SalOpStateTerminating) {
|
||||
/*check if CANCEL was sent before*/
|
||||
if (strcmp("CANCEL",belle_sip_request_get_method(belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(op->pending_client_trans))))!=0) {
|
||||
/*it wasn't sent */
|
||||
if (code<200) {
|
||||
cancelling_invite(op);
|
||||
}else{
|
||||
/* no need to send the INVITE because the UAS rejected the INVITE*/
|
||||
if (op->dialog==NULL) call_set_released(op);
|
||||
}
|
||||
} else {
|
||||
/*it was sent already, so just expect the 487 or any error response to send the call_released() notification*/
|
||||
if (code>=300){
|
||||
if (op->dialog==NULL) call_set_released(op);
|
||||
}
|
||||
}
|
||||
} else if (code >= 180 && code<300) {
|
||||
handle_sdp_from_response(op,response);
|
||||
op->base.root->callbacks.call_ringing(op);
|
||||
} else if (code>=300){
|
||||
call_set_error(op,response);
|
||||
if (op->dialog==NULL) call_set_released(op);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case BELLE_SIP_DIALOG_CONFIRMED: {
|
||||
switch (op->state) {
|
||||
case SalOpStateEarly:/*invite case*/
|
||||
case SalOpStateActive: /*re-invite case*/
|
||||
if (code >=200
|
||||
&& code<300
|
||||
&& strcmp("INVITE",belle_sip_request_get_method(req))==0) {
|
||||
handle_sdp_from_response(op,response);
|
||||
ack=belle_sip_dialog_create_ack(op->dialog,belle_sip_dialog_get_local_seq_number(op->dialog));
|
||||
if (ack==NULL) {
|
||||
ms_error("This call has been already terminated.");
|
||||
return ;
|
||||
}
|
||||
if (op->sdp_answer){
|
||||
set_sdp(BELLE_SIP_MESSAGE(ack),op->sdp_answer);
|
||||
belle_sip_object_unref(op->sdp_answer);
|
||||
op->sdp_answer=NULL;
|
||||
}
|
||||
belle_sip_dialog_send_ack(op->dialog,ack);
|
||||
op->base.root->callbacks.call_accepted(op); /*INVITE*/
|
||||
op->state=SalOpStateActive;
|
||||
} else if (code >= 300 && strcmp("INVITE",belle_sip_request_get_method(req))==0){
|
||||
call_set_error(op,response);
|
||||
} else {
|
||||
/*ignoring*/
|
||||
}
|
||||
break;
|
||||
case SalOpStateTerminating:
|
||||
sal_op_send_request(op,belle_sip_dialog_create_request(op->dialog,"BYE"));
|
||||
break;
|
||||
case SalOpStateTerminated:
|
||||
default:
|
||||
ms_error("Call op [%p] receives unexpected answer [%i] while in state [%s].",op,code, sal_op_state_to_string(op->state));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case BELLE_SIP_DIALOG_TERMINATED: {
|
||||
if (code >= 300){
|
||||
call_set_error(op,response);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default: {
|
||||
ms_error("call op [%p] receive answer [%i] not implemented",op,code);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void call_process_timeout(void *user_ctx, const belle_sip_timeout_event_t *event) {
|
||||
SalOp* op=(SalOp*)user_ctx;
|
||||
|
||||
if (op->state==SalOpStateTerminated) return;
|
||||
|
||||
if (!op->dialog) {
|
||||
/*call terminated very early*/
|
||||
op->base.root->callbacks.call_failure(op,SalErrorNoResponse,SalReasonUnknown,"Request Timeout",408);
|
||||
call_set_released(op);
|
||||
} else {
|
||||
/*dialog will terminated shortly, nothing to do*/
|
||||
}
|
||||
}
|
||||
|
||||
static void call_process_transaction_terminated(void *user_ctx, const belle_sip_transaction_terminated_event_t *event) {
|
||||
SalOp* op = (SalOp*)user_ctx;
|
||||
belle_sip_client_transaction_t *client_transaction=belle_sip_transaction_terminated_event_get_client_transaction(event);
|
||||
belle_sip_server_transaction_t *server_transaction=belle_sip_transaction_terminated_event_get_server_transaction(event);
|
||||
belle_sip_request_t* req;
|
||||
belle_sip_response_t* resp;
|
||||
if (client_transaction) {
|
||||
req=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction));
|
||||
resp=belle_sip_transaction_get_response(BELLE_SIP_TRANSACTION(client_transaction));
|
||||
} else {
|
||||
req=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(server_transaction));
|
||||
resp=belle_sip_transaction_get_response(BELLE_SIP_TRANSACTION(server_transaction));
|
||||
}
|
||||
if (op->state ==SalOpStateTerminating
|
||||
&& strcmp("BYE",belle_sip_request_get_method(req))==0
|
||||
&& (!resp || (belle_sip_response_get_status_code(resp) !=401
|
||||
&& belle_sip_response_get_status_code(resp) !=407))) {
|
||||
if (op->dialog==NULL) call_set_released(op);
|
||||
}
|
||||
}
|
||||
|
||||
static void call_terminated(SalOp* op,belle_sip_server_transaction_t* server_transaction, belle_sip_request_t* request,int status_code) {
|
||||
belle_sip_response_t* resp;
|
||||
op->base.root->callbacks.call_terminated(op,op->dir==SalOpDirIncoming?sal_op_get_from(op):sal_op_get_to(op));
|
||||
resp=sal_op_create_response_from_request(op,request,status_code);
|
||||
belle_sip_server_transaction_send_response(server_transaction,resp);
|
||||
}
|
||||
|
||||
static void unsupported_method(belle_sip_server_transaction_t* server_transaction,belle_sip_request_t* request) {
|
||||
belle_sip_response_t* resp;
|
||||
resp=belle_sip_response_create_from_request(request,500);
|
||||
belle_sip_server_transaction_send_response(server_transaction,resp);
|
||||
return;
|
||||
}
|
||||
|
||||
static void 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;
|
||||
}
|
||||
|
||||
static void process_request_event(void *op_base, const belle_sip_request_event_t *event) {
|
||||
SalOp* op = (SalOp*)op_base;
|
||||
belle_sip_server_transaction_t* server_transaction=NULL;
|
||||
belle_sdp_session_description_t* sdp;
|
||||
belle_sip_request_t* req = belle_sip_request_event_get_request(event);
|
||||
belle_sip_dialog_state_t dialog_state;
|
||||
belle_sip_response_t* resp;
|
||||
belle_sip_header_t* call_info;
|
||||
|
||||
if (strcmp("ACK",belle_sip_request_get_method(req))!=0){ /*ACK does'nt create srv transaction*/
|
||||
server_transaction = belle_sip_provider_create_server_transaction(op->base.root->prov,belle_sip_request_event_get_request(event));
|
||||
belle_sip_object_ref(server_transaction);
|
||||
belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(server_transaction),op);
|
||||
sal_op_ref(op);
|
||||
}
|
||||
|
||||
if (strcmp("INVITE",belle_sip_request_get_method(req))==0) {
|
||||
if (op->pending_server_trans) belle_sip_object_unref(op->pending_server_trans);
|
||||
/*updating pending invite transaction*/
|
||||
op->pending_server_trans=server_transaction;
|
||||
belle_sip_object_ref(op->pending_server_trans);
|
||||
}
|
||||
|
||||
if (!op->dialog) {
|
||||
set_or_update_dialog(op,belle_sip_provider_create_dialog(op->base.root->prov,BELLE_SIP_TRANSACTION(op->pending_server_trans)));
|
||||
ms_message("new incoming call from [%s] to [%s]",sal_op_get_from(op),sal_op_get_to(op));
|
||||
}
|
||||
dialog_state=belle_sip_dialog_get_state(op->dialog);
|
||||
switch(dialog_state) {
|
||||
case BELLE_SIP_DIALOG_NULL: {
|
||||
if (strcmp("INVITE",belle_sip_request_get_method(req))==0) {
|
||||
if (!op->replaces && (op->replaces=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_replaces_t))) {
|
||||
belle_sip_object_ref(op->replaces);
|
||||
} else if(op->replaces) {
|
||||
ms_warning("replace header already set");
|
||||
}
|
||||
|
||||
process_sdp_for_invite(op,req);
|
||||
|
||||
if ((call_info=belle_sip_message_get_header(BELLE_SIP_MESSAGE(req),"Call-Info"))) {
|
||||
if( strstr(belle_sip_header_extension_get_value(BELLE_SIP_HEADER_EXTENSION(call_info)),"answer-after=") != NULL) {
|
||||
op->auto_answer_asked=TRUE;
|
||||
ms_message("The caller asked to automatically answer the call(Emergency?)\n");
|
||||
}
|
||||
}
|
||||
|
||||
op->base.root->callbacks.call_received(op);
|
||||
|
||||
break;
|
||||
} /* else same behavior as for EARLY state*/
|
||||
}
|
||||
case BELLE_SIP_DIALOG_EARLY: {
|
||||
//hmm probably a cancel
|
||||
if (strcmp("CANCEL",belle_sip_request_get_method(req))==0) {
|
||||
if(belle_sip_request_event_get_server_transaction(event)) {
|
||||
/*first answer 200 ok to cancel*/
|
||||
belle_sip_server_transaction_send_response(server_transaction
|
||||
,sal_op_create_response_from_request(op,req,200));
|
||||
/*terminate invite transaction*/
|
||||
call_terminated(op
|
||||
,op->pending_server_trans
|
||||
,belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(op->pending_server_trans)),487);
|
||||
|
||||
|
||||
} else {
|
||||
/*call leg does not exist*/
|
||||
belle_sip_server_transaction_send_response(server_transaction
|
||||
,sal_op_create_response_from_request(op,req,481));
|
||||
}
|
||||
} else if (strcmp("PRACK",belle_sip_request_get_method(req))==0) {
|
||||
resp=sal_op_create_response_from_request(op,req,200);
|
||||
belle_sip_server_transaction_send_response(server_transaction,resp);
|
||||
} else {
|
||||
belle_sip_error("Unexpected method [%s] for dialog state BELLE_SIP_DIALOG_EARLY",belle_sip_request_get_method(req));
|
||||
unsupported_method(server_transaction,req);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BELLE_SIP_DIALOG_CONFIRMED:
|
||||
/*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);
|
||||
}
|
||||
}
|
||||
/*FIXME
|
||||
if (op->reinvite){
|
||||
op->reinvite=FALSE;
|
||||
}*/
|
||||
op->base.root->callbacks.call_ack(op);
|
||||
} else if(strcmp("BYE",belle_sip_request_get_method(req))==0) {
|
||||
resp=sal_op_create_response_from_request(op,req,200);
|
||||
belle_sip_server_transaction_send_response(server_transaction,resp);
|
||||
op->base.root->callbacks.call_terminated(op,op->dir==SalOpDirIncoming?sal_op_get_from(op):sal_op_get_to(op));
|
||||
op->state=SalOpStateTerminating;
|
||||
/*call end not notified by dialog deletion because transaction can end before dialog*/
|
||||
} else if(strcmp("INVITE",belle_sip_request_get_method(req))==0) {
|
||||
/*re-invite*/
|
||||
if (op->base.remote_media){
|
||||
sal_media_description_unref(op->base.remote_media);
|
||||
op->base.remote_media=NULL;
|
||||
}
|
||||
if (op->result){
|
||||
sal_media_description_unref(op->result);
|
||||
op->result=NULL;
|
||||
}
|
||||
process_sdp_for_invite(op,req);
|
||||
|
||||
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")) {
|
||||
/*vfu request*/
|
||||
ms_message("Receiving VFU request on op [%p]",op);
|
||||
if (op->base.root->callbacks.vfu_request){
|
||||
op->base.root->callbacks.vfu_request(op);
|
||||
|
||||
}
|
||||
}else{
|
||||
SalBody salbody;
|
||||
if (sal_op_get_body(op,(belle_sip_message_t*)req,&salbody)) {
|
||||
if (sal_body_has_type(&salbody,"application","dtmf-relay")){
|
||||
char tmp[10];
|
||||
if (sal_lines_get_value(salbody.data, "Signal",tmp, sizeof(tmp))){
|
||||
op->base.root->callbacks.dtmf_received(op,tmp[0]);
|
||||
}
|
||||
}else
|
||||
op->base.root->callbacks.info_received(op,&salbody);
|
||||
} else {
|
||||
op->base.root->callbacks.info_received(op,NULL);
|
||||
}
|
||||
}
|
||||
resp=sal_op_create_response_from_request(op,req,200);
|
||||
belle_sip_server_transaction_send_response(server_transaction,resp);
|
||||
}else if (strcmp("REFER",belle_sip_request_get_method(req))==0) {
|
||||
sal_op_process_refer(op,event,server_transaction);
|
||||
} else if (strcmp("NOTIFY",belle_sip_request_get_method(req))==0) {
|
||||
sal_op_call_process_notify(op,event,server_transaction);
|
||||
} else if (strcmp("OPTIONS",belle_sip_request_get_method(req))==0) {
|
||||
resp=sal_op_create_response_from_request(op,req,200);
|
||||
belle_sip_server_transaction_send_response(server_transaction,resp);
|
||||
} else if (strcmp("CANCEL",belle_sip_request_get_method(req))==0) {
|
||||
/*call leg does not exist because 200ok already sent*/
|
||||
belle_sip_server_transaction_send_response( server_transaction
|
||||
,sal_op_create_response_from_request(op,req,481));
|
||||
|
||||
} else{
|
||||
ms_error("unexpected method [%s] for dialog [%p]",belle_sip_request_get_method(req),op->dialog);
|
||||
unsupported_method(server_transaction,req);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ms_error("unexpected dialog state [%s]",belle_sip_dialog_state_to_string(dialog_state));
|
||||
break;
|
||||
}
|
||||
|
||||
if (server_transaction) belle_sip_object_unref(server_transaction);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*Call API*/
|
||||
int sal_call_set_local_media_description(SalOp *op, SalMediaDescription *desc){
|
||||
if (desc)
|
||||
sal_media_description_ref(desc);
|
||||
if (op->base.local_media)
|
||||
sal_media_description_unref(op->base.local_media);
|
||||
op->base.local_media=desc;
|
||||
|
||||
if (op->base.remote_media){
|
||||
/*case of an incoming call where we modify the local capabilities between the time
|
||||
* the call is ringing and it is accepted (for example if you want to accept without video*/
|
||||
/*reset the sdp answer so that it is computed again*/
|
||||
if (op->sdp_answer){
|
||||
belle_sip_object_unref(op->sdp_answer);
|
||||
op->sdp_answer=NULL;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static belle_sip_header_allow_t *create_allow(){
|
||||
belle_sip_header_allow_t* header_allow;
|
||||
header_allow = belle_sip_header_allow_create("INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO");
|
||||
return header_allow;
|
||||
}
|
||||
|
||||
static void sal_op_fill_invite(SalOp *op, belle_sip_request_t* invite) {
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(invite),BELLE_SIP_HEADER(create_allow()));
|
||||
|
||||
if (op->base.root->session_expires!=0){
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(invite),belle_sip_header_create( "Session-expires", "200"));
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(invite),belle_sip_header_create( "Supported", "timer"));
|
||||
}
|
||||
if (op->base.local_media){
|
||||
op->sdp_offering=TRUE;
|
||||
set_sdp_from_desc(BELLE_SIP_MESSAGE(invite),op->base.local_media);
|
||||
}else op->sdp_offering=FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
int sal_call(SalOp *op, const char *from, const char *to){
|
||||
belle_sip_request_t* invite;
|
||||
op->dir=SalOpDirOutgoing;
|
||||
|
||||
sal_op_set_from(op,from);
|
||||
sal_op_set_to(op,to);
|
||||
|
||||
ms_message("[%s] calling [%s] on op [%p]", from, to, op);
|
||||
invite=sal_op_build_request(op,"INVITE");
|
||||
|
||||
sal_op_fill_invite(op,invite);
|
||||
|
||||
sal_op_call_fill_cbs(op);
|
||||
if (op->replaces){
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(invite),BELLE_SIP_HEADER(op->replaces));
|
||||
}
|
||||
if (op->referred_by)
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(invite),BELLE_SIP_HEADER(op->referred_by));
|
||||
|
||||
return sal_op_send_request(op,invite);
|
||||
}
|
||||
|
||||
void sal_op_call_fill_cbs(SalOp*op) {
|
||||
op->callbacks.process_io_error=call_process_io_error;
|
||||
op->callbacks.process_response_event=call_process_response;
|
||||
op->callbacks.process_timeout=call_process_timeout;
|
||||
op->callbacks.process_transaction_terminated=call_process_transaction_terminated;
|
||||
op->callbacks.process_request_event=process_request_event;
|
||||
op->callbacks.process_dialog_terminated=process_dialog_terminated;
|
||||
op->type=SalOpCall;
|
||||
}
|
||||
|
||||
static void handle_offer_answer_response(SalOp* op, belle_sip_response_t* response) {
|
||||
if (op->base.local_media){
|
||||
/*this is the case where we received an invite without SDP*/
|
||||
if (op->sdp_offering) {
|
||||
set_sdp_from_desc(BELLE_SIP_MESSAGE(response),op->base.local_media);
|
||||
}else{
|
||||
|
||||
if (op->sdp_answer==NULL)
|
||||
sdp_process(op);
|
||||
|
||||
if (op->sdp_answer){
|
||||
set_sdp(BELLE_SIP_MESSAGE(response),op->sdp_answer);
|
||||
belle_sip_object_unref(op->sdp_answer);
|
||||
op->sdp_answer=NULL;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
ms_error("You are accepting a call but not defined any media capabilities !");
|
||||
}
|
||||
}
|
||||
|
||||
int sal_call_notify_ringing(SalOp *op, bool_t early_media){
|
||||
int status_code =early_media?183:180;
|
||||
belle_sip_request_t* req=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(op->pending_server_trans));
|
||||
belle_sip_response_t* ringing_response = sal_op_create_response_from_request(op,req,status_code);
|
||||
belle_sip_header_t *require;
|
||||
const char *tags=NULL;
|
||||
|
||||
if (early_media){
|
||||
handle_offer_answer_response(op,ringing_response);
|
||||
}
|
||||
require=belle_sip_message_get_header((belle_sip_message_t*)req,"Require");
|
||||
if (require) tags=belle_sip_header_get_unparsed_value(require);
|
||||
/* if client requires 100rel, then add necessary stuff*/
|
||||
if (tags && strstr(tags,"100rel")!=0) {
|
||||
|
||||
belle_sip_message_add_header((belle_sip_message_t*)ringing_response,BELLE_SIP_HEADER(belle_sip_header_extension_create("Require","100rel")));
|
||||
belle_sip_message_add_header((belle_sip_message_t*)ringing_response,BELLE_SIP_HEADER(belle_sip_header_extension_create("RSeq","1")));
|
||||
}
|
||||
|
||||
#ifndef SAL_OP_CALL_FORCE_CONTACT_IN_RINGING
|
||||
if (tags && strstr(tags,"100rel")!=0)
|
||||
#endif
|
||||
{
|
||||
belle_sip_header_address_t* contact= (belle_sip_header_address_t*)sal_op_get_contact_address(op);
|
||||
belle_sip_header_contact_t* contact_header;
|
||||
if (contact && (contact_header=belle_sip_header_contact_create(contact))) {
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(ringing_response),BELLE_SIP_HEADER(contact_header));
|
||||
}
|
||||
}
|
||||
belle_sip_server_transaction_send_response(op->pending_server_trans,ringing_response);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*accept an incoming call or, during a call accept a reINVITE*/
|
||||
int sal_call_accept(SalOp*h){
|
||||
belle_sip_response_t *response;
|
||||
belle_sip_header_contact_t* contact_header;
|
||||
|
||||
if (!h->pending_server_trans) {
|
||||
ms_error("No transaction to accept for op [%p]",h);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* sends a 200 OK */
|
||||
response = sal_op_create_response_from_request(h,belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(h->pending_server_trans)),200);
|
||||
|
||||
if (response==NULL){
|
||||
ms_error("Fail to build answer for call");
|
||||
return -1;
|
||||
}
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),BELLE_SIP_HEADER(create_allow()));
|
||||
if (h->base.root->session_expires!=0){
|
||||
if (h->supports_session_timers) {
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),belle_sip_header_create("Supported", "timer"));
|
||||
}
|
||||
}
|
||||
|
||||
if ((contact_header=sal_op_create_contact(h))) {
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),BELLE_SIP_HEADER(contact_header));
|
||||
}
|
||||
|
||||
handle_offer_answer_response(h,response);
|
||||
|
||||
belle_sip_server_transaction_send_response(h->pending_server_trans,response);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sal_call_decline(SalOp *op, SalReason reason, const char *redirection /*optional*/){
|
||||
belle_sip_response_t* response;
|
||||
belle_sip_header_contact_t* contact=NULL;
|
||||
int status=sal_reason_to_sip_code(reason);
|
||||
|
||||
if (reason==SalReasonRedirect){
|
||||
if (redirection!=NULL) {
|
||||
if (strstr(redirection,"sip:")!=0) status=302;
|
||||
status=380;
|
||||
contact= belle_sip_header_contact_new();
|
||||
belle_sip_header_address_set_uri(BELLE_SIP_HEADER_ADDRESS(contact),belle_sip_uri_parse(redirection));
|
||||
} else {
|
||||
ms_error("Cannot redirect to null");
|
||||
}
|
||||
}
|
||||
response = sal_op_create_response_from_request(op,belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(op->pending_server_trans)),status);
|
||||
if (contact) belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),BELLE_SIP_HEADER(contact));
|
||||
belle_sip_server_transaction_send_response(op->pending_server_trans,response);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sal_call_update(SalOp *op, const char *subject){
|
||||
belle_sip_request_t *reinvite=belle_sip_dialog_create_request(op->dialog,"INVITE");
|
||||
if (reinvite){
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(reinvite),belle_sip_header_create( "Subject", subject));
|
||||
sal_op_fill_invite(op, reinvite);
|
||||
return sal_op_send_request(op,reinvite);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
SalMediaDescription * sal_call_get_remote_media_description(SalOp *h){
|
||||
return h->base.remote_media;;
|
||||
}
|
||||
|
||||
SalMediaDescription * sal_call_get_final_media_description(SalOp *h){
|
||||
if (h->base.local_media && h->base.remote_media && !h->result){
|
||||
sdp_process(h);
|
||||
}
|
||||
return h->result;
|
||||
}
|
||||
|
||||
int sal_call_send_dtmf(SalOp *h, char dtmf){
|
||||
if (h->dialog && (belle_sip_dialog_get_state(h->dialog) == BELLE_SIP_DIALOG_CONFIRMED || belle_sip_dialog_get_state(h->dialog) == BELLE_SIP_DIALOG_EARLY)){
|
||||
belle_sip_request_t *req=belle_sip_dialog_create_queued_request(h->dialog,"INFO");
|
||||
if (req){
|
||||
int bodylen;
|
||||
char dtmf_body[128]={0};
|
||||
|
||||
snprintf(dtmf_body, sizeof(dtmf_body)-1, "Signal=%c\r\nDuration=250\r\n", dtmf);
|
||||
bodylen=strlen(dtmf_body);
|
||||
belle_sip_message_set_body((belle_sip_message_t*)req,dtmf_body,bodylen);
|
||||
belle_sip_message_add_header((belle_sip_message_t*)req,(belle_sip_header_t*)belle_sip_header_content_length_create(bodylen));
|
||||
belle_sip_message_add_header((belle_sip_message_t*)req,(belle_sip_header_t*)belle_sip_header_content_type_create("application", "dtmf-relay"));
|
||||
sal_op_send_request(h,req);
|
||||
}else ms_error("sal_call_send_dtmf(): could not build request");
|
||||
}else ms_error("sal_call_send_dtmf(): no dialog");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sal_call_terminate(SalOp *op){
|
||||
belle_sip_dialog_state_t dialog_state=op->dialog?belle_sip_dialog_get_state(op->dialog):BELLE_SIP_DIALOG_NULL;
|
||||
if (op->state==SalOpStateTerminating || op->state==SalOpStateTerminated) {
|
||||
ms_error("Cannot terminate op [%p] in state [%s]",op,sal_op_state_to_string(op->state));
|
||||
return -1;
|
||||
}
|
||||
switch(dialog_state) {
|
||||
case BELLE_SIP_DIALOG_CONFIRMED: {
|
||||
sal_op_send_request(op,belle_sip_dialog_create_request(op->dialog,"BYE"));
|
||||
op->state=SalOpStateTerminating;
|
||||
break;
|
||||
}
|
||||
case BELLE_SIP_DIALOG_NULL: {
|
||||
if (op->dir == SalOpDirIncoming) {
|
||||
sal_call_decline(op, SalReasonDeclined,NULL);
|
||||
op->state=SalOpStateTerminated;
|
||||
} else if (op->pending_client_trans){
|
||||
if (belle_sip_transaction_get_state(BELLE_SIP_TRANSACTION(op->pending_client_trans)) == BELLE_SIP_TRANSACTION_PROCEEDING){
|
||||
cancelling_invite(op);
|
||||
}else{
|
||||
/* Case where the CANCEL cannot be sent because no provisional response was received so far.
|
||||
* The Op must be kept for the time of the transaction in case a response is received later.
|
||||
* The state is passed to Terminating to remember to terminate later.
|
||||
*/
|
||||
op->state=SalOpStateTerminating;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BELLE_SIP_DIALOG_EARLY: {
|
||||
if (op->dir == SalOpDirIncoming) {
|
||||
sal_call_decline(op, SalReasonDeclined,NULL);
|
||||
op->state=SalOpStateTerminated;
|
||||
} else {
|
||||
cancelling_invite(op);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
ms_error("sal_call_terminate not implemented yet for dialog state [%s]",belle_sip_dialog_state_to_string(dialog_state));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool_t sal_call_autoanswer_asked(SalOp *op){
|
||||
return op->auto_answer_asked;
|
||||
}
|
||||
|
||||
void sal_call_send_vfu_request(SalOp *op){
|
||||
char info_body[] =
|
||||
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>"
|
||||
"<media_control>"
|
||||
" <vc_primitive>"
|
||||
" <to_encoder>"
|
||||
" <picture_fast_update></picture_fast_update>"
|
||||
" </to_encoder>"
|
||||
" </vc_primitive>"
|
||||
"</media_control>";
|
||||
size_t content_lenth = sizeof(info_body) - 1;
|
||||
belle_sip_dialog_state_t dialog_state=op->dialog?belle_sip_dialog_get_state(op->dialog):BELLE_SIP_DIALOG_NULL; /*no dialog = dialog in NULL state*/
|
||||
if (dialog_state == BELLE_SIP_DIALOG_CONFIRMED) {
|
||||
belle_sip_request_t* info = belle_sip_dialog_create_queued_request(op->dialog,"INFO");
|
||||
int error=TRUE;
|
||||
if (info) {
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(info),BELLE_SIP_HEADER(belle_sip_header_content_type_create("application","media_control+xml")));
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(info),BELLE_SIP_HEADER(belle_sip_header_content_length_create(content_lenth)));
|
||||
belle_sip_message_set_body(BELLE_SIP_MESSAGE(info),info_body,content_lenth);
|
||||
error=sal_op_send_request(op,info);
|
||||
}
|
||||
if (error)
|
||||
ms_warning("Cannot send vfu request to [%s] ", sal_op_get_to(op));
|
||||
|
||||
} else {
|
||||
ms_warning("Cannot send vfu request to [%s] because dialog [%p] in wrong state [%s]",sal_op_get_to(op)
|
||||
,op->dialog
|
||||
,belle_sip_dialog_state_to_string(dialog_state));
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
int sal_call_is_offerer(const SalOp *h){
|
||||
return h->sdp_offering;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
254
coreapi/bellesip_sal/sal_op_call_transfer.c
Normal file
|
|
@ -0,0 +1,254 @@
|
|||
/*
|
||||
linphone
|
||||
Copyright (C) 2012 Belledonne Communications, Grenoble, France
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#include "sal_impl.h"
|
||||
#include "offeranswer.h"
|
||||
|
||||
|
||||
|
||||
/*call transfer*/
|
||||
static void sal_op_set_replaces(SalOp* op,belle_sip_header_replaces_t* replaces) {
|
||||
if (op->replaces){
|
||||
belle_sip_object_unref(op->replaces);
|
||||
}
|
||||
op->replaces=replaces;
|
||||
belle_sip_object_ref(op->replaces);
|
||||
}
|
||||
static void sal_op_set_referred_by(SalOp* op,belle_sip_header_referred_by_t* referred_by) {
|
||||
if (op->referred_by){
|
||||
belle_sip_object_unref(op->referred_by);
|
||||
}
|
||||
op->referred_by=referred_by;
|
||||
belle_sip_object_ref(op->referred_by);
|
||||
}
|
||||
|
||||
|
||||
int sal_call_refer_to(SalOp *op, belle_sip_header_refer_to_t* refer_to, belle_sip_header_referred_by_t* referred_by){
|
||||
char* tmp;
|
||||
belle_sip_request_t* req=op->dialog?belle_sip_dialog_create_request(op->dialog,"REFER"):NULL; /*cannot create request if dialog not set yet*/
|
||||
if (!req) {
|
||||
tmp=belle_sip_uri_to_string(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(refer_to)));
|
||||
ms_error("Cannot refer to [%s] for op [%p]",tmp,op);
|
||||
belle_sip_free(tmp);
|
||||
return -1;
|
||||
}
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(refer_to));
|
||||
if (referred_by) belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(referred_by));
|
||||
return sal_op_send_request(op,req);
|
||||
}
|
||||
|
||||
int sal_call_refer(SalOp *op, const char *refer_to){
|
||||
belle_sip_header_address_t *referred_by;
|
||||
belle_sip_header_refer_to_t* refer_to_header;
|
||||
if (op->dialog) {
|
||||
referred_by=(belle_sip_header_address_t*)belle_sip_object_clone(BELLE_SIP_OBJECT(belle_sip_dialog_get_local_party(op->dialog)));
|
||||
}else{
|
||||
referred_by=BELLE_SIP_HEADER_ADDRESS(sal_op_get_from_address(op));
|
||||
}
|
||||
refer_to_header=belle_sip_header_refer_to_create(belle_sip_header_address_parse(refer_to));
|
||||
|
||||
return sal_call_refer_to(op,refer_to_header,belle_sip_header_referred_by_create(referred_by));
|
||||
}
|
||||
|
||||
int sal_call_refer_with_replaces(SalOp *op, SalOp *other_call_op){
|
||||
belle_sip_dialog_state_t other_call_dialog_state=other_call_op->dialog?belle_sip_dialog_get_state(other_call_op->dialog):BELLE_SIP_DIALOG_NULL;
|
||||
belle_sip_dialog_state_t op_dialog_state=op->dialog?belle_sip_dialog_get_state(op->dialog):BELLE_SIP_DIALOG_NULL;
|
||||
belle_sip_header_replaces_t* replaces;
|
||||
belle_sip_header_refer_to_t* refer_to;
|
||||
belle_sip_header_referred_by_t* referred_by;
|
||||
const char* from_tag;
|
||||
const char* to_tag;
|
||||
char* escaped_replaces;
|
||||
/*first, build refer to*/
|
||||
if (other_call_dialog_state!=BELLE_SIP_DIALOG_CONFIRMED) {
|
||||
ms_error(" wrong dialog state [%s] for op [%p], should be BELLE_SIP_DIALOG_CONFIRMED",belle_sip_dialog_state_to_string(other_call_dialog_state)
|
||||
,other_call_op);
|
||||
return -1;
|
||||
}
|
||||
if (op_dialog_state!=BELLE_SIP_DIALOG_CONFIRMED) {
|
||||
ms_error(" wrong dialog state [%s] for op [%p], should be BELLE_SIP_DIALOG_CONFIRMED",belle_sip_dialog_state_to_string(op_dialog_state)
|
||||
,op);
|
||||
return -1;
|
||||
}
|
||||
|
||||
refer_to=belle_sip_header_refer_to_create(belle_sip_dialog_get_remote_party(other_call_op->dialog));
|
||||
belle_sip_parameters_clean(BELLE_SIP_PARAMETERS(refer_to));
|
||||
if (belle_sip_dialog_is_server(other_call_op->dialog)) {
|
||||
to_tag=belle_sip_dialog_get_local_tag(other_call_op->dialog);
|
||||
from_tag=belle_sip_dialog_get_remote_tag(other_call_op->dialog);;
|
||||
|
||||
} else {
|
||||
from_tag=belle_sip_dialog_get_local_tag(other_call_op->dialog);
|
||||
to_tag=belle_sip_dialog_get_remote_tag(other_call_op->dialog);;
|
||||
}
|
||||
replaces=belle_sip_header_replaces_create(belle_sip_header_call_id_get_call_id(belle_sip_dialog_get_call_id(other_call_op->dialog))
|
||||
,from_tag,to_tag);
|
||||
escaped_replaces=belle_sip_header_replaces_value_to_escaped_string(replaces);
|
||||
belle_sip_uri_set_header(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(refer_to)),"Replaces",escaped_replaces);
|
||||
belle_sip_free(escaped_replaces);
|
||||
referred_by=belle_sip_header_referred_by_create(belle_sip_dialog_get_local_party(op->dialog));
|
||||
belle_sip_parameters_clean(BELLE_SIP_PARAMETERS(referred_by));
|
||||
return sal_call_refer_to(op,refer_to,referred_by);
|
||||
}
|
||||
/*
|
||||
int sal_call_accept_refer(SalOp *h){
|
||||
ms_fatal("sal_call_accept_refer not implemented yet");
|
||||
return -1;
|
||||
}*/
|
||||
/*informs this call is consecutive to an incoming refer */
|
||||
int sal_call_set_referer(SalOp *h, SalOp *refered_call){
|
||||
if (refered_call->replaces)
|
||||
sal_op_set_replaces(h,refered_call->replaces);
|
||||
if (refered_call->referred_by)
|
||||
sal_op_set_referred_by(h,refered_call->referred_by);
|
||||
return 0;
|
||||
}
|
||||
/* returns the SalOp of a call that should be replaced by h, if any */
|
||||
SalOp *sal_call_get_replaces(SalOp *op){
|
||||
if (op && op->replaces){
|
||||
belle_sip_dialog_t* dialog=belle_sip_provider_find_dialog(op->base.root->prov
|
||||
,belle_sip_header_replaces_get_call_id(op->replaces)
|
||||
,belle_sip_header_replaces_get_from_tag(op->replaces)
|
||||
,belle_sip_header_replaces_get_to_tag(op->replaces));
|
||||
|
||||
if (dialog) {
|
||||
return (SalOp*)belle_sip_dialog_get_application_data(dialog);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int send_notify_for_refer(SalOp* op, int code, const char *reason){
|
||||
belle_sip_request_t* notify=belle_sip_dialog_create_queued_request(op->dialog,"NOTIFY");
|
||||
char *sipfrag=belle_sip_strdup_printf("SIP/2.0 %i %s\r\n",code,reason);
|
||||
size_t content_length=strlen(sipfrag);
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify)
|
||||
,BELLE_SIP_HEADER(belle_sip_header_subscription_state_create(BELLE_SIP_SUBSCRIPTION_STATE_ACTIVE,-1)));
|
||||
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify),belle_sip_header_create("Event","refer"));
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify),BELLE_SIP_HEADER(belle_sip_header_content_type_create("message","sipfrag")));
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify),BELLE_SIP_HEADER(belle_sip_header_content_length_create(content_length)));
|
||||
belle_sip_message_assign_body(BELLE_SIP_MESSAGE(notify),sipfrag,content_length);
|
||||
return sal_op_send_request(op,notify);
|
||||
}
|
||||
|
||||
static void notify_last_response(SalOp *op, SalOp *newcall){
|
||||
belle_sip_client_transaction_t *tr=newcall->pending_client_trans;
|
||||
belle_sip_response_t *resp=NULL;
|
||||
if (tr){
|
||||
resp=belle_sip_transaction_get_response((belle_sip_transaction_t*)tr);
|
||||
}
|
||||
if (resp==NULL){
|
||||
send_notify_for_refer(op, 100, "Trying");
|
||||
}else{
|
||||
send_notify_for_refer(op, belle_sip_response_get_status_code(resp), belle_sip_response_get_reason_phrase(resp));
|
||||
}
|
||||
}
|
||||
|
||||
int sal_call_notify_refer_state(SalOp *op, SalOp *newcall){
|
||||
belle_sip_dialog_state_t state;
|
||||
if(belle_sip_dialog_get_state(op->dialog) == BELLE_SIP_DIALOG_TERMINATED){
|
||||
return 0;
|
||||
}
|
||||
state = newcall->dialog?belle_sip_dialog_get_state(newcall->dialog):BELLE_SIP_DIALOG_NULL;
|
||||
switch(state) {
|
||||
case BELLE_SIP_DIALOG_EARLY:
|
||||
send_notify_for_refer(op, 100, "Trying");
|
||||
break;
|
||||
case BELLE_SIP_DIALOG_CONFIRMED:
|
||||
send_notify_for_refer(op, 200, "Ok");
|
||||
break;
|
||||
case BELLE_SIP_DIALOG_TERMINATED:
|
||||
case BELLE_SIP_DIALOG_NULL:
|
||||
notify_last_response(op,newcall);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void sal_op_process_refer(SalOp *op, const belle_sip_request_event_t *event, belle_sip_server_transaction_t *server_transaction){
|
||||
belle_sip_request_t* req = belle_sip_request_event_get_request(event);
|
||||
belle_sip_header_refer_to_t *refer_to= belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_refer_to_t);
|
||||
belle_sip_header_referred_by_t *referred_by= belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_referred_by_t);
|
||||
belle_sip_response_t* resp;
|
||||
belle_sip_uri_t* refer_to_uri;
|
||||
char* refer_to_uri_str;
|
||||
|
||||
ms_message("Receiving REFER request on op [%p]",op);
|
||||
if (refer_to) {
|
||||
refer_to_uri=belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(refer_to));
|
||||
|
||||
if (refer_to_uri && belle_sip_uri_get_header(refer_to_uri,"Replaces")) {
|
||||
sal_op_set_replaces(op,belle_sip_header_replaces_create2(belle_sip_uri_get_header(refer_to_uri,"Replaces")));
|
||||
belle_sip_uri_remove_header(refer_to_uri,"Replaces");
|
||||
}
|
||||
if (referred_by){
|
||||
sal_op_set_referred_by(op,referred_by);
|
||||
}
|
||||
refer_to_uri_str=belle_sip_uri_to_string(refer_to_uri);
|
||||
resp = sal_op_create_response_from_request(op,req,202);
|
||||
belle_sip_server_transaction_send_response(server_transaction,resp);
|
||||
op->base.root->callbacks.refer_received(op->base.root,op,refer_to_uri_str);
|
||||
belle_sip_free(refer_to_uri_str);
|
||||
} else {
|
||||
ms_warning("cannot do anything with the refer without destination\n");
|
||||
resp = sal_op_create_response_from_request(op,req,501);
|
||||
belle_sip_server_transaction_send_response(server_transaction,resp);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void sal_op_call_process_notify(SalOp *op, const belle_sip_request_event_t *event, belle_sip_server_transaction_t* server_transaction){
|
||||
belle_sip_request_t* req = belle_sip_request_event_get_request(event);
|
||||
const char* body = belle_sip_message_get_body(BELLE_SIP_MESSAGE(req));
|
||||
belle_sip_header_t* header_event=belle_sip_message_get_header(BELLE_SIP_MESSAGE(req),"Event");
|
||||
belle_sip_header_content_type_t* content_type = belle_sip_message_get_header_by_type(req,belle_sip_header_content_type_t);
|
||||
belle_sip_response_t* resp;
|
||||
|
||||
ms_message("Receiving NOTIFY request on op [%p]",op);
|
||||
if (header_event
|
||||
&& strncasecmp(belle_sip_header_extension_get_value(BELLE_SIP_HEADER_EXTENSION(header_event)),"refer",strlen("refer"))==0
|
||||
&& content_type
|
||||
&& strcmp(belle_sip_header_content_type_get_type(content_type),"message")==0
|
||||
&& strcmp(belle_sip_header_content_type_get_subtype(content_type),"sipfrag")==0
|
||||
&& body){
|
||||
belle_sip_response_t* sipfrag=BELLE_SIP_RESPONSE(belle_sip_message_parse(body));
|
||||
|
||||
if (sipfrag){
|
||||
int code=belle_sip_response_get_status_code(sipfrag);
|
||||
SalReferStatus status=SalReferFailed;
|
||||
if (code==100){
|
||||
status=SalReferTrying;
|
||||
}else if (code==200){
|
||||
status=SalReferSuccess;
|
||||
}else if (code>=400){
|
||||
status=SalReferFailed;
|
||||
}
|
||||
belle_sip_object_unref(sipfrag);
|
||||
resp = sal_op_create_response_from_request(op,req,200);
|
||||
belle_sip_server_transaction_send_response(server_transaction,resp);
|
||||
op->base.root->callbacks.notify_refer(op,status);
|
||||
}
|
||||
}else{
|
||||
ms_error("Notify without sipfrag, trashing");
|
||||
resp = sal_op_create_response_from_request(op,req,501);
|
||||
belle_sip_server_transaction_send_response(server_transaction,resp);
|
||||
}
|
||||
}
|
||||
|
||||
268
coreapi/bellesip_sal/sal_op_events.c
Normal file
|
|
@ -0,0 +1,268 @@
|
|||
/*
|
||||
linphone
|
||||
Copyright (C) 2012 Belledonne Communications, Grenoble, France
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#include "sal_impl.h"
|
||||
|
||||
SalSubscribeStatus get_subscription_state(belle_sip_message_t *msg){
|
||||
belle_sip_header_subscription_state_t* subscription_state_header=belle_sip_message_get_header_by_type(msg,belle_sip_header_subscription_state_t);
|
||||
SalSubscribeStatus sss=SalSubscribeNone;
|
||||
if (subscription_state_header){
|
||||
if (strcmp(belle_sip_header_subscription_state_get_state(subscription_state_header),BELLE_SIP_SUBSCRIPTION_STATE_TERMINATED)==0)
|
||||
sss=SalSubscribeTerminated;
|
||||
else if (strcmp(belle_sip_header_subscription_state_get_state(subscription_state_header),BELLE_SIP_SUBSCRIPTION_STATE_PENDING)==0)
|
||||
sss=SalSubscribePending;
|
||||
else if (strcmp(belle_sip_header_subscription_state_get_state(subscription_state_header),BELLE_SIP_SUBSCRIPTION_STATE_ACTIVE)==0)
|
||||
sss=SalSubscribeActive;
|
||||
}
|
||||
return sss;
|
||||
}
|
||||
|
||||
static void subscribe_refresher_listener (belle_sip_refresher_t* refresher
|
||||
,void* user_pointer
|
||||
,unsigned int status_code
|
||||
,const char* reason_phrase) {
|
||||
SalOp* op = (SalOp*)user_pointer;
|
||||
SalError error=SalErrorUnknown;
|
||||
SalReason sr=SalReasonUnknown;
|
||||
belle_sip_transaction_t *tr=BELLE_SIP_TRANSACTION(belle_sip_refresher_get_transaction(refresher));
|
||||
/*belle_sip_response_t* response=belle_sip_transaction_get_response(tr);*/
|
||||
SalSubscribeStatus sss=SalSubscribeTerminated;
|
||||
|
||||
ms_message("Subscribe refresher [%i] reason [%s] ",status_code,reason_phrase?reason_phrase:"none");
|
||||
if (status_code>=200 && status_code<300){
|
||||
if (status_code==200) sss=SalSubscribeActive;
|
||||
else if (status_code==202) sss=SalSubscribePending;
|
||||
set_or_update_dialog(op,belle_sip_transaction_get_dialog(tr));
|
||||
}
|
||||
if (status_code>=200){
|
||||
sal_compute_sal_errors_from_code(status_code,&error,&sr);
|
||||
op->base.root->callbacks.subscribe_response(op,sss,error,sr);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void subscribe_process_io_error(void *user_ctx, const belle_sip_io_error_event_t *event){
|
||||
ms_error("subscribe_process_io_error not implemented yet");
|
||||
}
|
||||
|
||||
static void subscribe_process_dialog_terminated(void *ctx, const belle_sip_dialog_terminated_event_t *event) {
|
||||
SalOp* op= (SalOp*)ctx;
|
||||
if (op->dialog) {
|
||||
op->dialog=NULL;
|
||||
sal_op_unref(op);
|
||||
}
|
||||
}
|
||||
|
||||
static void subscribe_response_event(void *op_base, const belle_sip_response_event_t *event){
|
||||
}
|
||||
|
||||
static void subscribe_process_timeout(void *user_ctx, const belle_sip_timeout_event_t *event) {
|
||||
}
|
||||
|
||||
static void subscribe_process_transaction_terminated(void *user_ctx, const belle_sip_transaction_terminated_event_t *event) {
|
||||
}
|
||||
|
||||
static void handle_notify(SalOp *op, belle_sip_request_t *req, const char *eventname, SalBody * body){
|
||||
SalSubscribeStatus sub_state;
|
||||
belle_sip_header_subscription_state_t* subscription_state_header=belle_sip_message_get_header_by_type(req,belle_sip_header_subscription_state_t);
|
||||
belle_sip_response_t* resp;
|
||||
belle_sip_server_transaction_t* server_transaction = op->pending_server_trans;
|
||||
|
||||
if (!subscription_state_header || strcasecmp(BELLE_SIP_SUBSCRIPTION_STATE_TERMINATED,belle_sip_header_subscription_state_get_state(subscription_state_header)) ==0) {
|
||||
sub_state=SalSubscribeTerminated;
|
||||
ms_message("Outgoing subscription terminated by remote [%s]",sal_op_get_to(op));
|
||||
} else
|
||||
sub_state=SalSubscribeActive;
|
||||
sal_op_ref(op);
|
||||
op->base.root->callbacks.notify(op,sub_state,eventname,body);
|
||||
resp=sal_op_create_response_from_request(op,req,200);
|
||||
belle_sip_server_transaction_send_response(server_transaction,resp);
|
||||
sal_op_unref(op);
|
||||
}
|
||||
|
||||
static void subscribe_process_request_event(void *op_base, const belle_sip_request_event_t *event) {
|
||||
SalOp* op = (SalOp*)op_base;
|
||||
belle_sip_server_transaction_t* server_transaction = belle_sip_provider_create_server_transaction(op->base.root->prov,belle_sip_request_event_get_request(event));
|
||||
belle_sip_request_t* req = belle_sip_request_event_get_request(event);
|
||||
belle_sip_dialog_state_t dialog_state;
|
||||
belle_sip_header_expires_t* expires = belle_sip_message_get_header_by_type(req,belle_sip_header_expires_t);
|
||||
belle_sip_header_t *event_header;
|
||||
SalBody body;
|
||||
belle_sip_response_t* resp;
|
||||
const char *eventname=NULL;
|
||||
const char *method=belle_sip_request_get_method(req);
|
||||
|
||||
belle_sip_object_ref(server_transaction);
|
||||
if (op->pending_server_trans) belle_sip_object_unref(op->pending_server_trans);
|
||||
op->pending_server_trans=server_transaction;
|
||||
|
||||
event_header=belle_sip_message_get_header((belle_sip_message_t*)req,"Event");
|
||||
sal_op_get_body(op,(belle_sip_message_t*)req,&body);
|
||||
|
||||
if (event_header==NULL){
|
||||
ms_warning("No event header in incoming SUBSCRIBE.");
|
||||
resp=sal_op_create_response_from_request(op,req,400);
|
||||
belle_sip_server_transaction_send_response(server_transaction,resp);
|
||||
return;
|
||||
}
|
||||
if (op->event==NULL) {
|
||||
op->event=event_header;
|
||||
belle_sip_object_ref(op->event);
|
||||
}
|
||||
eventname=belle_sip_header_get_unparsed_value(event_header);
|
||||
|
||||
if (!op->dialog) {
|
||||
if (strcmp(method,"SUBSCRIBE")==0){
|
||||
op->dialog=belle_sip_provider_create_dialog(op->base.root->prov,BELLE_SIP_TRANSACTION(server_transaction));
|
||||
belle_sip_dialog_set_application_data(op->dialog,op);
|
||||
sal_op_ref(op);
|
||||
ms_message("new incoming subscription from [%s] to [%s]",sal_op_get_from(op),sal_op_get_to(op));
|
||||
}else{ /*this is a NOTIFY*/
|
||||
handle_notify(op,req,eventname,&body);
|
||||
return;
|
||||
}
|
||||
}
|
||||
dialog_state=belle_sip_dialog_get_state(op->dialog);
|
||||
switch(dialog_state) {
|
||||
|
||||
case BELLE_SIP_DIALOG_NULL: {
|
||||
op->base.root->callbacks.subscribe_received(op,eventname,body.type ? &body : NULL);
|
||||
break;
|
||||
}
|
||||
case BELLE_SIP_DIALOG_EARLY:
|
||||
ms_error("unexpected method [%s] for dialog [%p] in state BELLE_SIP_DIALOG_EARLY ",belle_sip_request_get_method(req),op->dialog);
|
||||
break;
|
||||
|
||||
case BELLE_SIP_DIALOG_CONFIRMED:
|
||||
if (strcmp("NOTIFY",method)==0) {
|
||||
handle_notify(op,req,eventname,&body);
|
||||
} else if (strcmp("SUBSCRIBE",method)==0) {
|
||||
/*either a refresh of an unsubscribe*/
|
||||
if (expires && belle_sip_header_expires_get_expires(expires)>0) {
|
||||
resp=sal_op_create_response_from_request(op,req,200);
|
||||
belle_sip_server_transaction_send_response(server_transaction,resp);
|
||||
} else if(expires) {
|
||||
ms_message("Unsubscribe received from [%s]",sal_op_get_from(op));
|
||||
resp=sal_op_create_response_from_request(op,req,200);
|
||||
belle_sip_server_transaction_send_response(server_transaction,resp);
|
||||
op->base.root->callbacks.subscribe_closed(op);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default: {
|
||||
ms_error("unexpected dialog state [%s]",belle_sip_dialog_state_to_string(dialog_state));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sal_op_subscribe_fill_cbs(SalOp*op) {
|
||||
op->callbacks.process_io_error=subscribe_process_io_error;
|
||||
op->callbacks.process_response_event=subscribe_response_event;
|
||||
op->callbacks.process_timeout=subscribe_process_timeout;
|
||||
op->callbacks.process_transaction_terminated=subscribe_process_transaction_terminated;
|
||||
op->callbacks.process_request_event=subscribe_process_request_event;
|
||||
op->callbacks.process_dialog_terminated=subscribe_process_dialog_terminated;
|
||||
op->type=SalOpSubscribe;
|
||||
}
|
||||
|
||||
|
||||
int sal_subscribe(SalOp *op, const char *from, const char *to, const char *eventname, int expires, const SalBody *body){
|
||||
belle_sip_request_t *req=NULL;
|
||||
|
||||
if (from)
|
||||
sal_op_set_from(op,from);
|
||||
if (to)
|
||||
sal_op_set_to(op,to);
|
||||
|
||||
if (!op->dialog){
|
||||
sal_op_subscribe_fill_cbs(op);
|
||||
/*???sal_exosip_fix_route(op); make sure to ha ;lr*/
|
||||
req=sal_op_build_request(op,"SUBSCRIBE");
|
||||
if (eventname){
|
||||
if (op->event) belle_sip_object_unref(op->event);
|
||||
op->event=belle_sip_header_create("Event",eventname);
|
||||
belle_sip_object_ref(op->event);
|
||||
}
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),op->event);
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_expires_create(expires)));
|
||||
sal_op_add_body(op,(belle_sip_message_t*)req,body);
|
||||
return sal_op_send_and_create_refresher(op,req,expires,subscribe_refresher_listener);
|
||||
}else if (op->refresher){
|
||||
const belle_sip_transaction_t *tr=(const belle_sip_transaction_t*) belle_sip_refresher_get_transaction(op->refresher);
|
||||
belle_sip_request_t *last_req=belle_sip_transaction_get_request(tr);
|
||||
/* modify last request to update body*/
|
||||
sal_op_add_body(op,(belle_sip_message_t*)last_req,body);
|
||||
return belle_sip_refresher_refresh(op->refresher,expires);
|
||||
}
|
||||
ms_warning("sal_subscribe(): no dialog and no refresher ?");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int sal_unsubscribe(SalOp *op){
|
||||
if (op->refresher){
|
||||
const belle_sip_transaction_t *tr=(const belle_sip_transaction_t*) belle_sip_refresher_get_transaction(op->refresher);
|
||||
belle_sip_request_t *last_req=belle_sip_transaction_get_request(tr);
|
||||
sal_op_add_body(op,(belle_sip_message_t*)last_req,NULL);
|
||||
belle_sip_refresher_refresh(op->refresher,0);
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int sal_subscribe_accept(SalOp *op){
|
||||
belle_sip_request_t* req=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(op->pending_server_trans));
|
||||
belle_sip_header_expires_t* expires = belle_sip_message_get_header_by_type(req,belle_sip_header_expires_t);
|
||||
belle_sip_response_t* resp = sal_op_create_response_from_request(op,req,200);
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(resp),BELLE_SIP_HEADER(expires));
|
||||
belle_sip_server_transaction_send_response(op->pending_server_trans,resp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sal_subscribe_decline(SalOp *op, SalReason reason){
|
||||
belle_sip_response_t* resp = belle_sip_response_create_from_request(belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(op->pending_server_trans)),
|
||||
sal_reason_to_sip_code(reason));
|
||||
belle_sip_server_transaction_send_response(op->pending_server_trans,resp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sal_notify(SalOp *op, const SalBody *body){
|
||||
belle_sip_request_t* notify;
|
||||
|
||||
if (!op->dialog) return -1;
|
||||
|
||||
if (!(notify=belle_sip_dialog_create_queued_request(op->dialog,"NOTIFY"))) return -1;
|
||||
|
||||
if (op->event) belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify),op->event);
|
||||
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify)
|
||||
,BELLE_SIP_HEADER(belle_sip_header_subscription_state_create(BELLE_SIP_SUBSCRIPTION_STATE_ACTIVE,600)));
|
||||
|
||||
sal_op_add_body(op,(belle_sip_message_t*)notify, body);
|
||||
return sal_op_send_request(op,notify);
|
||||
}
|
||||
|
||||
int sal_notify_close(SalOp *op){
|
||||
belle_sip_request_t* notify;
|
||||
if (!op->dialog) return -1;
|
||||
if (!(notify=belle_sip_dialog_create_queued_request(op->dialog,"NOTIFY"))) return -1;
|
||||
if (op->event) belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify),op->event);
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify)
|
||||
,BELLE_SIP_HEADER(belle_sip_header_subscription_state_create(BELLE_SIP_SUBSCRIPTION_STATE_TERMINATED,-1)));
|
||||
return sal_op_send_request(op,notify);
|
||||
}
|
||||
|
||||
608
coreapi/bellesip_sal/sal_op_impl.c
Normal file
|
|
@ -0,0 +1,608 @@
|
|||
/*
|
||||
linphone
|
||||
Copyright (C) 2012 Belledonne Communications, Grenoble, France
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#include "sal_impl.h"
|
||||
|
||||
|
||||
/*create an operation */
|
||||
SalOp * sal_op_new(Sal *sal){
|
||||
SalOp *op=ms_new0(SalOp,1);
|
||||
__sal_op_init(op,sal);
|
||||
op->type=SalOpUnknown;
|
||||
op->privacy=SalPrivacyNone;
|
||||
op->manual_refresher=FALSE;/*tells that requests with expiry (SUBSCRIBE, PUBLISH) will be automatically refreshed*/
|
||||
sal_op_ref(op);
|
||||
return op;
|
||||
}
|
||||
|
||||
void sal_op_release(SalOp *op){
|
||||
/*if in terminating state, keep this state because it means we are waiting for a response to be able to terminate the operation.*/
|
||||
if (op->state!=SalOpStateTerminating)
|
||||
op->state=SalOpStateTerminated;
|
||||
sal_op_set_user_pointer(op,NULL);/*mandatory because releasing op doesn't not mean freeing op. Make sure back pointer will not be used later*/
|
||||
if (op->refresher) {
|
||||
belle_sip_refresher_stop(op->refresher);
|
||||
}
|
||||
sal_op_unref(op);
|
||||
}
|
||||
|
||||
void sal_op_release_impl(SalOp *op){
|
||||
ms_message("Destroying op [%p] of type [%s]",op,sal_op_type_to_string(op->type));
|
||||
if (op->pending_auth_transaction) belle_sip_object_unref(op->pending_auth_transaction);
|
||||
if (op->auth_info) {
|
||||
sal_remove_pending_auth(op->base.root,op);
|
||||
sal_auth_info_delete(op->auth_info);
|
||||
}
|
||||
if (op->sdp_answer) belle_sip_object_unref(op->sdp_answer);
|
||||
if (op->refresher) {
|
||||
belle_sip_object_unref(op->refresher);
|
||||
op->refresher=NULL;
|
||||
}
|
||||
if (op->result)
|
||||
sal_media_description_unref(op->result);
|
||||
if(op->replaces) belle_sip_object_unref(op->replaces);
|
||||
if(op->referred_by) belle_sip_object_unref(op->referred_by);
|
||||
|
||||
if (op->pending_client_trans) belle_sip_object_unref(op->pending_client_trans);
|
||||
if (op->pending_server_trans) belle_sip_object_unref(op->pending_server_trans);
|
||||
if (op->event) belle_sip_object_unref(op->event);
|
||||
__sal_op_free(op);
|
||||
return ;
|
||||
}
|
||||
|
||||
void sal_op_authenticate(SalOp *op, const SalAuthInfo *info){
|
||||
if (op->type == SalOpRegister) {
|
||||
/*Registration authenticate is just about registering again*/
|
||||
sal_register_refresh(op,-1);
|
||||
}else {
|
||||
/*for sure auth info will be accesible from the provider*/
|
||||
sal_process_authentication(op);
|
||||
}
|
||||
return ;
|
||||
}
|
||||
|
||||
void sal_op_cancel_authentication(SalOp *h){
|
||||
ms_fatal("sal_op_cancel_authentication not implemented yet");
|
||||
return ;
|
||||
}
|
||||
|
||||
SalAuthInfo * sal_op_get_auth_requested(SalOp *op){
|
||||
return op->auth_info;
|
||||
}
|
||||
|
||||
belle_sip_header_contact_t* sal_op_create_contact(SalOp *op){
|
||||
belle_sip_header_contact_t* contact_header;
|
||||
belle_sip_uri_t* contact_uri;
|
||||
if (sal_op_get_contact_address(op)) {
|
||||
contact_header = belle_sip_header_contact_create(BELLE_SIP_HEADER_ADDRESS(sal_op_get_contact_address(op)));
|
||||
} else {
|
||||
contact_header= belle_sip_header_contact_new();
|
||||
}
|
||||
if (!(contact_uri=belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(contact_header)))) {
|
||||
/*no uri, just creating a new one*/
|
||||
contact_uri=belle_sip_uri_new();
|
||||
belle_sip_header_address_set_uri(BELLE_SIP_HEADER_ADDRESS(contact_header),contact_uri);
|
||||
}
|
||||
belle_sip_uri_set_secure(contact_uri,sal_op_is_secure(op));
|
||||
|
||||
belle_sip_header_contact_set_automatic(contact_header,op->base.root->auto_contacts);
|
||||
if (op->base.root->uuid){
|
||||
if (belle_sip_parameters_has_parameter(BELLE_SIP_PARAMETERS(contact_header),"+sip.instance")==0){
|
||||
char *instance_id=belle_sip_strdup_printf("\"<urn:uuid:%s>\"",op->base.root->uuid);
|
||||
belle_sip_parameters_set_parameter(BELLE_SIP_PARAMETERS(contact_header),"+sip.instance",instance_id);
|
||||
belle_sip_free(instance_id);
|
||||
}
|
||||
}
|
||||
return contact_header;
|
||||
}
|
||||
|
||||
belle_sip_header_t * sal_make_supported_header(Sal *sal){
|
||||
return belle_sip_header_create("Supported","replaces, outbound");
|
||||
}
|
||||
|
||||
belle_sip_request_t* sal_op_build_request(SalOp *op,const char* method) {
|
||||
belle_sip_header_from_t* from_header;
|
||||
belle_sip_header_to_t* to_header;
|
||||
belle_sip_provider_t* prov=op->base.root->prov;
|
||||
belle_sip_request_t *req;
|
||||
belle_sip_uri_t* req_uri;
|
||||
char token[10];
|
||||
|
||||
|
||||
if (strcmp("REGISTER",method)==0 || op->privacy==SalPrivacyNone) {
|
||||
from_header = belle_sip_header_from_create(BELLE_SIP_HEADER_ADDRESS(sal_op_get_from_address(op))
|
||||
,belle_sip_random_token(token,sizeof(token)));
|
||||
} else {
|
||||
from_header=belle_sip_header_from_create2("Anonymous <sip:anonymous@anonymous.invalid>",belle_sip_random_token(token,sizeof(token)));
|
||||
}
|
||||
/*make sure to preserve components like headers or port*/
|
||||
req_uri = (belle_sip_uri_t*)belle_sip_object_clone((belle_sip_object_t*)belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(sal_op_get_to_address(op))));
|
||||
belle_sip_uri_set_secure(req_uri,sal_op_is_secure(op));
|
||||
|
||||
to_header = belle_sip_header_to_create(BELLE_SIP_HEADER_ADDRESS(sal_op_get_to_address(op)),NULL);
|
||||
|
||||
req=belle_sip_request_create(
|
||||
req_uri,
|
||||
method,
|
||||
belle_sip_provider_create_call_id(prov),
|
||||
belle_sip_header_cseq_create(20,method),
|
||||
from_header,
|
||||
to_header,
|
||||
belle_sip_header_via_new(),
|
||||
70);
|
||||
|
||||
if (op->privacy & SalPrivacyId) {
|
||||
belle_sip_header_p_preferred_identity_t* p_preferred_identity=belle_sip_header_p_preferred_identity_create(BELLE_SIP_HEADER_ADDRESS(sal_op_get_from_address(op)));
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(p_preferred_identity));
|
||||
}
|
||||
if (strcmp("REGISTER",method)!=0 && op->privacy!=SalPrivacyNone ){
|
||||
belle_sip_header_privacy_t* privacy_header=belle_sip_header_privacy_new();
|
||||
if (op->privacy&SalPrivacyCritical)
|
||||
belle_sip_header_privacy_add_privacy(privacy_header,sal_privacy_to_string(SalPrivacyCritical));
|
||||
if (op->privacy&SalPrivacyHeader)
|
||||
belle_sip_header_privacy_add_privacy(privacy_header,sal_privacy_to_string(SalPrivacyHeader));
|
||||
if (op->privacy&SalPrivacyId)
|
||||
belle_sip_header_privacy_add_privacy(privacy_header,sal_privacy_to_string(SalPrivacyId));
|
||||
if (op->privacy&SalPrivacyNone)
|
||||
belle_sip_header_privacy_add_privacy(privacy_header,sal_privacy_to_string(SalPrivacyNone));
|
||||
if (op->privacy&SalPrivacySession)
|
||||
belle_sip_header_privacy_add_privacy(privacy_header,sal_privacy_to_string(SalPrivacySession));
|
||||
if (op->privacy&SalPrivacyUser)
|
||||
belle_sip_header_privacy_add_privacy(privacy_header,sal_privacy_to_string(SalPrivacyUser));
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(privacy_header));
|
||||
}
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),sal_make_supported_header(op->base.root));
|
||||
return req;
|
||||
}
|
||||
|
||||
belle_sip_response_t *sal_op_create_response_from_request(SalOp *op, belle_sip_request_t *req, int code){
|
||||
return sal_create_response_from_request(op->base.root,req,code);
|
||||
}
|
||||
|
||||
/*ping: main purpose is to obtain its own contact address behind firewalls*/
|
||||
int sal_ping(SalOp *op, const char *from, const char *to){
|
||||
sal_op_set_from(op,from);
|
||||
sal_op_set_to(op,to);
|
||||
return sal_op_send_request(op,sal_op_build_request(op,"OPTIONS"));
|
||||
}
|
||||
|
||||
void sal_op_set_remote_ua(SalOp*op,belle_sip_message_t* message) {
|
||||
belle_sip_header_user_agent_t* user_agent=belle_sip_message_get_header_by_type(message,belle_sip_header_user_agent_t);
|
||||
char user_agent_string[256];
|
||||
if(user_agent && belle_sip_header_user_agent_get_products_as_string(user_agent,user_agent_string,sizeof(user_agent_string))>0) {
|
||||
op->base.remote_ua=ms_strdup(user_agent_string);
|
||||
}
|
||||
}
|
||||
|
||||
int sal_op_send_request_with_expires(SalOp* op, belle_sip_request_t* request,int expires) {
|
||||
belle_sip_header_expires_t* expires_header=(belle_sip_header_expires_t*)belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_EXPIRES);
|
||||
|
||||
if (!expires_header && expires>=0) {
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_HEADER(expires_header=belle_sip_header_expires_new()));
|
||||
}
|
||||
if (expires_header) belle_sip_header_expires_set_expires(expires_header,expires);
|
||||
return sal_op_send_request(op,request);
|
||||
}
|
||||
|
||||
void sal_op_resend_request(SalOp* op, belle_sip_request_t* request) {
|
||||
belle_sip_header_cseq_t* cseq=(belle_sip_header_cseq_t*)belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_CSEQ);
|
||||
belle_sip_header_cseq_set_seq_number(cseq,belle_sip_header_cseq_get_seq_number(cseq)+1);
|
||||
sal_op_send_request(op,request);
|
||||
}
|
||||
|
||||
static void add_headers(belle_sip_header_t *h, belle_sip_message_t *msg){
|
||||
if (belle_sip_message_get_header(msg,belle_sip_header_get_name(h))==NULL)
|
||||
belle_sip_message_add_header(msg,h);
|
||||
}
|
||||
|
||||
static void _sal_op_add_custom_headers(SalOp *op, belle_sip_message_t *msg){
|
||||
if (op->base.sent_custom_headers){
|
||||
belle_sip_message_t *ch=(belle_sip_message_t*)op->base.sent_custom_headers;
|
||||
belle_sip_list_t *l=belle_sip_message_get_all_headers(ch);
|
||||
belle_sip_list_for_each2(l,(void (*)(void *, void *))add_headers,msg);
|
||||
belle_sip_list_free(l);
|
||||
}
|
||||
}
|
||||
|
||||
static int _sal_op_send_request_with_contact(SalOp* op, belle_sip_request_t* request,bool_t add_contact) {
|
||||
belle_sip_client_transaction_t* client_transaction;
|
||||
belle_sip_provider_t* prov=op->base.root->prov;
|
||||
belle_sip_uri_t* outbound_proxy=NULL;
|
||||
belle_sip_header_contact_t* contact;
|
||||
int result =-1;
|
||||
belle_sip_uri_t *next_hop_uri=NULL;
|
||||
|
||||
_sal_op_add_custom_headers(op, (belle_sip_message_t*)request);
|
||||
|
||||
if (!op->dialog || belle_sip_dialog_get_state(op->dialog) == BELLE_SIP_DIALOG_NULL) {
|
||||
/*don't put route header if dialog is in confirmed state*/
|
||||
const MSList *elem=sal_op_get_route_addresses(op);
|
||||
const char *transport;
|
||||
const char *method=belle_sip_request_get_method(request);
|
||||
|
||||
if (elem) {
|
||||
outbound_proxy=belle_sip_header_address_get_uri((belle_sip_header_address_t*)elem->data);
|
||||
next_hop_uri=outbound_proxy;
|
||||
}else{
|
||||
next_hop_uri=(belle_sip_uri_t*)belle_sip_object_clone((belle_sip_object_t*)belle_sip_request_get_uri(request));
|
||||
}
|
||||
transport=belle_sip_uri_get_transport_param(next_hop_uri);
|
||||
if (transport==NULL){
|
||||
/*compatibility mode: by default it should be udp as not explicitely set and if no udp listening point is available, then use
|
||||
* the first available transport*/
|
||||
if (!belle_sip_uri_is_secure(next_hop_uri)){
|
||||
if (belle_sip_provider_get_listening_point(prov,"UDP")==0){
|
||||
if (belle_sip_provider_get_listening_point(prov,"TCP")!=NULL){
|
||||
transport="tcp";
|
||||
}else if (belle_sip_provider_get_listening_point(prov,"TLS")!=NULL ){
|
||||
transport="tls";
|
||||
}
|
||||
}
|
||||
if (transport){
|
||||
belle_sip_message("Transport is not specified, using %s because UDP is not available.",transport);
|
||||
belle_sip_uri_set_transport_param(next_hop_uri,transport);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((strcmp(method,"REGISTER")==0 || strcmp(method,"SUBSCRIBE")==0) && transport &&
|
||||
(strcasecmp(transport,"TCP")==0 || strcasecmp(transport,"TLS")==0)){
|
||||
/*RFC 5923: add 'alias' parameter to tell the server that we want it to keep the connection for future requests*/
|
||||
belle_sip_header_via_t *via=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(request),belle_sip_header_via_t);
|
||||
belle_sip_parameters_set_parameter(BELLE_SIP_PARAMETERS(via),"alias",NULL);
|
||||
}
|
||||
}
|
||||
|
||||
client_transaction = belle_sip_provider_create_client_transaction(prov,request);
|
||||
belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(client_transaction),sal_op_ref(op));
|
||||
if (op->pending_client_trans) belle_sip_object_unref(op->pending_client_trans);
|
||||
op->pending_client_trans=client_transaction; /*update pending inv for being able to cancel*/
|
||||
belle_sip_object_ref(op->pending_client_trans);
|
||||
|
||||
if (belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(request),belle_sip_header_user_agent_t)==NULL)
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_HEADER(op->base.root->user_agent));
|
||||
|
||||
if (add_contact) {
|
||||
contact = sal_op_create_contact(op);
|
||||
belle_sip_message_set_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_HEADER(contact));
|
||||
}
|
||||
if (!belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_AUTHORIZATION)
|
||||
&& !belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_PROXY_AUTHORIZATION)) {
|
||||
/*hmm just in case we already have authentication param in cache*/
|
||||
belle_sip_provider_add_authorization(op->base.root->prov,request,NULL,NULL);
|
||||
}
|
||||
result = belle_sip_client_transaction_send_request_to(client_transaction,next_hop_uri/*might be null*/);
|
||||
|
||||
/*update call id if not set yet for this OP*/
|
||||
if (result == 0 && !op->base.call_id) {
|
||||
op->base.call_id=ms_strdup(belle_sip_header_call_id_get_call_id(BELLE_SIP_HEADER_CALL_ID(belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(request), belle_sip_header_call_id_t))));
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
int sal_op_send_request(SalOp* op, belle_sip_request_t* request) {
|
||||
bool_t need_contact=FALSE;
|
||||
if (request==NULL) {
|
||||
return -1; /*sanity check*/
|
||||
}
|
||||
/*
|
||||
Header field where proxy ACK BYE CAN INV OPT REG
|
||||
___________________________________________________________
|
||||
Contact R o - - m o o
|
||||
*/
|
||||
if (strcmp(belle_sip_request_get_method(request),"INVITE")==0
|
||||
||strcmp(belle_sip_request_get_method(request),"REGISTER")==0
|
||||
||strcmp(belle_sip_request_get_method(request),"SUBSCRIBE")==0
|
||||
||strcmp(belle_sip_request_get_method(request),"OPTIONS")==0
|
||||
||strcmp(belle_sip_request_get_method(request),"REFER")==0) /* Despite contact seems not mandatory, call flow example show a Contact in REFER requests*/
|
||||
need_contact=TRUE;
|
||||
|
||||
return _sal_op_send_request_with_contact(op, request,need_contact);
|
||||
}
|
||||
|
||||
SalReason sal_reason_to_sip_code(SalReason r){
|
||||
int ret=500;
|
||||
switch(r){
|
||||
case SalReasonUnknown:
|
||||
ret=400;
|
||||
break;
|
||||
case SalReasonBusy:
|
||||
ret=486;
|
||||
break;
|
||||
case SalReasonDeclined:
|
||||
ret=603;
|
||||
break;
|
||||
case SalReasonDoNotDisturb:
|
||||
ret=600;
|
||||
break;
|
||||
case SalReasonForbidden:
|
||||
ret=403;
|
||||
break;
|
||||
case SalReasonMedia:
|
||||
ret=415;
|
||||
break;
|
||||
case SalReasonNotFound:
|
||||
ret=404;
|
||||
break;
|
||||
case SalReasonRedirect:
|
||||
ret=302;
|
||||
break;
|
||||
case SalReasonTemporarilyUnavailable:
|
||||
ret=480;
|
||||
break;
|
||||
case SalReasonServiceUnavailable:
|
||||
ret=503;
|
||||
break;
|
||||
case SalReasonRequestPending:
|
||||
ret=491;
|
||||
break;
|
||||
case SalReasonUnauthorized:
|
||||
ret=401;
|
||||
break;
|
||||
case SalReasonNotAcceptable:
|
||||
ret=488;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void sal_compute_sal_errors_from_code(int code ,SalError* sal_err,SalReason* sal_reason) {
|
||||
switch(code) {
|
||||
case 400:
|
||||
*sal_err=SalErrorUnknown;
|
||||
break;
|
||||
case 401:
|
||||
case 407:
|
||||
*sal_err=SalErrorFailure;
|
||||
*sal_reason=SalReasonUnauthorized;
|
||||
break;
|
||||
case 403:
|
||||
*sal_err=SalErrorFailure;
|
||||
*sal_reason=SalReasonForbidden;
|
||||
break;
|
||||
case 404:
|
||||
*sal_err=SalErrorFailure;
|
||||
*sal_reason=SalReasonNotFound;
|
||||
break;
|
||||
case 415:
|
||||
*sal_err=SalErrorFailure;
|
||||
*sal_reason=SalReasonMedia;
|
||||
break;
|
||||
case 422:
|
||||
ms_error ("422 not implemented yet");;
|
||||
break;
|
||||
case 480:
|
||||
*sal_err=SalErrorFailure;
|
||||
*sal_reason=SalReasonTemporarilyUnavailable;
|
||||
break;
|
||||
case 486:
|
||||
*sal_err=SalErrorFailure;
|
||||
*sal_reason=SalReasonBusy;
|
||||
break;
|
||||
case 487:
|
||||
break;
|
||||
case 488:
|
||||
*sal_err=SalErrorFailure;
|
||||
*sal_reason=SalReasonNotAcceptable;
|
||||
break;
|
||||
case 491:
|
||||
*sal_err=SalErrorFailure;
|
||||
*sal_reason=SalReasonRequestPending;
|
||||
break;
|
||||
case 600:
|
||||
*sal_err=SalErrorFailure;
|
||||
*sal_reason=SalReasonDoNotDisturb;
|
||||
break;
|
||||
case 603:
|
||||
*sal_err=SalErrorFailure;
|
||||
*sal_reason=SalReasonDeclined;
|
||||
break;
|
||||
case 503:
|
||||
*sal_err=SalErrorFailure;
|
||||
*sal_reason=SalReasonServiceUnavailable;
|
||||
break;
|
||||
default:
|
||||
if (code>=300){
|
||||
*sal_err=SalErrorFailure;
|
||||
*sal_reason=SalReasonUnknown;
|
||||
}else if (code>=100){
|
||||
*sal_err=SalErrorNone;
|
||||
*sal_reason=SalReasonUnknown;
|
||||
}else if (code==0){
|
||||
*sal_err=SalErrorNoResponse;
|
||||
}
|
||||
/* no break */
|
||||
}
|
||||
}
|
||||
/*return TRUE if error code*/
|
||||
bool_t sal_compute_sal_errors(belle_sip_response_t* response,SalError* sal_err,SalReason* sal_reason,char* reason, size_t reason_size) {
|
||||
int code = belle_sip_response_get_status_code(response);
|
||||
belle_sip_header_t* reason_header = belle_sip_message_get_header(BELLE_SIP_MESSAGE(response),"Reason");
|
||||
*sal_err=SalErrorUnknown;
|
||||
*sal_reason = SalReasonUnknown;
|
||||
|
||||
if (reason_header){
|
||||
snprintf(reason
|
||||
,reason_size
|
||||
,"%s %s"
|
||||
,belle_sip_response_get_reason_phrase(response)
|
||||
,belle_sip_header_extension_get_value(BELLE_SIP_HEADER_EXTENSION(reason_header)));
|
||||
} else {
|
||||
strncpy(reason,belle_sip_response_get_reason_phrase(response),reason_size);
|
||||
}
|
||||
if (code>=400) {
|
||||
sal_compute_sal_errors_from_code(code,sal_err,sal_reason);
|
||||
return TRUE;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
void set_or_update_dialog(SalOp* op, belle_sip_dialog_t* dialog) {
|
||||
/*check if dialog has changed*/
|
||||
if (dialog && dialog != op->dialog) {
|
||||
ms_message("Dialog set from [%p] to [%p] for op [%p]",op->dialog,dialog,op);
|
||||
/*fixme, shouldn't we cancel previous dialog*/
|
||||
if (op->dialog) {
|
||||
belle_sip_dialog_set_application_data(op->dialog,NULL);
|
||||
belle_sip_object_unref(op->dialog);
|
||||
sal_op_unref(op);
|
||||
}
|
||||
op->dialog=dialog;
|
||||
belle_sip_dialog_set_application_data(op->dialog,op);
|
||||
sal_op_ref(op);
|
||||
belle_sip_object_ref(op->dialog);
|
||||
}
|
||||
}
|
||||
/*return reffed op*/
|
||||
SalOp* sal_op_ref(SalOp* op) {
|
||||
op->ref++;
|
||||
return op;
|
||||
}
|
||||
/*return null, destroy op if ref count =0*/
|
||||
void* sal_op_unref(SalOp* op) {
|
||||
op->ref--;
|
||||
if (op->ref==0) {
|
||||
sal_op_release_impl(op);
|
||||
}else if (op->ref<0){
|
||||
ms_fatal("SalOp [%p]: too many unrefs.",op);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int sal_op_send_and_create_refresher(SalOp* op,belle_sip_request_t* req, int expires,belle_sip_refresher_listener_t listener ) {
|
||||
if (sal_op_send_request_with_expires(op,req,expires)==0) {
|
||||
if (op->refresher) {
|
||||
belle_sip_refresher_stop(op->refresher);
|
||||
belle_sip_object_unref(op->refresher);
|
||||
}
|
||||
if ((op->refresher = belle_sip_client_transaction_create_refresher(op->pending_client_trans))) {
|
||||
belle_sip_refresher_set_listener(op->refresher,listener,op);
|
||||
belle_sip_refresher_set_retry_after(op->refresher,op->base.root->refresher_retry_after);
|
||||
belle_sip_refresher_enable_manual_mode(op->refresher,op->manual_refresher);
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char* sal_op_state_to_string(const SalOpState value) {
|
||||
switch(value) {
|
||||
case SalOpStateEarly: return"SalOpStateEarly";
|
||||
case SalOpStateActive: return "SalOpStateActive";
|
||||
case SalOpStateTerminating: return "SalOpStateTerminating";
|
||||
case SalOpStateTerminated: return "SalOpStateTerminated";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Warning: this function takes owneship of the custom headers
|
||||
*/
|
||||
void sal_op_set_sent_custom_header(SalOp *op, SalCustomHeader* ch){
|
||||
SalOpBase *b=(SalOpBase *)op;
|
||||
if (b->sent_custom_headers){
|
||||
sal_custom_header_free(b->sent_custom_headers);
|
||||
b->sent_custom_headers=NULL;
|
||||
}
|
||||
if (ch) belle_sip_object_ref((belle_sip_message_t*)ch);
|
||||
b->sent_custom_headers=ch;
|
||||
}
|
||||
|
||||
void sal_op_assign_recv_headers(SalOp *op, belle_sip_message_t *incoming){
|
||||
if (incoming) belle_sip_object_ref(incoming);
|
||||
if (op->base.recv_custom_headers){
|
||||
belle_sip_object_unref(op->base.recv_custom_headers);
|
||||
op->base.recv_custom_headers=NULL;
|
||||
}
|
||||
if (incoming){
|
||||
op->base.recv_custom_headers=(SalCustomHeader*)incoming;
|
||||
}
|
||||
}
|
||||
|
||||
const char *sal_op_get_remote_contact(const SalOp *op){
|
||||
return sal_custom_header_find(op->base.recv_custom_headers,"Contact");
|
||||
}
|
||||
|
||||
void sal_op_add_body(SalOp *op, belle_sip_message_t *req, const SalBody *body){
|
||||
belle_sip_message_remove_header((belle_sip_message_t*)req,"Content-type");
|
||||
belle_sip_message_remove_header((belle_sip_message_t*)req,"Content-length");
|
||||
belle_sip_message_remove_header((belle_sip_message_t*)req,"Content-encoding");
|
||||
belle_sip_message_set_body((belle_sip_message_t*)req,NULL,0);
|
||||
if (body && body->type && body->subtype && body->data){
|
||||
belle_sip_message_add_header((belle_sip_message_t*)req,
|
||||
(belle_sip_header_t*)belle_sip_header_content_type_create(body->type,body->subtype));
|
||||
belle_sip_message_add_header((belle_sip_message_t*)req,
|
||||
(belle_sip_header_t*)belle_sip_header_content_length_create(body->size));
|
||||
belle_sip_message_set_body((belle_sip_message_t*)req,(const char*)body->data,body->size);
|
||||
if (body->encoding){
|
||||
belle_sip_message_add_header((belle_sip_message_t*)req,(belle_sip_header_t*)
|
||||
belle_sip_header_create("Content-encoding",body->encoding));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool_t sal_op_get_body(SalOp *op, belle_sip_message_t *msg, SalBody *salbody){
|
||||
const char *body = NULL;
|
||||
belle_sip_header_content_type_t *content_type;
|
||||
belle_sip_header_content_length_t *clen=NULL;
|
||||
belle_sip_header_t *content_encoding;
|
||||
|
||||
content_type=belle_sip_message_get_header_by_type(msg,belle_sip_header_content_type_t);
|
||||
if (content_type){
|
||||
body=belle_sip_message_get_body(msg);
|
||||
clen=belle_sip_message_get_header_by_type(msg,belle_sip_header_content_length_t);
|
||||
}
|
||||
content_encoding=belle_sip_message_get_header(msg,"Content-encoding");
|
||||
|
||||
memset(salbody,0,sizeof(SalBody));
|
||||
|
||||
if (content_type && body && clen) {
|
||||
salbody->type=belle_sip_header_content_type_get_type(content_type);
|
||||
salbody->subtype=belle_sip_header_content_type_get_subtype(content_type);
|
||||
salbody->data=body;
|
||||
salbody->size=belle_sip_header_content_length_get_content_length(clen);
|
||||
if (content_encoding)
|
||||
salbody->encoding=belle_sip_header_get_unparsed_value(content_encoding);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void sal_op_set_privacy(SalOp* op,SalPrivacyMask privacy) {
|
||||
op->privacy=privacy;
|
||||
}
|
||||
SalPrivacyMask sal_op_get_privacy(const SalOp* op) {
|
||||
return op->privacy;
|
||||
}
|
||||
|
||||
bool_t sal_op_is_secure(const SalOp* op) {
|
||||
const SalAddress* from = sal_op_get_from_address(op);
|
||||
const SalAddress* to = sal_op_get_to_address(op);
|
||||
|
||||
return from && to && strcasecmp("sips",sal_address_get_scheme(from))==0 && strcasecmp("sips",sal_address_get_scheme(to))==0;
|
||||
}
|
||||
|
||||
void sal_op_set_manual_refresher_mode(SalOp *op, bool_t enabled){
|
||||
op->manual_refresher=enabled;
|
||||
}
|
||||
30
coreapi/bellesip_sal/sal_op_info.c
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
linphone
|
||||
Copyright (C) 2012 Belledonne Communications, Grenoble, France
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#include "sal_impl.h"
|
||||
|
||||
|
||||
int sal_send_info(SalOp *op, const char *from, const char *to, const SalBody *body){
|
||||
if (op->dialog){
|
||||
belle_sip_request_t *req=belle_sip_dialog_create_queued_request(op->dialog,"INFO");
|
||||
sal_op_add_body(op,(belle_sip_message_t*)req,body);
|
||||
return sal_op_send_request(op,req);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
170
coreapi/bellesip_sal/sal_op_message.c
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
/*
|
||||
linphone
|
||||
Copyright (C) 2012 Belledonne Communications, Grenoble, France
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#include "sal_impl.h"
|
||||
|
||||
static void process_error( SalOp* op) {
|
||||
if (op->dir == SalOpDirOutgoing) {
|
||||
op->base.root->callbacks.text_delivery_update(op,SalTextDeliveryFailed);
|
||||
} else {
|
||||
ms_warning("unexpected io error for incoming message on op [%p]",op);
|
||||
}
|
||||
op->state=SalOpStateTerminated;
|
||||
|
||||
}
|
||||
|
||||
static void process_io_error(void *user_ctx, const belle_sip_io_error_event_t *event){
|
||||
SalOp* op = (SalOp*)user_ctx;
|
||||
// belle_sip_object_t* source = belle_sip_io_error_event_get_source(event);
|
||||
// if (BELLE_SIP_IS_INSTANCE_OF(source,belle_sip_transaction_t)) {
|
||||
// /*reset op to make sure transaction terminated does not need op*/
|
||||
// belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(source),NULL);
|
||||
// }
|
||||
process_error(op);
|
||||
}
|
||||
static void process_timeout(void *user_ctx, const belle_sip_timeout_event_t *event) {
|
||||
SalOp* op=(SalOp*)user_ctx;
|
||||
// belle_sip_client_transaction_t *client_transaction=belle_sip_timeout_event_get_client_transaction(event);
|
||||
// belle_sip_server_transaction_t *server_transaction=belle_sip_timeout_event_get_server_transaction(event);
|
||||
// /*reset op to make sure transaction terminated does not need op*/
|
||||
// if (client_transaction) {
|
||||
// belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(client_transaction),NULL);
|
||||
// } else {
|
||||
// belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(server_transaction),NULL);
|
||||
// }
|
||||
process_error(op);
|
||||
|
||||
}
|
||||
static void process_response_event(void *op_base, const belle_sip_response_event_t *event){
|
||||
SalOp* op = (SalOp*)op_base;
|
||||
/*belle_sip_client_transaction_t *client_transaction=belle_sip_response_event_get_client_transaction(event);*/
|
||||
int code = belle_sip_response_get_status_code(belle_sip_response_event_get_response(event));
|
||||
SalTextDeliveryStatus status;
|
||||
if (code>=100 && code <200)
|
||||
status=SalTextDeliveryInProgress;
|
||||
else if (code>=200 && code <300)
|
||||
status=SalTextDeliveryDone;
|
||||
else
|
||||
status=SalTextDeliveryFailed;
|
||||
if (status != SalTextDeliveryInProgress) {
|
||||
/*reset op to make sure transaction terminated does not need op
|
||||
belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(client_transaction),NULL);*/
|
||||
}
|
||||
op->base.root->callbacks.text_delivery_update(op,status);
|
||||
|
||||
}
|
||||
static bool_t is_plain_text(belle_sip_header_content_type_t* content_type) {
|
||||
return strcmp("text",belle_sip_header_content_type_get_type(content_type))==0
|
||||
&& strcmp("plain",belle_sip_header_content_type_get_subtype(content_type))==0;
|
||||
}
|
||||
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 void process_request_event(void *op_base, const belle_sip_request_event_t *event) {
|
||||
SalOp* op = (SalOp*)op_base;
|
||||
belle_sip_request_t* req = belle_sip_request_event_get_request(event);
|
||||
belle_sip_server_transaction_t* server_transaction = belle_sip_provider_create_server_transaction(op->base.root->prov,req);
|
||||
belle_sip_header_address_t* address;
|
||||
belle_sip_header_from_t* from_header;
|
||||
belle_sip_header_content_type_t* content_type;
|
||||
belle_sip_response_t* resp;
|
||||
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;
|
||||
bool_t external_body=FALSE;
|
||||
|
||||
from_header=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_from_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)))) {
|
||||
|
||||
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));
|
||||
snprintf(message_id,sizeof(message_id)-1,"%s%i"
|
||||
,belle_sip_header_call_id_get_call_id(call_id)
|
||||
,belle_sip_header_cseq_get_seq_number(cseq));
|
||||
salmsg.from=from;
|
||||
salmsg.text=plain_text?belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)):NULL;
|
||||
salmsg.url=NULL;
|
||||
if (external_body && belle_sip_parameters_get_parameter(BELLE_SIP_PARAMETERS(content_type),"URL")) {
|
||||
size_t url_length=strlen(belle_sip_parameters_get_parameter(BELLE_SIP_PARAMETERS(content_type),"URL"));
|
||||
salmsg.url = ms_strdup(belle_sip_parameters_get_parameter(BELLE_SIP_PARAMETERS(content_type),"URL")+1); /* skip first "*/
|
||||
((char*)salmsg.url)[url_length-2]='\0'; /*remove trailing "*/
|
||||
}
|
||||
salmsg.message_id=message_id;
|
||||
salmsg.time=date ? belle_sip_header_date_get_time(date) : time(NULL);
|
||||
op->base.root->callbacks.text_received(op,&salmsg);
|
||||
belle_sip_object_unref(address);
|
||||
belle_sip_free(from);
|
||||
if (salmsg.url) ms_free((char*)salmsg.url);
|
||||
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));
|
||||
response_code=501; /*not implemented sound appropriate*/
|
||||
}
|
||||
resp = belle_sip_response_create_from_request(req,response_code);
|
||||
belle_sip_server_transaction_send_response(server_transaction,resp);
|
||||
sal_op_release(op);
|
||||
}
|
||||
|
||||
int sal_message_send(SalOp *op, const char *from, const char *to, const char* content_type, const char *msg){
|
||||
belle_sip_request_t* req;
|
||||
char content_type_raw[256];
|
||||
size_t content_length = msg?strlen(msg):0;
|
||||
time_t curtime=time(NULL);
|
||||
|
||||
sal_op_message_fill_cbs(op);
|
||||
if (from)
|
||||
sal_op_set_from(op,from);
|
||||
if (to)
|
||||
sal_op_set_to(op,to);
|
||||
op->dir=SalOpDirOutgoing;
|
||||
|
||||
req=sal_op_build_request(op,"MESSAGE");
|
||||
if (sal_op_get_contact(op)){
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(sal_op_create_contact(op)));
|
||||
}
|
||||
snprintf(content_type_raw,sizeof(content_type_raw),BELLE_SIP_CONTENT_TYPE ": %s",content_type);
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_content_type_parse(content_type_raw)));
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_content_length_create(content_length)));
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_date_create_from_time(&curtime)));
|
||||
belle_sip_message_set_body(BELLE_SIP_MESSAGE(req),msg,content_length);
|
||||
return sal_op_send_request(op,req);
|
||||
|
||||
}
|
||||
|
||||
int sal_text_send(SalOp *op, const char *from, const char *to, const char *msg) {
|
||||
return sal_message_send(op,from,to,"text/plain",msg);
|
||||
}
|
||||
|
||||
void sal_op_message_fill_cbs(SalOp*op) {
|
||||
op->callbacks.process_io_error=process_io_error;
|
||||
op->callbacks.process_response_event=process_response_event;
|
||||
op->callbacks.process_timeout=process_timeout;
|
||||
op->callbacks.process_request_event=process_request_event;
|
||||
op->type=SalOpMessage;
|
||||
}
|
||||
363
coreapi/bellesip_sal/sal_op_presence.c
Normal file
|
|
@ -0,0 +1,363 @@
|
|||
/*
|
||||
linphone
|
||||
Copyright (C) 2012 Belledonne Communications, Grenoble, France
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#include "sal_impl.h"
|
||||
|
||||
|
||||
void sal_add_presence_info(SalOp *op, belle_sip_message_t *notify, SalPresenceModel *presence) {
|
||||
char *contact_info;
|
||||
char *content = NULL;
|
||||
size_t content_length;
|
||||
|
||||
if (presence){
|
||||
belle_sip_header_from_t *from=belle_sip_message_get_header_by_type(notify,belle_sip_header_from_t);
|
||||
contact_info=belle_sip_uri_to_string(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(from)));
|
||||
op->base.root->callbacks.convert_presence_to_xml_requested(op, presence, contact_info, &content);
|
||||
ms_free(contact_info);
|
||||
if (content == NULL) return;
|
||||
}
|
||||
|
||||
belle_sip_message_remove_header(BELLE_SIP_MESSAGE(notify),BELLE_SIP_CONTENT_TYPE);
|
||||
belle_sip_message_remove_header(BELLE_SIP_MESSAGE(notify),BELLE_SIP_CONTENT_LENGTH);
|
||||
belle_sip_message_set_body(BELLE_SIP_MESSAGE(notify),NULL,0);
|
||||
|
||||
if (content){
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify)
|
||||
,BELLE_SIP_HEADER(belle_sip_header_content_type_create("application","pidf+xml")));
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify)
|
||||
,BELLE_SIP_HEADER(belle_sip_header_content_length_create(content_length=strlen(content))));
|
||||
belle_sip_message_set_body(BELLE_SIP_MESSAGE(notify),content,content_length);
|
||||
ms_free(content);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void presence_process_io_error(void *user_ctx, const belle_sip_io_error_event_t *event){
|
||||
ms_error("presence_process_io_error not implemented yet");
|
||||
}
|
||||
|
||||
static void presence_process_dialog_terminated(void *ctx, const belle_sip_dialog_terminated_event_t *event) {
|
||||
SalOp* op= (SalOp*)ctx;
|
||||
if (op->dialog) {
|
||||
sal_op_unref(op);
|
||||
op->dialog=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void presence_refresher_listener(belle_sip_refresher_t* refresher, void* user_pointer, unsigned int status_code, const char* reason_phrase){
|
||||
SalOp* op = (SalOp*)user_pointer;
|
||||
switch(status_code){
|
||||
case 481: {
|
||||
|
||||
ms_message("The server or remote ua lost the SUBSCRIBE dialog context. Let's restart a new one.");
|
||||
belle_sip_refresher_stop(op->refresher);
|
||||
if (op->dialog) { /*delete previous dialog if any*/
|
||||
belle_sip_dialog_set_application_data(op->dialog,NULL);
|
||||
belle_sip_object_unref(op->dialog);
|
||||
op->dialog=NULL;
|
||||
}
|
||||
|
||||
if (sal_op_get_contact_address(op)) {
|
||||
/*contact is also probably not good*/
|
||||
SalAddress* contact=sal_address_clone(sal_op_get_contact_address(op));
|
||||
sal_address_set_port(contact,-1);
|
||||
sal_address_set_domain(contact,NULL);
|
||||
sal_op_set_contact_address(op,contact);
|
||||
sal_address_destroy(contact);
|
||||
}
|
||||
|
||||
sal_subscribe_presence(op,NULL,NULL,-1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void presence_response_event(void *op_base, const belle_sip_response_event_t *event){
|
||||
SalOp* op = (SalOp*)op_base;
|
||||
belle_sip_dialog_state_t dialog_state;
|
||||
belle_sip_client_transaction_t* client_transaction = belle_sip_response_event_get_client_transaction(event);
|
||||
belle_sip_response_t* response=belle_sip_response_event_get_response(event);
|
||||
belle_sip_request_t* request=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction));
|
||||
int code = belle_sip_response_get_status_code(response);
|
||||
char reason[256]={0};
|
||||
SalError error=SalErrorUnknown;
|
||||
SalReason sr=SalReasonUnknown;
|
||||
belle_sip_header_expires_t* expires;
|
||||
|
||||
if (sal_compute_sal_errors(response,&error,&sr,reason, sizeof(reason))) {
|
||||
ms_error("subscription to [%s] rejected reason [%s]",sal_op_get_to(op),reason[0]!=0?reason:sal_reason_to_string(sr));
|
||||
op->base.root->callbacks.notify_presence(op,SalSubscribeTerminated, NULL,NULL); /*NULL = offline*/
|
||||
return;
|
||||
}
|
||||
set_or_update_dialog(op_base,belle_sip_response_event_get_dialog(event));
|
||||
if (!op->dialog) {
|
||||
ms_message("presence op [%p] receive out of dialog answer [%i]",op,code);
|
||||
return;
|
||||
}
|
||||
dialog_state=belle_sip_dialog_get_state(op->dialog);
|
||||
|
||||
switch(dialog_state) {
|
||||
case BELLE_SIP_DIALOG_NULL:
|
||||
case BELLE_SIP_DIALOG_EARLY: {
|
||||
ms_error("presence op [%p] receive an unexpected answer [%i]",op,code);
|
||||
break;
|
||||
}
|
||||
case BELLE_SIP_DIALOG_CONFIRMED: {
|
||||
if (strcmp("SUBSCRIBE",belle_sip_request_get_method(request))==0) {
|
||||
expires=belle_sip_message_get_header_by_type(request,belle_sip_header_expires_t);
|
||||
if(op->refresher) {
|
||||
belle_sip_refresher_stop(op->refresher);
|
||||
belle_sip_object_unref(op->refresher);
|
||||
op->refresher=NULL;
|
||||
}
|
||||
if (expires>0){
|
||||
op->refresher=belle_sip_client_transaction_create_refresher(client_transaction);
|
||||
belle_sip_refresher_set_listener(op->refresher,presence_refresher_listener,op);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BELLE_SIP_DIALOG_TERMINATED:
|
||||
if (op->refresher) {
|
||||
belle_sip_refresher_stop(op->refresher);
|
||||
belle_sip_object_unref(op->refresher);
|
||||
op->refresher=NULL;
|
||||
}
|
||||
break;
|
||||
default: {
|
||||
ms_error("presence op [%p] receive answer [%i] not implemented",op,code);
|
||||
}
|
||||
/* no break */
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
static void presence_process_timeout(void *user_ctx, const belle_sip_timeout_event_t *event) {
|
||||
ms_error("presence_process_timeout not implemented yet");
|
||||
}
|
||||
|
||||
static void presence_process_transaction_terminated(void *user_ctx, const belle_sip_transaction_terminated_event_t *event) {
|
||||
ms_message("presence_process_transaction_terminated not implemented yet");
|
||||
}
|
||||
|
||||
static SalPresenceModel * process_presence_notification(SalOp *op, belle_sip_request_t *req) {
|
||||
belle_sip_header_content_type_t *content_type = belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req), belle_sip_header_content_type_t);
|
||||
belle_sip_header_content_length_t *content_length = belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req), belle_sip_header_content_length_t);
|
||||
const char *body = belle_sip_message_get_body(BELLE_SIP_MESSAGE(req));
|
||||
SalPresenceModel *result = NULL;
|
||||
|
||||
if ((content_type == NULL) || (content_length == NULL))
|
||||
return NULL;
|
||||
if (belle_sip_header_content_length_get_content_length(content_length) == 0)
|
||||
return NULL;
|
||||
|
||||
op->base.root->callbacks.parse_presence_requested(op,
|
||||
belle_sip_header_content_type_get_type(content_type),
|
||||
belle_sip_header_content_type_get_subtype(content_type),
|
||||
body,
|
||||
&result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void handle_notify(SalOp *op, belle_sip_request_t *req){
|
||||
belle_sip_response_t* resp;
|
||||
belle_sip_server_transaction_t* server_transaction=op->pending_server_trans;
|
||||
belle_sip_header_subscription_state_t* subscription_state_header=belle_sip_message_get_header_by_type(req,belle_sip_header_subscription_state_t);
|
||||
SalSubscribeStatus sub_state;
|
||||
|
||||
if (strcmp("NOTIFY",belle_sip_request_get_method(req))==0) {
|
||||
SalPresenceModel *presence_model = NULL;
|
||||
const char* body = belle_sip_message_get_body(BELLE_SIP_MESSAGE(req));
|
||||
if (body==NULL){
|
||||
ms_error("No body in NOTIFY received from [%s]",sal_op_get_from(op));
|
||||
resp = sal_op_create_response_from_request(op, req, 415);
|
||||
belle_sip_server_transaction_send_response(server_transaction,resp);
|
||||
return;
|
||||
}
|
||||
presence_model = process_presence_notification(op, req);
|
||||
if (presence_model != NULL) {
|
||||
/* Presence notification body parsed successfully. */
|
||||
if (!subscription_state_header || strcasecmp(BELLE_SIP_SUBSCRIPTION_STATE_TERMINATED,belle_sip_header_subscription_state_get_state(subscription_state_header)) ==0) {
|
||||
sub_state=SalSubscribeTerminated;
|
||||
ms_message("Outgoing subscription terminated by remote [%s]",sal_op_get_to(op));
|
||||
} else {
|
||||
sub_state=SalSubscribeActive;
|
||||
}
|
||||
resp = sal_op_create_response_from_request(op, req, 200); /*create first because the op may be destroyed by notify_presence */
|
||||
op->base.root->callbacks.notify_presence(op, sub_state, presence_model, NULL);
|
||||
|
||||
} else {
|
||||
/* Formatting error in presence notification body. */
|
||||
ms_error("Wrongly formatted presence notification received");
|
||||
resp = sal_op_create_response_from_request(op, req, 400);
|
||||
}
|
||||
belle_sip_server_transaction_send_response(server_transaction,resp);
|
||||
}
|
||||
}
|
||||
|
||||
static void presence_process_request_event(void *op_base, const belle_sip_request_event_t *event) {
|
||||
SalOp* op = (SalOp*)op_base;
|
||||
belle_sip_server_transaction_t* server_transaction = belle_sip_provider_create_server_transaction(op->base.root->prov,belle_sip_request_event_get_request(event));
|
||||
belle_sip_request_t* req = belle_sip_request_event_get_request(event);
|
||||
belle_sip_dialog_state_t dialog_state;
|
||||
belle_sip_header_expires_t* expires = belle_sip_message_get_header_by_type(req,belle_sip_header_expires_t);
|
||||
belle_sip_response_t* resp;
|
||||
const char *method=belle_sip_request_get_method(req);
|
||||
|
||||
belle_sip_object_ref(server_transaction);
|
||||
if (op->pending_server_trans) belle_sip_object_unref(op->pending_server_trans);
|
||||
op->pending_server_trans=server_transaction;
|
||||
|
||||
|
||||
if (!op->dialog) {
|
||||
if (strcmp(method,"SUBSCRIBE")==0){
|
||||
op->dialog=belle_sip_provider_create_dialog(op->base.root->prov,BELLE_SIP_TRANSACTION(server_transaction));
|
||||
belle_sip_dialog_set_application_data(op->dialog,op);
|
||||
sal_op_ref(op);
|
||||
ms_message("new incoming subscription from [%s] to [%s]",sal_op_get_from(op),sal_op_get_to(op));
|
||||
}else{ /* this is a NOTIFY */
|
||||
ms_message("Receiving out of dialog notify");
|
||||
handle_notify(op,req);
|
||||
return;
|
||||
}
|
||||
}
|
||||
dialog_state=belle_sip_dialog_get_state(op->dialog);
|
||||
switch(dialog_state) {
|
||||
case BELLE_SIP_DIALOG_NULL: {
|
||||
op->base.root->callbacks.subscribe_presence_received(op,sal_op_get_from(op));
|
||||
break;
|
||||
}
|
||||
case BELLE_SIP_DIALOG_EARLY:
|
||||
ms_error("unexpected method [%s] for dialog [%p] in state BELLE_SIP_DIALOG_EARLY ",method,op->dialog);
|
||||
break;
|
||||
|
||||
case BELLE_SIP_DIALOG_CONFIRMED:
|
||||
if (strcmp("NOTIFY",method)==0) {
|
||||
handle_notify(op,req);
|
||||
} else if (strcmp("SUBSCRIBE",method)==0) {
|
||||
/*either a refresh or an unsubscribe*/
|
||||
if (expires && belle_sip_header_expires_get_expires(expires)>0) {
|
||||
op->base.root->callbacks.subscribe_presence_received(op,sal_op_get_from(op));
|
||||
} else if(expires) {
|
||||
ms_message("Unsubscribe received from [%s]",sal_op_get_from(op));
|
||||
resp=sal_op_create_response_from_request(op,req,200);
|
||||
belle_sip_server_transaction_send_response(server_transaction,resp);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ms_error("unexpected dialog state [%s]",belle_sip_dialog_state_to_string(dialog_state));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void sal_op_presence_fill_cbs(SalOp*op) {
|
||||
op->callbacks.process_io_error=presence_process_io_error;
|
||||
op->callbacks.process_response_event=presence_response_event;
|
||||
op->callbacks.process_timeout=presence_process_timeout;
|
||||
op->callbacks.process_transaction_terminated=presence_process_transaction_terminated;
|
||||
op->callbacks.process_request_event=presence_process_request_event;
|
||||
op->callbacks.process_dialog_terminated=presence_process_dialog_terminated;
|
||||
op->type=SalOpPresence;
|
||||
}
|
||||
|
||||
|
||||
/*presence Subscribe/notify*/
|
||||
int sal_subscribe_presence(SalOp *op, const char *from, const char *to, int expires){
|
||||
belle_sip_request_t *req=NULL;
|
||||
if (from)
|
||||
sal_op_set_from(op,from);
|
||||
if (to)
|
||||
sal_op_set_to(op,to);
|
||||
|
||||
sal_op_presence_fill_cbs(op);
|
||||
|
||||
if (expires==-1){
|
||||
if (op->refresher){
|
||||
expires=belle_sip_refresher_get_expires(op->refresher);
|
||||
belle_sip_object_unref(op->refresher);
|
||||
op->refresher=NULL;
|
||||
}else{
|
||||
ms_error("sal_subscribe_presence(): cannot guess expires from previous refresher.");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (!op->event){
|
||||
op->event=belle_sip_header_create("Event","presence");
|
||||
belle_sip_object_ref(op->event);
|
||||
}
|
||||
belle_sip_parameters_remove_parameter(BELLE_SIP_PARAMETERS(op->base.from_address),"tag");
|
||||
belle_sip_parameters_remove_parameter(BELLE_SIP_PARAMETERS(op->base.to_address),"tag");
|
||||
req=sal_op_build_request(op,"SUBSCRIBE");
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),op->event);
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_expires_create(expires)));
|
||||
|
||||
return sal_op_send_request(op,req);
|
||||
}
|
||||
|
||||
|
||||
static belle_sip_request_t *create_presence_notify(SalOp *op){
|
||||
belle_sip_request_t* notify=belle_sip_dialog_create_queued_request(op->dialog,"NOTIFY");
|
||||
if (!notify) return NULL;
|
||||
|
||||
belle_sip_message_add_header((belle_sip_message_t*)notify,belle_sip_header_create("Event","presence"));
|
||||
return notify;
|
||||
}
|
||||
|
||||
static int sal_op_check_dialog_state(SalOp *op) {
|
||||
belle_sip_dialog_state_t state=op->dialog?belle_sip_dialog_get_state(op->dialog): BELLE_SIP_DIALOG_NULL;
|
||||
if (state != BELLE_SIP_DIALOG_CONFIRMED) {
|
||||
ms_warning("Cannot notify presence for op [%p] because dialog in state [%s]",op, belle_sip_dialog_state_to_string(state));
|
||||
return -1;
|
||||
} else
|
||||
return 0;
|
||||
|
||||
}
|
||||
int sal_notify_presence(SalOp *op, SalPresenceModel *presence){
|
||||
belle_sip_request_t* notify=NULL;
|
||||
if (sal_op_check_dialog_state(op)) {
|
||||
return -1;
|
||||
}
|
||||
notify=create_presence_notify(op);
|
||||
if (!notify) return-1;
|
||||
|
||||
sal_add_presence_info(op,BELLE_SIP_MESSAGE(notify),presence); /*FIXME, what about expires ??*/
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify)
|
||||
,BELLE_SIP_HEADER(belle_sip_header_subscription_state_create(BELLE_SIP_SUBSCRIPTION_STATE_ACTIVE,600)));
|
||||
return sal_op_send_request(op,notify);
|
||||
}
|
||||
|
||||
int sal_notify_presence_close(SalOp *op){
|
||||
belle_sip_request_t* notify=NULL;
|
||||
if (sal_op_check_dialog_state(op)) {
|
||||
return -1;
|
||||
}
|
||||
notify=create_presence_notify(op);
|
||||
if (!notify) return-1;
|
||||
|
||||
sal_add_presence_info(op,BELLE_SIP_MESSAGE(notify),NULL); /*FIXME, what about expires ??*/
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify)
|
||||
,BELLE_SIP_HEADER(belle_sip_header_subscription_state_create(BELLE_SIP_SUBSCRIPTION_STATE_TERMINATED,-1)));
|
||||
return sal_op_send_request(op,notify);
|
||||
}
|
||||
|
||||
|
||||
|
||||
114
coreapi/bellesip_sal/sal_op_publish.c
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
linphone
|
||||
Copyright (C) 2012 Belledonne Communications, Grenoble, France
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#include "sal_impl.h"
|
||||
|
||||
|
||||
static void publish_refresher_listener (belle_sip_refresher_t* refresher
|
||||
,void* user_pointer
|
||||
,unsigned int status_code
|
||||
,const char* reason_phrase) {
|
||||
SalOp* op = (SalOp*)user_pointer;
|
||||
/*belle_sip_response_t* response=belle_sip_transaction_get_response(BELLE_SIP_TRANSACTION(belle_sip_refresher_get_transaction(refresher)));*/
|
||||
ms_message("Publish refresher [%i] reason [%s] for proxy [%s]",status_code,reason_phrase?reason_phrase:"none",sal_op_get_proxy(op));
|
||||
if (status_code==412){
|
||||
/*resubmit the request after removing the SIP-If-Match*/
|
||||
const belle_sip_client_transaction_t* last_publish_trans=belle_sip_refresher_get_transaction(op->refresher);
|
||||
belle_sip_request_t* last_publish=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(last_publish_trans));
|
||||
belle_sip_message_remove_header((belle_sip_message_t*)last_publish,"SIP-If-Match");
|
||||
belle_sip_refresher_refresh(op->refresher,BELLE_SIP_REFRESHER_REUSE_EXPIRES);
|
||||
}else if (status_code==0){
|
||||
op->base.root->callbacks.on_expire(op);
|
||||
}else if (status_code>=200){
|
||||
SalError err;
|
||||
SalReason reason;
|
||||
sal_compute_sal_errors_from_code(status_code,&err,&reason);
|
||||
op->base.root->callbacks.on_publish_response(op,err,reason);
|
||||
}
|
||||
}
|
||||
|
||||
static void publish_response_event(void *userctx, const belle_sip_response_event_t *event){
|
||||
SalOp *op=(SalOp*)userctx;
|
||||
int code=belle_sip_response_get_status_code(belle_sip_response_event_get_response(event));
|
||||
SalError err;
|
||||
SalReason reason;
|
||||
sal_compute_sal_errors_from_code(code,&err,&reason);
|
||||
op->base.root->callbacks.on_publish_response(op,err,reason);
|
||||
}
|
||||
|
||||
void sal_op_publish_fill_cbs(SalOp*op) {
|
||||
op->callbacks.process_response_event=publish_response_event;
|
||||
op->type=SalOpPublish;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sending a publish with 0 expires removes the event state and such request shall not contain a body.
|
||||
* See RFC3903, section 4.5
|
||||
*/
|
||||
|
||||
/*presence publish */
|
||||
int sal_publish_presence(SalOp *op, const char *from, const char *to, int expires, SalPresenceModel *presence){
|
||||
belle_sip_request_t *req=NULL;
|
||||
if(!op->refresher || !belle_sip_refresher_get_transaction(op->refresher)) {
|
||||
if (from)
|
||||
sal_op_set_from(op,from);
|
||||
if (to)
|
||||
sal_op_set_to(op,to);
|
||||
|
||||
op->type=SalOpPublish;
|
||||
req=sal_op_build_request(op,"PUBLISH");
|
||||
if (sal_op_get_contact(op)){
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(sal_op_create_contact(op)));
|
||||
}
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),belle_sip_header_create("Event","presence"));
|
||||
sal_add_presence_info(op,BELLE_SIP_MESSAGE(req),presence);
|
||||
return sal_op_send_and_create_refresher(op,req,expires,publish_refresher_listener);
|
||||
} else {
|
||||
/*update presence status*/
|
||||
const belle_sip_client_transaction_t* last_publish_trans=belle_sip_refresher_get_transaction(op->refresher);
|
||||
belle_sip_request_t* last_publish=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(last_publish_trans));
|
||||
sal_add_presence_info(op,BELLE_SIP_MESSAGE(last_publish),expires!=0 ? presence : NULL);
|
||||
return belle_sip_refresher_refresh(op->refresher,expires);
|
||||
}
|
||||
}
|
||||
|
||||
int sal_publish(SalOp *op, const char *from, const char *to, const char *eventname, int expires, const SalBody *body){
|
||||
belle_sip_request_t *req=NULL;
|
||||
if(!op->refresher || !belle_sip_refresher_get_transaction(op->refresher)) {
|
||||
if (from)
|
||||
sal_op_set_from(op,from);
|
||||
if (to)
|
||||
sal_op_set_to(op,to);
|
||||
|
||||
sal_op_publish_fill_cbs(op);
|
||||
req=sal_op_build_request(op,"PUBLISH");
|
||||
if (sal_op_get_contact(op)){
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(sal_op_create_contact(op)));
|
||||
}
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),belle_sip_header_create("Event",eventname));
|
||||
sal_op_add_body(op,BELLE_SIP_MESSAGE(req),body);
|
||||
return sal_op_send_and_create_refresher(op,req,expires,publish_refresher_listener);
|
||||
} else {
|
||||
/*update status*/
|
||||
const belle_sip_client_transaction_t* last_publish_trans=belle_sip_refresher_get_transaction(op->refresher);
|
||||
belle_sip_request_t* last_publish=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(last_publish_trans));
|
||||
/*update body*/
|
||||
sal_op_add_body(op,BELLE_SIP_MESSAGE(last_publish),expires!=0 ? body : NULL);
|
||||
return belle_sip_refresher_refresh(op->refresher,expires==-1 ? BELLE_SIP_REFRESHER_REUSE_EXPIRES : expires);
|
||||
}
|
||||
}
|
||||
108
coreapi/bellesip_sal/sal_op_registration.c
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
linphone
|
||||
Copyright (C) 2012 Belledonne Communications, Grenoble, France
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#include "sal_impl.h"
|
||||
|
||||
|
||||
static void register_refresher_listener (belle_sip_refresher_t* refresher
|
||||
,void* user_pointer
|
||||
,unsigned int status_code
|
||||
,const char* reason_phrase) {
|
||||
SalOp* op = (SalOp*)user_pointer;
|
||||
SalError sal_err;
|
||||
SalReason sal_reason;
|
||||
belle_sip_response_t* response=belle_sip_transaction_get_response(BELLE_SIP_TRANSACTION(belle_sip_refresher_get_transaction(refresher)));
|
||||
ms_message("Register refresher [%i] reason [%s] for proxy [%s]",status_code,reason_phrase,sal_op_get_proxy(op));
|
||||
|
||||
if (belle_sip_refresher_get_auth_events(refresher)) {
|
||||
if (op->auth_info) sal_auth_info_delete(op->auth_info);
|
||||
/*only take first one for now*/
|
||||
op->auth_info=sal_auth_info_create((belle_sip_auth_event_t*)(belle_sip_refresher_get_auth_events(refresher)->data));
|
||||
}
|
||||
if(status_code == 200) {
|
||||
/*check service route rfc3608*/
|
||||
belle_sip_header_service_route_t* service_route;
|
||||
belle_sip_header_address_t* service_route_address=NULL;
|
||||
if ((service_route=belle_sip_message_get_header_by_type(response,belle_sip_header_service_route_t))) {
|
||||
service_route_address=belle_sip_header_address_create(NULL,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(service_route)));
|
||||
}
|
||||
sal_op_set_service_route(op,(const SalAddress*)service_route_address);
|
||||
if (service_route_address) belle_sip_object_unref(service_route_address);
|
||||
|
||||
sal_remove_pending_auth(op->base.root,op); /*just in case*/
|
||||
op->base.root->callbacks.register_success(op,belle_sip_refresher_get_expires(op->refresher)>0);
|
||||
} else if (status_code>=400) {
|
||||
/* from rfc3608, 6.1.
|
||||
If the UA refreshes the registration, the stored value of the Service-
|
||||
Route is updated according to the Service-Route header field of the
|
||||
latest 200 class response. If there is no Service-Route header field
|
||||
in the response, the UA clears any service route for that address-
|
||||
of-record previously stored by the UA. If the re-registration
|
||||
request is refused or if an existing registration expires and the UA
|
||||
chooses not to re-register, the UA SHOULD discard any stored service
|
||||
route for that address-of-record. */
|
||||
sal_op_set_service_route(op,NULL);
|
||||
|
||||
sal_compute_sal_errors_from_code(status_code,&sal_err,&sal_reason);
|
||||
op->base.root->callbacks.register_failure(op,sal_err,sal_reason,reason_phrase);
|
||||
if (op->auth_info) {
|
||||
/*add pending auth*/
|
||||
sal_add_pending_auth(op->base.root,op);
|
||||
if (status_code==403)
|
||||
op->base.root->callbacks.auth_failure(op,op->auth_info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int sal_register(SalOp *op, const char *proxy, const char *from, int expires){
|
||||
belle_sip_request_t *req;
|
||||
belle_sip_uri_t* req_uri;
|
||||
|
||||
if (op->refresher){
|
||||
belle_sip_refresher_stop(op->refresher);
|
||||
belle_sip_object_unref(op->refresher);
|
||||
op->refresher=NULL;
|
||||
}
|
||||
|
||||
op->type=SalOpRegister;
|
||||
sal_op_set_from(op,from);
|
||||
sal_op_set_to(op,from);
|
||||
sal_op_set_route(op,proxy);
|
||||
req = sal_op_build_request(op,"REGISTER");
|
||||
req_uri = belle_sip_request_get_uri(req);
|
||||
belle_sip_uri_set_user(req_uri,NULL); /*remove userinfo if any*/
|
||||
if (op->base.root->use_dates){
|
||||
time_t curtime=time(NULL);
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_date_create_from_time(&curtime)));
|
||||
}
|
||||
belle_sip_message_set_header(BELLE_SIP_MESSAGE(req),(belle_sip_header_t*)sal_op_create_contact(op));
|
||||
return sal_op_send_and_create_refresher(op,req,expires,register_refresher_listener);
|
||||
}
|
||||
|
||||
int sal_register_refresh(SalOp *op, int expires){
|
||||
if (op->refresher)
|
||||
return belle_sip_refresher_refresh(op->refresher,expires);
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
int sal_unregister(SalOp *op){
|
||||
return sal_register_refresh(op,0);
|
||||
}
|
||||
|
||||
|
||||
496
coreapi/bellesip_sal/sal_sdp.c
Normal file
|
|
@ -0,0 +1,496 @@
|
|||
/*
|
||||
linphone
|
||||
Copyright (C) 2012 Belledonne Communications, Grenoble, France
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#include "sal_impl.h"
|
||||
#define keywordcmp(key,b) strncmp(key,b,sizeof(key))
|
||||
|
||||
|
||||
static void add_ice_candidates(belle_sdp_media_description_t *md, const SalStreamDescription *desc){
|
||||
char buffer[1024];
|
||||
const SalIceCandidate *candidate;
|
||||
int nb;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_ICE_CANDIDATES; i++) {
|
||||
candidate = &desc->ice_candidates[i];
|
||||
if ((candidate->addr[0] == '\0') || (candidate->port == 0)) break;
|
||||
nb = snprintf(buffer, sizeof(buffer), "%s %u UDP %u %s %d typ %s",
|
||||
candidate->foundation, candidate->componentID, candidate->priority, candidate->addr, candidate->port, candidate->type);
|
||||
if (nb < 0) {
|
||||
ms_error("Cannot add ICE candidate attribute!");
|
||||
return;
|
||||
}
|
||||
if (candidate->raddr[0] != '\0') {
|
||||
nb = snprintf(buffer + nb, sizeof(buffer) - nb, " raddr %s rport %d", candidate->raddr, candidate->rport);
|
||||
if (nb < 0) {
|
||||
ms_error("Cannot add ICE candidate attribute!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
belle_sdp_media_description_add_attribute(md,belle_sdp_attribute_create("candidate",buffer));
|
||||
}
|
||||
}
|
||||
|
||||
static void add_ice_remote_candidates(belle_sdp_media_description_t *md, const SalStreamDescription *desc){
|
||||
char buffer[1024];
|
||||
char *ptr = buffer;
|
||||
const SalIceRemoteCandidate *candidate;
|
||||
int offset = 0;
|
||||
int i;
|
||||
|
||||
buffer[0] = '\0';
|
||||
for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_ICE_REMOTE_CANDIDATES; i++) {
|
||||
candidate = &desc->ice_remote_candidates[i];
|
||||
if ((candidate->addr[0] != '\0') && (candidate->port != 0)) {
|
||||
offset = snprintf(ptr, buffer + sizeof(buffer) - ptr, "%s%d %s %d", (i > 0) ? " " : "", i + 1, candidate->addr, candidate->port);
|
||||
if (offset < 0) {
|
||||
ms_error("Cannot add ICE remote-candidates attribute!");
|
||||
return;
|
||||
}
|
||||
ptr += offset;
|
||||
}
|
||||
}
|
||||
if (buffer[0] != '\0') belle_sdp_media_description_add_attribute(md,belle_sdp_attribute_create("remote-candidates",buffer));
|
||||
}
|
||||
|
||||
static belle_sdp_media_description_t *stream_description_to_sdp ( const SalMediaDescription *md, const SalStreamDescription *stream ) {
|
||||
belle_sdp_mime_parameter_t* mime_param;
|
||||
belle_sdp_media_description_t* media_desc;
|
||||
int j;
|
||||
MSList* pt_it;
|
||||
PayloadType* pt;
|
||||
char buffer[1024];
|
||||
char* dir=NULL;
|
||||
const char *rtp_addr;
|
||||
const char *rtcp_addr;
|
||||
int rtp_port;
|
||||
int rtcp_port;
|
||||
bool_t different_rtp_and_rtcp_addr;
|
||||
|
||||
rtp_addr=stream->rtp_addr;
|
||||
rtcp_addr=stream->rtcp_addr;
|
||||
rtp_port=stream->rtp_port;
|
||||
rtcp_port=stream->rtcp_port;
|
||||
|
||||
media_desc = belle_sdp_media_description_create ( sal_stream_type_to_string ( stream->type )
|
||||
,stream->rtp_port
|
||||
,1
|
||||
,sal_media_proto_to_string ( stream->proto )
|
||||
,NULL );
|
||||
if (stream->payloads) {
|
||||
for ( pt_it=stream->payloads; pt_it!=NULL; pt_it=pt_it->next ) {
|
||||
pt= ( PayloadType* ) pt_it->data;
|
||||
mime_param= belle_sdp_mime_parameter_create ( pt->mime_type
|
||||
, payload_type_get_number ( pt )
|
||||
, pt->clock_rate
|
||||
,stream->type==SalAudio?1:-1 );
|
||||
belle_sdp_mime_parameter_set_parameters ( mime_param,pt->recv_fmtp );
|
||||
if ( stream->ptime>0 ) {
|
||||
belle_sdp_mime_parameter_set_ptime ( mime_param,stream->ptime );
|
||||
}
|
||||
belle_sdp_media_description_append_values_from_mime_parameter ( media_desc,mime_param );
|
||||
belle_sip_object_unref ( mime_param );
|
||||
}
|
||||
} else {
|
||||
/* to comply with SDP we cannot have an empty payload type number list */
|
||||
/* as it happens only when mline is declined with a zero port, it does not matter to put whatever codec*/
|
||||
belle_sip_list_t* format = belle_sip_list_append(NULL,0);
|
||||
belle_sdp_media_set_media_formats(belle_sdp_media_description_get_media(media_desc),format);
|
||||
}
|
||||
/*only add a c= line within the stream description if address are differents*/
|
||||
if (rtp_addr[0]!='\0' && strcmp(rtp_addr,md->addr)!=0){
|
||||
bool_t inet6;
|
||||
if (strchr(rtp_addr,':')!=NULL){
|
||||
inet6=TRUE;
|
||||
}else inet6=FALSE;
|
||||
belle_sdp_media_description_set_connection(media_desc,belle_sdp_connection_create("IN", inet6 ? "IP6" : "IP4", rtp_addr));
|
||||
}
|
||||
|
||||
if ( stream->bandwidth>0 )
|
||||
belle_sdp_media_description_set_bandwidth ( media_desc,"AS",stream->bandwidth );
|
||||
|
||||
if ( stream->proto == SalProtoRtpSavp ) {
|
||||
/* add crypto lines */
|
||||
for ( j=0; j<SAL_CRYPTO_ALGO_MAX; j++ ) {
|
||||
|
||||
switch ( stream->crypto[j].algo ) {
|
||||
case AES_128_SHA1_80:
|
||||
snprintf ( buffer, sizeof ( buffer ), "%d %s inline:%s",
|
||||
stream->crypto[j].tag, "AES_CM_128_HMAC_SHA1_80", stream->crypto[j].master_key );
|
||||
belle_sdp_media_description_add_attribute ( media_desc,belle_sdp_attribute_create ( "crypto",buffer ) );
|
||||
break;
|
||||
case AES_128_SHA1_32:
|
||||
snprintf ( buffer, sizeof ( buffer ), "%d %s inline:%s",
|
||||
stream->crypto[j].tag, "AES_CM_128_HMAC_SHA1_32", stream->crypto[j].master_key );
|
||||
belle_sdp_media_description_add_attribute ( media_desc,belle_sdp_attribute_create ( "crypto",buffer ) );
|
||||
break;
|
||||
case AES_128_NO_AUTH:
|
||||
ms_warning ( "Unsupported crypto suite: AES_128_NO_AUTH" );
|
||||
break;
|
||||
case NO_CIPHER_SHA1_80:
|
||||
ms_warning ( "Unsupported crypto suite: NO_CIPHER_SHA1_80" );
|
||||
break;
|
||||
default:
|
||||
j = SAL_CRYPTO_ALGO_MAX;
|
||||
/* no break */
|
||||
}
|
||||
}
|
||||
}
|
||||
switch ( stream->dir ) {
|
||||
case SalStreamSendRecv:
|
||||
/*dir="sendrecv";*/
|
||||
dir=NULL;
|
||||
break;
|
||||
case SalStreamRecvOnly:
|
||||
dir="recvonly";
|
||||
break;
|
||||
case SalStreamSendOnly:
|
||||
dir="sendonly";
|
||||
break;
|
||||
case SalStreamInactive:
|
||||
dir="inactive";
|
||||
break;
|
||||
}
|
||||
if ( dir ) belle_sdp_media_description_add_attribute ( media_desc,belle_sdp_attribute_create ( dir,NULL ) );
|
||||
|
||||
if (rtp_port != 0) {
|
||||
different_rtp_and_rtcp_addr = (rtcp_addr[0] != '\0') && (strcmp(rtp_addr, rtcp_addr) != 0);
|
||||
if ((rtcp_port != (rtp_port + 1)) || (different_rtp_and_rtcp_addr == TRUE)) {
|
||||
if (different_rtp_and_rtcp_addr == TRUE) {
|
||||
snprintf(buffer, sizeof(buffer), "%u IN IP4 %s", rtcp_port, rtcp_addr);
|
||||
} else {
|
||||
snprintf(buffer, sizeof(buffer), "%u",rtcp_port);
|
||||
}
|
||||
belle_sdp_media_description_add_attribute(media_desc,belle_sdp_attribute_create ("rtcp",buffer));
|
||||
}
|
||||
}
|
||||
if (stream->ice_completed == TRUE) {
|
||||
belle_sdp_media_description_add_attribute(media_desc,belle_sdp_attribute_create ("nortpproxy","yes"));
|
||||
}
|
||||
if (stream->ice_mismatch == TRUE) {
|
||||
belle_sdp_media_description_add_attribute(media_desc,belle_sdp_attribute_create ("ice-mismatch",NULL));
|
||||
} else {
|
||||
if (rtp_port != 0) {
|
||||
if (stream->ice_pwd[0] != '\0')
|
||||
belle_sdp_media_description_add_attribute(media_desc,belle_sdp_attribute_create ("ice-pwd",stream->ice_pwd));
|
||||
if (stream->ice_ufrag[0] != '\0')
|
||||
belle_sdp_media_description_add_attribute(media_desc,belle_sdp_attribute_create ("ice-ufrag",stream->ice_ufrag));
|
||||
add_ice_candidates(media_desc,stream);
|
||||
add_ice_remote_candidates(media_desc,stream);
|
||||
}
|
||||
}
|
||||
|
||||
return media_desc;
|
||||
}
|
||||
|
||||
belle_sdp_session_description_t * media_description_to_sdp ( const SalMediaDescription *desc ) {
|
||||
belle_sdp_session_description_t* session_desc=belle_sdp_session_description_new();
|
||||
bool_t inet6;
|
||||
belle_sdp_origin_t* origin;
|
||||
int i;
|
||||
|
||||
if ( strchr ( desc->addr,':' ) !=NULL ) {
|
||||
inet6=1;
|
||||
} else inet6=0;
|
||||
belle_sdp_session_description_set_version ( session_desc,belle_sdp_version_create ( 0 ) );
|
||||
|
||||
origin = belle_sdp_origin_create ( desc->username
|
||||
,desc->session_id
|
||||
,desc->session_ver
|
||||
,"IN"
|
||||
, inet6 ? "IP6" :"IP4"
|
||||
,desc->addr );
|
||||
|
||||
belle_sdp_session_description_set_origin ( session_desc,origin );
|
||||
|
||||
belle_sdp_session_description_set_session_name ( session_desc,belle_sdp_session_name_create ( "Talk" ) );
|
||||
|
||||
if ( (!sal_media_description_has_dir ( desc,SalStreamSendOnly ) && !sal_media_description_has_dir ( desc,SalStreamInactive ))
|
||||
|| desc->ice_ufrag[0] != '\0' ) {
|
||||
belle_sdp_session_description_set_connection ( session_desc
|
||||
,belle_sdp_connection_create ( "IN",inet6 ? "IP6" :"IP4",desc->addr ) );
|
||||
|
||||
} else {
|
||||
belle_sdp_session_description_set_connection ( session_desc
|
||||
,belle_sdp_connection_create ( "IN"
|
||||
,inet6 ? "IP6" :"IP4"
|
||||
,inet6 ? "::0" :"0.0.0.0" ) );
|
||||
|
||||
}
|
||||
|
||||
belle_sdp_session_description_set_time_description ( session_desc,belle_sdp_time_description_create ( 0,0 ) );
|
||||
|
||||
if ( desc->bandwidth>0 ) {
|
||||
belle_sdp_session_description_set_bandwidth ( session_desc,"AS",desc->bandwidth );
|
||||
}
|
||||
|
||||
if (desc->ice_completed == TRUE) belle_sdp_session_description_add_attribute(session_desc, belle_sdp_attribute_create("nortpproxy","yes"));
|
||||
if (desc->ice_pwd[0] != '\0') belle_sdp_session_description_add_attribute(session_desc, belle_sdp_attribute_create("ice-pwd",desc->ice_pwd));
|
||||
if (desc->ice_ufrag[0] != '\0') belle_sdp_session_description_add_attribute(session_desc, belle_sdp_attribute_create("ice-ufrag",desc->ice_ufrag));
|
||||
|
||||
for ( i=0; i<desc->n_total_streams; i++ ) {
|
||||
belle_sdp_session_description_add_media_description ( session_desc,stream_description_to_sdp(desc,&desc->streams[i]));
|
||||
}
|
||||
return session_desc;
|
||||
}
|
||||
|
||||
|
||||
int sdp_to_media_description ( belle_sdp_session_description_t *session_desc, SalMediaDescription *desc ) {
|
||||
/*
|
||||
typedef struct SalMediaDescription{
|
||||
int refcount;
|
||||
char addr[64];
|
||||
char username[64];
|
||||
int nstreams;
|
||||
int bandwidth;
|
||||
unsigned int session_ver;
|
||||
unsigned int session_id;
|
||||
SalStreamDescription streams[SAL_MEDIA_DESCRIPTION_MAX_STREAMS];
|
||||
} SalMediaDescription;
|
||||
*/
|
||||
belle_sdp_connection_t* cnx;
|
||||
belle_sip_list_t* media_desc_it;
|
||||
belle_sdp_media_description_t* media_desc;
|
||||
const char *mtype,*proto;
|
||||
SalStreamDescription *stream;
|
||||
belle_sdp_media_t* media;
|
||||
belle_sip_list_t* mime_params=NULL;
|
||||
belle_sip_list_t* mime_param_it=NULL;
|
||||
belle_sdp_mime_parameter_t* mime_param;
|
||||
PayloadType *pt;
|
||||
belle_sip_list_t* attribute_it;
|
||||
const belle_sdp_attribute_t* attribute;
|
||||
int valid_count = 0;
|
||||
char tmp[256], tmp2[256];
|
||||
int nb=0;
|
||||
SalStreamDir stream_dir=SalStreamSendRecv;
|
||||
const char* value;
|
||||
|
||||
desc->n_active_streams = 0;
|
||||
desc->n_total_streams = 0;
|
||||
|
||||
if ( ( cnx=belle_sdp_session_description_get_connection ( session_desc ) ) && belle_sdp_connection_get_address ( cnx ) ) {
|
||||
strncpy ( desc->addr,belle_sdp_connection_get_address ( cnx ),sizeof ( desc->addr ) );
|
||||
}
|
||||
if ( belle_sdp_session_description_get_bandwidth ( session_desc,"AS" ) >0 ) {
|
||||
desc->bandwidth=belle_sdp_session_description_get_bandwidth ( session_desc,"AS" );
|
||||
}
|
||||
/*in some very rare case, session attribute may set stream dir*/
|
||||
if ( belle_sdp_session_description_get_attribute ( session_desc,"sendrecv" ) ) {
|
||||
stream_dir=SalStreamSendRecv;
|
||||
} else if ( belle_sdp_session_description_get_attribute ( session_desc,"sendonly" ) ) {
|
||||
stream_dir=SalStreamSendOnly;
|
||||
} else if ( belle_sdp_session_description_get_attribute ( session_desc,"recvonly" ) ) {
|
||||
stream_dir=SalStreamRecvOnly;
|
||||
} else if ( belle_sdp_session_description_get_attribute ( session_desc,"inactive" ) ) {
|
||||
stream_dir=SalStreamInactive;
|
||||
}
|
||||
|
||||
/* Get ICE remote ufrag and remote pwd, and ice_lite flag */
|
||||
value=belle_sdp_session_description_get_attribute_value(session_desc,"ice-ufrag");
|
||||
if (value) strncpy(desc->ice_ufrag, value, sizeof(desc->ice_ufrag));
|
||||
|
||||
value=belle_sdp_session_description_get_attribute_value(session_desc,"ice-pwd");
|
||||
if (value) strncpy(desc->ice_pwd, value, sizeof(desc->ice_pwd));
|
||||
|
||||
value=belle_sdp_session_description_get_attribute_value(session_desc,"ice-lite");
|
||||
if (value) desc->ice_lite = TRUE;
|
||||
|
||||
for ( media_desc_it=belle_sdp_session_description_get_media_descriptions ( session_desc )
|
||||
; media_desc_it!=NULL
|
||||
; media_desc_it=media_desc_it->next ) {
|
||||
int nb_ice_candidates=0;
|
||||
media_desc=BELLE_SDP_MEDIA_DESCRIPTION ( media_desc_it->data );
|
||||
stream=&desc->streams[desc->n_total_streams];
|
||||
media=belle_sdp_media_description_get_media ( media_desc );
|
||||
|
||||
memset ( stream,0,sizeof ( *stream ) );
|
||||
|
||||
proto = belle_sdp_media_get_protocol ( media );
|
||||
stream->proto=SalProtoUnknown;
|
||||
if ( proto ) {
|
||||
if ( strcasecmp ( proto,"RTP/AVP" ) ==0 )
|
||||
stream->proto=SalProtoRtpAvp;
|
||||
else if ( strcasecmp ( proto,"RTP/SAVP" ) ==0 ) {
|
||||
stream->proto=SalProtoRtpSavp;
|
||||
}
|
||||
}
|
||||
if ( ( cnx=belle_sdp_media_description_get_connection ( media_desc ) ) && belle_sdp_connection_get_address ( cnx ) ) {
|
||||
strncpy ( stream->rtp_addr,belle_sdp_connection_get_address ( cnx ),sizeof ( stream->rtp_addr ) );
|
||||
}
|
||||
|
||||
stream->rtp_port=belle_sdp_media_get_media_port ( media );
|
||||
|
||||
if ( stream->rtp_port > 0 )
|
||||
desc->n_active_streams++;
|
||||
|
||||
mtype = belle_sdp_media_get_media_type ( media );
|
||||
if ( strcasecmp ( "audio", mtype ) == 0 ) {
|
||||
stream->type=SalAudio;
|
||||
} else if ( strcasecmp ( "video", mtype ) == 0 ) {
|
||||
stream->type=SalVideo;
|
||||
} else {
|
||||
stream->type=SalOther;
|
||||
strncpy ( stream->typeother,mtype,sizeof ( stream->typeother )-1 );
|
||||
}
|
||||
|
||||
if ( belle_sdp_media_description_get_bandwidth ( media_desc,"AS" ) >0 ) {
|
||||
stream->bandwidth=belle_sdp_media_description_get_bandwidth ( media_desc,"AS" );
|
||||
}
|
||||
|
||||
|
||||
if ( belle_sdp_media_description_get_attribute ( media_desc,"sendrecv" ) ) {
|
||||
stream->dir=SalStreamSendRecv;
|
||||
} else if ( belle_sdp_media_description_get_attribute ( media_desc,"sendonly" ) ) {
|
||||
stream->dir=SalStreamSendOnly;
|
||||
} else if ( belle_sdp_media_description_get_attribute ( media_desc,"recvonly" ) ) {
|
||||
stream->dir=SalStreamRecvOnly;
|
||||
} else if ( belle_sdp_media_description_get_attribute ( media_desc,"inactive" ) ) {
|
||||
stream->dir=SalStreamInactive;
|
||||
} else {
|
||||
stream->dir=stream_dir; /*takes default value if not present*/
|
||||
}
|
||||
|
||||
/* for each payload type */
|
||||
mime_params=belle_sdp_media_description_build_mime_parameters ( media_desc );
|
||||
for ( mime_param_it=mime_params
|
||||
; mime_param_it!=NULL
|
||||
; mime_param_it=mime_param_it->next ) {
|
||||
mime_param=BELLE_SDP_MIME_PARAMETER ( mime_param_it->data )
|
||||
|
||||
pt=payload_type_new();
|
||||
payload_type_set_number ( pt,belle_sdp_mime_parameter_get_media_format ( mime_param ) );
|
||||
pt->clock_rate=belle_sdp_mime_parameter_get_rate ( mime_param );
|
||||
pt->mime_type=ms_strdup ( belle_sdp_mime_parameter_get_type ( mime_param ) );
|
||||
pt->channels=belle_sdp_mime_parameter_get_channel_count ( mime_param );
|
||||
payload_type_set_send_fmtp ( pt,belle_sdp_mime_parameter_get_parameters ( mime_param ) );
|
||||
stream->payloads=ms_list_append ( stream->payloads,pt );
|
||||
stream->ptime=belle_sdp_mime_parameter_get_ptime ( mime_param );
|
||||
ms_message ( "Found payload %s/%i fmtp=%s",pt->mime_type,pt->clock_rate,
|
||||
pt->send_fmtp ? pt->send_fmtp : "" );
|
||||
}
|
||||
if ( mime_params ) belle_sip_list_free_with_data ( mime_params,belle_sip_object_unref );
|
||||
|
||||
|
||||
/* Get media specific RTCP attribute */
|
||||
stream->rtcp_port = stream->rtp_port + 1;
|
||||
snprintf(stream->rtcp_addr, sizeof(stream->rtcp_addr), "%s", stream->rtp_addr);
|
||||
attribute=belle_sdp_media_description_get_attribute(media_desc,"rtcp");
|
||||
if (attribute && (value=belle_sdp_attribute_get_value(attribute))!=NULL){
|
||||
char tmp[256];
|
||||
int nb = sscanf(value, "%d IN IP4 %s", &stream->rtcp_port, tmp);
|
||||
if (nb == 1) {
|
||||
/* SDP rtcp attribute only contains the port */
|
||||
} else if (nb == 2) {
|
||||
strncpy(stream->rtcp_addr, tmp, sizeof(stream->rtcp_addr));
|
||||
} else {
|
||||
ms_warning("sdp has a strange a=rtcp line (%s) nb=%i", value, nb);
|
||||
}
|
||||
}
|
||||
|
||||
/* read crypto lines if any */
|
||||
if ( stream->proto == SalProtoRtpSavp ) {
|
||||
valid_count=0;
|
||||
memset ( &stream->crypto, 0, sizeof ( stream->crypto ) );
|
||||
for ( attribute_it=belle_sdp_media_description_get_attributes ( media_desc )
|
||||
; valid_count < SAL_CRYPTO_ALGO_MAX && attribute_it!=NULL;
|
||||
attribute_it=attribute_it->next ) {
|
||||
attribute=BELLE_SDP_ATTRIBUTE ( attribute_it->data );
|
||||
|
||||
if ( keywordcmp ( "crypto",belle_sdp_attribute_get_name ( attribute ) ) ==0 && belle_sdp_attribute_get_value ( attribute ) !=NULL ) {
|
||||
nb = sscanf ( belle_sdp_attribute_get_value ( attribute ), "%d %256s inline:%256s",
|
||||
&stream->crypto[valid_count].tag,
|
||||
tmp,
|
||||
tmp2 );
|
||||
ms_message ( "Found valid crypto line (tag:%d algo:'%s' key:'%s'",
|
||||
stream->crypto[valid_count].tag,
|
||||
tmp,
|
||||
tmp2 );
|
||||
if ( nb == 3 ) {
|
||||
if ( keywordcmp ( "AES_CM_128_HMAC_SHA1_80",tmp ) == 0 )
|
||||
stream->crypto[valid_count].algo = AES_128_SHA1_80;
|
||||
else if ( keywordcmp ( "AES_CM_128_HMAC_SHA1_32",tmp ) == 0 )
|
||||
stream->crypto[valid_count].algo = AES_128_SHA1_32;
|
||||
else {
|
||||
ms_warning ( "Failed to parse crypto-algo: '%s'", tmp );
|
||||
stream->crypto[valid_count].algo = 0;
|
||||
}
|
||||
if ( stream->crypto[valid_count].algo ) {
|
||||
strncpy ( stream->crypto[valid_count].master_key, tmp2, 41 );
|
||||
stream->crypto[valid_count].master_key[40] = '\0';
|
||||
ms_message ( "Found valid crypto line (tag:%d algo:'%s' key:'%s'",
|
||||
stream->crypto[valid_count].tag,
|
||||
tmp,
|
||||
stream->crypto[valid_count].master_key );
|
||||
valid_count++;
|
||||
}
|
||||
} else {
|
||||
ms_warning ( "sdp has a strange a= line (%s) nb=%i",belle_sdp_attribute_get_value ( attribute ),nb );
|
||||
}
|
||||
}
|
||||
}
|
||||
ms_message ( "Found: %d valid crypto lines", valid_count );
|
||||
}
|
||||
|
||||
/* Get ICE candidate attributes if any */
|
||||
for (attribute_it = belle_sdp_media_description_get_attributes(media_desc); attribute_it != NULL; attribute_it=attribute_it->next) {
|
||||
const char *att_name;
|
||||
attribute=(belle_sdp_attribute_t*)attribute_it->data;
|
||||
att_name=belle_sdp_attribute_get_name(attribute);
|
||||
value=belle_sdp_attribute_get_value(attribute);
|
||||
if ((keywordcmp("candidate", att_name) == 0) && (value != NULL)) {
|
||||
SalIceCandidate *candidate = &stream->ice_candidates[nb_ice_candidates];
|
||||
int nb = sscanf(value, "%s %u UDP %u %s %d typ %s raddr %s rport %d",
|
||||
candidate->foundation, &candidate->componentID, &candidate->priority, candidate->addr, &candidate->port,
|
||||
candidate->type, candidate->raddr, &candidate->rport);
|
||||
if ((nb == 6) || (nb == 8)) nb_ice_candidates++;
|
||||
else memset(candidate, 0, sizeof(*candidate));
|
||||
} else if ((keywordcmp("remote-candidates", att_name) == 0) && (value != NULL)) {
|
||||
SalIceRemoteCandidate candidate;
|
||||
unsigned int componentID;
|
||||
int offset;
|
||||
const char *ptr = value;
|
||||
const char *endptr=value+strlen(ptr);
|
||||
while (3 == sscanf(ptr, "%u %s %u%n", &componentID, candidate.addr, &candidate.port, &offset)) {
|
||||
if ((componentID > 0) && (componentID <= SAL_MEDIA_DESCRIPTION_MAX_ICE_REMOTE_CANDIDATES)) {
|
||||
SalIceRemoteCandidate *remote_candidate = &stream->ice_remote_candidates[componentID - 1];
|
||||
strncpy(remote_candidate->addr, candidate.addr, sizeof(remote_candidate->addr));
|
||||
remote_candidate->port = candidate.port;
|
||||
}
|
||||
ptr += offset;
|
||||
if (ptr<endptr){
|
||||
if (ptr[offset] == ' ') ptr += 1;
|
||||
}else break;
|
||||
}
|
||||
} else if ((keywordcmp("ice-ufrag", att_name) == 0) && (value != NULL)) {
|
||||
strncpy(stream->ice_ufrag, value, sizeof(stream->ice_ufrag));
|
||||
} else if ((keywordcmp("ice-pwd", att_name) == 0) && (value != NULL)) {
|
||||
strncpy(stream->ice_pwd, value, sizeof(stream->ice_pwd));
|
||||
} else if (keywordcmp("ice-mismatch", att_name) == 0) {
|
||||
stream->ice_mismatch = TRUE;
|
||||
}
|
||||
}
|
||||
desc->n_total_streams++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -18,36 +18,35 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
*/
|
||||
|
||||
|
||||
#include "sal.h"
|
||||
#include "sal/sal.h"
|
||||
|
||||
#include "linphonecore.h"
|
||||
#include "private.h"
|
||||
#include "mediastreamer2/mediastream.h"
|
||||
#include "lpconfig.h"
|
||||
|
||||
// stat
|
||||
#ifndef WIN32
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
static void register_failure(SalOp *op, SalError error, SalReason reason, const char *details);
|
||||
|
||||
static int media_parameters_changed(LinphoneCall *call, SalMediaDescription *oldmd, SalMediaDescription *newmd) {
|
||||
if (call->params.in_conference != call->current_params.in_conference) return SAL_MEDIA_DESCRIPTION_CHANGED;
|
||||
if (call->up_bw != linphone_core_get_upload_bandwidth(call->core)) return SAL_MEDIA_DESCRIPTION_CHANGED;
|
||||
return sal_media_description_equals(oldmd, newmd);
|
||||
if (call->localdesc_changed) ms_message("Local description has changed: %i", call->localdesc_changed);
|
||||
return call->localdesc_changed | sal_media_description_equals(oldmd, newmd);
|
||||
}
|
||||
|
||||
void linphone_core_update_streams_destinations(LinphoneCore *lc, LinphoneCall *call, SalMediaDescription *old_md, SalMediaDescription *new_md) {
|
||||
SalStreamDescription *old_audiodesc = NULL;
|
||||
SalStreamDescription *old_videodesc = NULL;
|
||||
SalStreamDescription *new_audiodesc = NULL;
|
||||
SalStreamDescription *new_videodesc = NULL;
|
||||
char *rtp_addr, *rtcp_addr;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < old_md->n_active_streams; i++) {
|
||||
if (old_md->streams[i].type == SalAudio) {
|
||||
old_audiodesc = &old_md->streams[i];
|
||||
} else if (old_md->streams[i].type == SalVideo) {
|
||||
old_videodesc = &old_md->streams[i];
|
||||
}
|
||||
}
|
||||
for (i = 0; i < new_md->n_active_streams; i++) {
|
||||
if (new_md->streams[i].type == SalAudio) {
|
||||
new_audiodesc = &new_md->streams[i];
|
||||
|
|
@ -68,31 +67,15 @@ void linphone_core_update_streams_destinations(LinphoneCore *lc, LinphoneCall *c
|
|||
ms_message("Change video stream destination: RTP=%s:%d RTCP=%s:%d", rtp_addr, new_videodesc->rtp_port, rtcp_addr, new_videodesc->rtcp_port);
|
||||
rtp_session_set_remote_addr_full(call->videostream->ms.session, rtp_addr, new_videodesc->rtp_port, rtcp_addr, new_videodesc->rtcp_port);
|
||||
}
|
||||
#else
|
||||
(void)new_videodesc;
|
||||
#endif
|
||||
|
||||
/* Copy address and port values from new_md to old_md since we will keep old_md as resultdesc */
|
||||
strcpy(old_md->addr, new_md->addr);
|
||||
if (old_audiodesc && new_audiodesc) {
|
||||
strcpy(old_audiodesc->rtp_addr, new_audiodesc->rtp_addr);
|
||||
strcpy(old_audiodesc->rtcp_addr, new_audiodesc->rtcp_addr);
|
||||
old_audiodesc->rtp_port = new_audiodesc->rtp_port;
|
||||
old_audiodesc->rtcp_port = new_audiodesc->rtcp_port;
|
||||
}
|
||||
if (old_videodesc && new_videodesc) {
|
||||
strcpy(old_videodesc->rtp_addr, new_videodesc->rtp_addr);
|
||||
strcpy(old_videodesc->rtcp_addr, new_videodesc->rtcp_addr);
|
||||
old_videodesc->rtp_port = new_videodesc->rtp_port;
|
||||
old_videodesc->rtcp_port = new_videodesc->rtcp_port;
|
||||
}
|
||||
}
|
||||
|
||||
void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMediaDescription *new_md){
|
||||
SalMediaDescription *oldmd=call->resultdesc;
|
||||
|
||||
if (lc->ringstream!=NULL){
|
||||
ring_stop(lc->ringstream);
|
||||
lc->ringstream=NULL;
|
||||
}
|
||||
linphone_core_stop_ringing(lc);
|
||||
if (new_md!=NULL){
|
||||
sal_media_description_ref(new_md);
|
||||
call->media_pending=FALSE;
|
||||
|
|
@ -108,24 +91,20 @@ void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMedia
|
|||
ms_message("Media descriptions are different, need to restart the streams.");
|
||||
} else {
|
||||
if (md_changed == SAL_MEDIA_DESCRIPTION_UNCHANGED) {
|
||||
/*as nothing has changed, keep the oldmd */
|
||||
call->resultdesc=oldmd;
|
||||
sal_media_description_unref(new_md);
|
||||
if (call->all_muted){
|
||||
ms_message("Early media finished, unmuting inputs...");
|
||||
/*we were in early media, now we want to enable real media */
|
||||
linphone_call_enable_camera (call,linphone_call_camera_enabled (call));
|
||||
if (call->audiostream)
|
||||
linphone_core_mute_mic (lc, linphone_core_is_mic_muted(lc));
|
||||
linphone_core_enable_mic(lc, linphone_core_mic_enabled(lc));
|
||||
#ifdef VIDEO_ENABLED
|
||||
if (call->videostream && call->camera_active)
|
||||
video_stream_change_camera(call->videostream,lc->video_conf.device );
|
||||
#endif
|
||||
}
|
||||
ms_message("No need to restart streams, SDP is unchanged.");
|
||||
return;
|
||||
}
|
||||
else {
|
||||
goto end;
|
||||
}else {
|
||||
if (md_changed & SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED) {
|
||||
ms_message("Network parameters have changed, update them.");
|
||||
linphone_core_update_streams_destinations(lc, call, oldmd, new_md);
|
||||
|
|
@ -134,17 +113,13 @@ void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMedia
|
|||
ms_message("Crypto parameters have changed, update them.");
|
||||
linphone_call_update_crypto_parameters(call, oldmd, new_md);
|
||||
}
|
||||
call->resultdesc = oldmd;
|
||||
sal_media_description_unref(new_md);
|
||||
return;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
}
|
||||
linphone_call_stop_media_streams (call);
|
||||
linphone_call_init_media_streams (call);
|
||||
}
|
||||
if (oldmd)
|
||||
sal_media_description_unref(oldmd);
|
||||
|
||||
if (new_md) {
|
||||
bool_t all_muted=FALSE;
|
||||
|
|
@ -166,6 +141,10 @@ void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMedia
|
|||
if (call->state==LinphoneCallPausing && call->paused_by_app && ms_list_size(lc->calls)==1){
|
||||
linphone_core_play_named_tone(lc,LinphoneToneCallOnHold);
|
||||
}
|
||||
end:
|
||||
if (oldmd)
|
||||
sal_media_description_unref(oldmd);
|
||||
|
||||
}
|
||||
#if 0
|
||||
static bool_t is_duplicate_call(LinphoneCore *lc, const LinphoneAddress *from, const LinphoneAddress *to){
|
||||
|
|
@ -182,9 +161,9 @@ static bool_t is_duplicate_call(LinphoneCore *lc, const LinphoneAddress *from, c
|
|||
#endif
|
||||
|
||||
static bool_t already_a_call_with_remote_address(const LinphoneCore *lc, const LinphoneAddress *remote) {
|
||||
MSList *elem;
|
||||
ms_warning(" searching for already_a_call_with_remote_address.");
|
||||
|
||||
MSList *elem;
|
||||
for(elem=lc->calls;elem!=NULL;elem=elem->next){
|
||||
const LinphoneCall *call=(LinphoneCall*)elem->data;
|
||||
const LinphoneAddress *cRemote=linphone_call_get_remote_address(call);
|
||||
|
|
@ -215,25 +194,37 @@ static void call_received(SalOp *h){
|
|||
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(h));
|
||||
LinphoneCall *call;
|
||||
const char *from,*to;
|
||||
char *alt_contact;
|
||||
LinphoneAddress *from_addr, *to_addr;
|
||||
bool_t prevent_colliding_calls=lp_config_get_int(lc->config,"sip","prevent_colliding_calls",TRUE);
|
||||
|
||||
/* first check if we can answer successfully to this invite */
|
||||
if (lc->presence_mode==LinphoneStatusBusy ||
|
||||
lc->presence_mode==LinphoneStatusOffline ||
|
||||
lc->presence_mode==LinphoneStatusDoNotDisturb ||
|
||||
lc->presence_mode==LinphoneStatusMoved){
|
||||
if (lc->presence_mode==LinphoneStatusBusy )
|
||||
sal_call_decline(h,SalReasonBusy,NULL);
|
||||
else if (lc->presence_mode==LinphoneStatusOffline)
|
||||
sal_call_decline(h,SalReasonTemporarilyUnavailable,NULL);
|
||||
else if (lc->presence_mode==LinphoneStatusDoNotDisturb)
|
||||
sal_call_decline(h,SalReasonTemporarilyUnavailable,NULL);
|
||||
else if (lc->alt_contact!=NULL && lc->presence_mode==LinphoneStatusMoved)
|
||||
sal_call_decline(h,SalReasonRedirect,lc->alt_contact);
|
||||
if (linphone_presence_model_get_basic_status(lc->presence_model) == LinphonePresenceBasicStatusClosed) {
|
||||
LinphonePresenceActivity *activity = linphone_presence_model_get_activity(lc->presence_model);
|
||||
switch (linphone_presence_activity_get_type(activity)) {
|
||||
case LinphonePresenceActivityBusy:
|
||||
sal_call_decline(h,SalReasonBusy,NULL);
|
||||
break;
|
||||
case LinphonePresenceActivityAppointment:
|
||||
case LinphonePresenceActivityMeeting:
|
||||
case LinphonePresenceActivityOffline:
|
||||
case LinphonePresenceActivityWorship:
|
||||
sal_call_decline(h,SalReasonTemporarilyUnavailable,NULL);
|
||||
break;
|
||||
case LinphonePresenceActivityPermanentAbsence:
|
||||
alt_contact = linphone_presence_model_get_contact(lc->presence_model);
|
||||
if (alt_contact != NULL) {
|
||||
sal_call_decline(h,SalReasonRedirect,alt_contact);
|
||||
ms_free(alt_contact);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
sal_op_release(h);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!linphone_core_can_we_add_call(lc)){/*busy*/
|
||||
sal_call_decline(h,SalReasonBusy,NULL);
|
||||
sal_op_release(h);
|
||||
|
|
@ -282,17 +273,16 @@ static void call_ringing(SalOp *h){
|
|||
|
||||
if (call==NULL) return;
|
||||
|
||||
/*set privacy*/
|
||||
call->current_params.privacy=(LinphonePrivacyMask)sal_op_get_privacy(call->op);
|
||||
|
||||
if (lc->vtable.display_status)
|
||||
lc->vtable.display_status(lc,_("Remote ringing."));
|
||||
|
||||
md=sal_call_get_final_media_description(h);
|
||||
if (md==NULL){
|
||||
if (lc->ringstream && lc->dmfs_playing_start_time!=0){
|
||||
ring_stop(lc->ringstream);
|
||||
lc->ringstream=NULL;
|
||||
lc->dmfs_playing_start_time=0;
|
||||
}
|
||||
if (lc->ringstream!=NULL) return; /*already ringing !*/
|
||||
linphone_core_stop_dtmf_stream(lc);
|
||||
if (lc->ringstream!=NULL) return;/*already ringing !*/
|
||||
if (lc->sound_conf.play_sndcard!=NULL){
|
||||
MSSndCard *ringcard=lc->sound_conf.lsd_card ? lc->sound_conf.lsd_card : lc->sound_conf.play_sndcard;
|
||||
if (call->localdesc->streams[0].max_rate>0) ms_snd_card_set_preferred_sample_rate(ringcard, call->localdesc->streams[0].max_rate);
|
||||
|
|
@ -316,10 +306,7 @@ static void call_ringing(SalOp *h){
|
|||
if (lc->vtable.display_status)
|
||||
lc->vtable.display_status(lc,_("Early media."));
|
||||
linphone_call_set_state(call,LinphoneCallOutgoingEarlyMedia,"Early media");
|
||||
if (lc->ringstream!=NULL){
|
||||
ring_stop(lc->ringstream);
|
||||
lc->ringstream=NULL;
|
||||
}
|
||||
linphone_core_stop_ringing(lc);
|
||||
ms_message("Doing early media...");
|
||||
linphone_core_update_streams(lc,call,md);
|
||||
}
|
||||
|
|
@ -339,6 +326,8 @@ static void call_accepted(SalOp *op){
|
|||
ms_warning("No call to accept.");
|
||||
return ;
|
||||
}
|
||||
/*set privacy*/
|
||||
call->current_params.privacy=(LinphonePrivacyMask)sal_op_get_privacy(call->op);
|
||||
|
||||
/* Handle remote ICE attributes if any. */
|
||||
if (call->ice_session != NULL) {
|
||||
|
|
@ -351,7 +340,7 @@ static void call_accepted(SalOp *op){
|
|||
#endif //BUILD_UPNP
|
||||
|
||||
md=sal_call_get_final_media_description(op);
|
||||
if (md)
|
||||
if (md) /*make sure re-invite will not propose video again*/
|
||||
call->params.has_video &= linphone_core_media_description_contains_video_stream(md);
|
||||
|
||||
if (call->state==LinphoneCallOutgoingProgress ||
|
||||
|
|
@ -402,7 +391,10 @@ static void call_accepted(SalOp *op){
|
|||
}
|
||||
}
|
||||
}
|
||||
linphone_core_update_streams (lc,call,md);
|
||||
linphone_core_update_streams(lc,call,md);
|
||||
/*also reflect the change if the "wished" params, in order to avoid to propose SAVP or video again
|
||||
* further in the call, for example during pause,resume, conferencing reINVITEs*/
|
||||
linphone_call_fix_call_parameters(call);
|
||||
if (!call->current_params.in_conference)
|
||||
lc->current_call=call;
|
||||
linphone_call_set_state(call, LinphoneCallStreamsRunning, "Streams running");
|
||||
|
|
@ -451,8 +443,9 @@ static void call_accept_update(LinphoneCore *lc, LinphoneCall *call){
|
|||
linphone_call_update_remote_session_id_and_ver(call);
|
||||
sal_call_accept(call->op);
|
||||
md=sal_call_get_final_media_description(call->op);
|
||||
if (md && !sal_media_description_empty(md))
|
||||
if (md && !sal_media_description_empty(md)){
|
||||
linphone_core_update_streams(lc,call,md);
|
||||
}
|
||||
}
|
||||
|
||||
static void call_resumed(LinphoneCore *lc, LinphoneCall *call){
|
||||
|
|
@ -460,7 +453,6 @@ static void call_resumed(LinphoneCore *lc, LinphoneCall *call){
|
|||
if(lc->vtable.display_status)
|
||||
lc->vtable.display_status(lc,_("We have been resumed."));
|
||||
linphone_call_set_state(call,LinphoneCallStreamsRunning,"Connected (streams running)");
|
||||
linphone_call_set_transfer_state(call, LinphoneCallIdle);
|
||||
}
|
||||
|
||||
static void call_paused_by_remote(LinphoneCore *lc, LinphoneCall *call){
|
||||
|
|
@ -472,6 +464,16 @@ static void call_paused_by_remote(LinphoneCore *lc, LinphoneCall *call){
|
|||
}
|
||||
|
||||
static void call_updated_by_remote(LinphoneCore *lc, LinphoneCall *call){
|
||||
/*first check if media capabilities are compatible*/
|
||||
SalMediaDescription* md;
|
||||
linphone_call_make_local_media_description(lc,call);
|
||||
sal_call_set_local_media_description(call->op,call->localdesc);
|
||||
md=sal_call_get_final_media_description(call->op);
|
||||
if (md && (sal_media_description_empty(md) || linphone_core_incompatible_security(lc,md))){
|
||||
sal_call_decline(call->op,SalReasonNotAcceptable,NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
if(lc->vtable.display_status)
|
||||
lc->vtable.display_status(lc,_("Call is updated by remote."));
|
||||
call->defer_update=FALSE;
|
||||
|
|
@ -533,10 +535,12 @@ static void call_terminated(SalOp *op, const char *from){
|
|||
break;
|
||||
}
|
||||
ms_message("Current call terminated...");
|
||||
if (call->refer_pending){
|
||||
linphone_core_start_refered_call(lc,call);
|
||||
}
|
||||
//we stop the call only if we have this current call or if we are in call
|
||||
if (lc->ringstream!=NULL && ( (ms_list_size(lc->calls) == 1) || linphone_core_in_call(lc) )) {
|
||||
ring_stop(lc->ringstream);
|
||||
lc->ringstream=NULL;
|
||||
linphone_core_stop_ringing(lc);
|
||||
}
|
||||
linphone_call_stop_media_streams(call);
|
||||
if (lc->vtable.show!=NULL)
|
||||
|
|
@ -560,9 +564,10 @@ static void call_failure(SalOp *op, SalError error, SalReason sr, const char *de
|
|||
char *msg603=_("Call declined.");
|
||||
const char *msg=details;
|
||||
LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op);
|
||||
LinphoneCall *referer=call->referer;
|
||||
|
||||
if (call==NULL){
|
||||
ms_warning("Call faillure reported on already cleaned call ?");
|
||||
ms_warning("Call faillure reported on already terminated call.");
|
||||
return ;
|
||||
}
|
||||
|
||||
|
|
@ -612,55 +617,83 @@ static void call_failure(SalOp *op, SalError error, SalReason sr, const char *de
|
|||
if (call->params.media_encryption == LinphoneMediaEncryptionSRTP &&
|
||||
!linphone_core_is_media_encryption_mandatory(lc)) {
|
||||
int i;
|
||||
ms_message("Outgoing call failed with SRTP (SAVP) enabled - retrying with AVP");
|
||||
ms_message("Outgoing call [%p] failed with SRTP (SAVP) enabled",call);
|
||||
linphone_call_stop_media_streams(call);
|
||||
if (call->state==LinphoneCallOutgoingInit || call->state==LinphoneCallOutgoingProgress){
|
||||
if ( call->state==LinphoneCallOutgoingInit
|
||||
|| call->state==LinphoneCallOutgoingProgress
|
||||
|| call->state==LinphoneCallOutgoingRinging /*push case*/
|
||||
|| call->state==LinphoneCallOutgoingEarlyMedia){
|
||||
ms_message("Retrying call [%p] with AVP",call);
|
||||
/* clear SRTP local params */
|
||||
call->params.media_encryption = LinphoneMediaEncryptionNone;
|
||||
for(i=0; i<call->localdesc->n_active_streams; i++) {
|
||||
call->localdesc->streams[i].proto = SalProtoRtpAvp;
|
||||
memset(call->localdesc->streams[i].crypto, 0, sizeof(call->localdesc->streams[i].crypto));
|
||||
}
|
||||
linphone_core_start_invite(lc, call);
|
||||
linphone_core_restart_invite(lc, call);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
|
||||
}
|
||||
msg=_("Incompatible media parameters.");
|
||||
if (lc->vtable.display_status)
|
||||
lc->vtable.display_status(lc,msg);
|
||||
break;
|
||||
case SalReasonRequestPending:
|
||||
/*restore previous state, the application will decide to resubmit the action if relevant*/
|
||||
call->reason=linphone_reason_from_sal(sr);
|
||||
linphone_call_set_state(call,call->prevstate,msg);
|
||||
return;
|
||||
break;
|
||||
default:
|
||||
if (lc->vtable.display_status)
|
||||
lc->vtable.display_status(lc,_("Call failed."));
|
||||
}
|
||||
}
|
||||
|
||||
if (lc->ringstream!=NULL) {
|
||||
ring_stop(lc->ringstream);
|
||||
lc->ringstream=NULL;
|
||||
}
|
||||
linphone_call_stop_media_streams (call);
|
||||
if (call->referer && linphone_call_get_state(call->referer)==LinphoneCallPaused && call->referer->was_automatically_paused){
|
||||
/*resume to the call that send us the refer automatically*/
|
||||
linphone_core_resume_call(lc,call->referer);
|
||||
/*some call error are not fatal*/
|
||||
switch (call->state) {
|
||||
case LinphoneCallUpdating:
|
||||
case LinphoneCallPausing:
|
||||
case LinphoneCallResuming:
|
||||
ms_message("Call error on state [%s], restoring previous state",linphone_call_state_to_string(call->prevstate));
|
||||
call->reason=linphone_reason_from_sal(sr);
|
||||
linphone_call_set_state(call, call->prevstate,details);
|
||||
return;
|
||||
default:
|
||||
break; /*nothing to do*/
|
||||
}
|
||||
|
||||
linphone_core_stop_ringing(lc);
|
||||
linphone_call_stop_media_streams(call);
|
||||
|
||||
#ifdef BUILD_UPNP
|
||||
linphone_call_delete_upnp_session(call);
|
||||
#endif //BUILD_UPNP
|
||||
|
||||
if (sr == SalReasonDeclined) {
|
||||
call->reason=LinphoneReasonDeclined;
|
||||
|
||||
call->reason=linphone_reason_from_sal(sr);
|
||||
if (sr==SalReasonDeclined){
|
||||
linphone_call_set_state(call,LinphoneCallEnd,"Call declined.");
|
||||
} else if (sr == SalReasonNotFound) {
|
||||
call->reason=LinphoneReasonNotFound;
|
||||
linphone_call_set_state(call,LinphoneCallError,"User not found.");
|
||||
} else if (sr == SalReasonBusy) {
|
||||
call->reason=LinphoneReasonBusy;
|
||||
linphone_call_set_state(call,LinphoneCallError,"User is busy.");
|
||||
linphone_core_play_named_tone(lc,LinphoneToneBusy);
|
||||
} else {
|
||||
linphone_call_set_state(call,LinphoneCallError,msg);
|
||||
}else{
|
||||
linphone_call_set_state(call,LinphoneCallError,details);
|
||||
if (sr==SalReasonBusy)
|
||||
linphone_core_play_named_tone(lc,LinphoneToneBusy);
|
||||
}
|
||||
|
||||
if (referer){
|
||||
/*
|
||||
* 1- resume call automatically if we had to pause it before to execute the transfer
|
||||
* 2- notify other party of the transfer faillure
|
||||
* This must be done at the end because transferer call can't be resumed until transfer-target call is changed to error state.
|
||||
* This must be done in this order because if the notify transaction will prevent the resume transaction to take place.
|
||||
* On the contrary, the notify transaction is queued and then executed after the resume completes.
|
||||
**/
|
||||
if (linphone_call_get_state(referer)==LinphoneCallPaused && referer->was_automatically_paused){
|
||||
/*resume to the call that send us the refer automatically*/
|
||||
linphone_core_resume_call(lc,referer);
|
||||
referer->was_automatically_paused=FALSE;
|
||||
}
|
||||
linphone_core_notify_refer_state(lc,referer,call);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -671,54 +704,14 @@ static void call_released(SalOp *op){
|
|||
}else ms_error("call_released() for already destroyed call ?");
|
||||
}
|
||||
|
||||
static void auth_requested(SalOp *h, const char *realm, const char *username){
|
||||
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(h));
|
||||
LinphoneAuthInfo *ai=(LinphoneAuthInfo*)linphone_core_find_auth_info(lc,realm,username);
|
||||
LinphoneCall *call=is_a_linphone_call(sal_op_get_user_pointer(h));
|
||||
|
||||
if (call && call->ping_op==h){
|
||||
/*don't request authentication for ping requests. Their purpose is just to get any
|
||||
* answer to get the Via's received and rport parameters.
|
||||
*/
|
||||
ms_message("auth_requested(): ignored for ping request.");
|
||||
return;
|
||||
}
|
||||
|
||||
ms_message("auth_requested() for realm=%s, username=%s",realm,username);
|
||||
|
||||
if (ai && ai->works==FALSE && ai->usecount>=3){
|
||||
/*case we tried 3 times to authenticate, without success */
|
||||
/*Better is to stop (implemeted below in else statement), and retry later*/
|
||||
if (ms_time(NULL)-ai->last_use_time>30){
|
||||
ai->usecount=0; /*so that we can allow to retry */
|
||||
}
|
||||
}
|
||||
|
||||
if (ai && (ai->works || ai->usecount<3)){
|
||||
SalAuthInfo sai;
|
||||
sai.username=ai->username;
|
||||
sai.userid=ai->userid;
|
||||
sai.realm=ai->realm;
|
||||
sai.password=ai->passwd;
|
||||
ms_message("auth_requested(): authenticating realm=%s, username=%s",realm,username);
|
||||
sal_op_authenticate(h,&sai);
|
||||
ai->usecount++;
|
||||
ai->last_use_time=ms_time(NULL);
|
||||
}else{
|
||||
if (ai && ai->works==FALSE) {
|
||||
sal_op_cancel_authentication(h);
|
||||
}
|
||||
if (lc->vtable.auth_info_requested)
|
||||
lc->vtable.auth_info_requested(lc,realm,username);
|
||||
}
|
||||
}
|
||||
|
||||
static void auth_success(SalOp *h, const char *realm, const char *username){
|
||||
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(h));
|
||||
LinphoneAuthInfo *ai=(LinphoneAuthInfo*)linphone_core_find_auth_info(lc,realm,username);
|
||||
static void auth_failure(SalOp *op, SalAuthInfo* info) {
|
||||
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
|
||||
LinphoneAuthInfo *ai=(LinphoneAuthInfo*)linphone_core_find_auth_info(lc,info->realm,info->username,info->domain);
|
||||
if (ai){
|
||||
ms_message("%s/%s authentication works.",realm,username);
|
||||
ai->works=TRUE;
|
||||
ms_message("%s/%s/%s authentication fails.",info->realm,info->username,info->domain);
|
||||
}
|
||||
if (lc->vtable.auth_info_requested) {
|
||||
lc->vtable.auth_info_requested(lc,info->realm,info->username,info->domain);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -727,7 +720,7 @@ static void register_success(SalOp *op, bool_t registered){
|
|||
LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)sal_op_get_user_pointer(op);
|
||||
char *msg;
|
||||
|
||||
if (cfg->deletion_date!=0){
|
||||
if (!cfg || cfg->deletion_date!=0){
|
||||
ms_message("Registration success for removed proxy config, ignored");
|
||||
return;
|
||||
}
|
||||
|
|
@ -763,18 +756,21 @@ static void register_failure(SalOp *op, SalError error, SalReason reason, const
|
|||
lc->vtable.display_status(lc,msg);
|
||||
ms_free(msg);
|
||||
}
|
||||
if (error== SalErrorFailure && reason == SalReasonForbidden) {
|
||||
linphone_proxy_config_set_error(cfg, LinphoneReasonBadCredentials);
|
||||
} else if (error == SalErrorNoResponse) {
|
||||
linphone_proxy_config_set_error(cfg, LinphoneReasonNoResponse);
|
||||
|
||||
linphone_proxy_config_set_error(cfg,linphone_reason_from_sal(reason));
|
||||
|
||||
if (error== SalErrorFailure
|
||||
&& reason == SalReasonServiceUnavailable
|
||||
&& linphone_proxy_config_get_state(cfg) == LinphoneRegistrationOk) {
|
||||
linphone_proxy_config_set_state(cfg,LinphoneRegistrationProgress,_("Service unavailable, retrying"));
|
||||
} else {
|
||||
linphone_proxy_config_set_state(cfg,LinphoneRegistrationFailed,details);
|
||||
}
|
||||
linphone_proxy_config_set_state(cfg,LinphoneRegistrationFailed,details);
|
||||
if (error== SalErrorFailure && reason == SalReasonForbidden) {
|
||||
const char *realm=NULL,*username=NULL;
|
||||
if (sal_op_get_auth_requested(op,&realm,&username)==0){
|
||||
if (lc->vtable.auth_info_requested)
|
||||
lc->vtable.auth_info_requested(lc,realm,username);
|
||||
}
|
||||
if (cfg->publish_op){
|
||||
/*prevent publish to be sent now until registration gets successful*/
|
||||
sal_op_release(cfg->publish_op);
|
||||
cfg->publish_op=NULL;
|
||||
cfg->send_publish=cfg->publish;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -854,25 +850,25 @@ static void text_received(SalOp *op, const SalMessage *msg){
|
|||
}
|
||||
}
|
||||
|
||||
static void notify(SalOp *op, const char *from, const char *msg){
|
||||
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
|
||||
LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer (op);
|
||||
ms_message("get a %s notify from %s",msg,from);
|
||||
if(lc->vtable.notify_recv)
|
||||
lc->vtable.notify_recv(lc,call,from,msg);
|
||||
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);
|
||||
}
|
||||
|
||||
static void notify_presence(SalOp *op, SalSubscribeStatus ss, SalPresenceStatus status, const char *msg){
|
||||
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
|
||||
linphone_notify_recv(lc,op,ss,status);
|
||||
static void convert_presence_to_xml_requested(SalOp *op, SalPresenceModel *presence, const char *contact, char **content) {
|
||||
linphone_notify_convert_presence_to_xml(op, presence, contact, content);
|
||||
}
|
||||
|
||||
static void subscribe_received(SalOp *op, const char *from){
|
||||
static void notify_presence(SalOp *op, SalSubscribeStatus ss, SalPresenceModel *model, const char *msg){
|
||||
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
|
||||
linphone_notify_recv(lc,op,ss,model);
|
||||
}
|
||||
|
||||
static void subscribe_presence_received(SalOp *op, const char *from){
|
||||
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
|
||||
linphone_subscription_new(lc,op,from);
|
||||
}
|
||||
|
||||
static void subscribe_closed(SalOp *op, const char *from){
|
||||
static void subscribe_presence_closed(SalOp *op, const char *from){
|
||||
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
|
||||
linphone_subscription_closed(lc,op);
|
||||
}
|
||||
|
|
@ -892,6 +888,80 @@ static void ping_reply(SalOp *op){
|
|||
}
|
||||
}
|
||||
|
||||
static const char *get_client_cert_path(LinphoneCore *lc) {
|
||||
static char cldir[200] = {0};
|
||||
#ifdef HAVE_GETENV
|
||||
if (!cldir[0]) {
|
||||
static char default_path[200] = {0};
|
||||
snprintf(default_path, sizeof(default_path), "%s%s", getenv("HOME"), "/linphone_certs");
|
||||
snprintf(cldir, sizeof(cldir), "%s", lp_config_get_string(lc->config,"sip","client_certificates_dir", default_path));
|
||||
}
|
||||
#endif
|
||||
return cldir;
|
||||
}
|
||||
static bool_t fill_auth_info_with_client_certificate(LinphoneCore *lc, SalAuthInfo* sai) {
|
||||
char chain_file[200];
|
||||
char key_file[200];
|
||||
const char *path = get_client_cert_path(lc);
|
||||
|
||||
snprintf(chain_file, sizeof(chain_file), "%s%s", path, "/chain.pem");
|
||||
|
||||
snprintf(key_file, sizeof(key_file), "%s%s", path, "/key.pem");
|
||||
|
||||
#ifndef WIN32
|
||||
{
|
||||
// optinal check for files
|
||||
struct stat st;
|
||||
if (stat(key_file,&st)) {
|
||||
ms_warning("No client certificate key found in %s", key_file);
|
||||
return FALSE;
|
||||
}
|
||||
if (stat(chain_file,&st)) {
|
||||
ms_warning("No client certificate chain found in %s", chain_file);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
sal_certificates_chain_parse_file(sai, chain_file, SAL_CERTIFICATE_RAW_FORMAT_PEM );
|
||||
sal_signing_key_parse_file(sai, key_file, "");
|
||||
return sai->certificates && sai->key;
|
||||
}
|
||||
|
||||
static bool_t fill_auth_info(LinphoneCore *lc, SalAuthInfo* sai) {
|
||||
LinphoneAuthInfo *ai=(LinphoneAuthInfo*)linphone_core_find_auth_info(lc,sai->realm,sai->username,sai->domain);
|
||||
if (ai) {
|
||||
sai->userid=ms_strdup(ai->userid?ai->userid:ai->username);
|
||||
sai->password=ai->passwd?ms_strdup(ai->passwd):NULL;
|
||||
sai->ha1=ai->ha1?ms_strdup(ai->ha1):NULL;
|
||||
ai->usecount++;
|
||||
ai->last_use_time=ms_time(NULL);
|
||||
return TRUE;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
static bool_t auth_requested(Sal* sal, SalAuthInfo* sai) {
|
||||
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal);
|
||||
if (sai->mode == SalAuthModeHttpDigest) {
|
||||
if (fill_auth_info(lc,sai)) {
|
||||
return TRUE;
|
||||
} else {
|
||||
if (lc->vtable.auth_info_requested) {
|
||||
lc->vtable.auth_info_requested(lc,sai->realm,sai->username,sai->domain);
|
||||
if (fill_auth_info(lc,sai)) {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
} else if (sai->mode == SalAuthModeTls) {
|
||||
return fill_auth_info_with_client_certificate(lc,sai);
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static void notify_refer(SalOp *op, SalReferStatus status){
|
||||
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
|
||||
LinphoneCall *call=(LinphoneCall*) sal_op_get_user_pointer(op);
|
||||
|
|
@ -935,6 +1005,7 @@ static LinphoneChatMessageState chatStatusSal2Linphone(SalTextDeliveryStatus sta
|
|||
static int op_equals(LinphoneCall *a, SalOp *b) {
|
||||
return a->op !=b; /*return 0 if equals*/
|
||||
}
|
||||
|
||||
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);
|
||||
|
|
@ -942,15 +1013,101 @@ static void text_delivery_update(SalOp *op, SalTextDeliveryStatus status){
|
|||
chat_msg->state=chatStatusSal2Linphone(status);
|
||||
linphone_chat_message_store_state(chat_msg);
|
||||
if (chat_msg && chat_msg->cb) {
|
||||
ms_message("Notifying text delivery with status %i",chat_msg->state);
|
||||
chat_msg->cb(chat_msg
|
||||
,chat_msg->state
|
||||
,chat_msg->cb_ud);
|
||||
}
|
||||
linphone_chat_message_destroy(chat_msg);
|
||||
if (status != SalTextDeliveryInProgress) { /*don't release op if progress*/
|
||||
linphone_chat_message_destroy(chat_msg);
|
||||
|
||||
if (!ms_list_find_custom((MSList*)calls, (MSCompareFunc) op_equals, op)) {
|
||||
/*op was only create for messaging purpose, destroying*/
|
||||
sal_op_release(op);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void info_received(SalOp *op, const SalBody *body){
|
||||
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
|
||||
linphone_core_notify_info_message(lc,op,body);
|
||||
}
|
||||
|
||||
static void subscribe_response(SalOp *op, SalSubscribeStatus status, SalError error, SalReason reason){
|
||||
LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op);
|
||||
|
||||
if (!ms_list_find_custom((MSList*)calls, (MSCompareFunc) op_equals, op)) {
|
||||
/*op was only create for messaging purpose, destroying*/
|
||||
sal_op_release(op);
|
||||
if (lev==NULL) return;
|
||||
|
||||
if (status==SalSubscribeActive){
|
||||
linphone_event_set_state(lev,LinphoneSubscriptionActive);
|
||||
}else if (status==SalSubscribePending){
|
||||
linphone_event_set_state(lev,LinphoneSubscriptionPending);
|
||||
}else{
|
||||
linphone_event_set_reason(lev, linphone_reason_from_sal(reason));
|
||||
linphone_event_set_state(lev,LinphoneSubscriptionError);
|
||||
}
|
||||
}
|
||||
|
||||
static void notify(SalOp *op, SalSubscribeStatus st, const char *eventname, const SalBody *body){
|
||||
LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op);
|
||||
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
|
||||
LinphoneContent content;
|
||||
|
||||
if (lev==NULL) {
|
||||
/*out of subscribe notify */
|
||||
lev=linphone_event_new_with_op(lc,op,LinphoneSubscriptionOutgoing,eventname);
|
||||
}
|
||||
if (lc->vtable.notify_received){
|
||||
const LinphoneContent *ct=linphone_content_from_sal_body(&content,body);
|
||||
if (ct) lc->vtable.notify_received(lc,lev,eventname,ct);
|
||||
}
|
||||
if (st!=SalSubscribeNone){
|
||||
linphone_event_set_state(lev,linphone_subscription_state_from_sal(st));
|
||||
}
|
||||
}
|
||||
|
||||
static void subscribe_received(SalOp *op, const char *eventname, const SalBody *body){
|
||||
LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op);
|
||||
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
|
||||
|
||||
if (lev==NULL) {
|
||||
lev=linphone_event_new_with_op(lc,op,LinphoneSubscriptionIncoming,eventname);
|
||||
linphone_event_set_state(lev,LinphoneSubscriptionIncomingReceived);
|
||||
}else{
|
||||
/*subscribe refresh, unhandled*/
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void subscribe_closed(SalOp *op){
|
||||
LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op);
|
||||
|
||||
linphone_event_set_state(lev,LinphoneSubscriptionTerminated);
|
||||
}
|
||||
|
||||
static void on_publish_response(SalOp* op, SalError err, SalReason reason){
|
||||
LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op);
|
||||
|
||||
if (lev==NULL) return;
|
||||
if (err==SalErrorNone){
|
||||
if (!lev->terminating)
|
||||
linphone_event_set_publish_state(lev,LinphonePublishOk);
|
||||
else
|
||||
linphone_event_set_publish_state(lev,LinphonePublishCleared);
|
||||
|
||||
}else{
|
||||
linphone_event_set_reason(lev,linphone_reason_from_sal(reason));
|
||||
linphone_event_set_publish_state(lev,LinphonePublishError);
|
||||
}
|
||||
}
|
||||
|
||||
static void on_expire(SalOp *op){
|
||||
LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op);
|
||||
|
||||
if (lev==NULL) return;
|
||||
|
||||
if (linphone_event_get_publish_state(lev)==LinphonePublishOk){
|
||||
linphone_event_set_publish_state(lev,LinphonePublishExpiring);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -963,8 +1120,7 @@ SalCallbacks linphone_sal_callbacks={
|
|||
call_terminated,
|
||||
call_failure,
|
||||
call_released,
|
||||
auth_requested,
|
||||
auth_success,
|
||||
auth_failure,
|
||||
register_success,
|
||||
register_failure,
|
||||
vfu_request,
|
||||
|
|
@ -972,12 +1128,21 @@ SalCallbacks linphone_sal_callbacks={
|
|||
refer_received,
|
||||
text_received,
|
||||
text_delivery_update,
|
||||
notify,
|
||||
notify_presence,
|
||||
notify_refer,
|
||||
subscribe_received,
|
||||
subscribe_closed,
|
||||
subscribe_response,
|
||||
notify,
|
||||
subscribe_presence_received,
|
||||
subscribe_presence_closed,
|
||||
parse_presence_requested,
|
||||
convert_presence_to_xml_requested,
|
||||
notify_presence,
|
||||
ping_reply,
|
||||
auth_requested,
|
||||
info_received,
|
||||
on_publish_response,
|
||||
on_expire
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
138
coreapi/chat.c
|
|
@ -31,6 +31,15 @@
|
|||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns an array of chat rooms
|
||||
* @param lc #LinphoneCore object
|
||||
* @return An array of #LinpĥoneChatRoom
|
||||
**/
|
||||
MSList* linphone_core_get_chat_rooms(LinphoneCore *lc) {
|
||||
return lc->chatrooms;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new chat room for messaging from a sip uri like sip:joe@sip.linphone.org
|
||||
* @param lc #LinphoneCore object
|
||||
|
|
@ -50,6 +59,32 @@ LinphoneChatRoom * linphone_core_create_chat_room(LinphoneCore *lc, const char *
|
|||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool_t linphone_chat_room_matches(LinphoneChatRoom *cr, const LinphoneAddress *from){
|
||||
return linphone_address_weak_equal(cr->peer_url,from);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new chat room for messaging from a sip uri like sip:joe@sip.linphone.org if not already existing, else return exisiting one
|
||||
* @param lc #LinphoneCore object
|
||||
* @param to destination address for messages
|
||||
* @return #LinphoneChatRoom where messaging can take place.
|
||||
*/
|
||||
LinphoneChatRoom* linphone_core_get_or_create_chat_room(LinphoneCore* lc, const char* to) {
|
||||
LinphoneAddress *to_addr=linphone_core_interpret_url(lc,to);
|
||||
LinphoneChatRoom *ret;
|
||||
|
||||
if (to_addr==NULL){
|
||||
ms_error("linphone_core_get_or_create_chat_room(): Cannot make a valid address with %s",to);
|
||||
return NULL;
|
||||
}
|
||||
ret=linphone_core_get_chat_room(lc,to_addr);
|
||||
linphone_address_destroy(to_addr);
|
||||
if (!ret){
|
||||
ret=linphone_core_create_chat_room(lc,to);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy a LinphoneChatRoom.
|
||||
|
|
@ -60,16 +95,16 @@ void linphone_chat_room_destroy(LinphoneChatRoom *cr){
|
|||
lc->chatrooms=ms_list_remove(lc->chatrooms,(void *) cr);
|
||||
linphone_address_destroy(cr->peer_url);
|
||||
ms_free(cr->peer);
|
||||
ms_free(cr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatMessage* msg){
|
||||
const char *route=NULL;
|
||||
const char *identity=linphone_core_find_best_identity(cr->lc,cr->peer_url,&route);
|
||||
SalOp *op=NULL;
|
||||
LinphoneCall *call;
|
||||
char* content_type;
|
||||
const char *identity=NULL;
|
||||
time_t t=time(NULL);
|
||||
|
||||
if (lp_config_get_int(cr->lc->config,"sip","chat_use_call_dialogs",0)){
|
||||
|
|
@ -82,19 +117,20 @@ static void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatM
|
|||
ms_message("send SIP message through the existing call.");
|
||||
op = call->op;
|
||||
call->pending_message=msg;
|
||||
identity=linphone_core_find_best_identity(cr->lc,linphone_call_get_remote_address(call));
|
||||
}
|
||||
}
|
||||
}
|
||||
msg->time=t;
|
||||
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);
|
||||
sal_op_set_route(op,route);
|
||||
linphone_configure_op(cr->lc,op,cr->peer_url,msg->custom_headers,lp_config_get_int(cr->lc->config,"sip","chat_msg_with_contact",0));
|
||||
sal_op_set_user_pointer(op, msg); /*if out of call, directly store msg*/
|
||||
if (msg->custom_headers){
|
||||
sal_op_set_custom_header(op,msg->custom_headers);
|
||||
msg->custom_headers=NULL; /*transfered to the SalOp*/
|
||||
}
|
||||
}
|
||||
if (msg->external_body_url) {
|
||||
content_type=ms_strdup_printf("message/external-body; access-type=URL; URL=\"%s\"",msg->external_body_url);
|
||||
|
|
@ -105,7 +141,7 @@ static void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatM
|
|||
}
|
||||
msg->dir=LinphoneChatMessageOutgoing;
|
||||
msg->from=linphone_address_new(identity);
|
||||
linphone_chat_message_store(msg);
|
||||
msg->storage_id=linphone_chat_message_store(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -118,12 +154,6 @@ void linphone_chat_room_send_message(LinphoneChatRoom *cr, const char *msg) {
|
|||
_linphone_chat_room_send_message(cr,linphone_chat_room_create_message(cr,msg));
|
||||
}
|
||||
|
||||
bool_t linphone_chat_room_matches(LinphoneChatRoom *cr, const LinphoneAddress *from){
|
||||
if (linphone_address_get_username(cr->peer_url) && linphone_address_get_username(from) &&
|
||||
strcmp(linphone_address_get_username(cr->peer_url),linphone_address_get_username(from))==0) return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void linphone_chat_room_message_received(LinphoneChatRoom *cr, LinphoneCore *lc, LinphoneChatMessage *msg){
|
||||
if (msg->message)
|
||||
//legacy API
|
||||
|
|
@ -181,14 +211,15 @@ void linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessag
|
|||
msg->time=sal_msg->time;
|
||||
msg->state=LinphoneChatMessageStateDelivered;
|
||||
msg->is_read=FALSE;
|
||||
ch=sal_op_get_custom_header(op);
|
||||
msg->dir=LinphoneChatMessageIncoming;
|
||||
ch=sal_op_get_recv_custom_header(op);
|
||||
if (ch) msg->custom_headers=sal_custom_header_clone(ch);
|
||||
|
||||
if (sal_msg->url) {
|
||||
linphone_chat_message_set_external_body_url(msg, sal_msg->url);
|
||||
}
|
||||
linphone_address_destroy(addr);
|
||||
linphone_chat_message_store(msg);
|
||||
msg->storage_id=linphone_chat_message_store(msg);
|
||||
linphone_chat_room_message_received(cr,lc,msg);
|
||||
ms_free(cleanfrom);
|
||||
ms_free(from);
|
||||
|
|
@ -238,6 +269,41 @@ LinphoneChatMessage* linphone_chat_room_create_message(LinphoneChatRoom *cr, con
|
|||
return msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a message attached to a dedicated chat room;
|
||||
* @param cr the chat room.
|
||||
* @param message text message, NULL if absent.
|
||||
* @param external_body_url the URL given in external body or NULL.
|
||||
* @param state the LinphoneChatMessage.State of the message.
|
||||
* @param time the time_t at which the message has been received/sent.
|
||||
* @param is_read TRUE if the message should be flagged as read, FALSE otherwise.
|
||||
* @param is_incoming TRUE if the message has been received, FALSE otherwise.
|
||||
* @return a new #LinphoneChatMessage
|
||||
*/
|
||||
LinphoneChatMessage* linphone_chat_room_create_message_2(
|
||||
LinphoneChatRoom *cr, const char* message, const char* external_body_url,
|
||||
LinphoneChatMessageState state, time_t time, bool_t is_read, bool_t is_incoming) {
|
||||
LinphoneCore *lc=linphone_chat_room_get_lc(cr);
|
||||
|
||||
LinphoneChatMessage* msg = ms_new0(LinphoneChatMessage,1);
|
||||
msg->chat_room=(LinphoneChatRoom*)cr;
|
||||
msg->message=message?ms_strdup(message):NULL;
|
||||
msg->external_body_url=external_body_url?ms_strdup(external_body_url):NULL;
|
||||
msg->time=time;
|
||||
msg->state=state;
|
||||
msg->is_read=is_read;
|
||||
if (is_incoming) {
|
||||
msg->dir=LinphoneChatMessageIncoming;
|
||||
linphone_chat_message_set_from(msg, linphone_chat_room_get_peer_address(cr));
|
||||
linphone_chat_message_set_to(msg, linphone_address_new(linphone_core_get_identity(lc)));
|
||||
} else {
|
||||
msg->dir=LinphoneChatMessageOutgoing;
|
||||
linphone_chat_message_set_to(msg, linphone_chat_room_get_peer_address(cr));
|
||||
linphone_chat_message_set_from(msg, linphone_address_new(linphone_core_get_identity(lc)));
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message to peer member of this chat room.
|
||||
* @param cr #LinphoneChatRoom object
|
||||
|
|
@ -246,7 +312,7 @@ LinphoneChatMessage* linphone_chat_room_create_message(LinphoneChatRoom *cr, con
|
|||
* @param ud user data for the status cb.
|
||||
* @note The LinphoneChatMessage must not be destroyed until the the callback is called.
|
||||
*/
|
||||
void linphone_chat_room_send_message2(LinphoneChatRoom *cr, LinphoneChatMessage* msg,LinphoneChatMessageStateChangeCb status_cb, void* ud) {
|
||||
void linphone_chat_room_send_message2(LinphoneChatRoom *cr, LinphoneChatMessage* msg,LinphoneChatMessageStateChangedCb status_cb, void* ud) {
|
||||
msg->cb=status_cb;
|
||||
msg->cb_ud=ud;
|
||||
msg->state=LinphoneChatMessageStateInProgress;
|
||||
|
|
@ -261,7 +327,7 @@ const char* linphone_chat_message_state_to_string(const LinphoneChatMessageState
|
|||
case LinphoneChatMessageStateIdle:return "LinphoneChatMessageStateIdle";
|
||||
case LinphoneChatMessageStateInProgress:return "LinphoneChatMessageStateInProgress";
|
||||
case LinphoneChatMessageStateDelivered:return "LinphoneChatMessageStateDelivered";
|
||||
case LinphoneChatMessageStateNotDelivered:return "LinphoneChatMessageStateNotDelivered";
|
||||
case LinphoneChatMessageStateNotDelivered:return "LinphoneChatMessageStateNotDelivered";
|
||||
default: return "Unknown state";
|
||||
}
|
||||
|
||||
|
|
@ -336,6 +402,16 @@ const LinphoneAddress* linphone_chat_message_get_from(const LinphoneChatMessage*
|
|||
return message->from;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set destination of the message
|
||||
*@param message #LinphoneChatMessage obj
|
||||
*@param to #LinphoneAddress destination of this message (copied)
|
||||
*/
|
||||
void linphone_chat_message_set_to(LinphoneChatMessage* message, const LinphoneAddress* to) {
|
||||
if(message->to) linphone_address_destroy(message->to);
|
||||
message->to=linphone_address_clone(to);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get destination of the message
|
||||
*@param message #LinphoneChatMessage obj
|
||||
|
|
@ -401,6 +477,31 @@ const char * linphone_chat_message_get_custom_header(LinphoneChatMessage* messag
|
|||
return sal_custom_header_find(message->custom_headers,header_name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns TRUE if the message has been read, otherwise returns FALSE.
|
||||
* @param message the message
|
||||
**/
|
||||
bool_t linphone_chat_message_is_read(LinphoneChatMessage* message) {
|
||||
return message->is_read;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns TRUE if the message has been sent, returns FALSE if the message has been received.
|
||||
* @param message the message
|
||||
**/
|
||||
bool_t linphone_chat_message_is_outgoing(LinphoneChatMessage* message) {
|
||||
return message->dir == LinphoneChatMessageOutgoing;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the id used to identify this message in the storage database
|
||||
* @param message the message
|
||||
* @return the id
|
||||
*/
|
||||
unsigned int linphone_chat_message_get_storage_id(LinphoneChatMessage* message) {
|
||||
return message->storage_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Duplicate a LinphoneChatMessage
|
||||
**/
|
||||
|
|
@ -425,6 +526,7 @@ LinphoneChatMessage* linphone_chat_message_clone(const LinphoneChatMessage* msg)
|
|||
new_message->cb=msg->cb;
|
||||
new_message->time=msg->time;
|
||||
new_message->state=msg->state;
|
||||
new_message->storage_id=msg->storage_id;
|
||||
if (msg->from) new_message->from=linphone_address_clone(msg->from);
|
||||
return new_message;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -218,6 +218,7 @@ int linphone_core_add_to_conference(LinphoneCore *lc, LinphoneCall *call){
|
|||
|
||||
static int remove_from_conference(LinphoneCore *lc, LinphoneCall *call, bool_t active){
|
||||
int err=0;
|
||||
char *str;
|
||||
|
||||
if (!call->current_params.in_conference){
|
||||
if (call->params.in_conference){
|
||||
|
|
@ -230,7 +231,7 @@ static int remove_from_conference(LinphoneCore *lc, LinphoneCall *call, bool_t a
|
|||
}
|
||||
call->params.in_conference=FALSE;
|
||||
|
||||
char *str=linphone_call_get_remote_address_as_string(call);
|
||||
str=linphone_call_get_remote_address_as_string(call);
|
||||
ms_message("%s will be removed from conference", str);
|
||||
ms_free(str);
|
||||
if (active){
|
||||
|
|
@ -289,10 +290,11 @@ static int convert_conference_to_call(LinphoneCore *lc){
|
|||
* @returns 0 if successful, -1 otherwise.
|
||||
**/
|
||||
int linphone_core_remove_from_conference(LinphoneCore *lc, LinphoneCall *call){
|
||||
int err;
|
||||
char * str=linphone_call_get_remote_address_as_string(call);
|
||||
ms_message("Removing call %s from the conference", str);
|
||||
ms_free(str);
|
||||
int err=remove_from_conference(lc,call, FALSE);
|
||||
err=remove_from_conference(lc,call, FALSE);
|
||||
if (err){
|
||||
ms_error("Error removing participant from conference.");
|
||||
return err;
|
||||
|
|
@ -341,13 +343,14 @@ int linphone_core_leave_conference(LinphoneCore *lc){
|
|||
* @returns 0 if successful, -1 otherwise
|
||||
**/
|
||||
int linphone_core_enter_conference(LinphoneCore *lc){
|
||||
LinphoneConference *conf;
|
||||
if (linphone_core_sound_resources_locked(lc)) {
|
||||
return -1;
|
||||
}
|
||||
if (lc->current_call != NULL) {
|
||||
_linphone_core_pause_call(lc, lc->current_call);
|
||||
}
|
||||
LinphoneConference *conf=&lc->conf_ctx;
|
||||
conf=&lc->conf_ctx;
|
||||
if (conf->local_participant==NULL) add_local_endpoint(conf,lc);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -265,11 +265,13 @@ void ec_calibrator_destroy(EcCalibrator *ecc){
|
|||
|
||||
int linphone_core_start_echo_calibration(LinphoneCore *lc, LinphoneEcCalibrationCallback cb,
|
||||
LinphoneEcCalibrationAudioInit audio_init_cb, LinphoneEcCalibrationAudioUninit audio_uninit_cb, void *cb_data){
|
||||
unsigned int rate;
|
||||
|
||||
if (lc->ecc!=NULL){
|
||||
ms_error("Echo calibration is still on going !");
|
||||
return -1;
|
||||
}
|
||||
unsigned int rate = lp_config_get_int(lc->config,"sound","echo_cancellation_rate",8000);
|
||||
rate = lp_config_get_int(lc->config,"sound","echo_cancellation_rate",8000);
|
||||
lc->ecc=ec_calibrator_new(lc->sound_conf.play_sndcard,lc->sound_conf.capt_sndcard,rate,cb,audio_init_cb,audio_uninit_cb,cb_data);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
282
coreapi/event.c
Normal file
|
|
@ -0,0 +1,282 @@
|
|||
/*
|
||||
linphone
|
||||
Copyright (C) 2000 - 2010 Simon MORLAT (simon.morlat@linphone.org)
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "private.h"
|
||||
#include "lpconfig.h"
|
||||
|
||||
|
||||
LinphoneSubscriptionState linphone_subscription_state_from_sal(SalSubscribeStatus ss){
|
||||
switch(ss){
|
||||
case SalSubscribeNone: return LinphoneSubscriptionNone;
|
||||
case SalSubscribePending: return LinphoneSubscriptionPending;
|
||||
case SalSubscribeTerminated: return LinphoneSubscriptionTerminated;
|
||||
case SalSubscribeActive: return LinphoneSubscriptionActive;
|
||||
}
|
||||
return LinphoneSubscriptionNone;
|
||||
}
|
||||
|
||||
const char *linphone_subscription_state_to_string(LinphoneSubscriptionState state){
|
||||
switch(state){
|
||||
case LinphoneSubscriptionNone: return "LinphoneSubscriptionNone";
|
||||
case LinphoneSubscriptionIncomingReceived: return "LinphoneSubscriptionIncomingReceived";
|
||||
case LinphoneSubscriptionOutoingInit: return "LinphoneSubscriptionOutoingInit";
|
||||
case LinphoneSubscriptionPending: return "LinphoneSubscriptionPending";
|
||||
case LinphoneSubscriptionActive: return "LinphoneSubscriptionActive";
|
||||
case LinphoneSubscriptionTerminated: return "LinphoneSubscriptionTerminated";
|
||||
case LinphoneSubscriptionError: return "LinphoneSubscriptionError";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LINPHONE_PUBLIC const char *linphone_publish_state_to_string(LinphonePublishState state){
|
||||
switch(state){
|
||||
case LinphonePublishNone: return "LinphonePublishNone";
|
||||
case LinphonePublishProgress: return "LinphonePublishProgress";
|
||||
case LinphonePublishOk: return "LinphonePublishOk";
|
||||
case LinphonePublishError: return "LinphonePublishError";
|
||||
case LinphonePublishCleared: return "LinphonePublishCleared";
|
||||
case LinphonePublishExpiring: return "LinphonePublishExpiring";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static LinphoneEvent * linphone_event_new_base(LinphoneCore *lc, LinphoneSubscriptionDir dir, const char *name, SalOp *op){
|
||||
LinphoneEvent *lev=ms_new0(LinphoneEvent,1);
|
||||
lev->lc=lc;
|
||||
lev->dir=dir;
|
||||
lev->op=op;
|
||||
lev->refcnt=1;
|
||||
lev->name=ms_strdup(name);
|
||||
sal_op_set_user_pointer(lev->op,lev);
|
||||
return lev;
|
||||
}
|
||||
|
||||
LinphoneEvent *linphone_event_new(LinphoneCore *lc, LinphoneSubscriptionDir dir, const char *name){
|
||||
LinphoneEvent *lev=linphone_event_new_base(lc, dir, name, sal_op_new(lc->sal));
|
||||
return lev;
|
||||
}
|
||||
|
||||
LinphoneEvent *linphone_event_new_with_op(LinphoneCore *lc, SalOp *op, LinphoneSubscriptionDir dir, const char *name){
|
||||
LinphoneEvent *lev=linphone_event_new_base(lc, dir, name, op);
|
||||
if (dir==LinphoneSubscriptionIncoming){
|
||||
lev->resource_addr=linphone_address_clone((LinphoneAddress*)sal_op_get_to_address(op));
|
||||
lev->from=linphone_address_clone((LinphoneAddress*)sal_op_get_from_address(lev->op));
|
||||
}else{
|
||||
lev->resource_addr=linphone_address_clone((LinphoneAddress*)sal_op_get_from_address(op));
|
||||
}
|
||||
return lev;
|
||||
}
|
||||
|
||||
void linphone_event_set_state(LinphoneEvent *lev, LinphoneSubscriptionState state){
|
||||
LinphoneCore *lc=lev->lc;
|
||||
if (lev->subscription_state!=state){
|
||||
ms_message("LinphoneEvent [%p] moving to subscription state %s",lev,linphone_subscription_state_to_string(state));
|
||||
lev->subscription_state=state;
|
||||
if (lc->vtable.subscription_state_changed){
|
||||
lc->vtable.subscription_state_changed(lev->lc,lev,state);
|
||||
}
|
||||
if (state==LinphoneSubscriptionTerminated){
|
||||
linphone_event_unref(lev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void linphone_event_set_publish_state(LinphoneEvent *lev, LinphonePublishState state){
|
||||
LinphoneCore *lc=lev->lc;
|
||||
if (lev->publish_state!=state){
|
||||
ms_message("LinphoneEvent [%p] moving to publish state %s",lev,linphone_publish_state_to_string(state));
|
||||
lev->publish_state=state;
|
||||
if (lc->vtable.publish_state_changed){
|
||||
lc->vtable.publish_state_changed(lev->lc,lev,state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LinphonePublishState linphone_event_get_publish_state(const LinphoneEvent *lev){
|
||||
return lev->publish_state;
|
||||
}
|
||||
|
||||
void linphone_event_set_reason(LinphoneEvent *lev, LinphoneReason reason){
|
||||
lev->reason=reason;
|
||||
}
|
||||
|
||||
LinphoneReason linphone_event_get_reason(const LinphoneEvent *lev){
|
||||
return lev->reason;
|
||||
}
|
||||
|
||||
LinphoneEvent *linphone_core_subscribe(LinphoneCore *lc, const LinphoneAddress *resource, const char *event, int expires, const LinphoneContent *body){
|
||||
LinphoneEvent *lev=linphone_event_new(lc, LinphoneSubscriptionOutgoing, event);
|
||||
SalBody salbody;
|
||||
linphone_configure_op(lc,lev->op,resource,NULL,TRUE);
|
||||
lev->resource_addr=linphone_address_clone(resource);
|
||||
lev->from=linphone_address_clone((LinphoneAddress*)sal_op_get_from_address(lev->op));
|
||||
sal_subscribe(lev->op,NULL,NULL,event,expires,sal_body_from_content(&salbody,body));
|
||||
linphone_event_set_state(lev,LinphoneSubscriptionOutoingInit);
|
||||
return lev;
|
||||
}
|
||||
|
||||
|
||||
int linphone_event_update_subscribe(LinphoneEvent *lev, const LinphoneContent *body){
|
||||
SalBody salbody;
|
||||
if (lev->subscription_state!=LinphoneSubscriptionActive){
|
||||
ms_error("linphone_event_update_subscribe(): cannot update subscription if subscription wasn't accepted.");
|
||||
return -1;
|
||||
}
|
||||
if (lev->dir!=LinphoneSubscriptionOutgoing){
|
||||
ms_error("linphone_event_deny_subscription(): cannot update an incoming subscription.");
|
||||
return -1;
|
||||
}
|
||||
return sal_subscribe(lev->op,NULL,NULL,NULL,-1,sal_body_from_content(&salbody,body));
|
||||
}
|
||||
|
||||
int linphone_event_accept_subscription(LinphoneEvent *lev){
|
||||
int err;
|
||||
if (lev->subscription_state!=LinphoneSubscriptionIncomingReceived){
|
||||
ms_error("linphone_event_accept_subscription(): cannot accept subscription if subscription wasn't just received.");
|
||||
return -1;
|
||||
}
|
||||
err=sal_subscribe_accept(lev->op);
|
||||
if (err==0){
|
||||
linphone_event_set_state(lev,LinphoneSubscriptionActive);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int linphone_event_deny_subscription(LinphoneEvent *lev, LinphoneReason reason){
|
||||
int err;
|
||||
if (lev->subscription_state!=LinphoneSubscriptionIncomingReceived){
|
||||
ms_error("linphone_event_deny_subscription(): cannot deny subscription if subscription wasn't just received.");
|
||||
return -1;
|
||||
}
|
||||
err=sal_subscribe_decline(lev->op,linphone_reason_to_sal(reason));
|
||||
linphone_event_set_state(lev,LinphoneSubscriptionTerminated);
|
||||
return err;
|
||||
}
|
||||
|
||||
int linphone_event_notify(LinphoneEvent *lev, const LinphoneContent *body){
|
||||
SalBody salbody;
|
||||
if (lev->subscription_state!=LinphoneSubscriptionActive){
|
||||
ms_error("linphone_event_notify(): cannot notify if subscription is not active.");
|
||||
return -1;
|
||||
}
|
||||
if (lev->dir!=LinphoneSubscriptionIncoming){
|
||||
ms_error("linphone_event_notify(): cannot notify if not an incoming subscription.");
|
||||
return -1;
|
||||
}
|
||||
return sal_notify(lev->op,sal_body_from_content(&salbody,body));
|
||||
}
|
||||
|
||||
LinphoneEvent *linphone_core_publish(LinphoneCore *lc, const LinphoneAddress *resource, const char *event, int expires, const LinphoneContent *body){
|
||||
SalBody salbody;
|
||||
int err;
|
||||
LinphoneEvent *lev=linphone_event_new(lc,LinphoneSubscriptionInvalidDir, event);
|
||||
linphone_configure_op(lc,lev->op,resource,NULL,lp_config_get_int(lc->config,"sip","publish_msg_with_contact",0));
|
||||
sal_op_set_manual_refresher_mode(lev->op,lp_config_get_int(lc->config,"sip","refresh_generic_publish",1));
|
||||
err=sal_publish(lev->op,NULL,NULL,event,expires,sal_body_from_content(&salbody,body));
|
||||
if (err==0){
|
||||
linphone_event_set_publish_state(lev,LinphonePublishProgress);
|
||||
}else{
|
||||
linphone_event_unref(lev);
|
||||
lev=NULL;
|
||||
}
|
||||
return lev;
|
||||
}
|
||||
|
||||
int linphone_event_update_publish(LinphoneEvent *lev, const LinphoneContent *body){
|
||||
SalBody salbody;
|
||||
int err;
|
||||
err=sal_publish(lev->op,NULL,NULL,NULL,-1,sal_body_from_content(&salbody,body));
|
||||
if (err==0){
|
||||
linphone_event_set_publish_state(lev,LinphonePublishProgress);
|
||||
}else{
|
||||
linphone_event_set_publish_state(lev,LinphonePublishError);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
void linphone_event_set_user_data(LinphoneEvent *ev, void *up){
|
||||
ev->userdata=up;
|
||||
}
|
||||
|
||||
void *linphone_event_get_user_data(const LinphoneEvent *ev){
|
||||
return ev->userdata;
|
||||
}
|
||||
|
||||
void linphone_event_terminate(LinphoneEvent *lev){
|
||||
lev->terminating=TRUE;
|
||||
if (lev->dir==LinphoneSubscriptionIncoming){
|
||||
sal_notify_close(lev->op);
|
||||
}else if (lev->dir==LinphoneSubscriptionOutgoing){
|
||||
sal_unsubscribe(lev->op);
|
||||
}
|
||||
|
||||
if (lev->publish_state!=LinphonePublishNone){
|
||||
if (lev->publish_state==LinphonePublishOk){
|
||||
sal_publish(lev->op,NULL,NULL,NULL,0,NULL);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (lev->subscription_state!=LinphoneSubscriptionNone){
|
||||
linphone_event_set_state(lev,LinphoneSubscriptionTerminated);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
LinphoneEvent *linphone_event_ref(LinphoneEvent *lev){
|
||||
lev->refcnt++;
|
||||
return lev;
|
||||
}
|
||||
|
||||
static void linphone_event_destroy(LinphoneEvent *lev){
|
||||
if (lev->op)
|
||||
sal_op_release(lev->op);
|
||||
ms_free(lev->name);
|
||||
if (lev->resource_addr) linphone_address_destroy(lev->resource_addr);
|
||||
if (lev->from) linphone_address_destroy(lev->from);
|
||||
ms_free(lev);
|
||||
}
|
||||
|
||||
void linphone_event_unref(LinphoneEvent *lev){
|
||||
lev->refcnt--;
|
||||
if (lev->refcnt==0) linphone_event_destroy(lev);
|
||||
}
|
||||
|
||||
LinphoneSubscriptionDir linphone_event_get_subscription_dir(LinphoneEvent *lev){
|
||||
return lev->dir;
|
||||
}
|
||||
|
||||
LinphoneSubscriptionState linphone_event_get_subscription_state(const LinphoneEvent *lev){
|
||||
return lev->subscription_state;
|
||||
}
|
||||
|
||||
const char *linphone_event_get_name(const LinphoneEvent *lev){
|
||||
return lev->name;
|
||||
}
|
||||
|
||||
const LinphoneAddress *linphone_event_get_from(const LinphoneEvent *lev){
|
||||
return lev->from;
|
||||
}
|
||||
|
||||
const LinphoneAddress *linphone_event_get_resource(const LinphoneEvent *lev){
|
||||
return lev->resource_addr;
|
||||
}
|
||||
|
||||
237
coreapi/event.h
Normal file
|
|
@ -0,0 +1,237 @@
|
|||
/*
|
||||
linphone
|
||||
Copyright (C) 2000 - 2010 Simon MORLAT (simon.morlat@linphone.org)
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#ifndef LINPHONEEVENT_H
|
||||
#define LINPHONEEVENT_H
|
||||
|
||||
/**
|
||||
* @addtogroup subscriptions
|
||||
* @{
|
||||
**/
|
||||
|
||||
struct _LinphoneEvent;
|
||||
|
||||
/**
|
||||
* Object representing an event state, which is subcribed or published.
|
||||
* @see linphone_core_publish()
|
||||
* @see linphone_core_subscribe()
|
||||
**/
|
||||
typedef struct _LinphoneEvent LinphoneEvent;
|
||||
|
||||
/**
|
||||
* Enum for subscription direction (incoming or outgoing).
|
||||
**/
|
||||
enum _LinphoneSubscriptionDir{
|
||||
LinphoneSubscriptionIncoming,
|
||||
LinphoneSubscriptionOutgoing,
|
||||
LinphoneSubscriptionInvalidDir
|
||||
};
|
||||
|
||||
/**
|
||||
* Typedef alias for _LinphoneSubscriptionDir
|
||||
**/
|
||||
typedef enum _LinphoneSubscriptionDir LinphoneSubscriptionDir;
|
||||
|
||||
/**
|
||||
* Enum for subscription states.
|
||||
**/
|
||||
enum _LinphoneSubscriptionState{
|
||||
LinphoneSubscriptionNone, /**< Initial state, should not be used.**/
|
||||
LinphoneSubscriptionOutoingInit, /**<An outgoing subcription was created*/
|
||||
LinphoneSubscriptionIncomingReceived, /**<An incoming subcription is received*/
|
||||
LinphoneSubscriptionPending, /**<Subscription is pending, waiting for user approval*/
|
||||
LinphoneSubscriptionActive, /**<Subscription is accepted.*/
|
||||
LinphoneSubscriptionTerminated, /**<Subscription is terminated normally*/
|
||||
LinphoneSubscriptionError /**<Subscription encountered an error, indicated by linphone_event_get_reason()*/
|
||||
};
|
||||
|
||||
/**
|
||||
* Typedef for subscription state enum.
|
||||
**/
|
||||
typedef enum _LinphoneSubscriptionState LinphoneSubscriptionState;
|
||||
|
||||
LINPHONE_PUBLIC const char *linphone_subscription_state_to_string(LinphoneSubscriptionState state);
|
||||
|
||||
/**
|
||||
* Enum for publish states.
|
||||
**/
|
||||
enum _LinphonePublishState{
|
||||
LinphonePublishNone, /**< Initial state, do not use**/
|
||||
LinphonePublishProgress, /**<An outgoing subcription was created*/
|
||||
LinphonePublishOk, /**<Publish is accepted.*/
|
||||
LinphonePublishError, /**<Publish encoutered an error, linphone_event_get_reason() gives reason code*/
|
||||
LinphonePublishExpiring, /**<Publish is about to expire, only sent if [sip]->refresh_generic_publish property is set to 0.*/
|
||||
LinphonePublishCleared /**<Event has been un published*/
|
||||
};
|
||||
|
||||
/**
|
||||
* Typedef for publish state enum
|
||||
**/
|
||||
typedef enum _LinphonePublishState LinphonePublishState;
|
||||
|
||||
LINPHONE_PUBLIC const char *linphone_publish_state_to_string(LinphonePublishState state);
|
||||
|
||||
/**
|
||||
* Callback prototype for notifying the application about notification received from the network.
|
||||
**/
|
||||
typedef void (*LinphoneCoreNotifyReceivedCb)(LinphoneCore *lc, LinphoneEvent *lev, const char *notified_event, const LinphoneContent *body);
|
||||
|
||||
/**
|
||||
* Callback prototype for notifying the application about changes of subscription states, including arrival of new subscriptions.
|
||||
**/
|
||||
typedef void (*LinphoneCoreSubscriptionStateChangedCb)(LinphoneCore *lc, LinphoneEvent *lev, LinphoneSubscriptionState state);
|
||||
|
||||
/**
|
||||
* Callback prototype for notifying the application about changes of publish states.
|
||||
**/
|
||||
typedef void (*LinphoneCorePublishStateChangedCb)(LinphoneCore *lc, LinphoneEvent *lev, LinphonePublishState state);
|
||||
|
||||
/**
|
||||
* Create an outgoing subscription, specifying the destination resource, the event name, and an optional content body.
|
||||
* If accepted, the subscription runs for a finite period, but is automatically renewed if not terminated before.
|
||||
* @param lc the #LinphoneCore
|
||||
* @param resource the destination resource
|
||||
* @param event the event name
|
||||
* @param expires the whished duration of the subscription
|
||||
* @param body an optional body, may be NULL.
|
||||
* @return a LinphoneEvent holding the context of the created subcription.
|
||||
**/
|
||||
LINPHONE_PUBLIC LinphoneEvent *linphone_core_subscribe(LinphoneCore *lc, const LinphoneAddress *resource, const char *event, int expires, const LinphoneContent *body);
|
||||
|
||||
/**
|
||||
* Update an outgoing subscription.
|
||||
* @param lev a LinphoneEvent
|
||||
* @param body an optional body to include in the subscription update, may be NULL.
|
||||
**/
|
||||
LINPHONE_PUBLIC int linphone_event_update_subscribe(LinphoneEvent *lev, const LinphoneContent *body);
|
||||
|
||||
|
||||
/**
|
||||
* Accept an incoming subcription.
|
||||
**/
|
||||
LINPHONE_PUBLIC int linphone_event_accept_subscription(LinphoneEvent *lev);
|
||||
/**
|
||||
* Deny an incoming subscription with given reason.
|
||||
**/
|
||||
LINPHONE_PUBLIC int linphone_event_deny_subscription(LinphoneEvent *lev, LinphoneReason reason);
|
||||
/**
|
||||
* Send a notification.
|
||||
* @param lev a #LinphoneEvent corresponding to an incoming subscription previously received and accepted.
|
||||
* @param body an optional body containing the actual notification data.
|
||||
* @return 0 if successful, -1 otherwise.
|
||||
**/
|
||||
LINPHONE_PUBLIC int linphone_event_notify(LinphoneEvent *lev, const LinphoneContent *body);
|
||||
|
||||
|
||||
/**
|
||||
* Publish an event state.
|
||||
* After expiry, the publication is refreshed unless it is terminated before.
|
||||
* @param lc the #LinphoneCore
|
||||
* @param resource the resource uri for the event
|
||||
* @param event the event name
|
||||
* @param expires the lifetime of the publication
|
||||
* @param body the actual published data
|
||||
* @return the LinphoneEvent holding the context of the publish.
|
||||
**/
|
||||
LINPHONE_PUBLIC LinphoneEvent *linphone_core_publish(LinphoneCore *lc, const LinphoneAddress *resource, const char *event, int expires, const LinphoneContent *body);
|
||||
|
||||
/**
|
||||
* Update a publication.
|
||||
* @param lev the #LinphoneEvent
|
||||
* @param body the new data to be published
|
||||
**/
|
||||
LINPHONE_PUBLIC int linphone_event_update_publish(LinphoneEvent *lev, const LinphoneContent *body);
|
||||
|
||||
|
||||
/**
|
||||
* Return reason code (in case of error state reached).
|
||||
**/
|
||||
LINPHONE_PUBLIC LinphoneReason linphone_event_get_reason(const LinphoneEvent *lev);
|
||||
|
||||
/**
|
||||
* Get subscription state. If the event object was not created by a subscription mechanism, #LinphoneSubscriptionNone is returned.
|
||||
**/
|
||||
LINPHONE_PUBLIC LinphoneSubscriptionState linphone_event_get_subscription_state(const LinphoneEvent *lev);
|
||||
|
||||
/**
|
||||
* Get publish state. If the event object was not created by a publish mechanism, #LinphonePublishNone is returned.
|
||||
**/
|
||||
LINPHONE_PUBLIC LinphonePublishState linphone_event_get_publish_state(const LinphoneEvent *lev);
|
||||
|
||||
/**
|
||||
* Get subscription direction.
|
||||
* If the object wasn't created by a subscription mechanism, #LinphoneSubscriptionInvalidDir is returned.
|
||||
**/
|
||||
LINPHONE_PUBLIC LinphoneSubscriptionDir linphone_event_get_subscription_dir(LinphoneEvent *lev);
|
||||
|
||||
/**
|
||||
* Set a user (application) pointer.
|
||||
**/
|
||||
LINPHONE_PUBLIC void linphone_event_set_user_data(LinphoneEvent *ev, void *up);
|
||||
|
||||
/**
|
||||
* Retrieve user pointer.
|
||||
**/
|
||||
LINPHONE_PUBLIC void *linphone_event_get_user_data(const LinphoneEvent *ev);
|
||||
|
||||
/**
|
||||
* Terminate an incoming or outgoing subscription that was previously acccepted, or a previous publication.
|
||||
* This function does not unref the object. The core will unref() if it does not need this object anymore.
|
||||
*
|
||||
* For subscribed event, when the subscription is terminated normally or because of an error, the core will unref.
|
||||
* For published events, no unref is performed. This is because it is allowed to re-publish an expired publish, as well as retry it in case of error.
|
||||
**/
|
||||
LINPHONE_PUBLIC void linphone_event_terminate(LinphoneEvent *lev);
|
||||
|
||||
|
||||
/**
|
||||
* Increase reference count of LinphoneEvent.
|
||||
* By default LinphoneEvents created by the core are owned by the core only.
|
||||
* An application that wishes to retain a reference to it must call linphone_event_ref().
|
||||
* When this reference is no longer needed, linphone_event_unref() must be called.
|
||||
*
|
||||
**/
|
||||
LINPHONE_PUBLIC LinphoneEvent *linphone_event_ref(LinphoneEvent *lev);
|
||||
|
||||
/**
|
||||
* Decrease reference count.
|
||||
* @see linphone_event_ref()
|
||||
**/
|
||||
LINPHONE_PUBLIC void linphone_event_unref(LinphoneEvent *lev);
|
||||
|
||||
/**
|
||||
* Get the name of the event as specified in the event package RFC.
|
||||
**/
|
||||
LINPHONE_PUBLIC const char *linphone_event_get_name(const LinphoneEvent *lev);
|
||||
|
||||
/**
|
||||
* Get the "from" address of the subscription.
|
||||
**/
|
||||
LINPHONE_PUBLIC const LinphoneAddress *linphone_event_get_from(const LinphoneEvent *lev);
|
||||
|
||||
/**
|
||||
* Get the resource address of the subscription or publish.
|
||||
**/
|
||||
LINPHONE_PUBLIC const LinphoneAddress *linphone_event_get_resource(const LinphoneEvent *lev);
|
||||
|
||||
/**
|
||||
* @}
|
||||
**/
|
||||
|
||||
|
||||
#endif
|
||||
320
coreapi/friend.c
|
|
@ -62,6 +62,8 @@ const char *linphone_online_status_to_string(LinphoneOnlineStatus ss){
|
|||
case LinphoneStatusPending:
|
||||
str=_("Pending");
|
||||
break;
|
||||
case LinphoneStatusVacation:
|
||||
str=_("Vacation");
|
||||
default:
|
||||
str=_("Unknown-bug");
|
||||
}
|
||||
|
|
@ -71,16 +73,16 @@ const char *linphone_online_status_to_string(LinphoneOnlineStatus ss){
|
|||
static int friend_compare(const void * a, const void * b){
|
||||
LinphoneAddress *fa=((LinphoneFriend*)a)->uri;
|
||||
LinphoneAddress *fb=((LinphoneFriend*)b)->uri;
|
||||
if (linphone_address_weak_equal (fa,fb)) return 0;
|
||||
if (linphone_address_weak_equal(fa,fb)) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
MSList *linphone_find_friend(MSList *fl, const LinphoneAddress *friend, LinphoneFriend **lf){
|
||||
MSList *linphone_find_friend_by_address(MSList *fl, const LinphoneAddress *addr, LinphoneFriend **lf){
|
||||
MSList *res=NULL;
|
||||
LinphoneFriend dummy;
|
||||
if (lf!=NULL) *lf=NULL;
|
||||
dummy.uri=(LinphoneAddress*)friend;
|
||||
dummy.uri=(LinphoneAddress*)addr;
|
||||
res=ms_list_find_custom(fl,friend_compare,&dummy);
|
||||
if (lf!=NULL && res!=NULL) *lf=(LinphoneFriend*)res->data;
|
||||
return res;
|
||||
|
|
@ -97,35 +99,20 @@ LinphoneFriend *linphone_find_friend_by_inc_subscribe(MSList *l, SalOp *op){
|
|||
|
||||
LinphoneFriend *linphone_find_friend_by_out_subscribe(MSList *l, SalOp *op){
|
||||
MSList *elem;
|
||||
LinphoneFriend *lf;
|
||||
for (elem=l;elem!=NULL;elem=elem->next){
|
||||
LinphoneFriend *lf=(LinphoneFriend*)elem->data;
|
||||
lf=(LinphoneFriend*)elem->data;
|
||||
if (lf->outsub==op) return lf;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void __linphone_friend_do_subscribe(LinphoneFriend *fr){
|
||||
char *friend=NULL;
|
||||
const char *route=NULL;
|
||||
const char *from=NULL;
|
||||
const char *fixed_contact=NULL;
|
||||
LinphoneProxyConfig *cfg;
|
||||
LinphoneCore *lc=fr->lc;
|
||||
|
||||
friend=linphone_address_as_string(fr->uri);
|
||||
cfg=linphone_core_lookup_known_proxy(fr->lc,linphone_friend_get_address(fr));
|
||||
if (cfg!=NULL){
|
||||
route=linphone_proxy_config_get_route(cfg);
|
||||
from=linphone_proxy_config_get_identity(cfg);
|
||||
if (cfg->op){
|
||||
fixed_contact=sal_op_get_contact(cfg->op);
|
||||
if (fixed_contact) {
|
||||
ms_message("Contact for subscribe has been fixed using proxy to %s",fixed_contact);
|
||||
}
|
||||
}
|
||||
}else from=linphone_core_get_primary_contact(fr->lc);
|
||||
if (fr->outsub==NULL){
|
||||
/* people for which we don't have yet an answer should appear as offline */
|
||||
fr->status=LinphoneStatusOffline;
|
||||
fr->presence=NULL;
|
||||
/*
|
||||
if (fr->lc->vtable.notify_recv)
|
||||
fr->lc->vtable.notify_recv(fr->lc,(LinphoneFriend*)fr);
|
||||
|
|
@ -134,36 +121,42 @@ void __linphone_friend_do_subscribe(LinphoneFriend *fr){
|
|||
sal_op_release(fr->outsub);
|
||||
fr->outsub=NULL;
|
||||
}
|
||||
fr->outsub=sal_op_new(fr->lc->sal);
|
||||
sal_op_set_route(fr->outsub,route);
|
||||
sal_op_set_contact(fr->outsub,fixed_contact);
|
||||
sal_subscribe_presence(fr->outsub,from,friend);
|
||||
fr->outsub=sal_op_new(lc->sal);
|
||||
linphone_configure_op(lc,fr->outsub,fr->uri,NULL,TRUE);
|
||||
sal_subscribe_presence(fr->outsub,NULL,NULL,lp_config_get_int(lc->config,"sip","subscribe_expires",600));
|
||||
fr->subscribe_active=TRUE;
|
||||
ms_free(friend);
|
||||
}
|
||||
|
||||
LinphoneFriend * linphone_friend_new(){
|
||||
LinphoneFriend *obj=ms_new0(LinphoneFriend,1);
|
||||
obj->pol=LinphoneSPAccept;
|
||||
obj->status=LinphoneStatusOffline;
|
||||
obj->presence=NULL;
|
||||
obj->subscribe=TRUE;
|
||||
return obj;
|
||||
}
|
||||
|
||||
LinphoneFriend *linphone_friend_new_with_addr(const char *addr){
|
||||
LinphoneFriend *linphone_friend_new_with_address(const char *addr){
|
||||
LinphoneAddress* linphone_address = linphone_address_new(addr);
|
||||
LinphoneFriend *fr;
|
||||
|
||||
if (linphone_address == NULL) {
|
||||
ms_error("Cannot create friend for address [%s]",addr?addr:"null");
|
||||
return NULL;
|
||||
}
|
||||
LinphoneFriend *fr=linphone_friend_new();
|
||||
if (linphone_friend_set_addr(fr,linphone_address)<0){
|
||||
linphone_friend_destroy(fr);
|
||||
return NULL;
|
||||
}
|
||||
fr=linphone_friend_new();
|
||||
linphone_friend_set_address(fr,linphone_address);
|
||||
linphone_address_destroy(linphone_address);
|
||||
return fr;
|
||||
}
|
||||
|
||||
void linphone_friend_set_user_data(LinphoneFriend *lf, void *data){
|
||||
lf->up=data;
|
||||
}
|
||||
|
||||
void* linphone_friend_get_user_data(const LinphoneFriend *lf){
|
||||
return lf->up;
|
||||
}
|
||||
|
||||
bool_t linphone_friend_in_list(const LinphoneFriend *lf){
|
||||
return lf->lc!=NULL;
|
||||
}
|
||||
|
|
@ -185,7 +178,7 @@ void linphone_core_interpret_friend_uri(LinphoneCore *lc, const char *uri, char
|
|||
}else if (lc->default_proxy!=NULL){
|
||||
/*try adding domain part from default current proxy*/
|
||||
LinphoneAddress * id=linphone_address_new(linphone_core_get_identity(lc));
|
||||
if (id!=NULL){
|
||||
if ((id!=NULL) && (uri[0] != '\0')){
|
||||
linphone_address_set_display_name(id,NULL);
|
||||
linphone_address_set_username(id,uri);
|
||||
*result=linphone_address_as_string(id);
|
||||
|
|
@ -198,14 +191,16 @@ void linphone_core_interpret_friend_uri(LinphoneCore *lc, const char *uri, char
|
|||
}else{
|
||||
ms_warning("Fail to interpret friend uri %s",uri);
|
||||
}
|
||||
}else *result=linphone_address_as_string(fr);
|
||||
linphone_address_destroy(fr);
|
||||
}else {
|
||||
*result=linphone_address_as_string(fr);
|
||||
linphone_address_destroy(fr);
|
||||
}
|
||||
}
|
||||
|
||||
int linphone_friend_set_addr(LinphoneFriend *lf, const LinphoneAddress *addr){
|
||||
int linphone_friend_set_address(LinphoneFriend *lf, const LinphoneAddress *addr){
|
||||
LinphoneAddress *fr=linphone_address_clone(addr);
|
||||
linphone_address_clean(fr);
|
||||
if (lf->uri!=NULL) linphone_address_destroy(lf->uri);
|
||||
if (lf->uri!=NULL) linphone_address_destroy(lf->uri);
|
||||
lf->uri=fr;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -231,54 +226,12 @@ int linphone_friend_set_inc_subscribe_policy(LinphoneFriend *fr, LinphoneSubscri
|
|||
return 0;
|
||||
}
|
||||
|
||||
SalPresenceStatus linphone_online_status_to_sal(LinphoneOnlineStatus os){
|
||||
switch(os){
|
||||
case LinphoneStatusOffline:
|
||||
return SalPresenceOffline;
|
||||
break;
|
||||
case LinphoneStatusOnline:
|
||||
return SalPresenceOnline;
|
||||
break;
|
||||
case LinphoneStatusBusy:
|
||||
return SalPresenceBusy;
|
||||
break;
|
||||
case LinphoneStatusBeRightBack:
|
||||
return SalPresenceBerightback;
|
||||
break;
|
||||
case LinphoneStatusAway:
|
||||
return SalPresenceAway;
|
||||
break;
|
||||
case LinphoneStatusOnThePhone:
|
||||
return SalPresenceOnthephone;
|
||||
break;
|
||||
case LinphoneStatusOutToLunch:
|
||||
return SalPresenceOuttolunch;
|
||||
break;
|
||||
case LinphoneStatusDoNotDisturb:
|
||||
return SalPresenceDonotdisturb;
|
||||
break;
|
||||
case LinphoneStatusMoved:
|
||||
return SalPresenceMoved;
|
||||
break;
|
||||
case LinphoneStatusAltService:
|
||||
return SalPresenceAltService;
|
||||
break;
|
||||
case LinphoneStatusPending:
|
||||
return SalPresenceOffline;
|
||||
break;
|
||||
default:
|
||||
return SalPresenceOffline;
|
||||
break;
|
||||
}
|
||||
return SalPresenceOffline;
|
||||
}
|
||||
|
||||
void linphone_friend_notify(LinphoneFriend *lf, LinphoneOnlineStatus os){
|
||||
void linphone_friend_notify(LinphoneFriend *lf, LinphonePresenceModel *presence){
|
||||
char *addr=linphone_address_as_string(linphone_friend_get_address(lf));
|
||||
ms_message("Want to notify %s, insub=%p",addr,lf->insub);
|
||||
ms_free(addr);
|
||||
if (lf->insub!=NULL){
|
||||
sal_notify_presence(lf->insub,linphone_online_status_to_sal(os),NULL);
|
||||
sal_notify_presence(lf->insub,(SalPresenceModel *)presence);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -289,10 +242,19 @@ static void linphone_friend_unsubscribe(LinphoneFriend *lf){
|
|||
}
|
||||
}
|
||||
|
||||
static void linphone_friend_invalidate_subscription(LinphoneFriend *lf){
|
||||
if (lf->outsub!=NULL) {
|
||||
sal_op_release(lf->outsub);
|
||||
lf->outsub=NULL;
|
||||
lf->subscribe_active=FALSE;
|
||||
}
|
||||
lf->initial_subscribes_sent=FALSE;
|
||||
}
|
||||
|
||||
void linphone_friend_close_subscriptions(LinphoneFriend *lf){
|
||||
linphone_friend_unsubscribe(lf);
|
||||
if (lf->insub){
|
||||
sal_notify_close(lf->insub);
|
||||
sal_notify_presence_close(lf->insub);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -306,6 +268,7 @@ void linphone_friend_destroy(LinphoneFriend *lf){
|
|||
sal_op_release(lf->outsub);
|
||||
lf->outsub=NULL;
|
||||
}
|
||||
if (lf->presence != NULL) linphone_presence_model_unref(lf->presence);
|
||||
if (lf->uri!=NULL) linphone_address_destroy(lf->uri);
|
||||
if (lf->info!=NULL) buddy_info_free(lf->info);
|
||||
ms_free(lf);
|
||||
|
|
@ -315,6 +278,12 @@ const LinphoneAddress *linphone_friend_get_address(const LinphoneFriend *lf){
|
|||
return lf->uri;
|
||||
}
|
||||
|
||||
const char * linphone_friend_get_name(const LinphoneFriend *lf) {
|
||||
LinphoneAddress *fr = lf->uri;
|
||||
if (fr == NULL) return NULL;
|
||||
return linphone_address_get_display_name(fr);
|
||||
}
|
||||
|
||||
bool_t linphone_friend_get_send_subscribe(const LinphoneFriend *lf){
|
||||
return lf->subscribe;
|
||||
}
|
||||
|
|
@ -324,7 +293,87 @@ LinphoneSubscribePolicy linphone_friend_get_inc_subscribe_policy(const LinphoneF
|
|||
}
|
||||
|
||||
LinphoneOnlineStatus linphone_friend_get_status(const LinphoneFriend *lf){
|
||||
return lf->status;
|
||||
LinphoneOnlineStatus online_status = LinphoneStatusOffline;
|
||||
LinphonePresenceBasicStatus basic_status = LinphonePresenceBasicStatusClosed;
|
||||
LinphonePresenceActivity *activity = NULL;
|
||||
unsigned int nb_activities = 0;
|
||||
|
||||
if (lf->presence != NULL) {
|
||||
basic_status = linphone_presence_model_get_basic_status(lf->presence);
|
||||
nb_activities = linphone_presence_model_get_nb_activities(lf->presence);
|
||||
online_status = (basic_status == LinphonePresenceBasicStatusOpen) ? LinphoneStatusOnline : LinphoneStatusOffline;
|
||||
if (nb_activities > 1) {
|
||||
char *tmp = NULL;
|
||||
const LinphoneAddress *addr = linphone_friend_get_address(lf);
|
||||
if (addr) tmp = linphone_address_as_string(addr);
|
||||
ms_warning("Friend %s has several activities, get status from the first one", tmp ? tmp : "unknown");
|
||||
if (tmp) ms_free(tmp);
|
||||
nb_activities = 1;
|
||||
}
|
||||
if (nb_activities == 1) {
|
||||
activity = linphone_presence_model_get_activity(lf->presence);
|
||||
switch (linphone_presence_activity_get_type(activity)) {
|
||||
case LinphonePresenceActivityBreakfast:
|
||||
case LinphonePresenceActivityDinner:
|
||||
case LinphonePresenceActivityLunch:
|
||||
case LinphonePresenceActivityMeal:
|
||||
online_status = LinphoneStatusOutToLunch;
|
||||
break;
|
||||
case LinphonePresenceActivityAppointment:
|
||||
case LinphonePresenceActivityMeeting:
|
||||
case LinphonePresenceActivityPerformance:
|
||||
case LinphonePresenceActivityPresentation:
|
||||
case LinphonePresenceActivitySpectator:
|
||||
case LinphonePresenceActivityWorking:
|
||||
case LinphonePresenceActivityWorship:
|
||||
online_status = LinphoneStatusDoNotDisturb;
|
||||
break;
|
||||
case LinphonePresenceActivityAway:
|
||||
case LinphonePresenceActivitySleeping:
|
||||
online_status = LinphoneStatusAway;
|
||||
break;
|
||||
case LinphonePresenceActivityHoliday:
|
||||
case LinphonePresenceActivityTravel:
|
||||
case LinphonePresenceActivityVacation:
|
||||
online_status = LinphoneStatusVacation;
|
||||
break;
|
||||
case LinphonePresenceActivityBusy:
|
||||
case LinphonePresenceActivityLookingForWork:
|
||||
case LinphonePresenceActivityPlaying:
|
||||
case LinphonePresenceActivityShopping:
|
||||
case LinphonePresenceActivityTV:
|
||||
online_status = LinphoneStatusBusy;
|
||||
break;
|
||||
case LinphonePresenceActivityInTransit:
|
||||
case LinphonePresenceActivitySteering:
|
||||
online_status = LinphoneStatusBeRightBack;
|
||||
break;
|
||||
case LinphonePresenceActivityOnThePhone:
|
||||
online_status = LinphoneStatusOnThePhone;
|
||||
break;
|
||||
case LinphonePresenceActivityOther:
|
||||
case LinphonePresenceActivityPermanentAbsence:
|
||||
online_status = LinphoneStatusMoved;
|
||||
break;
|
||||
case LinphonePresenceActivityUnknown:
|
||||
/* Rely on the basic status information. */
|
||||
break;
|
||||
case LinphonePresenceActivityOnline:
|
||||
/* Should not happen! */
|
||||
ms_warning("LinphonePresenceActivityOnline should not happen here!");
|
||||
break;
|
||||
case LinphonePresenceActivityOffline:
|
||||
online_status = LinphoneStatusOffline;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return online_status;
|
||||
}
|
||||
|
||||
const LinphonePresenceModel * linphone_friend_get_presence_model(LinphoneFriend *lf) {
|
||||
return lf->presence;
|
||||
}
|
||||
|
||||
BuddyInfo * linphone_friend_get_info(const LinphoneFriend *lf){
|
||||
|
|
@ -332,27 +381,28 @@ BuddyInfo * linphone_friend_get_info(const LinphoneFriend *lf){
|
|||
}
|
||||
|
||||
void linphone_friend_apply(LinphoneFriend *fr, LinphoneCore *lc){
|
||||
LinphonePresenceModel *model;
|
||||
|
||||
if (fr->uri==NULL) {
|
||||
ms_warning("No sip url defined.");
|
||||
return;
|
||||
}
|
||||
fr->lc=lc;
|
||||
|
||||
|
||||
linphone_core_write_friends_config(lc);
|
||||
|
||||
if (fr->inc_subscribe_pending){
|
||||
switch(fr->pol){
|
||||
case LinphoneSPWait:
|
||||
linphone_friend_notify(fr,LinphoneStatusPending);
|
||||
model = linphone_presence_model_new_with_activity(LinphonePresenceActivityOther, "Waiting for user acceptance");
|
||||
linphone_friend_notify(fr,model);
|
||||
linphone_presence_model_unref(model);
|
||||
break;
|
||||
case LinphoneSPAccept:
|
||||
if (fr->lc!=NULL)
|
||||
{
|
||||
linphone_friend_notify(fr,fr->lc->presence_mode);
|
||||
}
|
||||
linphone_friend_notify(fr,fr->lc->presence_model);
|
||||
break;
|
||||
case LinphoneSPDeny:
|
||||
linphone_friend_notify(fr,LinphoneStatusOffline);
|
||||
linphone_friend_notify(fr,NULL);
|
||||
break;
|
||||
}
|
||||
fr->inc_subscribe_pending=FALSE;
|
||||
|
|
@ -360,6 +410,8 @@ void linphone_friend_apply(LinphoneFriend *fr, LinphoneCore *lc){
|
|||
if (fr->subscribe && fr->subscribe_active==FALSE){
|
||||
ms_message("Sending a new SUBSCRIBE");
|
||||
__linphone_friend_do_subscribe(fr);
|
||||
}else if (fr->subscribe_active && !fr->subscribe){
|
||||
linphone_friend_unsubscribe(fr);
|
||||
}
|
||||
ms_message("linphone_friend_apply() done.");
|
||||
lc->bl_refresh=TRUE;
|
||||
|
|
@ -375,6 +427,14 @@ void linphone_friend_done(LinphoneFriend *fr){
|
|||
linphone_friend_apply(fr,fr->lc);
|
||||
}
|
||||
|
||||
LinphoneFriend * linphone_core_create_friend(LinphoneCore *lc) {
|
||||
return linphone_friend_new();
|
||||
}
|
||||
|
||||
LinphoneFriend * linphone_core_create_friend_with_address(LinphoneCore *lc, const char *address) {
|
||||
return linphone_friend_new_with_address(address);
|
||||
}
|
||||
|
||||
void linphone_core_add_friend(LinphoneCore *lc, LinphoneFriend *lf)
|
||||
{
|
||||
ms_return_if_fail(lf->lc==NULL);
|
||||
|
|
@ -388,27 +448,57 @@ void linphone_core_add_friend(LinphoneCore *lc, LinphoneFriend *lf)
|
|||
return ;
|
||||
}
|
||||
lc->friends=ms_list_append(lc->friends,lf);
|
||||
lf->lc=lc;
|
||||
if ( linphone_core_ready(lc)) linphone_friend_apply(lf,lc);
|
||||
else lf->commit=TRUE;
|
||||
return ;
|
||||
}
|
||||
|
||||
void linphone_core_remove_friend(LinphoneCore *lc, LinphoneFriend* fl){
|
||||
MSList *el=ms_list_find(lc->friends,(void *)fl);
|
||||
MSList *el=ms_list_find(lc->friends,fl);
|
||||
if (el!=NULL){
|
||||
linphone_friend_destroy((LinphoneFriend*)el->data);
|
||||
lc->friends=ms_list_remove_link(lc->friends,el);
|
||||
linphone_core_write_friends_config(lc);
|
||||
}else{
|
||||
ms_error("linphone_core_remove_friend(): friend [%p] is not part of core's list.",fl);
|
||||
}
|
||||
}
|
||||
|
||||
void linphone_core_send_initial_subscribes(LinphoneCore *lc){
|
||||
const MSList *elem;
|
||||
if (lc->initial_subscribes_sent) return;
|
||||
lc->initial_subscribes_sent=TRUE; /*set to true and see if looping on friends will change this status*/
|
||||
for(elem=lc->friends;elem!=NULL;elem=elem->next){
|
||||
LinphoneFriend *f=(LinphoneFriend*)elem->data;
|
||||
if (f->commit)
|
||||
LinphoneProxyConfig* cfg;
|
||||
if (f->subscribe && !f->initial_subscribes_sent) {
|
||||
lc->initial_subscribes_sent=FALSE; /*at least 1 was not sent */
|
||||
if ((cfg=linphone_core_lookup_known_proxy(f->lc,linphone_friend_get_address(f)))) {
|
||||
/*check if already registered*/
|
||||
if (linphone_proxy_config_get_state(cfg) != LinphoneRegistrationOk)
|
||||
continue; /*skip this friend because not registered yet*/
|
||||
else {
|
||||
char* lf_string = linphone_address_as_string(linphone_friend_get_address(f));
|
||||
ms_message("Identity [%s] registered, we can now subscribe to [%s]",linphone_proxy_config_get_identity(cfg),lf_string);
|
||||
ms_free(lf_string);
|
||||
}
|
||||
}
|
||||
linphone_friend_apply(f,lc);
|
||||
f->initial_subscribes_sent=TRUE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void linphone_core_invalidate_friend_subscriptions(LinphoneCore *lc){
|
||||
const MSList *elem;
|
||||
for(elem=lc->friends;elem!=NULL;elem=elem->next){
|
||||
LinphoneFriend *f=(LinphoneFriend*)elem->data;
|
||||
linphone_friend_invalidate_subscription(f);
|
||||
}
|
||||
lc->initial_subscribes_sent=FALSE;
|
||||
}
|
||||
|
||||
void linphone_friend_set_ref_key(LinphoneFriend *lf, const char *key){
|
||||
|
|
@ -426,38 +516,22 @@ const char *linphone_friend_get_ref_key(const LinphoneFriend *lf){
|
|||
return lf->refkey;
|
||||
}
|
||||
|
||||
static bool_t username_match(const char *u1, const char *u2){
|
||||
if (u1==NULL && u2==NULL) return TRUE;
|
||||
if (u1 && u2 && strcasecmp(u1,u2)==0) return TRUE;
|
||||
return FALSE;
|
||||
LinphoneFriend *linphone_core_find_friend(const LinphoneCore *lc, const LinphoneAddress *addr){
|
||||
LinphoneFriend *lf=NULL;
|
||||
MSList *elem;
|
||||
for(elem=lc->friends;elem!=NULL;elem=ms_list_next(elem)){
|
||||
lf=(LinphoneFriend*)elem->data;
|
||||
if (linphone_address_weak_equal(lf->uri,addr))
|
||||
break;
|
||||
lf=NULL;
|
||||
}
|
||||
return lf;
|
||||
}
|
||||
|
||||
LinphoneFriend *linphone_core_get_friend_by_address(const LinphoneCore *lc, const char *uri){
|
||||
LinphoneAddress *puri=linphone_address_new(uri);
|
||||
const MSList *elem;
|
||||
const char *username;
|
||||
const char *domain;
|
||||
LinphoneFriend *lf=NULL;
|
||||
|
||||
if (puri==NULL){
|
||||
return NULL;
|
||||
}
|
||||
username=linphone_address_get_username(puri);
|
||||
domain=linphone_address_get_domain(puri);
|
||||
if (domain==NULL) {
|
||||
linphone_address_destroy(puri);
|
||||
return NULL;
|
||||
}
|
||||
for(elem=lc->friends;elem!=NULL;elem=ms_list_next(elem)){
|
||||
lf=(LinphoneFriend*)elem->data;
|
||||
const char *it_username=linphone_address_get_username(lf->uri);
|
||||
const char *it_host=linphone_address_get_domain(lf->uri);;
|
||||
if (strcasecmp(domain,it_host)==0 && username_match(username,it_username)){
|
||||
break;
|
||||
}
|
||||
lf=NULL;
|
||||
}
|
||||
linphone_address_destroy(puri);
|
||||
LinphoneFriend *lf=puri ? linphone_core_find_friend(lc,puri) : NULL;
|
||||
if (puri) linphone_address_unref(puri);
|
||||
return lf;
|
||||
}
|
||||
|
||||
|
|
@ -511,7 +585,7 @@ LinphoneFriend * linphone_friend_new_from_config_file(LinphoneCore *lc, int inde
|
|||
if (tmp==NULL) {
|
||||
return NULL;
|
||||
}
|
||||
lf=linphone_friend_new_with_addr(tmp);
|
||||
lf=linphone_friend_new_with_address(tmp);
|
||||
if (lf==NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -165,7 +165,7 @@ MAN_LINKS = NO
|
|||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the XML output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_XML = NO
|
||||
GENERATE_XML = YES
|
||||
XML_OUTPUT = xml
|
||||
XML_SCHEMA =
|
||||
XML_DTD =
|
||||
|
|
@ -190,7 +190,7 @@ EXPAND_ONLY_PREDEF = NO
|
|||
SEARCH_INCLUDES = YES
|
||||
INCLUDE_PATH = .
|
||||
INCLUDE_FILE_PATTERNS = *.h
|
||||
PREDEFINED = DOXYGEN
|
||||
PREDEFINED = DOXYGEN MS2_PUBLIC= LINPHONE_PUBLIC=
|
||||
EXPAND_AS_DEFINED =
|
||||
SKIP_FUNCTION_MACROS = YES
|
||||
#---------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ if HAVE_DOXYGEN
|
|||
# docdir & pkgdocdir are not always defined by automake
|
||||
pkgdocdir=$(docdir)/$(PACKAGE)-$(VERSION)
|
||||
doc_htmldir=$(pkgdocdir)/html
|
||||
doc_xmldir=$(pkgdocdir)/xml
|
||||
|
||||
doc_html_DATA = $(top_builddir)/coreapi/help/doc/html/html.tar
|
||||
|
||||
|
|
@ -20,21 +21,32 @@ $(top_builddir)/coreapi/help/doc/html/index.html: $(SOURCES) Doxyfile Makefile.a
|
|||
rm -rf doc
|
||||
$(DOXYGEN) Doxyfile
|
||||
|
||||
doc_xml_DATA = $(top_builddir)/coreapi/help/doc/xml/xml.tar
|
||||
|
||||
$(doc_xml_DATA): $(top_builddir)/coreapi/help/doc/xml/index.xml
|
||||
cd $(top_builddir)/coreapi/help/doc/xml/ && tar cf xml.tar *
|
||||
|
||||
$(top_builddir)/coreapi/help/doc/xml/index.xml: $(top_builddir)/coreapi/help/doc/html/index.html
|
||||
|
||||
|
||||
install-data-hook:
|
||||
cd $(DESTDIR)$(doc_htmldir) && tar xf html.tar && rm -f html.tar
|
||||
cd $(DESTDIR)$(doc_xmldir) && tar xf xml.tar && rm -f xml.tar
|
||||
|
||||
uninstall-hook:
|
||||
cd $(DESTDIR)$(doc_htmldir) && rm -f *
|
||||
cd $(DESTDIR)$(doc_xmldir) && rm -f *
|
||||
|
||||
endif
|
||||
|
||||
clean-local:
|
||||
rm -rf doc
|
||||
|
||||
if ENABLE_TESTS
|
||||
#tutorials
|
||||
if BUILD_TESTS
|
||||
noinst_PROGRAMS=helloworld registration buddy_status chatroom
|
||||
|
||||
if ENABLE_TUTORIALS
|
||||
|
||||
noinst_PROGRAMS=helloworld registration buddy_status chatroom notify
|
||||
|
||||
helloworld_SOURCES=helloworld.c
|
||||
LINPHONE_TUTOS=$(helloworld_SOURCES)
|
||||
|
|
@ -57,17 +69,18 @@ chatroom_SOURCES=chatroom.c
|
|||
LINPHONE_TUTOS+=$(chatroom_SOURCES)
|
||||
|
||||
chatroom_LDADD=$(helloworld_LDADD)
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
notify_SOURCES=notify.c
|
||||
LINPHONE_TUTOS+=$(notify_SOURCES)
|
||||
|
||||
notify_LDADD=$(helloworld_LDADD)
|
||||
|
||||
AM_CFLAGS=\
|
||||
-I$(top_srcdir)/coreapi \
|
||||
$(STRICT_OPTIONS) \
|
||||
-DIN_LINPHONE \
|
||||
$(ORTP_CFLAGS) \
|
||||
$(OSIP_CFLAGS) \
|
||||
$(MEDIASTREAMER_CFLAGS) \
|
||||
$(EXOSIP_CFLAGS) \
|
||||
-DENABLE_TRACE \
|
||||
-DLOG_DOMAIN=\"LinphoneCore\" \
|
||||
$(IPV6_CFLAGS) \
|
||||
|
|
@ -78,3 +91,4 @@ AM_CFLAGS=\
|
|||
tutodir=$(datadir)/tutorials/linphone
|
||||
|
||||
tuto_DATA=$(LINPHONE_TUTOS)
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -51,12 +51,15 @@ static void stop(int signum){
|
|||
* presence state change notification callback
|
||||
*/
|
||||
static void notify_presence_recv_updated (LinphoneCore *lc, LinphoneFriend *friend) {
|
||||
const LinphonePresenceModel* model = linphone_friend_get_presence_model(friend);
|
||||
const LinphoneAddress* friend_address = linphone_friend_get_address(friend);
|
||||
LinphonePresenceActivity *activity = linphone_presence_model_get_activity(model);
|
||||
char *activity_str = linphone_presence_activity_to_string(activity);
|
||||
printf("New state state [%s] for user id [%s] \n"
|
||||
,linphone_online_status_to_string(linphone_friend_get_status(friend))
|
||||
,activity_str
|
||||
,linphone_address_as_string (friend_address));
|
||||
}
|
||||
static void new_subscription_request (LinphoneCore *lc, LinphoneFriend *friend, const char* url) {
|
||||
static void new_subscription_requested (LinphoneCore *lc, LinphoneFriend *friend, const char* url) {
|
||||
const LinphoneAddress* friend_address = linphone_friend_get_address(friend);
|
||||
printf(" [%s] wants to see your status, accepting\n"
|
||||
,linphone_address_as_string (friend_address));
|
||||
|
|
@ -103,11 +106,11 @@ int main(int argc, char *argv[]){
|
|||
#endif
|
||||
/*
|
||||
Fill the LinphoneCoreVTable with application callbacks.
|
||||
All are optional. Here we only use the both notify_presence_recv and new_subscription_request callbacks
|
||||
All are optional. Here we only use the both notify_presence_received and new_subscription_requested callbacks
|
||||
in order to get notifications about friend status.
|
||||
*/
|
||||
vtable.notify_presence_recv=notify_presence_recv_updated;
|
||||
vtable.new_subscription_request=new_subscription_request;
|
||||
vtable.notify_presence_received=notify_presence_recv_updated;
|
||||
vtable.new_subscription_requested=new_subscription_requested;
|
||||
vtable.registration_state_changed=registration_state_changed; /*just in case sip proxy is used*/
|
||||
|
||||
/*
|
||||
|
|
@ -126,7 +129,7 @@ int main(int argc, char *argv[]){
|
|||
}
|
||||
LinphoneAuthInfo *info;
|
||||
if (password!=NULL){
|
||||
info=linphone_auth_info_new(linphone_address_get_username(from),NULL,password,NULL,NULL); /*create authentication structure from identity*/
|
||||
info=linphone_auth_info_new(linphone_address_get_username(from),NULL,password,NULL,NULL,NULL); /*create authentication structure from identity*/
|
||||
linphone_core_add_auth_info(lc,info); /*add authentication info to LinphoneCore*/
|
||||
}
|
||||
|
||||
|
|
@ -152,7 +155,7 @@ int main(int argc, char *argv[]){
|
|||
LinphoneFriend* my_friend=NULL;
|
||||
|
||||
if (dest_friend) {
|
||||
my_friend = linphone_friend_new_with_addr(dest_friend); /*creates friend object from dest*/
|
||||
my_friend = linphone_friend_new_with_address(dest_friend); /*creates friend object from dest*/
|
||||
if (my_friend == NULL) {
|
||||
printf("bad destination uri for friend [%s]\n",dest_friend);
|
||||
goto end;
|
||||
|
|
@ -164,7 +167,8 @@ int main(int argc, char *argv[]){
|
|||
|
||||
}
|
||||
|
||||
linphone_core_set_presence_info(lc,0,NULL,LinphoneStatusOnline); /*set my status to online*/
|
||||
/*set my status to online*/
|
||||
linphone_core_set_presence_model(lc, linphone_presence_model_new_with_activity(LinphonePresenceActivityOnline, NULL));
|
||||
|
||||
/* main loop for receiving notifications and doing background linphone core work: */
|
||||
while(running){
|
||||
|
|
@ -172,7 +176,8 @@ int main(int argc, char *argv[]){
|
|||
ms_usleep(50000);
|
||||
}
|
||||
|
||||
linphone_core_set_presence_info(lc,0,NULL,LinphoneStatusOffline); /* change my presence status to offline*/
|
||||
/* change my presence status to offline*/
|
||||
linphone_core_set_presence_model(lc, linphone_presence_model_new_with_activity(LinphonePresenceActivityOffline, NULL));
|
||||
linphone_core_iterate(lc); /* just to make sure new status is initiate message is issued */
|
||||
|
||||
linphone_friend_edit(my_friend); /* start editing friend */
|
||||
|
|
|
|||
|
|
@ -152,7 +152,7 @@ linphone_friend_done(my_friend); /*commit changes triggering an UNSUBSCRIBE mess
|
|||
|
||||
|
||||
<b> Publishing presence status </b>
|
||||
<br>Local presence status can be changed using function linphone_core_set_presence_info() .New status is propagated to all friends \link linphone_core_add_friend() previously added \endlink to #LinphoneCore.
|
||||
<br>Local presence status can be changed using function linphone_core_set_presence_model() .New status is propagated to all friends \link linphone_core_add_friend() previously added \endlink to #LinphoneCore.
|
||||
|
||||
<b>Handling incoming subscription request</b>
|
||||
<br> New incoming subscription requests are process according to \link linphone_friend_set_inc_subscribe_policy() the incoming subscription policy state \endlink for subscription initiated by \link linphone_core_add_friend() members of the buddy list. \endlink
|
||||
|
|
|
|||
|
|
@ -23,18 +23,23 @@ import org.linphone.core.LinphoneCall;
|
|||
import org.linphone.core.LinphoneCallStats;
|
||||
import org.linphone.core.LinphoneChatMessage;
|
||||
import org.linphone.core.LinphoneChatRoom;
|
||||
import org.linphone.core.LinphoneContent;
|
||||
import org.linphone.core.LinphoneCore;
|
||||
import org.linphone.core.LinphoneCore.EcCalibratorStatus;
|
||||
import org.linphone.core.LinphoneCoreException;
|
||||
import org.linphone.core.LinphoneCoreFactory;
|
||||
import org.linphone.core.LinphoneCoreListener;
|
||||
import org.linphone.core.LinphoneEvent;
|
||||
import org.linphone.core.LinphoneFriend;
|
||||
import org.linphone.core.LinphoneInfoMessage;
|
||||
import org.linphone.core.LinphoneProxyConfig;
|
||||
import org.linphone.core.OnlineStatus;
|
||||
import org.linphone.core.LinphoneCall.State;
|
||||
import org.linphone.core.LinphoneCore.GlobalState;
|
||||
import org.linphone.core.LinphoneCore.RegistrationState;
|
||||
import org.linphone.core.LinphoneFriend.SubscribePolicy;
|
||||
import org.linphone.core.PublishState;
|
||||
import org.linphone.core.SubscriptionState;
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
@ -156,7 +161,7 @@ public class TutorialBuddyStatus implements LinphoneCoreListener {
|
|||
|
||||
if (mySipPassword != null) {
|
||||
// create authentication structure from identity and add to linphone
|
||||
lc.addAuthInfo(lcFactory.createAuthInfo(username, mySipPassword, null));
|
||||
lc.addAuthInfo(lcFactory.createAuthInfo(username, mySipPassword, null, domain));
|
||||
}
|
||||
|
||||
// create proxy config
|
||||
|
|
@ -241,5 +246,39 @@ public class TutorialBuddyStatus implements LinphoneCoreListener {
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transferState(LinphoneCore lc, LinphoneCall call,
|
||||
State new_call_state) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void infoReceived(LinphoneCore lc, LinphoneCall call, LinphoneInfoMessage info) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void subscriptionStateChanged(LinphoneCore lc, LinphoneEvent ev,
|
||||
SubscriptionState state) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyReceived(LinphoneCore lc, LinphoneEvent ev,
|
||||
String eventName, LinphoneContent content) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void publishStateChanged(LinphoneCore lc, LinphoneEvent ev,
|
||||
PublishState state) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import org.linphone.core.LinphoneCall.State;
|
|||
import org.linphone.core.LinphoneCallStats;
|
||||
import org.linphone.core.LinphoneChatMessage;
|
||||
import org.linphone.core.LinphoneChatRoom;
|
||||
import org.linphone.core.LinphoneContent;
|
||||
import org.linphone.core.LinphoneCore;
|
||||
import org.linphone.core.LinphoneCore.EcCalibratorStatus;
|
||||
import org.linphone.core.LinphoneCore.GlobalState;
|
||||
|
|
@ -31,8 +32,12 @@ import org.linphone.core.LinphoneCore.RegistrationState;
|
|||
import org.linphone.core.LinphoneCoreException;
|
||||
import org.linphone.core.LinphoneCoreFactory;
|
||||
import org.linphone.core.LinphoneCoreListener;
|
||||
import org.linphone.core.LinphoneEvent;
|
||||
import org.linphone.core.LinphoneFriend;
|
||||
import org.linphone.core.LinphoneInfoMessage;
|
||||
import org.linphone.core.LinphoneProxyConfig;
|
||||
import org.linphone.core.PublishState;
|
||||
import org.linphone.core.SubscriptionState;
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -115,7 +120,7 @@ public class TutorialChatRoom implements LinphoneCoreListener, LinphoneChatMessa
|
|||
|
||||
try {
|
||||
// Next step is to create a chat room
|
||||
LinphoneChatRoom chatRoom = lc.createChatRoom(destinationSipAddress);
|
||||
LinphoneChatRoom chatRoom = lc.getOrCreateChatRoom(destinationSipAddress);
|
||||
|
||||
// Send message
|
||||
LinphoneChatMessage chatMessage = chatRoom.createLinphoneChatMessage("Hello world");
|
||||
|
|
@ -163,5 +168,39 @@ public class TutorialChatRoom implements LinphoneCoreListener, LinphoneChatMessa
|
|||
write("Sent message [" + msg.getText() + "] new state is " + state.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transferState(LinphoneCore lc, LinphoneCall call,
|
||||
State new_call_state) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void infoReceived(LinphoneCore lc, LinphoneCall call, LinphoneInfoMessage info) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void subscriptionStateChanged(LinphoneCore lc, LinphoneEvent ev,
|
||||
SubscriptionState state) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyReceived(LinphoneCore lc, LinphoneEvent ev,
|
||||
String eventName, LinphoneContent content) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void publishStateChanged(LinphoneCore lc, LinphoneEvent ev,
|
||||
PublishState state) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,16 +23,21 @@ import org.linphone.core.LinphoneCall;
|
|||
import org.linphone.core.LinphoneCallStats;
|
||||
import org.linphone.core.LinphoneChatMessage;
|
||||
import org.linphone.core.LinphoneChatRoom;
|
||||
import org.linphone.core.LinphoneContent;
|
||||
import org.linphone.core.LinphoneCore;
|
||||
import org.linphone.core.LinphoneCore.EcCalibratorStatus;
|
||||
import org.linphone.core.LinphoneCoreException;
|
||||
import org.linphone.core.LinphoneCoreFactory;
|
||||
import org.linphone.core.LinphoneCoreListener;
|
||||
import org.linphone.core.LinphoneEvent;
|
||||
import org.linphone.core.LinphoneFriend;
|
||||
import org.linphone.core.LinphoneInfoMessage;
|
||||
import org.linphone.core.LinphoneProxyConfig;
|
||||
import org.linphone.core.LinphoneCall.State;
|
||||
import org.linphone.core.LinphoneCore.GlobalState;
|
||||
import org.linphone.core.LinphoneCore.RegistrationState;
|
||||
import org.linphone.core.PublishState;
|
||||
import org.linphone.core.SubscriptionState;
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -167,5 +172,39 @@ public class TutorialHelloWorld implements LinphoneCoreListener {
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transferState(LinphoneCore lc, LinphoneCall call,
|
||||
State new_call_state) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void infoReceived(LinphoneCore lc, LinphoneCall call, LinphoneInfoMessage info) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void subscriptionStateChanged(LinphoneCore lc, LinphoneEvent ev,
|
||||
SubscriptionState state) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyReceived(LinphoneCore lc, LinphoneEvent ev,
|
||||
String eventName, LinphoneContent content) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void publishStateChanged(LinphoneCore lc, LinphoneEvent ev,
|
||||
PublishState state) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,16 +23,21 @@ import org.linphone.core.LinphoneCall;
|
|||
import org.linphone.core.LinphoneCallStats;
|
||||
import org.linphone.core.LinphoneChatMessage;
|
||||
import org.linphone.core.LinphoneChatRoom;
|
||||
import org.linphone.core.LinphoneContent;
|
||||
import org.linphone.core.LinphoneCore;
|
||||
import org.linphone.core.LinphoneCore.EcCalibratorStatus;
|
||||
import org.linphone.core.LinphoneCoreException;
|
||||
import org.linphone.core.LinphoneCoreFactory;
|
||||
import org.linphone.core.LinphoneCoreListener;
|
||||
import org.linphone.core.LinphoneEvent;
|
||||
import org.linphone.core.LinphoneFriend;
|
||||
import org.linphone.core.LinphoneInfoMessage;
|
||||
import org.linphone.core.LinphoneProxyConfig;
|
||||
import org.linphone.core.LinphoneCall.State;
|
||||
import org.linphone.core.LinphoneCore.GlobalState;
|
||||
import org.linphone.core.LinphoneCore.RegistrationState;
|
||||
import org.linphone.core.PublishState;
|
||||
import org.linphone.core.SubscriptionState;
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -126,7 +131,7 @@ public class TutorialRegistration implements LinphoneCoreListener {
|
|||
|
||||
if (password != null) {
|
||||
// create authentication structure from identity and add to linphone
|
||||
lc.addAuthInfo(lcFactory.createAuthInfo(username, password, null));
|
||||
lc.addAuthInfo(lcFactory.createAuthInfo(username, password, null, domain));
|
||||
}
|
||||
|
||||
// create proxy config
|
||||
|
|
@ -198,6 +203,40 @@ public class TutorialRegistration implements LinphoneCoreListener {
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transferState(LinphoneCore lc, LinphoneCall call,
|
||||
State new_call_state) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void infoReceived(LinphoneCore lc, LinphoneCall call, LinphoneInfoMessage info) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void subscriptionStateChanged(LinphoneCore lc, LinphoneEvent ev,
|
||||
SubscriptionState state) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyReceived(LinphoneCore lc, LinphoneEvent ev,
|
||||
String eventName, LinphoneContent content) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void publishStateChanged(LinphoneCore lc, LinphoneEvent ev,
|
||||
PublishState state) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
183
coreapi/help/notify.c
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
|
||||
/*
|
||||
linphone
|
||||
Copyright (C) 2013 Belledonne Communications SARL
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup notify_tutorials Generic subscribe/notify example
|
||||
* @ingroup tutorials
|
||||
*This program is a _very_ simple usage example of liblinphone.
|
||||
*It demonstrates how to listen to a SIP subscription.
|
||||
*It then sends notify requests back periodically.
|
||||
*first argument must be like sip:jehan@sip.linphone.org , second must be password .
|
||||
*<br>
|
||||
*ex registration sip:jehan@sip.linphone.org secret
|
||||
*<br>Registration is cleared on SIGINT
|
||||
*<br>
|
||||
*@include registration.c
|
||||
|
||||
*
|
||||
*/
|
||||
|
||||
#define DEBUG 1
|
||||
|
||||
#ifdef IN_LINPHONE
|
||||
#include "linphonecore.h"
|
||||
#else
|
||||
#include "linphone/linphonecore.h"
|
||||
#endif
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
static bool_t running=TRUE;
|
||||
|
||||
static void stop(int signum){
|
||||
running=FALSE;
|
||||
}
|
||||
|
||||
typedef struct MyAppData{
|
||||
LinphoneEvent *ev;
|
||||
}MyAppData;
|
||||
|
||||
/**
|
||||
* Registration state notification callback
|
||||
*/
|
||||
static void registration_state_changed(LinphoneCore *lc, LinphoneProxyConfig *cfg, LinphoneRegistrationState cstate, const char *message){
|
||||
printf("New registration state %s for user id [%s] at proxy [%s]\n"
|
||||
,linphone_registration_state_to_string(cstate)
|
||||
,linphone_proxy_config_get_identity(cfg)
|
||||
,linphone_proxy_config_get_addr(cfg));
|
||||
}
|
||||
|
||||
static void subscription_state_changed(LinphoneCore *lc, LinphoneEvent *ev, LinphoneSubscriptionState state){
|
||||
MyAppData *data=(MyAppData*)linphone_core_get_user_data(lc);
|
||||
if (state==LinphoneSubscriptionIncomingReceived){
|
||||
printf("Receiving new subscription for event %s\n",linphone_event_get_name(ev));
|
||||
if (data->ev==NULL) {
|
||||
linphone_event_accept_subscription(ev);
|
||||
data->ev=linphone_event_ref(ev);
|
||||
}else{
|
||||
linphone_event_deny_subscription(ev,LinphoneReasonBusy);
|
||||
}
|
||||
}else if (state==LinphoneSubscriptionTerminated){
|
||||
if (data->ev==ev){
|
||||
linphone_event_unref(data->ev);
|
||||
data->ev=NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LinphoneCore *lc;
|
||||
int main(int argc, char *argv[]){
|
||||
LinphoneCoreVTable vtable={0};
|
||||
MyAppData *data=ms_new0(MyAppData,1);
|
||||
char* identity=NULL;
|
||||
char* password=NULL;
|
||||
int i;
|
||||
|
||||
/* takes sip uri identity from the command line arguments */
|
||||
if (argc>1){
|
||||
identity=argv[1];
|
||||
}
|
||||
|
||||
/* takes password from the command line arguments */
|
||||
if (argc>2){
|
||||
password=argv[2];
|
||||
}
|
||||
|
||||
signal(SIGINT,stop);
|
||||
|
||||
#ifdef DEBUG
|
||||
linphone_core_enable_logs(NULL); /*enable liblinphone logs.*/
|
||||
#endif
|
||||
/*
|
||||
Fill the LinphoneCoreVTable with application callbacks.
|
||||
All are optional. Here we only use the registration_state_changed callbacks
|
||||
in order to get notifications about the progress of the registration.
|
||||
*/
|
||||
vtable.registration_state_changed=registration_state_changed;
|
||||
vtable.subscription_state_changed=subscription_state_changed;
|
||||
|
||||
/*
|
||||
Instanciate a LinphoneCore object given the LinphoneCoreVTable
|
||||
*/
|
||||
lc=linphone_core_new(&vtable,NULL,NULL,data);
|
||||
|
||||
LinphoneProxyConfig* proxy_cfg;
|
||||
/*create proxy config*/
|
||||
proxy_cfg = linphone_proxy_config_new();
|
||||
/*parse identity*/
|
||||
LinphoneAddress *from = linphone_address_new(identity);
|
||||
if (from==NULL){
|
||||
printf("%s not a valid sip uri, must be like sip:toto@sip.linphone.org \n",identity);
|
||||
goto end;
|
||||
}
|
||||
LinphoneAuthInfo *info;
|
||||
if (password!=NULL){
|
||||
info=linphone_auth_info_new(linphone_address_get_username(from),NULL,password,NULL,NULL,NULL); /*create authentication structure from identity*/
|
||||
linphone_core_add_auth_info(lc,info); /*add authentication info to LinphoneCore*/
|
||||
}
|
||||
|
||||
// configure proxy entries
|
||||
linphone_proxy_config_set_identity(proxy_cfg,identity); /*set identity with user name and domain*/
|
||||
const char* server_addr = linphone_address_get_domain(from); /*extract domain address from identity*/
|
||||
linphone_proxy_config_set_server_addr(proxy_cfg,server_addr); /* we assume domain = proxy server address*/
|
||||
linphone_proxy_config_enable_register(proxy_cfg,TRUE); /*activate registration for this proxy config*/
|
||||
linphone_address_destroy(from); /*release resource*/
|
||||
|
||||
linphone_core_add_proxy_config(lc,proxy_cfg); /*add proxy config to linphone core*/
|
||||
linphone_core_set_default_proxy(lc,proxy_cfg); /*set to default proxy*/
|
||||
|
||||
i=0;
|
||||
/* main loop for receiving notifications and doing background linphonecore work: */
|
||||
while(running){
|
||||
linphone_core_iterate(lc); /* first iterate initiates registration */
|
||||
ms_usleep(50000);
|
||||
++i;
|
||||
if (data->ev && i%100==0){
|
||||
LinphoneContent content;
|
||||
content.type="application";
|
||||
content.subtype="goodxml";
|
||||
content.data="really cool";
|
||||
content.size=strlen((const char*)content.data);
|
||||
linphone_event_notify(data->ev,&content);
|
||||
}
|
||||
}
|
||||
|
||||
linphone_core_get_default_proxy(lc,&proxy_cfg); /* get default proxy config*/
|
||||
linphone_proxy_config_edit(proxy_cfg); /*start editing proxy configuration*/
|
||||
linphone_proxy_config_enable_register(proxy_cfg,FALSE); /*de-activate registration for this proxy config*/
|
||||
linphone_proxy_config_done(proxy_cfg); /*initiate REGISTER with expire = 0*/
|
||||
|
||||
if (data->ev){
|
||||
linphone_event_terminate(data->ev);
|
||||
}
|
||||
|
||||
while(linphone_proxy_config_get_state(proxy_cfg) != LinphoneRegistrationCleared){
|
||||
linphone_core_iterate(lc); /*to make sure we receive call backs before shutting down*/
|
||||
ms_usleep(50000);
|
||||
}
|
||||
|
||||
end:
|
||||
printf("Shutting down...\n");
|
||||
linphone_core_destroy(lc);
|
||||
ms_free(data);
|
||||
printf("Exited\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -102,7 +102,7 @@ int main(int argc, char *argv[]){
|
|||
}
|
||||
LinphoneAuthInfo *info;
|
||||
if (password!=NULL){
|
||||
info=linphone_auth_info_new(linphone_address_get_username(from),NULL,password,NULL,NULL); /*create authentication structure from identity*/
|
||||
info=linphone_auth_info_new(linphone_address_get_username(from),NULL,password,NULL,NULL,NULL); /*create authentication structure from identity*/
|
||||
linphone_core_add_auth_info(lc,info); /*add authentication info to LinphoneCore*/
|
||||
}
|
||||
|
||||
|
|
|
|||
197
coreapi/info.c
Normal file
|
|
@ -0,0 +1,197 @@
|
|||
/***************************************************************************
|
||||
* info.c
|
||||
*
|
||||
* Thu May 16 11:48:01 2013
|
||||
* Copyright 2013 Belledonne Communications SARL
|
||||
* Author Simon Morlat
|
||||
* Email simon dot morlat at linphone dot org
|
||||
****************************************************************************/
|
||||
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "linphonecore.h"
|
||||
#include "private.h"
|
||||
#include "lpconfig.h"
|
||||
|
||||
|
||||
struct _LinphoneInfoMessage{
|
||||
LinphoneContent content;
|
||||
SalCustomHeader *headers;
|
||||
};
|
||||
|
||||
#define SET_STRING(ptr,field,val) \
|
||||
if (ptr->field) { \
|
||||
ms_free(ptr->field); \
|
||||
ptr->field=NULL; \
|
||||
} \
|
||||
if (val){ \
|
||||
ptr->field=ms_strdup(val); \
|
||||
}
|
||||
|
||||
static void linphone_content_copy(LinphoneContent *obj, const LinphoneContent *ref){
|
||||
SET_STRING(obj,type,ref->type);
|
||||
SET_STRING(obj,subtype,ref->subtype);
|
||||
SET_STRING(obj,encoding,ref->encoding);
|
||||
if (obj->data) {
|
||||
ms_free(obj->data);
|
||||
obj->data=NULL;
|
||||
}
|
||||
if (ref->data){
|
||||
obj->data=ms_malloc(ref->size+1);
|
||||
memcpy(obj->data, ref->data, ref->size);
|
||||
((char*)obj->data)[ref->size]='\0';
|
||||
}
|
||||
obj->size=ref->size;
|
||||
}
|
||||
|
||||
void linphone_content_uninit(LinphoneContent * obj){
|
||||
if (obj->type) ms_free(obj->type);
|
||||
if (obj->subtype) ms_free(obj->subtype);
|
||||
if (obj->data) ms_free(obj->data);
|
||||
if (obj->encoding) ms_free(obj->encoding);
|
||||
}
|
||||
|
||||
LinphoneContent *linphone_content_copy_from_sal_body(LinphoneContent *obj, const SalBody *ref){
|
||||
SET_STRING(obj,type,ref->type);
|
||||
SET_STRING(obj,subtype,ref->subtype);
|
||||
SET_STRING(obj,encoding,ref->encoding);
|
||||
if (obj->data) {
|
||||
ms_free(obj->data);
|
||||
obj->data=NULL;
|
||||
}
|
||||
if (ref->data){
|
||||
obj->data=ms_malloc(ref->size+1);
|
||||
memcpy(obj->data, ref->data, ref->size);
|
||||
((char*)obj->data)[ref->size]='\0';
|
||||
}
|
||||
obj->size=ref->size;
|
||||
return obj;
|
||||
}
|
||||
|
||||
const LinphoneContent *linphone_content_from_sal_body(LinphoneContent *obj, const SalBody *ref){
|
||||
if (ref && ref->type){
|
||||
obj->type=(char*)ref->type;
|
||||
obj->subtype=(char*)ref->subtype;
|
||||
obj->data=(void*)ref->data;
|
||||
obj->encoding=(char*)ref->encoding;
|
||||
obj->size=ref->size;
|
||||
return obj;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SalBody *sal_body_from_content(SalBody *body, const LinphoneContent *lc){
|
||||
if (lc && lc->type){
|
||||
body->type=lc->type;
|
||||
body->subtype=lc->subtype;
|
||||
body->data=lc->data;
|
||||
body->size=lc->size;
|
||||
body->encoding=lc->encoding;
|
||||
return body;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy a LinphoneInfoMessage
|
||||
**/
|
||||
void linphone_info_message_destroy(LinphoneInfoMessage *im){
|
||||
linphone_content_uninit(&im->content);
|
||||
sal_custom_header_free(im->headers);
|
||||
ms_free(im);
|
||||
}
|
||||
|
||||
|
||||
LinphoneInfoMessage *linphone_info_message_copy(const LinphoneInfoMessage *orig){
|
||||
LinphoneInfoMessage *im=ms_new0(LinphoneInfoMessage,1);
|
||||
linphone_content_copy(&im->content,&orig->content);
|
||||
if (orig->headers) im->headers=sal_custom_header_clone(orig->headers);
|
||||
return im;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an empty info message.
|
||||
* @param lc the LinphoneCore
|
||||
* @return a new LinphoneInfoMessage.
|
||||
*
|
||||
* The info message can later be filled with information using linphone_info_message_add_header() or linphone_info_message_set_content(),
|
||||
* and finally sent with linphone_core_send_info_message().
|
||||
**/
|
||||
LinphoneInfoMessage *linphone_core_create_info_message(LinphoneCore *lc){
|
||||
LinphoneInfoMessage *im=ms_new0(LinphoneInfoMessage,1);
|
||||
return im;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a LinphoneInfoMessage through an established call
|
||||
* @param call the call
|
||||
* @param info the info message
|
||||
**/
|
||||
int linphone_call_send_info_message(LinphoneCall *call, const LinphoneInfoMessage *info){
|
||||
SalBody body;
|
||||
sal_op_set_sent_custom_header(call->op,info->headers);
|
||||
return sal_send_info(call->op,NULL, NULL, sal_body_from_content(&body,&info->content));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a header to an info message to be sent.
|
||||
* @param im the info message
|
||||
* @param name the header'name
|
||||
* @param value the header's value
|
||||
**/
|
||||
void linphone_info_message_add_header(LinphoneInfoMessage *im, const char *name, const char *value){
|
||||
im->headers=sal_custom_header_append(im->headers, name, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain a header value from a received info message.
|
||||
* @param im the info message
|
||||
* @param name the header'name
|
||||
* @return the corresponding header's value, or NULL if not exists.
|
||||
**/
|
||||
const char *linphone_info_message_get_header(const LinphoneInfoMessage *im, const char *name){
|
||||
return sal_custom_header_find(im->headers,name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign a content to the info message.
|
||||
* @param im the linphone info message
|
||||
* @param content the content described as a #LinphoneContent structure.
|
||||
* All fields of the LinphoneContent are copied, thus the application can destroy/modify/recycloe the content object freely ater the function returns.
|
||||
**/
|
||||
void linphone_info_message_set_content(LinphoneInfoMessage *im, const LinphoneContent *content){
|
||||
linphone_content_copy(&im->content,content);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the info message's content as a #LinphoneContent structure.
|
||||
**/
|
||||
const LinphoneContent * linphone_info_message_get_content(const LinphoneInfoMessage *im){
|
||||
return im->content.type ? &im->content : NULL;
|
||||
}
|
||||
|
||||
void linphone_core_notify_info_message(LinphoneCore* lc,SalOp *op, const SalBody *body){
|
||||
LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op);
|
||||
if (call){
|
||||
LinphoneInfoMessage *info=ms_new0(LinphoneInfoMessage,1);
|
||||
info->headers=sal_custom_header_clone(sal_op_get_recv_custom_header(op));
|
||||
if (body) linphone_content_copy_from_sal_body(&info->content,body);
|
||||
if (lc->vtable.info_received)
|
||||
lc->vtable.info_received(lc,call,info);
|
||||
linphone_info_message_destroy(info);
|
||||
}
|
||||
}
|
||||
|
|
@ -36,6 +36,7 @@ LinphoneTunnel* linphone_core_get_tunnel(LinphoneCore *lc){
|
|||
struct _LinphoneTunnel {
|
||||
belledonnecomm::TunnelManager *manager;
|
||||
MSList *config_list;
|
||||
bool_t auto_detect_enabled;
|
||||
};
|
||||
|
||||
extern "C" LinphoneTunnel* linphone_core_tunnel_new(LinphoneCore *lc){
|
||||
|
|
@ -225,6 +226,7 @@ void linphone_tunnel_clean_servers(LinphoneTunnel *tunnel){
|
|||
}
|
||||
|
||||
void linphone_tunnel_enable(LinphoneTunnel *tunnel, bool_t enabled){
|
||||
tunnel->auto_detect_enabled = FALSE;
|
||||
lp_config_set_int(config(tunnel),"tunnel","enabled",(int)enabled);
|
||||
bcTunnel(tunnel)->enable(enabled);
|
||||
}
|
||||
|
|
@ -311,9 +313,14 @@ void linphone_tunnel_reconnect(LinphoneTunnel *tunnel){
|
|||
}
|
||||
|
||||
void linphone_tunnel_auto_detect(LinphoneTunnel *tunnel){
|
||||
tunnel->auto_detect_enabled = TRUE;
|
||||
bcTunnel(tunnel)->autoDetect();
|
||||
}
|
||||
|
||||
bool_t linphone_tunnel_auto_detect_enabled(LinphoneTunnel *tunnel) {
|
||||
return tunnel->auto_detect_enabled;
|
||||
}
|
||||
|
||||
static void my_ortp_logv(OrtpLogLevel level, const char *fmt, va_list args){
|
||||
ortp_logv(level,fmt,args);
|
||||
}
|
||||
|
|
|
|||