- resiprocate is back as a part of solid repo
This commit is contained in:
16
src/libs/resiprocate/.appveyor.yml
Normal file
16
src/libs/resiprocate/.appveyor.yml
Normal file
@@ -0,0 +1,16 @@
|
||||
image: Visual Studio 2015
|
||||
|
||||
configuration:
|
||||
- Debug
|
||||
- Release
|
||||
|
||||
platform:
|
||||
- x64
|
||||
- Win32
|
||||
|
||||
build:
|
||||
parallel: true
|
||||
project: reSIProcate_14_0.sln
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
12
src/libs/resiprocate/.clang-tidy
Normal file
12
src/libs/resiprocate/.clang-tidy
Normal file
@@ -0,0 +1,12 @@
|
||||
Checks: >-
|
||||
-*,
|
||||
bugprone-exception-escape,
|
||||
bugprone-move-forwarding-reference,
|
||||
bugprone-undefined-memory-manipulation,
|
||||
bugprone-unhandled-self-assignment,
|
||||
bugprone-use-after-move,
|
||||
performance-move-const-arg,
|
||||
performance-move-constructor-init,
|
||||
performance-no-automatic-move,
|
||||
performance-noexcept-move-constructor
|
||||
HeaderFilterRegex: .*
|
||||
5
src/libs/resiprocate/.editorconfig
Normal file
5
src/libs/resiprocate/.editorconfig
Normal file
@@ -0,0 +1,5 @@
|
||||
[*]
|
||||
indent_style=space
|
||||
|
||||
[*.{hxx,cxx,hpp,cpp,h,c}]
|
||||
indent_size=3
|
||||
92
src/libs/resiprocate/.github/workflows/ci.yml
vendored
Normal file
92
src/libs/resiprocate/.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
name: CI
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build with ${{ matrix.c-compiler }}
|
||||
runs-on: ubuntu-20.04
|
||||
container:
|
||||
image: debian:bullseye-slim
|
||||
options: --ulimit memlock=-1
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
c-compiler: [gcc-10, clang-13]
|
||||
include:
|
||||
- c-compiler: gcc-10
|
||||
cxx-compiler: g++-10
|
||||
- c-compiler: clang-13
|
||||
cxx-compiler: clang++-13
|
||||
env:
|
||||
CC: /usr/bin/${{ matrix.c-compiler }}
|
||||
CXX: /usr/bin/${{ matrix.cxx-compiler }}
|
||||
steps:
|
||||
- name: Get number of CPU cores
|
||||
uses: SimenB/github-actions-cpu-cores@v1.1.0
|
||||
id: cpu-cores
|
||||
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
echo "deb http://deb.debian.org/debian bullseye-backports main" > /etc/apt/sources.list.d/backports.list
|
||||
apt-get update -qq
|
||||
apt-get install -qq wget
|
||||
wget -O - http://apt.debify.org/add-apt-debify | bash
|
||||
apt-get update -qq
|
||||
apt-get install -qq \
|
||||
clang-13 \
|
||||
clang-tidy-13 \
|
||||
cmake \
|
||||
default-libmysqlclient-dev \
|
||||
g++-10 \
|
||||
git \
|
||||
gperf \
|
||||
libasio-dev \
|
||||
libboost-all-dev \
|
||||
libc-ares-dev \
|
||||
libcajun-dev \
|
||||
libcppunit-dev \
|
||||
libdb++-dev \
|
||||
libfmt-dev \
|
||||
libgeoip-dev \
|
||||
libgloox-dev \
|
||||
libgstreamermm-1.0-dev \
|
||||
libpcre3-dev \
|
||||
libpopt-dev \
|
||||
libpq-dev \
|
||||
postgresql-server-dev-all \
|
||||
libqpid-proton-cpp12-dev \
|
||||
libradcli-dev \
|
||||
libsipxtapi-dev \
|
||||
libsnmp-dev \
|
||||
libsoci-dev \
|
||||
libsrtp2-dev \
|
||||
libssl-dev \
|
||||
libtelepathy-qt5-dev \
|
||||
libwebsocketpp-dev \
|
||||
libxerces-c-dev \
|
||||
lld-13 \
|
||||
make \
|
||||
perl \
|
||||
python3-cxx-dev \
|
||||
python3-dev \
|
||||
sox \
|
||||
xxd
|
||||
|
||||
- name: Checkout source
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Bootstrap
|
||||
run: ./build/travis/bootstrap
|
||||
|
||||
- name: Configure
|
||||
run: ./build/travis/configure
|
||||
|
||||
- name: Build
|
||||
run: ./build/travis/build
|
||||
|
||||
- name: Analyse
|
||||
if: ${{ matrix.c-compiler == 'clang-13' }}
|
||||
run: run-clang-tidy-13 -j ${{ steps.cpu-cores.outputs.count }} -quiet
|
||||
|
||||
- name: Test
|
||||
run: make -j1 CTEST_OUTPUT_ON_FAILURE=1 test
|
||||
75
src/libs/resiprocate/.gitignore
vendored
Normal file
75
src/libs/resiprocate/.gitignore
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
# This file is only looked at when a checked-out SVN
|
||||
# repository is used as the source for a git repo.
|
||||
|
||||
*.dll
|
||||
*.o
|
||||
*.lo
|
||||
*.la
|
||||
*.bak
|
||||
*.obj
|
||||
*.pdb
|
||||
*.ilk
|
||||
*.idb
|
||||
*.log
|
||||
/Makefile
|
||||
/Makefile.in
|
||||
/.deps
|
||||
/.libs
|
||||
**/.vs
|
||||
/aclocal.m4
|
||||
/config.h
|
||||
/config.h.in
|
||||
/config.log
|
||||
/config.status
|
||||
/configure
|
||||
/libtool
|
||||
/m4
|
||||
/stamp-h1
|
||||
/autom4te.cache
|
||||
/build-aux
|
||||
/packages
|
||||
/resiprocate.spec
|
||||
/resiprocate-[0-9]*.tar.gz
|
||||
/resiprocate-[0-9]*.zip
|
||||
/resiprocate-contrib-[0-9]*.tar.gz
|
||||
/resiprocate-contrib-[0-9]*.zip
|
||||
repro_*.db
|
||||
reproInfo.hxx
|
||||
|
||||
/SVN-VERSION
|
||||
/.make_prefs
|
||||
/build/Makefile.conf
|
||||
tags
|
||||
*build.Linux*
|
||||
.dependlibs
|
||||
bin.debug.*
|
||||
obj.debug.*
|
||||
bin.opt.*
|
||||
obj.opt.*
|
||||
bin.gopt.*
|
||||
obj.gopt.*
|
||||
obj.prof.*
|
||||
bin.prof.*
|
||||
|
||||
**/[Ww]in32
|
||||
**/x64
|
||||
*.vcxproj.user
|
||||
**/Debug Dll
|
||||
**/Release Dll
|
||||
**/x64-Debug
|
||||
**/packages
|
||||
**/test/*.exe
|
||||
|
||||
/.idea
|
||||
/cmake-build-*
|
||||
|
||||
CMakeCache.txt
|
||||
CPackConfig.cmake
|
||||
CPackSourceConfig.cmake
|
||||
**/CMakeFiles/
|
||||
**/CTestTestfile.cmake
|
||||
**/cmake_install.cmake
|
||||
**/lib*.so
|
||||
**/lib*.so.*
|
||||
**/Testing/
|
||||
|
||||
89
src/libs/resiprocate/AUTHORS
Normal file
89
src/libs/resiprocate/AUTHORS
Normal file
@@ -0,0 +1,89 @@
|
||||
|
||||
Please add your name, email address and if you contribute on
|
||||
behalf of a company, please identity the name of the company,
|
||||
company registration number and the place of incorporation.
|
||||
|
||||
This file identifies the authors/contributors/copyright holders who
|
||||
have contributed works of any kind to the main reSIProcate
|
||||
distribution tarball.
|
||||
|
||||
This file does not cover the material in the contrib/ directory of
|
||||
the source control system, as each of those components is
|
||||
unmodified and distributed with it's own AUTHORS file.
|
||||
|
||||
$ git log | grep ^Author | sort -u | cut -f2 -d' '
|
||||
|
||||
adam
|
||||
adamr
|
||||
alan
|
||||
arosenberg
|
||||
bbramwel
|
||||
bcampen
|
||||
bko
|
||||
bob
|
||||
brocha
|
||||
bryan
|
||||
cbond
|
||||
cisco
|
||||
cktam
|
||||
dabryan
|
||||
daniel
|
||||
danweber
|
||||
Danweber
|
||||
davidb
|
||||
dbozzali
|
||||
dean
|
||||
derek
|
||||
Derek
|
||||
derekm
|
||||
dlb
|
||||
dpetrie
|
||||
dpocock: Daniel Pocock <daniel@pocock.com.au>
|
||||
dragos
|
||||
dsuh
|
||||
duanestorey
|
||||
dworley
|
||||
ekr
|
||||
emcmurry
|
||||
fjoanis
|
||||
fluffy
|
||||
greg
|
||||
jason
|
||||
jdeverick
|
||||
jgeras
|
||||
jmatthewsr
|
||||
jozsef
|
||||
kchmilar
|
||||
kdc
|
||||
kenho
|
||||
ken
|
||||
kittlitz
|
||||
kwhite
|
||||
lowekamp
|
||||
matthias
|
||||
maxb
|
||||
mfroman
|
||||
moetje
|
||||
nagendra
|
||||
nash
|
||||
nils
|
||||
(no
|
||||
partim
|
||||
pckizer
|
||||
rjsparks
|
||||
rohan
|
||||
ronh
|
||||
ryker
|
||||
sailesh
|
||||
satluri
|
||||
schanin
|
||||
sgodin
|
||||
shaun
|
||||
troll
|
||||
vann
|
||||
veer
|
||||
vinit
|
||||
wensong
|
||||
xmlscott
|
||||
|
||||
|
||||
67
src/libs/resiprocate/CCACHE_and_DISTCC.txt
Normal file
67
src/libs/resiprocate/CCACHE_and_DISTCC.txt
Normal file
@@ -0,0 +1,67 @@
|
||||
|
||||
If you use the helper scripts build/debian.sh or build/fedora.sh
|
||||
they will automatically check if you have ccache and distcc
|
||||
on your system and enable both of them.
|
||||
|
||||
ccache improves performance even if you only have a single system to
|
||||
build on.
|
||||
|
||||
For our scripts to work, please install both of them together, even
|
||||
if you only need one of them:
|
||||
|
||||
Debian/Ubuntu:
|
||||
|
||||
$ sudo apt install ccache distcc distcc-pump
|
||||
|
||||
Fedora/Red Hat/RPM-based systems:
|
||||
|
||||
$ sudo dnf install ccache distcc
|
||||
|
||||
On each host that will participate in a distcc build you need to install
|
||||
the distcc package and the same compiler used on the primary workstation.
|
||||
For example, if you are using GNU C/C++ locally, you need to install that
|
||||
on every distcc host. If you use CLang locally, you need to install that
|
||||
on every distcc host too.
|
||||
|
||||
If you are using the regular distcc TCP connection over a LAN or VPN,
|
||||
on each of the participating build servers, run the distccd daemon,
|
||||
for example:
|
||||
|
||||
$ distccd --daemon
|
||||
|
||||
If you are going to use distcc over SSH then do not start the daemon,
|
||||
the client starts it for you.
|
||||
|
||||
On the workstation where you are starting the build, you can setup
|
||||
the distcc configuration in an environment variable or configuration
|
||||
file. Here is a simple example with the environment variable:
|
||||
|
||||
$ export DISTCC_HOSTS='localhost/2 --localslots_cpp=5 192.168.1.105/63'
|
||||
|
||||
The above command includes the following:
|
||||
|
||||
localhost/2 - use up to 2 cores on the local CPU
|
||||
--localslots_cpp=5 - use up to 5 cores for C preprocessor locally
|
||||
192.168.1.105/63 - use up to 63 cores on server 192.168.1.105
|
||||
|
||||
If you want to use SSH instead of TCP, use this environment variable instead:
|
||||
|
||||
$ export DISTCC_HOSTS='localhost/2 --localslots_cpp=5 @192.168.1.105/63'
|
||||
|
||||
With the environment configured, you can now run the configure and compile.
|
||||
For example, on a Debian/Ubuntu host:
|
||||
|
||||
$ ssh 192.168.1.105 distccd --daemon
|
||||
$ export DISTCC_HOSTS='localhost/2 --localslots_cpp=5 192.168.1.105/63'
|
||||
$ build/debian.sh
|
||||
$ make clean
|
||||
$ make -j70
|
||||
|
||||
On a Fedora/Red Hat host:
|
||||
|
||||
$ ssh 192.168.1.105 distccd --daemon
|
||||
$ export DISTCC_HOSTS='localhost/2 --localslots_cpp=5 192.168.1.105/63'
|
||||
$ build/fedora.sh
|
||||
$ make clean
|
||||
$ make -j70
|
||||
|
||||
372
src/libs/resiprocate/CMakeLists.txt
Normal file
372
src/libs/resiprocate/CMakeLists.txt
Normal file
@@ -0,0 +1,372 @@
|
||||
project (resiprocate)
|
||||
|
||||
if (NOT OPENSSL_INCLUDE)
|
||||
message(FATAL_ERROR "OPENSSL_INCLUDE has to be directory with OpenSSL 1.1.x include files.")
|
||||
endif()
|
||||
|
||||
# Rely on C++ 20
|
||||
set (CMAKE_CXX_STANDARD 20)
|
||||
set (CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
set (DIR_ARES rutil/dns/ares)
|
||||
set (ARES_SOURCES
|
||||
${DIR_ARES}/ares_timeout.c
|
||||
${DIR_ARES}/ares_strerror.c
|
||||
${DIR_ARES}/ares_send.c
|
||||
${DIR_ARES}/ares_search.c
|
||||
${DIR_ARES}/ares_query.c
|
||||
${DIR_ARES}/ares_process.c
|
||||
${DIR_ARES}/ares_parse_ptr_reply.c
|
||||
${DIR_ARES}/ares_parse_a_reply.c
|
||||
${DIR_ARES}/ares_mkquery.c
|
||||
${DIR_ARES}/ares_local.c
|
||||
${DIR_ARES}/ares_init.c
|
||||
${DIR_ARES}/ares_gethostbyname.c
|
||||
${DIR_ARES}/ares_gethostbyaddr.c
|
||||
${DIR_ARES}/ares_free_string.c
|
||||
${DIR_ARES}/ares_free_hostent.c
|
||||
${DIR_ARES}/ares_free_errmem.c
|
||||
${DIR_ARES}/ares_fds.c
|
||||
${DIR_ARES}/ares_expand_name.c
|
||||
${DIR_ARES}/ares_destroy.c
|
||||
${DIR_ARES}/ares__read_line.c
|
||||
${DIR_ARES}/ares__get_hostent.c
|
||||
${DIR_ARES}/ares__close_sockets.c
|
||||
)
|
||||
|
||||
set (STACK_SOURCES
|
||||
resip/stack/TokenOrQuotedStringCategory.hxx
|
||||
resip/stack/TokenOrQuotedStringCategory.cxx
|
||||
resip/stack/TrickleIceContents.hxx
|
||||
resip/stack/TrickleIceContents.cxx
|
||||
resip/stack/TcpConnectState.hxx
|
||||
resip/stack/TcpConnectState.cxx
|
||||
resip/stack/gen/MonthHash.cxx
|
||||
resip/stack/gen/DayOfWeekHash.cxx
|
||||
resip/stack/Compression.cxx
|
||||
resip/stack/CallId.cxx
|
||||
resip/stack/BranchParameter.cxx
|
||||
resip/stack/BasicNonceHelper.cxx
|
||||
resip/stack/Auth.cxx
|
||||
resip/stack/ApplicationSip.cxx
|
||||
resip/stack/ApiCheck.cxx
|
||||
resip/stack/Aor.cxx
|
||||
resip/stack/DateCategory.cxx
|
||||
resip/stack/DataParameter.cxx
|
||||
resip/stack/CSeqCategory.cxx
|
||||
resip/stack/CpimContents.cxx
|
||||
resip/stack/ContentsFactoryBase.cxx
|
||||
resip/stack/Contents.cxx
|
||||
resip/stack/ConnectionManager.cxx
|
||||
resip/stack/ConnectionBase.cxx
|
||||
resip/stack/Connection.cxx
|
||||
resip/stack/DnsResult.cxx
|
||||
resip/stack/DnsInterface.cxx
|
||||
resip/stack/DeprecatedDialog.cxx
|
||||
resip/stack/GenericUri.cxx
|
||||
resip/stack/GenericContents.cxx
|
||||
resip/stack/FloatParameter.cxx
|
||||
resip/stack/ExternalBodyContents.cxx
|
||||
resip/stack/ExtensionParameter.cxx
|
||||
resip/stack/ExtensionHeader.cxx
|
||||
resip/stack/ExpiresCategory.cxx
|
||||
resip/stack/ExistsParameter.cxx
|
||||
resip/stack/ExistsOrDataParameter.cxx
|
||||
resip/stack/EventStackThread.cxx
|
||||
resip/stack/Embedded.cxx
|
||||
resip/stack/DtlsMessage.cxx
|
||||
resip/stack/gen/HeaderHash.cxx
|
||||
resip/stack/HeaderFieldValueList.cxx
|
||||
resip/stack/HeaderFieldValue.cxx
|
||||
resip/stack/MsgHeaderScanner.cxx
|
||||
resip/stack/Mime.cxx
|
||||
resip/stack/MethodTypes.cxx
|
||||
resip/stack/gen/MethodHash.cxx
|
||||
resip/stack/MessageWaitingContents.cxx
|
||||
resip/stack/MessageFilterRule.cxx
|
||||
resip/stack/Message.cxx
|
||||
resip/stack/LazyParser.cxx
|
||||
resip/stack/KeepAliveMessage.cxx
|
||||
resip/stack/InvalidContents.cxx
|
||||
resip/stack/InterruptableStackThread.cxx
|
||||
resip/stack/InteropHelper.cxx
|
||||
resip/stack/InternalTransport.cxx
|
||||
resip/stack/IntegerParameter.cxx
|
||||
resip/stack/IntegerCategory.cxx
|
||||
resip/stack/Helper.cxx
|
||||
resip/stack/HeaderTypes.cxx
|
||||
resip/stack/Headers.cxx
|
||||
resip/stack/gen/ParameterHash.cxx
|
||||
resip/stack/Parameter.cxx
|
||||
resip/stack/OctetContents.cxx
|
||||
resip/stack/NonceHelper.cxx
|
||||
resip/stack/NameAddr.cxx
|
||||
resip/stack/MultipartSignedContents.cxx
|
||||
resip/stack/MultipartRelatedContents.cxx
|
||||
resip/stack/MultipartMixedContents.cxx
|
||||
resip/stack/MultipartAlternativeContents.cxx
|
||||
resip/stack/SipStack.cxx
|
||||
resip/stack/SipMessage.cxx
|
||||
resip/stack/SipFrag.cxx
|
||||
resip/stack/SERNonceHelper.cxx
|
||||
resip/stack/SecurityAttributes.cxx
|
||||
resip/stack/SdpContents.cxx
|
||||
resip/stack/RportParameter.cxx
|
||||
resip/stack/Rlmi.cxx
|
||||
resip/stack/RequestLine.cxx
|
||||
resip/stack/RAckCategory.cxx
|
||||
resip/stack/QValueParameter.cxx
|
||||
resip/stack/QValue.cxx
|
||||
resip/stack/QuotedDataParameter.cxx
|
||||
resip/stack/PrivacyCategory.cxx
|
||||
resip/stack/PlainContents.cxx
|
||||
resip/stack/Pkcs8Contents.cxx
|
||||
resip/stack/Pkcs7Contents.cxx
|
||||
resip/stack/Pidf.cxx
|
||||
resip/stack/ParserContainerBase.cxx
|
||||
resip/stack/ParserCategory.cxx
|
||||
resip/stack/ParserCategories.cxx
|
||||
resip/stack/ParameterTypes.cxx
|
||||
resip/stack/X509Contents.cxx
|
||||
resip/stack/WarningCategory.cxx
|
||||
resip/stack/Via.cxx
|
||||
resip/stack/Uri.cxx
|
||||
resip/stack/UnknownParameter.cxx
|
||||
resip/stack/UInt32Parameter.cxx
|
||||
resip/stack/UInt32Category.cxx
|
||||
resip/stack/Cookie.hxx
|
||||
resip/stack/Cookie.cxx
|
||||
resip/stack/UdpTransport.cxx
|
||||
|
||||
resip/stack/WsBaseTransport.cxx
|
||||
resip/stack/WsBaseTransport.hxx
|
||||
resip/stack/WsConnectionBase.cxx
|
||||
resip/stack/WsConnectionBase.hxx
|
||||
resip/stack/WsConnection.cxx
|
||||
resip/stack/WsConnection.hxx
|
||||
resip/stack/WsTransport.cxx
|
||||
resip/stack/WsTransport.hxx
|
||||
resip/stack/WsFrameExtractor.cxx
|
||||
resip/stack/WsFrameExtractor.hxx
|
||||
resip/stack/WsCookieContext.cxx
|
||||
resip/stack/WsCookieContext.hxx
|
||||
resip/stack/WsDecorator.cxx
|
||||
resip/stack/WsDecorator.hxx
|
||||
resip/stack/ssl/WssTransport.cxx
|
||||
resip/stack/ssl/WssTransport.hxx
|
||||
resip/stack/ssl/WssConnection.cxx
|
||||
resip/stack/ssl/WssConnection.hxx
|
||||
resip/stack/ssl/TlsBaseTransport.cxx
|
||||
resip/stack/ssl/TlsBaseTransport.hxx
|
||||
|
||||
resip/stack/TuSelector.cxx
|
||||
resip/stack/TupleMarkManager.cxx
|
||||
resip/stack/Tuple.cxx
|
||||
resip/stack/TuIM.cxx
|
||||
resip/stack/TransportThread.cxx
|
||||
resip/stack/TransportSelector.cxx
|
||||
resip/stack/TransportFailure.cxx
|
||||
resip/stack/Transport.cxx
|
||||
resip/stack/TransactionUserMessage.cxx
|
||||
resip/stack/TransactionUser.cxx
|
||||
resip/stack/TransactionState.cxx
|
||||
resip/stack/TransactionMap.cxx
|
||||
resip/stack/TransactionController.cxx
|
||||
resip/stack/Token.cxx
|
||||
resip/stack/TimerQueue.cxx
|
||||
resip/stack/TimerMessage.cxx
|
||||
resip/stack/TimeAccumulate.cxx
|
||||
resip/stack/TcpTransport.cxx
|
||||
resip/stack/TcpConnection.cxx
|
||||
resip/stack/TcpBaseTransport.cxx
|
||||
resip/stack/Symbols.cxx
|
||||
resip/stack/StringCategory.cxx
|
||||
resip/stack/StatusLine.cxx
|
||||
resip/stack/StatisticsMessage.cxx
|
||||
resip/stack/StatisticsManager.cxx
|
||||
resip/stack/StatisticsHandler.cxx
|
||||
resip/stack/StatelessHandler.cxx
|
||||
resip/stack/StackThread.cxx
|
||||
resip/stack/ssl/Security.cxx
|
||||
#resip/stack/ssl/MacSecurity.cxx
|
||||
resip/stack/ssl/TlsConnection.cxx
|
||||
resip/stack/ssl/TlsTransport.cxx
|
||||
|
||||
resip/stack/BasicDomainMatcher.hxx
|
||||
resip/stack/BasicDomainMatcher.cxx
|
||||
)
|
||||
|
||||
if (CMAKE_SYSTEM MATCHES "Windows*")
|
||||
set (STACK_SOURCES ${STACK_SOURCES}
|
||||
resip/stack/ssl/WinSecurity.cxx)
|
||||
endif()
|
||||
|
||||
set (DUM_SOURCES
|
||||
resip/dum/DialogUsageManager.cxx
|
||||
resip/dum/DialogUsage.cxx
|
||||
resip/dum/DialogSetId.cxx
|
||||
resip/dum/DialogSet.cxx
|
||||
resip/dum/DialogId.cxx
|
||||
resip/dum/DialogEventStateManager.cxx
|
||||
resip/dum/DialogEventInfo.cxx
|
||||
resip/dum/Dialog.cxx
|
||||
resip/dum/DestroyUsage.cxx
|
||||
resip/dum/DefaultServerReferHandler.cxx
|
||||
resip/dum/ContactInstanceRecord.cxx
|
||||
resip/dum/ClientSubscription.cxx
|
||||
resip/dum/ClientRegistration.cxx
|
||||
resip/dum/ClientPublication.cxx
|
||||
resip/dum/ClientPagerMessage.cxx
|
||||
resip/dum/ClientOutOfDialogReq.cxx
|
||||
resip/dum/ClientInviteSession.cxx
|
||||
resip/dum/ClientAuthManager.cxx
|
||||
resip/dum/ClientAuthExtension.cxx
|
||||
resip/dum/ChallengeInfo.cxx
|
||||
resip/dum/CertMessage.cxx
|
||||
resip/dum/BaseUsage.cxx
|
||||
resip/dum/BaseSubscription.cxx
|
||||
resip/dum/BaseCreator.cxx
|
||||
resip/dum/AppDialogSetFactory.cxx
|
||||
resip/dum/AppDialogSet.cxx
|
||||
resip/dum/AppDialog.cxx
|
||||
resip/dum/KeepAliveTimeout.cxx
|
||||
resip/dum/KeepAliveManager.cxx
|
||||
resip/dum/InviteSessionHandler.cxx
|
||||
resip/dum/InviteSessionCreator.cxx
|
||||
resip/dum/InviteSession.cxx
|
||||
resip/dum/InMemorySyncRegDb.cxx
|
||||
resip/dum/InMemoryRegistrationDatabase.cxx
|
||||
resip/dum/IdentityHandler.cxx
|
||||
resip/dum/HttpProvider.cxx
|
||||
resip/dum/HttpGetMessage.cxx
|
||||
resip/dum/HandleManager.cxx
|
||||
resip/dum/HandleException.cxx
|
||||
resip/dum/Handled.cxx
|
||||
resip/dum/Handle.cxx
|
||||
resip/dum/EncryptionRequest.cxx
|
||||
resip/dum/DumTimeout.cxx
|
||||
resip/dum/DumThread.cxx
|
||||
resip/dum/DumProcessHandler.cxx
|
||||
resip/dum/DumHelper.cxx
|
||||
resip/dum/DumFeatureMessage.cxx
|
||||
resip/dum/DumFeatureChain.cxx
|
||||
resip/dum/DumFeature.cxx
|
||||
resip/dum/DumDecrypted.cxx
|
||||
resip/dum/ServerSubscription.cxx
|
||||
resip/dum/ServerRegistration.cxx
|
||||
resip/dum/ServerPublication.cxx
|
||||
resip/dum/ServerPagerMessage.cxx
|
||||
resip/dum/ServerOutOfDialogReq.cxx
|
||||
resip/dum/ServerInviteSession.cxx
|
||||
resip/dum/ServerAuthManager.cxx
|
||||
resip/dum/RegistrationHandler.cxx
|
||||
resip/dum/RegistrationCreator.cxx
|
||||
resip/dum/RedirectManager.cxx
|
||||
resip/dum/RADIUSServerAuthManager.cxx
|
||||
resip/dum/PublicationCreator.cxx
|
||||
resip/dum/Profile.cxx
|
||||
resip/dum/PagerMessageCreator.cxx
|
||||
resip/dum/OutOfDialogReqCreator.cxx
|
||||
resip/dum/OutgoingEvent.cxx
|
||||
resip/dum/NonDialogUsage.cxx
|
||||
resip/dum/NetworkAssociation.cxx
|
||||
resip/dum/MergedRequestRemovalCommand.cxx
|
||||
resip/dum/MergedRequestKey.cxx
|
||||
resip/dum/MasterProfile.cxx
|
||||
resip/dum/UserProfile.cxx
|
||||
resip/dum/UserAuthInfo.cxx
|
||||
resip/dum/TlsPeerAuthManager.cxx
|
||||
resip/dum/TargetCommand.cxx
|
||||
resip/dum/SubscriptionState.cxx
|
||||
resip/dum/SubscriptionHandler.cxx
|
||||
resip/dum/SubscriptionCreator.cxx
|
||||
resip/dum/ssl/EncryptionManager.cxx
|
||||
)
|
||||
|
||||
SET (RUTIL_SOURCES
|
||||
rutil/FileSystem.cxx
|
||||
rutil/FdPoll.cxx
|
||||
rutil/DnsUtil.cxx
|
||||
rutil/ssl/OpenSSLInit.cxx
|
||||
rutil/ssl/SHA1Stream.cxx
|
||||
rutil/dns/RRVip.cxx
|
||||
rutil/dns/RROverlay.cxx
|
||||
rutil/dns/RRList.cxx
|
||||
rutil/dns/RRCache.cxx
|
||||
rutil/dns/QueryTypes.cxx
|
||||
# rutil/dns/LocalDns.cxx
|
||||
rutil/dns/ExternalDnsFactory.cxx
|
||||
rutil/dns/DnsThread.cxx
|
||||
rutil/dns/DnsStub.cxx
|
||||
rutil/dns/DnsSrvRecord.cxx
|
||||
rutil/dns/DnsResourceRecord.cxx
|
||||
rutil/dns/DnsNaptrRecord.cxx
|
||||
rutil/dns/DnsHostRecord.cxx
|
||||
rutil/dns/DnsCnameRecord.cxx
|
||||
rutil/dns/DnsAAAARecord.cxx
|
||||
rutil/dns/AresDns.cxx
|
||||
rutil/DataStream.cxx
|
||||
rutil/Data.cxx
|
||||
rutil/CountStream.cxx
|
||||
rutil/ConfigParse.cxx
|
||||
# rutil/Condition.cxx
|
||||
rutil/Coders.cxx
|
||||
rutil/BaseException.cxx
|
||||
rutil/AbstractFifo.cxx
|
||||
rutil/XMLCursor.cxx
|
||||
rutil/vmd5.cxx
|
||||
rutil/TransportType.cxx
|
||||
rutil/Timer.cxx
|
||||
rutil/Time.cxx
|
||||
rutil/ThreadIf.cxx
|
||||
rutil/SysLogStream.cxx
|
||||
rutil/SysLogBuf.cxx
|
||||
rutil/Subsystem.cxx
|
||||
rutil/stun/Udp.cxx
|
||||
rutil/stun/Stun.cxx
|
||||
rutil/Socket.cxx
|
||||
rutil/ServerProcess.cxx
|
||||
rutil/SelectInterruptor.cxx
|
||||
rutil/RWMutex.cxx
|
||||
rutil/resipfaststreams.cxx
|
||||
# rutil/RecursiveMutex.cxx
|
||||
rutil/Random.cxx
|
||||
rutil/RADIUSDigestAuthenticator.cxx
|
||||
rutil/PoolBase.cxx
|
||||
rutil/Poll.cxx
|
||||
rutil/ParseException.cxx
|
||||
rutil/ParseBuffer.cxx
|
||||
# rutil/Mutex.cxx
|
||||
rutil/MD5Stream.cxx
|
||||
rutil/Log.cxx
|
||||
rutil/Lock.cxx
|
||||
rutil/KeyValueStore.cxx
|
||||
rutil/HeapInstanceCounter.cxx
|
||||
rutil/GeneralCongestionManager.cxx
|
||||
rutil/ssl/OpenSSLDeleter.hxx
|
||||
rutil/ssl/OpenSSLDeleter.cxx
|
||||
)
|
||||
|
||||
if (CMAKE_SYSTEM MATCHES "Windows*")
|
||||
set (RUTIL_SOURCES ${RUTIL_SOURCES} rutil/WinCompat.cxx)
|
||||
endif()
|
||||
|
||||
add_library(resiprocate STATIC ${ARES_SOURCES} ${RUTIL_SOURCES} ${STACK_SOURCES} ${DUM_SOURCES})
|
||||
|
||||
target_include_directories(resiprocate PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${DIR_ARES}
|
||||
${OPENSSL_INCLUDE}
|
||||
)
|
||||
|
||||
set (RESIP_DEFINES -DUSE_SSL -DUSE_IPV6 -DUSE_ARES)
|
||||
if (TARGET_WIN)
|
||||
set (RESIP_DEFINES ${RESIP_DEFINES} -DARES_LEGACY_DEFINES)
|
||||
else()
|
||||
set (RESIP_DEFINES ${RESIP_DEFINES} -DHAVE_ARPA_NAMESER_H)
|
||||
endif()
|
||||
|
||||
target_compile_definitions(resiprocate PUBLIC ${RESIP_DEFINES})
|
||||
target_link_libraries (resiprocate PUBLIC ${OPENSSL_SSL} ${OPENSSL_CRYPTO})
|
||||
833
src/libs/resiprocate/CMakeLists_stock.txt
Normal file
833
src/libs/resiprocate/CMakeLists_stock.txt
Normal file
@@ -0,0 +1,833 @@
|
||||
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/build/cmake_modules")
|
||||
|
||||
if(POLICY CMP0042)
|
||||
CMAKE_POLICY(SET CMP0042 NEW)
|
||||
endif(POLICY CMP0042)
|
||||
if(POLICY CMP0077)
|
||||
CMAKE_POLICY(SET CMP0077 NEW)
|
||||
endif(POLICY CMP0077)
|
||||
|
||||
# FIXME - how to include suffix such as 1.13.0~alpha1 ?
|
||||
# https://cmake.org/cmake/help/latest/variable/PROJECT_VERSION.html
|
||||
project(resiprocate VERSION 1.13.0)
|
||||
|
||||
# Warning: CMAKE_BUILD_TYPE
|
||||
#
|
||||
# Using CMAKE_BUILD_TYPE=Debug will create a build without the NDEBUG flag
|
||||
#
|
||||
# Any other CMAKE_BUILD_TYPE appears to set NDEBUG sometimes
|
||||
# Some documentation suggest that CMAKE_BUILD_TYPE=RelWithDebInfo will
|
||||
# not set the NDEBUG flag but this appears to be inconsistent.
|
||||
#
|
||||
# reSIProcate makes extensive use of assert()
|
||||
# assert() is disabled by NDEBUG
|
||||
# Application code should not rely on NDEBUG for any purpose, its only
|
||||
# purpose is for disabling assert()
|
||||
#
|
||||
# https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html#variable:CMAKE_BUILD_TYPE
|
||||
#
|
||||
|
||||
# shared library versioning
|
||||
|
||||
#set(SO_ABI "0.0.0")
|
||||
set(SO_RELEASE "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}")
|
||||
|
||||
include(GNUInstallDirs)
|
||||
include(Utilities)
|
||||
include(CheckStructHasMember)
|
||||
|
||||
enable_testing()
|
||||
|
||||
option(ENABLE_LOG_REPOSITORY_DETAILS "Log repository revision and branch" TRUE)
|
||||
if(ENABLE_LOG_REPOSITORY_DETAILS)
|
||||
find_package(Git REQUIRED)
|
||||
execute_process(
|
||||
COMMAND ${GIT_EXECUTABLE} describe --match="" --always --abbrev=40 --dirty
|
||||
OUTPUT_VARIABLE RESIPROCATE_GIT_ID
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
execute_process(
|
||||
COMMAND ${GIT_EXECUTABLE} rev-parse --abbrev-ref HEAD
|
||||
OUTPUT_VARIABLE RESIPROCATE_BRANCH_NAME
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
endif()
|
||||
|
||||
# https://cmake.org/cmake/help/latest/module/FindThreads.html
|
||||
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
|
||||
find_package(Threads REQUIRED)
|
||||
if(NOT Threads_FOUND)
|
||||
exit()
|
||||
endif()
|
||||
if(CMAKE_USE_PTHREADS_INIT)
|
||||
add_definitions(-D__REENTRANT)
|
||||
add_definitions(-pthread)
|
||||
endif()
|
||||
|
||||
set(REPRO_BUILD_REV ${PACKAGE_VERSION})
|
||||
set(REPRO_RELEASE_VERSION ${PACKAGE_VERSION})
|
||||
set(RESIP_SIP_MSG_MAX_BYTES 10485760)
|
||||
|
||||
# https://cmake.org/cmake/help/latest/module/TestBigEndian.html
|
||||
# see also
|
||||
# https://cmake.org/cmake/help/latest/variable/CMAKE_LANG_BYTE_ORDER.html
|
||||
include (TestBigEndian)
|
||||
test_big_endian(RESIP_BIG_ENDIAN)
|
||||
|
||||
CHECK_STRUCT_HAS_MEMBER(sockaddr_in sin_len arpa/inet.h HAVE_sockaddr_in_len)
|
||||
if(HAVE_sockaddr_in_len)
|
||||
add_definitions(-DHAVE_sockaddr_in_len)
|
||||
endif()
|
||||
|
||||
# Top-level user-settable variables (with defaults)
|
||||
# Those can be queried from the command line using "cmake -LH" and can be
|
||||
# specified on the command line, using cmake-gui or ccmake.
|
||||
option(WITH_C_ARES "Link against libc-ares (rather than rutil/dns/ares)" FALSE)
|
||||
option(WITH_SSL "Link against SSL libraries" TRUE)
|
||||
option(USE_POPT "Link against POPT libraries" FALSE)
|
||||
option(USE_SIGCOMP "Use OpenSigComp" FALSE)
|
||||
option(USE_FMT "Link against fmt library" FALSE)
|
||||
option(VERSIONED_SONAME "Include Major.Minor version in SONAME" TRUE)
|
||||
option(ENABLE_ANDROID "Enable Android build" FALSE)
|
||||
option(USE_IPV6 "Enable IPv6" TRUE)
|
||||
option(USE_DTLS "Enable DTLS" TRUE)
|
||||
option(PEDANTIC_STACK "Enable pedantic behavior (fully parse all messages)" FALSE)
|
||||
option(USE_MYSQL "Link against MySQL client libraries" FALSE)
|
||||
# some systems may have a newer version of libpq that is not
|
||||
# compatible with the packaged version of soci_postgresql
|
||||
option(USE_SOCI_POSTGRESQL "Build recon with SOCI PostgreSQL support" FALSE)
|
||||
# can't have both MariaDB C client and SOCI MySQL at the same
|
||||
# time in some environments, e.g. CentOS 8.1
|
||||
option(USE_SOCI_MYSQL "Build recon with SOCI MySQL support" FALSE)
|
||||
option(USE_POSTGRESQL "Link against PostgreSQL client libraries" FALSE)
|
||||
option(USE_MAXMIND_GEOIP "Link against MaxMind GeoIP libraries" FALSE)
|
||||
option(RESIP_HAVE_RADCLI "Link against radcli RADIUS client library" FALSE)
|
||||
option(USE_NETSNMP "Link against NetSNMP client libraries" FALSE)
|
||||
option(BUILD_REPRO "Build repro SIP proxy" TRUE)
|
||||
option(BUILD_DSO_PLUGINS "Build DSO plugins" TRUE)
|
||||
option(BUILD_RETURN "Build reTurn server" TRUE)
|
||||
option(BUILD_REND "Build rend" FALSE)
|
||||
option(BUILD_TFM "Build TFM, requires Netxx and cppunit" FALSE)
|
||||
option(BUILD_CLICKTOCALL "Build Click to call application" FALSE)
|
||||
option(BUILD_ICHAT_GW "Build iChat gateway, requires gloox" FALSE)
|
||||
option(BUILD_TELEPATHY_CM "Build Telepathy connection manager" FALSE)
|
||||
option(BUILD_RECON "Build reCon Conversation Manager library" FALSE)
|
||||
option(USE_SRTP1 "Use srtp 1.x instead of current version" FALSE)
|
||||
option(BUILD_RECONSERVER "Build reConServer" FALSE)
|
||||
option(USE_SIPXTAPI "Link against sipXtapi" FALSE)
|
||||
option(USE_KURENTO "Build Kurento client (requires websocketpp)" FALSE)
|
||||
option(USE_GSTREAMER "Link against Gstreamer" FALSE)
|
||||
option(USE_LIBWEBRTC "Link against LibWebRTC" FALSE)
|
||||
option(RECON_LOCAL_HW_TESTS "Attempt to use local audio hardware in unit tests" FALSE)
|
||||
option(BUILD_P2P "Build P2P, links against S2C and SSL, unfinished" FALSE)
|
||||
option(BUILD_PYTHON "Build components requiring Python" FALSE)
|
||||
option(BUILD_QPID_PROTON "Build components requiring qpid-proton (AMQP)" TRUE)
|
||||
option(RESIP_ASSERT_SYSLOG "Log assertion failures with Syslog" TRUE)
|
||||
option(REGENERATE_MEDIA_SAMPLES "Regenerate the header files containing raw audio samples (requires sox, xxd)" TRUE)
|
||||
|
||||
set(DEFAULT_BRIDGE_MAX_IN_OUTPUTS 20 CACHE STRING "recon: Maximum connections on bridge")
|
||||
|
||||
# This must be enabled when building with the Android ndkports tools.
|
||||
# It should not be enabled for any other case.
|
||||
option(USE_NDKPORTS_HACKS "Android ndkports build: use hardcoded paths to dependencies" FALSE)
|
||||
|
||||
#
|
||||
# Libtool / autotools is able to build both the static and shared
|
||||
# version of a library based on a single definition of the library.
|
||||
#
|
||||
# CMake is trying to support platforms like Windows that do not
|
||||
# allow both the static and shared library to share the same target
|
||||
# name.
|
||||
#
|
||||
# Therefore, with our initial CMake implementation, we only support
|
||||
# one type of build or the other.
|
||||
#
|
||||
# People who need both static and shared libraries can run the build
|
||||
# twice with alternate values of BUILD_SHARED_LIBS
|
||||
#
|
||||
# FIXME - can we replicate one of the hacks for building both static
|
||||
# and shared?
|
||||
# - it is a good idea to ask the CMake developers and ask the
|
||||
# packaging system maintainers (debhelper, rpmbuild)
|
||||
#
|
||||
# Example hacks:
|
||||
# https://stackoverflow.com/questions/2152077/is-it-possible-to-get-cmake-to-build-both-a-static-and-shared-library-at-the-sam
|
||||
# https://github.com/baresip/rem/pull/84/files
|
||||
#
|
||||
if(WIN32)
|
||||
set(BUILD_SHARED_LIBS_DEFAULT OFF)
|
||||
set(USE_CONTRIB_DEFAULT ON)
|
||||
set(USE_NUGET ON)
|
||||
else()
|
||||
set(BUILD_SHARED_LIBS_DEFAULT ON)
|
||||
set(USE_CONTRIB_DEFAULT OFF)
|
||||
set(USE_NUGET OFF)
|
||||
endif()
|
||||
option(BUILD_SHARED_LIBS "Build libraries as shared" ${BUILD_SHARED_LIBS_DEFAULT})
|
||||
option(USE_CONTRIB "Use libraries from contrib folder" ${USE_CONTRIB_DEFAULT})
|
||||
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
|
||||
########################
|
||||
### Helper functions ###
|
||||
########################
|
||||
|
||||
function(option_def)
|
||||
if(${ARGV0})
|
||||
add_definitions(-D${ARGV0})
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(set_def)
|
||||
set(${ARGV0} TRUE)
|
||||
add_definitions(-D${ARGV0})
|
||||
endfunction()
|
||||
|
||||
function(do_fail_win32)
|
||||
message(FATAL_ERROR "please complete Win32 support for ${ARGV0} in CMakeLists.txt")
|
||||
endfunction()
|
||||
|
||||
# See
|
||||
# https://cmake.org/cmake/help/latest/prop_tgt/SOVERSION.html
|
||||
# https://cmake.org/cmake/help/latest/prop_tgt/VERSION.html
|
||||
function(version_libname)
|
||||
if(SO_ABI)
|
||||
set_target_properties(${ARGV0} PROPERTIES SOVERSION ${SO_ABI})
|
||||
endif()
|
||||
# This logic tries to replicate the libtool -release X.Y ...
|
||||
# but it doesn't create the same symlink that libtool creates.
|
||||
# FIXME
|
||||
# Other people have complained about the same problem, e.g.
|
||||
# https://discourse.libsdl.org/t/patches-dynamic-library-name-should-it-be-libsdl2-2-0-so-or-libsdl2-so/19400/8
|
||||
if(VERSIONED_SONAME)
|
||||
set_target_properties(${ARGV0} PROPERTIES OUTPUT_NAME ${ARGV0}-${SO_RELEASE})
|
||||
file(CREATE_LINK lib${ARGV0}-${SO_RELEASE}.so ${CMAKE_CURRENT_BINARY_DIR}/lib${ARGV0}.so RESULT ${ARGV0}-IGNORE SYMBOLIC)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/lib${ARGV0}.so DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
if(NOT VERSIONED_SONAME)
|
||||
set(CMAKE_PLATFORM_NO_VERSIONED_SONAME True)
|
||||
endif()
|
||||
|
||||
################################
|
||||
### Per-program dependencies ###
|
||||
################################
|
||||
|
||||
set(USE_PCRE FALSE)
|
||||
set(USE_WEBSOCKETPP FALSE)
|
||||
|
||||
if(BUILD_REPRO)
|
||||
set(USE_BDB TRUE)
|
||||
set(USE_PCRE TRUE)
|
||||
set(USE_CAJUN TRUE)
|
||||
endif()
|
||||
|
||||
if(BUILD_RECON)
|
||||
set(USE_SRTP TRUE)
|
||||
endif()
|
||||
|
||||
if(BUILD_TFM)
|
||||
set(USE_NETXX TRUE)
|
||||
set(USE_CPPUNIT TRUE)
|
||||
endif()
|
||||
|
||||
if(BUILD_RETURN)
|
||||
set(USE_ASIO TRUE)
|
||||
#set(USE_BOOST TRUE) # Dependency has been replaced by C++11
|
||||
endif()
|
||||
|
||||
if(USE_KURENTO)
|
||||
set(USE_ASIO TRUE)
|
||||
set(USE_WEBSOCKETPP TRUE)
|
||||
endif()
|
||||
|
||||
if(BUILD_CLICKTOCALL)
|
||||
set(USE_PCRE TRUE)
|
||||
endif()
|
||||
|
||||
####################
|
||||
### Dependencies ###
|
||||
####################
|
||||
|
||||
if(NOT USE_CONTRIB)
|
||||
find_package(PkgConfig REQUIRED)
|
||||
endif()
|
||||
|
||||
# ares
|
||||
if(WITH_C_ARES)
|
||||
# Don't use built-in ares
|
||||
pkg_check_modules(cares libcares REQUIRED)
|
||||
|
||||
set(USE_CARES true)
|
||||
add_definitions(-DUSE_CARES)
|
||||
|
||||
set(ARES_LIBRARIES ${cares_LIBRARIES})
|
||||
include_directories(${cares_INCLUDE_DIR})
|
||||
else()
|
||||
# Use built-in ares
|
||||
set(USE_ARES true)
|
||||
add_definitions(-DUSE_ARES)
|
||||
|
||||
# Put the resip ares include dir before the system ones to not conflict with
|
||||
# c-ares if also present.
|
||||
include_directories(BEFORE rutil/dns/ares)
|
||||
|
||||
set(ARES_LIBRARIES resipares)
|
||||
endif()
|
||||
|
||||
if("${CMAKE_EXE_LINKER_FLAGS}" STREQUAL "/machine:x64")
|
||||
set(WIN_ARCH "x64")
|
||||
else()
|
||||
set(WIN_ARCH "Win32")
|
||||
endif()
|
||||
|
||||
# Download NuGet Package Manager and ensure it is in %PATH%
|
||||
# before running CMake
|
||||
if(USE_NUGET)
|
||||
find_program(NUGET_EXE NAMES nuget.exe REQUIRED)
|
||||
endif()
|
||||
|
||||
function(nuget_inst)
|
||||
exec_program(${NUGET_EXE}
|
||||
ARGS install "${ARGV1}" -Version ${ARGV2} -ExcludeVersion -OutputDirectory ${CMAKE_BINARY_DIR}/packages
|
||||
)
|
||||
set(${ARGV0}_TARGETS ${CMAKE_BINARY_DIR}/packages/${ARGV1}/build/native/${ARGV1}.targets PARENT_SCOPE)
|
||||
|
||||
set(PKG_TOP "${CMAKE_BINARY_DIR}/packages/${ARGV1}/build/native")
|
||||
set(PKG_LIB "${PKG_TOP}/lib/${WIN_ARCH}/Debug") # FIXME
|
||||
|
||||
set(${ARGV0}_ROOT_DIR "${PKG_TOP}" PARENT_SCOPE)
|
||||
|
||||
# These vary a lot from one package to the next. We
|
||||
# set them to some common default values but in many
|
||||
# cases the subsequent code needs to override these
|
||||
# values with package-specific values.
|
||||
set(${ARGV0}_INCLUDE_DIRS "${PKG_TOP}/include" PARENT_SCOPE)
|
||||
set(${ARGV0}_LIBRARIES_DIR "${PKG_LIB}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# OpenSSL
|
||||
if(WITH_SSL)
|
||||
if(USE_NUGET)
|
||||
nuget_inst(OPENSSL "zeroc.openssl.v142" "1.1.1.2")
|
||||
message("Using ${OPENSSL_ROOT_DIR} and ${OPENSSL_LIBRARIES}")
|
||||
# this is an argument to FindOpenSSL
|
||||
# https://cmake.org/cmake/help/latest/module/FindOpenSSL.html
|
||||
set(OPENSSL_USE_STATIC_LIBS True)
|
||||
# set(OPENSSL_CRYPTO_LIBRARY "${OPENSSL_LIBRARIES}/libcrypto.lib")
|
||||
set(OPENSSL_LIBRARIES
|
||||
"${OPENSSL_LIBRARIES_DIR}/libssl.lib"
|
||||
"${OPENSSL_LIBRARIES_DIR}/libcrypto.lib")
|
||||
# FIXME - check if those libraries and headers really exist
|
||||
set(OPENSSL_FOUND TRUE)
|
||||
elseif(USE_NDKPORTS_HACKS)
|
||||
if(NOT ANDROID_ABI)
|
||||
message(FATAL_ERROR "ndkports hack requested but ANDROID_ABI not set")
|
||||
endif()
|
||||
#set(distribution_DIR ${CMAKE_SOURCE_DIR}/../../../../distribution)
|
||||
#set(OPENSSL_ROOT_DIR ${distribution_DIR}/openssl/${ANDROID_ABI})
|
||||
set(OPENSSL_ROOT_DIR /src/openssl/build/port/aar/prefab/modules)
|
||||
|
||||
set(CRYPTO_LIBRARIES_DIR "${OPENSSL_ROOT_DIR}/crypto/libs/android.${ANDROID_ABI}")
|
||||
set(SSL_LIBRARIES_DIR "${OPENSSL_ROOT_DIR}/ssl/libs/android.${ANDROID_ABI}")
|
||||
set(OPENSSL_INCLUDE_DIR ${OPENSSL_ROOT_DIR}/ssl/include)
|
||||
set(OPENSSL_LIBRARIES
|
||||
"${SSL_LIBRARIES_DIR}/libssl.so"
|
||||
"${CRYPTO_LIBRARIES_DIR}/libcrypto.so")
|
||||
# FIXME - check if those libraries and headers really exist
|
||||
set(OPENSSL_FOUND TRUE)
|
||||
else()
|
||||
# SSL support is requested, so make it mandatory when calling find_package
|
||||
find_package(OpenSSL REQUIRED) # HINTS ${OPENSSL_LIBRARIES})
|
||||
endif()
|
||||
# Oldest OpenSSL API to target (1.1.1)
|
||||
add_compile_definitions(OPENSSL_API_COMPAT=0x10101000L)
|
||||
set_def(USE_SSL)
|
||||
else()
|
||||
# Explicitly set OPENSSL_FOUND to false since we didn't even run
|
||||
# find_package on it. It needs to be set to false for other CMake scripts to
|
||||
# know it is not being used.
|
||||
set(OPENSSL_FOUND FALSE)
|
||||
endif()
|
||||
|
||||
# popt
|
||||
# Debian: libpopt-dev
|
||||
if(USE_POPT)
|
||||
if(USE_CONTRIB)
|
||||
add_subdirectory(contrib/popt)
|
||||
set(POPT_LIBRARIES popt)
|
||||
set(POPT_INCLUDE_DIRS contrib/popt)
|
||||
else()
|
||||
find_package(popt REQUIRED)
|
||||
endif()
|
||||
set(HAVE_POPT_H true)
|
||||
add_definitions(-DHAVE_POPT_H)
|
||||
endif()
|
||||
|
||||
# OpenSigComp
|
||||
if(USE_SIGCOMP)
|
||||
if(USE_CONTRIB)
|
||||
add_subdirectory(contrib/opensigcomp)
|
||||
set(opensigcomp_LIBRARIES opensigcomp)
|
||||
else()
|
||||
find_package(opensigcomp REQUIRED)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# fmt
|
||||
# Debian: libfmt-dev
|
||||
if(USE_FMT)
|
||||
if(USE_CONTRIB)
|
||||
add_subdirectory(contrib/fmt)
|
||||
else()
|
||||
find_package(fmt REQUIRED)
|
||||
endif()
|
||||
set_def(USE_FMT)
|
||||
endif()
|
||||
|
||||
option_def(USE_IPV6)
|
||||
option_def(USE_DTLS)
|
||||
option_def(PEDANTIC_STACK)
|
||||
|
||||
# MySQL
|
||||
# Debian: default-libmysqlclient-dev
|
||||
if(USE_MYSQL)
|
||||
if(USE_CONTRIB)
|
||||
# There is a pre-compiled MySQL client binary in contrib
|
||||
# so we hardcode the paths to the headers and binary
|
||||
# artifacts.
|
||||
#add_subdirectory(contrib/MySQLConnectorC)
|
||||
set(MySQL_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/contrib/MySQLConnectorC")
|
||||
set(MySQL_INCLUDE_DIRS "${MySQL_ROOT}/include")
|
||||
set(MySQL_LIBRARIES "${MySQL_ROOT}/lib/debug/libmysql.lib")
|
||||
set(MySQL_FOUND TRUE)
|
||||
else()
|
||||
find_package(MySQL REQUIRED)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# soci (MySQL, PostgreSQL)
|
||||
# Debian: libsoci-dev
|
||||
# FIXME - hardcoded
|
||||
# FIXME - MySQL, PostgreSQL
|
||||
if(USE_SOCI_POSTGRESQL OR USE_SOCI_MYSQL)
|
||||
find_library(SOCI_LIBRARIES soci_core REQUIRED)
|
||||
# FIXME include path
|
||||
set(SOCI_INCLUDE_DIRS "/usr/include/soci")
|
||||
option_def(USE_SOCI_POSTGRESQL)
|
||||
option_def(USE_SOCI_MYSQL)
|
||||
endif()
|
||||
|
||||
# PostgreSQL
|
||||
# Debian: libpq-dev postgresql-server-dev-all
|
||||
if(USE_POSTGRESQL)
|
||||
if(USE_CONTRIB)
|
||||
add_subdirectory(contrib/psql)
|
||||
else()
|
||||
find_package(PostgreSQL REQUIRED)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# GeoIP
|
||||
# Debian: libgeoip-dev
|
||||
if(USE_MAXMIND_GEOIP)
|
||||
if(USE_CONTRIB)
|
||||
# FIXME - update reSIProcate for libmaxminddb - successor to GeoIP
|
||||
message(FATAL_ERROR "GeoIP has been deprecated upstream, see https://github.com/maxmind/geoip-api-c")
|
||||
#add_subdirectory(contrib/GeoIP)
|
||||
else()
|
||||
find_package(GeoIP REQUIRED)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# radcli (RADIUS client)
|
||||
# Debian: libradcli-dev
|
||||
# FIXME: do we need to support alternatives like
|
||||
# freeradius-client and radiusclient-ng?
|
||||
if(RESIP_HAVE_RADCLI)
|
||||
if(USE_CONTRIB)
|
||||
do_fail_win32("radcli")
|
||||
else()
|
||||
pkg_check_modules(LIBRADIUS radcli REQUIRED)
|
||||
endif()
|
||||
option_def(RESIP_HAVE_RADCLI)
|
||||
set_def(USE_RADIUS_CLIENT)
|
||||
endif()
|
||||
|
||||
# NetSNMP
|
||||
# Debian: libsnmp-dev
|
||||
if(USE_NETSNMP)
|
||||
if(USE_CONTRIB)
|
||||
do_fail_win32("netsnmp")
|
||||
else()
|
||||
# net-snmp-config --agent-libs
|
||||
pkg_check_modules(NETSNMP_AGENT netsnmp-agent REQUIRED)
|
||||
endif()
|
||||
set_def(USE_NETSNMP)
|
||||
endif()
|
||||
|
||||
option_def(BUILD_REPRO)
|
||||
|
||||
set(CMAKE_INSTALL_PKGLIBDIR ${CMAKE_INSTALL_LIBDIR}/${CMAKE_PROJECT_NAME})
|
||||
set(CMAKE_INSTALL_MIBDIR ${CMAKE_INSTALL_DATAROOTDIR}/snmp/mibs)
|
||||
|
||||
if(BUILD_DSO_PLUGINS)
|
||||
add_definitions(-DDSO_PLUGINS)
|
||||
set(INSTALL_REPRO_PLUGIN_DIR ${CMAKE_INSTALL_PKGLIBDIR}/repro/plugins)
|
||||
endif()
|
||||
|
||||
set(INSTALL_RETURN_PKGLIB_DIR ${CMAKE_INSTALL_PKGLIBDIR}/reTurnServer)
|
||||
|
||||
option_def(BUILD_RETURN)
|
||||
|
||||
option_def(BUILD_REND)
|
||||
|
||||
option_def(BUILD_TFM)
|
||||
|
||||
# BUILD_APPS has been omitted
|
||||
|
||||
option_def(BUILD_ICHAT_GW)
|
||||
|
||||
# Netxx
|
||||
# Debian: libnetxx-dev
|
||||
if(USE_NETXX)
|
||||
if(USE_CONTRIB)
|
||||
add_subdirectory(contrib/Netxx-0.3.2)
|
||||
set(Netxx_LIBRARIES Netxx)
|
||||
else()
|
||||
find_package(Netxx REQUIRED)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# cppunit
|
||||
# Debian: libcppunit-dev
|
||||
if(USE_CPPUNIT)
|
||||
if(USE_CONTRIB)
|
||||
add_subdirectory(contrib/cppunit)
|
||||
set(CPPUNIT_LIBRARIES cppunit)
|
||||
else()
|
||||
pkg_check_modules(CPPUNIT cppunit REQUIRED)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# BerkeleyDb
|
||||
# Debian: libdb++-dev
|
||||
if(USE_BDB)
|
||||
if(USE_NUGET)
|
||||
#nuget_inst(BERKELEYDB "BerkeleyDB-4_8_30-Cpp" "4.8.30.2")
|
||||
#set(BERKELEYDB_LIBRARIES_DIR "${BERKELEYDB_ROOT_DIR}/bin")
|
||||
#set(BERKELEYDB_LIBRARIES
|
||||
# "${BERKELEYDB_LIBRARIES_DIR}/lib/${WIN_ARCH}/Debug/libdb48d.lib")
|
||||
# https://www.nuget.org/packages/berkeley.db.v140
|
||||
nuget_inst(BERKELEYDB "berkeley.db.v140" "5.3.28.3")
|
||||
set(BERKELEYDB_LIBRARIES_DIR "${BERKELEYDB_ROOT_DIR}/lib/${WIN_ARCH}/Debug")
|
||||
set(BERKELEYDB_LIBRARIES
|
||||
"${BERKELEYDB_LIBRARIES_DIR}/libdb53d.lib")
|
||||
# FIXME - check if those libraries and headers really exist
|
||||
set(BERKELEYDB_FOUND TRUE)
|
||||
elseif(USE_CONTRIB)
|
||||
add_subdirectory(contrib/db)
|
||||
else()
|
||||
find_package(BerkeleyDb REQUIRED)
|
||||
endif()
|
||||
set(DB_HEADER "db_cxx.h")
|
||||
endif()
|
||||
|
||||
# PCRE
|
||||
# Debian: libpcre3-dev
|
||||
# FIXME - deprecate PCRE in favour of C++11 <regex>
|
||||
if(USE_PCRE)
|
||||
if(USE_NUGET)
|
||||
nuget_inst(PCRE "pcre" "8.33.0.1")
|
||||
if(BUILD_SHARED_LIBS)
|
||||
set(WIN_LIB_LINKING "dynamic")
|
||||
else()
|
||||
set(WIN_LIB_LINKING "static")
|
||||
add_definitions(-DPCRE_STATIC)
|
||||
endif()
|
||||
set(PCRE_LIBRARIES_DIR "${PCRE_ROOT_DIR}/lib/v110/${WIN_ARCH}/Debug/${WIN_LIB_LINKING}/utf8")
|
||||
set(PCRE_LIBRARIES
|
||||
"${PCRE_LIBRARIES_DIR}/pcre8.lib")
|
||||
# FIXME - check if those libraries and headers really exist
|
||||
if(NOT EXISTS "${PCRE_LIBRARIES}")
|
||||
message(FATAL_ERROR "could not find ${PCRE_LIBRARIES}")
|
||||
endif()
|
||||
set(PCRE_FOUND TRUE)
|
||||
elseif(USE_CONTRIB)
|
||||
add_subdirectory(contrib/pcre)
|
||||
set(PCRE_LIBRARIES pcre)
|
||||
else()
|
||||
pkg_check_modules(PCRE REQUIRED libpcre)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Cajun
|
||||
# Debian: libcajun-dev
|
||||
if(USE_CAJUN)
|
||||
if(USE_CONTRIB)
|
||||
# FIXME: convert Cajun to CMake build system
|
||||
# FIXME: include Cajun as a Git submodule or NuGet
|
||||
#add_subdirectory(contrib/cajun)
|
||||
set(CAJUN_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/contrib/cajun/include")
|
||||
else()
|
||||
find_package(cajun REQUIRED)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# ASIO
|
||||
# Debian: libasio-dev
|
||||
# modern ASIO requires C++11
|
||||
if(USE_ASIO)
|
||||
if(USE_CONTRIB)
|
||||
# FIXME: include asio as a Git submodule or NuGet
|
||||
set(ASIO_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/contrib/asio")
|
||||
else()
|
||||
find_package(ASIO REQUIRED)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Boost
|
||||
# Debian: libboost-all-dev
|
||||
if(USE_BOOST)
|
||||
if(USE_NUGET)
|
||||
nuget_inst(BOOST "boost" "1.80.0")
|
||||
message("Using ${BOOST_ROOT_DIR} and ${BOOST_LIBRARIES}")
|
||||
set(BOOST_LIBRARIES
|
||||
"${BOOST_LIBRARIES_DIR}/libboostcore.lib")
|
||||
# FIXME - check if those libraries and headers really exist
|
||||
set(BOOST_FOUND TRUE)
|
||||
else()
|
||||
find_package(Boost REQUIRED)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(BUILD_TELEPATHY_CM)
|
||||
option_def(BUILD_TELEPATHY_CM)
|
||||
set(USE_QT5)
|
||||
endif()
|
||||
|
||||
# Telepathy-Qt
|
||||
# Debian: libtelepathy-qt5-dev
|
||||
if(USE_QT5)
|
||||
# PKG_CHECK_MODULES([QT5], [Qt5Core, Qt5DBus Qt5Network])
|
||||
# PKG_CHECK_MODULES([TP_QT5], [TelepathyQt5, TelepathyQt5Service])])
|
||||
find_package(TelepathyQt5 REQUIRED)
|
||||
endif()
|
||||
|
||||
option_def(BUILD_RECON)
|
||||
|
||||
# SRTP2
|
||||
# Debian: libsrtp2-dev
|
||||
if(USE_SRTP)
|
||||
if(USE_SRTP1)
|
||||
find_package(srtp REQUIRED)
|
||||
else()
|
||||
# FIXME - not in NuGet, not CMake native
|
||||
if(USE_CONTRIB)
|
||||
add_subdirectory("contrib/srtp")
|
||||
#set(libsrtp2_INCLUDE_DIRS "${libsrtp2_INCLUDE_DIRS}")
|
||||
#set(libsrtp2_LIBRARIES "${libsrtp2_LIBRARIES}")
|
||||
# FIXME - these shouldn't be hard-coded, need to fix the above variables
|
||||
set(SRTP2_INCLUDE_DIRS "${libsrtp2_SOURCE_DIR}/include")
|
||||
set(SRTP2_LIBRARIES "${libsrtp2_BINARY_DIR}/contrib/srtp/${CMAKE_BUILD_TYPE}/srtp2.lib")
|
||||
set(SRTP_FOUND TRUE)
|
||||
else()
|
||||
find_package(srtp2 REQUIRED)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# sipXtapi
|
||||
# Debian: libsipxtapi-dev
|
||||
if(USE_SIPXTAPI)
|
||||
option_def(USE_SIPXTAPI)
|
||||
find_package(sipXtapi REQUIRED)
|
||||
if(NOT WIN32)
|
||||
set(SIPX_NO_RECORD true)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D__pingtel_on_posix__")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
option_def(USE_KURENTO)
|
||||
|
||||
# gstreamermm
|
||||
# Debian: libgstreamermm-1.0-dev
|
||||
if(USE_GSTREAMER)
|
||||
option_def(USE_GSTREAMER)
|
||||
pkg_check_modules(GSTREAMERMM_1_0 gstreamermm-1.0 REQUIRED)
|
||||
|
||||
# gstwebrtc-1.0
|
||||
# Debian: libgstreamer-plugins-bad1.0-dev
|
||||
pkg_check_modules(GST_WEBRTC gstreamer-webrtc-1.0 REQUIRED)
|
||||
endif()
|
||||
|
||||
option_def(USE_LIBWEBRTC)
|
||||
|
||||
option_def(RECON_LOCAL_HW_TESTS)
|
||||
|
||||
# Python
|
||||
# Debian: python3-dev python3-cxx-dev
|
||||
if(BUILD_PYTHON)
|
||||
find_package(Python3 COMPONENTS Development REQUIRED)
|
||||
pkg_check_modules(PYCXX PyCXX REQUIRED)
|
||||
if(NOT PYCXX_SRCDIR)
|
||||
pkg_get_variable(PYCXX_SRCDIR PyCXX srcdir)
|
||||
if(NOT PYCXX_SRCDIR)
|
||||
message(FATAL_ERROR "Failed to obtain PyCXX srcdir automatically, please set it manually or disable BUILD_PYTHON")
|
||||
endif()
|
||||
endif()
|
||||
add_definitions(-DPy_LIMITED_API=0x03090000)
|
||||
endif()
|
||||
|
||||
# Apache Qpid Proton
|
||||
# Debian: libqpid-proton-cpp12-dev
|
||||
if(BUILD_QPID_PROTON)
|
||||
if(USE_NUGET)
|
||||
# FIXME - they only publish the C API, need full C++ API
|
||||
nuget_inst(QPIDPROTON "Apache.Qpid.Proton" "1.0.0-M6")
|
||||
message("Using ${QPIDPROTON_ROOT_DIR} and ${QPIDPROTON_LIBRARIES}")
|
||||
set(QPIDPROTON_LIBRARIES
|
||||
"${QPIDPROTON_LIBRARIES_DIR}/libqpidproton.lib")
|
||||
# FIXME - check if those libraries and headers really exist
|
||||
set(QPIDPROTON_FOUND TRUE)
|
||||
else()
|
||||
pkg_check_modules(QPIDPROTON libqpid-proton-cpp REQUIRED)
|
||||
endif()
|
||||
option_def(BUILD_QPID_PROTON)
|
||||
endif()
|
||||
|
||||
option_def(RESIP_ASSERT_SYSLOG)
|
||||
|
||||
# FIXME
|
||||
# The AC_SEARCH_LIBS macro from autotools doesn't
|
||||
# appear to have an equivalent in CMake.
|
||||
# If we need to link against nsl or socket then it
|
||||
# needs to be specified manuall on the CMake command line.
|
||||
# AC_SEARCH_LIBS(gethostbyname, nsl)
|
||||
# AC_SEARCH_LIBS(socket, socket)
|
||||
|
||||
# websocketpp
|
||||
# Debian: libwebsocketpp-dev
|
||||
if(USE_WEBSOCKETPP)
|
||||
if(USE_NUGET)
|
||||
nuget_inst(WEBSOCKETPP "websocketpp-mtk.repack" "0.7.0-mtk19")
|
||||
message("Using ${WEBSOCKETPP_ROOT_DIR} and ${WEBSOCKETPP_LIBRARIES}")
|
||||
set(WEBSOCKETPP_LIBRARIES
|
||||
"${WEBSOCKETPP_LIBRARIES_DIR}/libwebsocketpp.lib")
|
||||
# FIXME - check if those libraries and headers really exist
|
||||
set(WEBSOCKETPP_FOUND TRUE)
|
||||
else()
|
||||
find_package(websocketpp REQUIRED)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# monotonic clock
|
||||
include(CheckCSourceRuns)
|
||||
|
||||
check_c_source_runs("
|
||||
#include <time.h>
|
||||
int main() {
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
return 0;
|
||||
}" HAVE_CLOCK_GETTIME_MONOTONIC)
|
||||
|
||||
if(HAVE_CLOCK_GETTIME_MONOTONIC)
|
||||
add_definitions(-DHAVE_CLOCK_GETTIME_MONOTONIC)
|
||||
endif()
|
||||
|
||||
# epoll
|
||||
include(CheckIncludeFiles)
|
||||
check_include_files(sys/epoll.h HAVE_EPOLL)
|
||||
|
||||
# HAVE_LIBDL from autotools obsolete,
|
||||
# now we use CMAKE_DL_LIBS to include the library
|
||||
# when necessary
|
||||
|
||||
# gperf
|
||||
set(GPERF_SIZE_TYPE "size_t")
|
||||
|
||||
if(WIN32)
|
||||
add_definitions(-DNOMINMAX)
|
||||
endif()
|
||||
|
||||
##############################
|
||||
### Generation of config.h ###
|
||||
##############################
|
||||
# TODO - Bring more values from autotools
|
||||
add_definitions(-DHAVE_CONFIG_H)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
# Used to group targets together when CMake generates projects for IDEs
|
||||
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||
|
||||
add_subdirectory(rutil)
|
||||
|
||||
add_subdirectory(resip)
|
||||
|
||||
if(BUILD_REPRO)
|
||||
add_subdirectory(repro)
|
||||
endif()
|
||||
|
||||
if(BUILD_TFM)
|
||||
add_subdirectory(tfm)
|
||||
endif()
|
||||
|
||||
add_subdirectory(media)
|
||||
|
||||
if(BUILD_RETURN)
|
||||
add_subdirectory(reTurn)
|
||||
endif()
|
||||
|
||||
if(BUILD_RECON)
|
||||
add_subdirectory(reflow)
|
||||
endif()
|
||||
|
||||
if(BUILD_P2P)
|
||||
add_subdirectory(p2p)
|
||||
endif()
|
||||
|
||||
add_subdirectory(apps)
|
||||
|
||||
# Create spec file for RPM packaging
|
||||
# The tarball containing a spec file can be fed directly
|
||||
# to the rpmbuild command.
|
||||
configure_file(
|
||||
resiprocate.spec.in
|
||||
resiprocate.spec
|
||||
@ONLY)
|
||||
|
||||
# Add 'make dist' command for creating release tarball
|
||||
set (CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
|
||||
set (CPACK_SOURCE_GENERATOR "TGZ")
|
||||
set (CPACK_SOURCE_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}-${CPACK_PACKAGE_VERSION}")
|
||||
|
||||
# pax appears to be the default, we need it due to some filenames
|
||||
#set (COMPRESSION_OPTIONS --format=pax)
|
||||
|
||||
list(APPEND CPACK_SOURCE_IGNORE_FILES "/\\\\.git/")
|
||||
list(APPEND CPACK_SOURCE_IGNORE_FILES "\\\\.gitignore")
|
||||
list(APPEND CPACK_SOURCE_IGNORE_FILES "/CMakeFiles/")
|
||||
list(APPEND CPACK_SOURCE_IGNORE_FILES "/_CPack_Packages/")
|
||||
list(APPEND CPACK_SOURCE_IGNORE_FILES "\\\\.deps/")
|
||||
list(APPEND CPACK_SOURCE_IGNORE_FILES "\\\\.libs/")
|
||||
list(APPEND CPACK_SOURCE_IGNORE_FILES "/.*\\\\.gz")
|
||||
list(APPEND CPACK_SOURCE_IGNORE_FILES "/.*\\\\.zip")
|
||||
list(APPEND CPACK_SOURCE_IGNORE_FILES ".*\\\\.o")
|
||||
list(APPEND CPACK_SOURCE_IGNORE_FILES "lib.*\\\\.so*")
|
||||
list(APPEND CPACK_SOURCE_IGNORE_FILES "/CMakeCache.txt")
|
||||
list(APPEND CPACK_SOURCE_IGNORE_FILES "/contrib/")
|
||||
list(APPEND CPACK_SOURCE_IGNORE_FILES "/debian/")
|
||||
list(APPEND CPACK_SOURCE_IGNORE_FILES "Makefile")
|
||||
list(APPEND CPACK_SOURCE_IGNORE_FILES "/config.h$")
|
||||
|
||||
include (CPack)
|
||||
add_custom_target (dist COMMAND ${CMAKE_MAKE_PROGRAM} package_source)
|
||||
|
||||
###############
|
||||
### Summary ###
|
||||
###############
|
||||
|
||||
include(FeatureSummary)
|
||||
feature_summary(WHAT ALL)
|
||||
54
src/libs/resiprocate/COPYING
Normal file
54
src/libs/resiprocate/COPYING
Normal file
@@ -0,0 +1,54 @@
|
||||
License note:
|
||||
- each source file has a license enclosed, usually in comments at
|
||||
the end of the file
|
||||
- individual authors have not always used an identical license
|
||||
block in their code, yet all the license blocks are for most
|
||||
purposes equivalent and compatible with the standard 3 clause
|
||||
BSD license
|
||||
- the bulk of the code is licensed under the terms of the Vovida
|
||||
license, which is like the BSD license with a 4th clause
|
||||
added restricting the use of the term VOCAL in the name
|
||||
of any derivative work. A full copy of the Vovida license
|
||||
is presented below.
|
||||
|
||||
|
||||
|
||||
The Vovida Software License, Version 1.0
|
||||
|
||||
Copyright (c) 2000-2008 Vovida Networks, Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
3. The names "VOCAL", "Vovida Open Communication Application Library",
|
||||
and "Vovida Open Communication Application Library (VOCAL)" must
|
||||
not be used to endorse or promote products derived from this
|
||||
software without prior written permission. For written
|
||||
permission, please contact vocal@vovida.org.
|
||||
|
||||
4. Products derived from this software may not be called "VOCAL", nor
|
||||
may "VOCAL" appear in their name, without prior written
|
||||
permission of Vovida Networks, Inc.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
|
||||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
|
||||
NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
|
||||
NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
|
||||
IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGE.
|
||||
79
src/libs/resiprocate/INSTALL
Normal file
79
src/libs/resiprocate/INSTALL
Normal file
@@ -0,0 +1,79 @@
|
||||
|
||||
|
||||
a) If using source code from the repository (not a tarball download),
|
||||
you must bootstrap the source tree:
|
||||
|
||||
autoreconf --install
|
||||
|
||||
This must be done:
|
||||
- after checking out the code for the first time
|
||||
- after changing configure.ac or any Makefile.am file
|
||||
|
||||
NOTE: the bootstrap process only works reliably when using the same
|
||||
(or a very similar) version of autotools as the officially
|
||||
tested reSIProcate releases. The official releases are
|
||||
bootstrapped using autotools on a Debian 6.0 (squeeze) system.
|
||||
|
||||
b) Run configure:
|
||||
|
||||
e.g. on a Debian system:
|
||||
|
||||
./configure --with-ssl --with-mysql --with-c-ares \
|
||||
CXXFLAGS="-DRESIP_FIXED_POINT"
|
||||
|
||||
NOTE: some things (e.g. reTurnServer) will ONLY build if you
|
||||
specify --with-ssl to link against SSL libraries
|
||||
|
||||
A more complete example, with tfm:
|
||||
|
||||
./configure \
|
||||
--with-ssl --with-mysql --with-radius --with-tfm \
|
||||
--enable-ipv6 \
|
||||
CXXFLAGS="-I`pwd`/contrib/Netxx-0.3.2/include" \
|
||||
LDFLAGS="-L`pwd`/contrib/Netxx-0.3.2/src"
|
||||
|
||||
(hint: if it fails to link against libNetxx.so, create a symlink, or
|
||||
delete libNetxx.so and it should link against libNetxx.a)
|
||||
|
||||
OR (using contrib/ares)
|
||||
|
||||
./configure --with-ssl --with-mysql --enable-ipv6 --with-popt"
|
||||
|
||||
c) Build everything:
|
||||
|
||||
make
|
||||
|
||||
or to build just one thing:
|
||||
|
||||
make -C rutil
|
||||
|
||||
and if you have multiple CPUs/CPU-cores/hyper-threading, you can build
|
||||
faster by telling make to use them in parallel, e.g.:
|
||||
|
||||
make -j 12
|
||||
|
||||
d) Test it, e.g. to test rutil:
|
||||
|
||||
make -C rutil check
|
||||
|
||||
e) Install somewhere:
|
||||
|
||||
mkdir /tmp/my-resip && make DESTDIR=/tmp/my-resip install
|
||||
|
||||
Supported Systems
|
||||
-----------------
|
||||
|
||||
Supported Platforms: (to add new platform support see build/Makefile.osarch)
|
||||
FreeBSD
|
||||
Linux
|
||||
QNX
|
||||
SunOS
|
||||
Mac
|
||||
cygwin
|
||||
|
||||
Supported toolchains: (to add new toolchain support see build/Makefile.tools)
|
||||
gnu (g++)
|
||||
Intel (icc)
|
||||
ARM cross-compiler (arm-linux-g++)
|
||||
Sunpro (CC)
|
||||
|
||||
111
src/libs/resiprocate/README
Normal file
111
src/libs/resiprocate/README
Normal file
@@ -0,0 +1,111 @@
|
||||
|
||||
-----------------------------------------------------------
|
||||
|
||||
IMPORTANT
|
||||
|
||||
- the notes below relate to the legacy build
|
||||
system from reSIProcate <= 1.7.x
|
||||
|
||||
- now, with reSIProcate 1.8.x and beyond,
|
||||
please see:
|
||||
|
||||
http://www.resiprocate.org/AutotoolsBuild
|
||||
|
||||
and
|
||||
|
||||
http://www.resiprocate.org/Configuration_Options
|
||||
|
||||
|
||||
-----------------------------------------------------------
|
||||
|
||||
Notes for the legacy build system:
|
||||
|
||||
|
||||
The legacy reSIProcate build system is derived from
|
||||
the VOCAL build system (http://www.vovida.org).
|
||||
|
||||
Adding New Files to a module
|
||||
----------------------------
|
||||
|
||||
Example: Adding a new file Foo.cxx to the stack
|
||||
|
||||
1) Edit resip/stack/Makefile
|
||||
2) Add Foo.cxx to the SRC list
|
||||
|
||||
Example: Adding a new file Bar.cxx to rutil
|
||||
1) Edit rutil/Makefile
|
||||
2) Add Bar.cxx to the SRC list
|
||||
|
||||
Notes:
|
||||
- All files noted in SRC list will be added to the target library
|
||||
- Adding a new header file does not need to be noted in the Makefile
|
||||
- To add something to the compile line add to CXXFLAGS.
|
||||
e.g. CXXFLAGS += -DMYSPECIALDEFINE
|
||||
- To add something to the link line add to LDFLAGS and/or LDLIBS
|
||||
e.g. LDFLAGS += -L/usr/local/myspeciallibdir
|
||||
e.g. LDLIBS += -lmyspeciallib
|
||||
|
||||
Creating an application based on the stack:
|
||||
|
||||
Option 1: (Using the resip build system)
|
||||
For example applications using the resip build system look at resip/stack/test or at repro.
|
||||
|
||||
###########################################################################################
|
||||
# Create a Makefile in the directory with the units with the following template
|
||||
# This should be the path to the build directory of resip (in the sip subdirectory)
|
||||
BUILD = ../../build
|
||||
|
||||
# Includes macros
|
||||
include $(BUILD)/Makefile.pre
|
||||
|
||||
# Add any options that need to be passed to the C++ compiler here
|
||||
#CXXFLAGS += -DMYSPECIALDEFINE
|
||||
|
||||
# Add any options that need to be passed to the C compiler here
|
||||
#CFLAGS += -DMYOTHERDEFINE
|
||||
|
||||
# Add any options that need to be passed to the linker here
|
||||
#LDFLAGS += -L/usr/local/mydir
|
||||
|
||||
# Add any libraries that need to be passed to the linker here
|
||||
#LDLIBS += -lmylib
|
||||
|
||||
# All of these packages are prerequisites for resiprocate
|
||||
PACKAGES += RESIP RUTIL OPENSSL ARES PTHREAD
|
||||
|
||||
# Add an entry to TESTPROGRAMS for each target that has a main in it
|
||||
# On linux this will generate an executable in bin.debug.Linux.i686/main
|
||||
TESTPROGRAMS += main.cxx
|
||||
|
||||
# Add each of the C++ or C files that other than the main
|
||||
# Each main target (from TESTPROGRAMS) will be linked with all of the files in SRC
|
||||
SRC = TestSupport.cxx
|
||||
|
||||
# Includes macros
|
||||
include $(BUILD)/Makefile.post
|
||||
###########################################################################################
|
||||
|
||||
Option 2: (Using a third party build system)
|
||||
|
||||
Prerequisites:
|
||||
- Install ares library from contrib/ares
|
||||
- cd contrib/ares
|
||||
- ./configure
|
||||
- make
|
||||
- make install
|
||||
|
||||
Pass the following flags to C++ compiler:
|
||||
Assumptions:
|
||||
- have pthreads
|
||||
- have openssl installed
|
||||
- have ares installed
|
||||
- resiprocate library is built and installed
|
||||
|
||||
# Linux Example
|
||||
CXXFLAGS += -Wall -fPIC -Wno-deprecated -march=i686 \
|
||||
-D_REENTRANT -DUSE_SSL -DNEW_MSG_HEADER_SCANNER -DUSE_IPV6 -DUSE_ARES \
|
||||
-I/usr/kerberos/include -I$(RESIP_DIR)/lib.debug.Linux.i686
|
||||
LDFLAGS += -L$(RESIP_DIR)/lib.debug.Linux.i686
|
||||
LDLIBS += -lresip -lrutil -lssl -lcrypto -lares -lpthread
|
||||
|
||||
|
||||
54
src/libs/resiprocate/README.cmake.txt
Normal file
54
src/libs/resiprocate/README.cmake.txt
Normal file
@@ -0,0 +1,54 @@
|
||||
CMake Instructions
|
||||
==================
|
||||
|
||||
This is currently an experiement to see how CMake could be used to build
|
||||
reSIProcate.
|
||||
|
||||
Currently, only the core of rutil and its unit tests are built. This is a proof
|
||||
of concept...
|
||||
|
||||
This was quickly tested on Mac OS, Linux (CentOS) and Windows 7...
|
||||
|
||||
To build an _out of tree_ build:
|
||||
|
||||
$ mkdir cmake_build # Or any other name
|
||||
$ cd cmake_build
|
||||
$ cmake ..
|
||||
$ make
|
||||
|
||||
Once this is built, you can run the unit tests with:
|
||||
|
||||
$ ctest
|
||||
|
||||
or, for verbose output:
|
||||
|
||||
$ ctest -V
|
||||
|
||||
If you want to start fresh either delete the out of tree build directory or
|
||||
delete the CMakeCache.txt file.
|
||||
|
||||
Configuration Flags
|
||||
===================
|
||||
|
||||
* This is not fully implemented on all flags yet *
|
||||
|
||||
CMake "cached" variables are used to specify options such as whether c-ares
|
||||
should be used or not. You can get the list and tweak them with:
|
||||
|
||||
$ cmake -i ..
|
||||
|
||||
You can also set them on the command line like:
|
||||
|
||||
$ cmake -DWITH_C_ARES=true ..
|
||||
|
||||
Future Considerations
|
||||
=====================
|
||||
|
||||
Installation Packages
|
||||
---------------------
|
||||
|
||||
CMake supports rpm/deb?/NSIS to build installable packages using CPack. If this
|
||||
built-in support can not be used we could always specify internal build targets
|
||||
that will run external commands to package the appropriate bundle depending on
|
||||
the platform.
|
||||
|
||||
96
src/libs/resiprocate/README_AMQP_Apache_Qpid_Proton.txt
Normal file
96
src/libs/resiprocate/README_AMQP_Apache_Qpid_Proton.txt
Normal file
@@ -0,0 +1,96 @@
|
||||
|
||||
We have started introducing support for AMQP messaging.
|
||||
|
||||
AMQP allows us to send notifications about events to other
|
||||
applications on topics and to receive notifications and commands
|
||||
over queues.
|
||||
|
||||
Maintainer
|
||||
----------
|
||||
|
||||
Daniel Pocock
|
||||
daniel@pocock.pro
|
||||
https://softwarefreedom.institute
|
||||
|
||||
Dependencies
|
||||
------------
|
||||
|
||||
Apache Qpid Proton C++
|
||||
Version tested: 0.22.0
|
||||
License: Apache 2.0
|
||||
|
||||
Apache Qpid Proton Python (optional, for testing)
|
||||
Version tested: 0.22.0
|
||||
|
||||
RabbitMQ (optional, can use other brokers too)
|
||||
Version tested: 3.8.9
|
||||
|
||||
Installing dependencies and compiling reSIProcate with Qpid Proton
|
||||
------------------------------------------------------------------
|
||||
|
||||
Debian / Ubuntu:
|
||||
|
||||
sudo apt install \
|
||||
libqpid-proton11-dev \
|
||||
libqpid-proton-cpp11-dev
|
||||
|
||||
./configure ... --with-qpid-proton ...
|
||||
|
||||
RPM:
|
||||
|
||||
sudo dnf install qpid-proton-cpp-devel
|
||||
|
||||
./configure ... --with-qpid-proton ...
|
||||
|
||||
Installing and configuring RabbitMQ
|
||||
-----------------------------------
|
||||
|
||||
Debian / Ubuntu:
|
||||
|
||||
sudo apt install rabbitmq-server
|
||||
sudo rabbitmq-plugins enable rabbitmq_amqp1_0
|
||||
sudo systemctl restart rabbitmq-server
|
||||
|
||||
RPM:
|
||||
|
||||
sudo dnf install rabbitmq-server
|
||||
sudo rabbitmq-plugins enable rabbitmq_amqp1_0
|
||||
sudo systemctl restart rabbitmq-server
|
||||
|
||||
Installing and using the Python command line utilities
|
||||
------------------------------------------------------
|
||||
|
||||
Debian / Ubuntu:
|
||||
sudo apt install python3-qpid-proton
|
||||
|
||||
RPM:
|
||||
sudo dnf install python-qpid
|
||||
|
||||
Example sending a JSON command to reConServer:
|
||||
|
||||
Uncomment the BrokerURL in reConServer.config or any of the other
|
||||
reSIProcate applications, repro.config, registrationAgent.config, ...
|
||||
|
||||
BrokerURL = amqp://localhost:5672//queue/sip.reconserver.cmd
|
||||
|
||||
(re)start the reConServer
|
||||
|
||||
Send the command:
|
||||
|
||||
./tools/send-cmd.py \
|
||||
-a localhost:5672/sip.reconserver.cmd \
|
||||
-m '{"command":"inviteToRoom","arguments":{"destination":"sip:cisco@10.1.2.3?transport=tcp","room":"room1"}}'
|
||||
|
||||
Example receiving messages from the reConServer queue or topic:
|
||||
|
||||
Uncomment the EventTopicURL in reConServer.config or any of the other
|
||||
reSIProcate applications, repro.config, registrationAgent.config, ...
|
||||
|
||||
EventTopicURL = amqp://localhost:5672//queue/sip.reconserver.events
|
||||
|
||||
(re)start the reConServer
|
||||
|
||||
Run the utility in the console, messages appear on stdout:
|
||||
|
||||
./tools/monitor-amqp-queue-topic.py \
|
||||
-a localhost:5672//queue/sip.reconserver.events
|
||||
77
src/libs/resiprocate/README_Android.txt
Normal file
77
src/libs/resiprocate/README_Android.txt
Normal file
@@ -0,0 +1,77 @@
|
||||
|
||||
About
|
||||
-----
|
||||
|
||||
Android is a Linux-like operating system. It uses the Linux kernel
|
||||
and the bionic C library rather than the more common glibc.
|
||||
|
||||
Android comes with an SDK for Java, the primary language used in
|
||||
app development and a Native Development Kit (NDK) for low-level
|
||||
languages such as C++.
|
||||
|
||||
History
|
||||
-------
|
||||
|
||||
Android support was first added to the stack in 2013 by Daniel Pocock
|
||||
|
||||
The Android build was updated in 2021 for API level 21 with
|
||||
support from Mobile Insight.
|
||||
|
||||
SDK and NDK evolution
|
||||
---------------------
|
||||
|
||||
The original SDK was based on the Eclipse IDE. Since 2014, the SDK
|
||||
is Android Studio, based on JetBrains' IntelliJ.
|
||||
|
||||
In the early days of the NDK, developers figured out how to integrate
|
||||
their build systems with the NDK toolchains manually using scripts.
|
||||
This was the approach used in the original reSIProcate Android effort.
|
||||
Specifically, the build/android-custom-ndk script was created as a
|
||||
wrapper around autotools. More recently, Google has included this
|
||||
strategy in their documentation:
|
||||
https://developer.android.com/ndk/guides/other_build_systems#autoconf
|
||||
|
||||
In 2016, Android Studio 2.2 introduced support for CMake with the NDK.
|
||||
Using CMake is not mandatory. The SDK/NDK bundles a specific version
|
||||
of CMake and if reSIProcate changes to CMake, it will be helpful
|
||||
to ensure the versions are compatible.
|
||||
https://android-developers.googleblog.com/2016/11/make-and-ndk-build-support-in-android.html
|
||||
|
||||
The original NDK was using the GCC toolchain for cross-compiling.
|
||||
In around 2016, GCC was deprecated in favor of the CLang toolchain.
|
||||
|
||||
The list of CPU architectures supported by Android has evolved over time:
|
||||
https://developer.android.com/ndk/guides/abis
|
||||
|
||||
Building for Android
|
||||
--------------------
|
||||
|
||||
On a Linux host, install the SDK and NDK using the usual procedure.
|
||||
|
||||
Clone the reSIProcate project.
|
||||
|
||||
The first time you build reSIProcate, you will also need to
|
||||
download and build OpenSSL for Android. Simply add the environment
|
||||
variable BUILD_OPENSSL=1 to the front of your command line.
|
||||
|
||||
It is necessary to set the NDK_HOME environment variable through
|
||||
the command line or your shell profile.
|
||||
|
||||
Here is an example:
|
||||
|
||||
BUILD_OPENSSL=1 \
|
||||
NDK_HOME=${HOME}/Android/Sdk/ndk/23.1.7779620 \
|
||||
build/android-custom-ndk
|
||||
|
||||
The binaries from both OpenSSL and reSIProcate are placed
|
||||
in the directory ${HOME}/ndk-prebuilt
|
||||
|
||||
When you configure the logger in your code, we recommended you
|
||||
enable the AndroidLogger from rutil/AndroidLogger.hxx
|
||||
and then all the reSIProcate log output will be passed through
|
||||
the Android logging system.
|
||||
|
||||
See the android-demo-message application for an example showing
|
||||
how to integrate the libraries into your own app.
|
||||
https://github.com/resiprocate/android-demo-message
|
||||
|
||||
251
src/libs/resiprocate/README_RPM-based-Linux.txt
Normal file
251
src/libs/resiprocate/README_RPM-based-Linux.txt
Normal file
@@ -0,0 +1,251 @@
|
||||
|
||||
We try to make packages for users of Fedora, RHEL, CentOS, Rocky Linux,
|
||||
derivatives and similar systems that use the RPM packaging system.
|
||||
|
||||
To support this effort, we also try to ensure all dependencies are
|
||||
available in Fedora, EPEL or a reliable third-party repository.
|
||||
|
||||
This document will help you if you wish to do one of these things:
|
||||
|
||||
a) building the source code in a local workspace for development, OR
|
||||
|
||||
b) building the RPMs yourself, the same way that we build official RPMs
|
||||
|
||||
|
||||
To get started, download your preferred distribution
|
||||
----------------------------------------------------
|
||||
|
||||
Download the installation ISO, Fedora:
|
||||
Fedora: https://getfedora.org/
|
||||
|
||||
Or a RHEL-compatible derivative like the old CentOS:
|
||||
Rocky Linux: https://rockylinux.org/download
|
||||
AlmaLinux: https://almalinux.org/
|
||||
|
||||
Install using default options.
|
||||
|
||||
Ensure you have sudo permissions
|
||||
--------------------------------
|
||||
|
||||
On RHEL and similar hosts, login as root on the console
|
||||
and run this command with your username:
|
||||
|
||||
usermod -aG wheel your-user-name
|
||||
|
||||
Logout and login again to verify you are in the correct group:
|
||||
|
||||
$ id
|
||||
|
||||
The output of the id command should include the wheel group.
|
||||
|
||||
RHEL, CentOS, Rocky Linux: enable repositories
|
||||
----------------------------------------------
|
||||
|
||||
In Fedora, all the necessary packages and repositories are available.
|
||||
Fedora users can skip this step. Users of RHEL and derivaties need
|
||||
to manually enable some repositories before you can install
|
||||
dependencies.
|
||||
|
||||
Enable powertools (for common *-devel packages)
|
||||
|
||||
sudo dnf -y install dnf-plugins-core
|
||||
sudo dnf config-manager --set-enabled powertools
|
||||
|
||||
Enable EPEL
|
||||
|
||||
sudo dnf install epel-release
|
||||
|
||||
Setup the rpmbuild tool, configuration and directory structure
|
||||
--------------------------------------------------------------
|
||||
|
||||
Based on the notes here:
|
||||
https://wiki.centos.org/HowTos/SetupRpmBuildEnvironment
|
||||
|
||||
Install the rpmbuild tool and some related packages:
|
||||
|
||||
sudo dnf install rpm-build
|
||||
sudo dnf install redhat-rpm-config
|
||||
sudo dnf install rpmdevtools
|
||||
|
||||
In your home directory, run the following command to create
|
||||
the RPM directory structure:
|
||||
|
||||
rpmdev-setuptree
|
||||
|
||||
Now you can verify the tree and config has been created correctly:
|
||||
|
||||
find ~/rpmbuild -type d
|
||||
cat ~/.rpmmacros
|
||||
|
||||
Install reSIProcate build environment dependencies
|
||||
--------------------------------------------------
|
||||
|
||||
sudo dnf install git \
|
||||
gcc-c++ \
|
||||
cmake \
|
||||
python3-devel python3-pycxx-devel \
|
||||
libdb-cxx libdb-cxx-devel \
|
||||
cppunit cppunit-devel \
|
||||
gperf \
|
||||
radcli-devel \
|
||||
c-ares-devel \
|
||||
libsrtp-devel \
|
||||
boost-devel \
|
||||
openssl-devel \
|
||||
mariadb-connector-c-devel \
|
||||
pcre-devel \
|
||||
popt-devel \
|
||||
postgresql-devel \
|
||||
xerces-c-devel \
|
||||
net-snmp-devel \
|
||||
qpid-proton-cpp-devel \
|
||||
soci-devel soci-postgresql-devel soci-mysql-devel \
|
||||
vim-common \
|
||||
sox \
|
||||
fmt-devel \
|
||||
websocketpp-devel \
|
||||
gstreamer1-devel \
|
||||
gstreamer1-plugins-base-devel \
|
||||
gstreamer1-plugins-bad-free-devel \
|
||||
gstreamermm-devel
|
||||
|
||||
Manually create some dependencies
|
||||
---------------------------------
|
||||
|
||||
Some dependencies are not available in EPEL right now. It is
|
||||
necessary to copy them from Fedora and build them locally. You
|
||||
can check the availability of some common dependencies by
|
||||
looking in the Fedora package catalog:
|
||||
|
||||
https://src.fedoraproject.org/rpms/asio
|
||||
https://src.fedoraproject.org/rpms/cajun-jsonapi
|
||||
|
||||
Try to install them with dnf, if the command fails, you need to
|
||||
add an extra repository or build them manually:
|
||||
|
||||
sudo dnf install asio-devel
|
||||
sudo dnf install cajun-jsonapi-devel
|
||||
|
||||
Here is an example to build asio-devel from source, use exactly the
|
||||
same sequence of commands for cajun-jsonapi-devel or any other
|
||||
missing dependency. Notice the repository name is not exactly the
|
||||
same as the package name.
|
||||
|
||||
mkdir -p ~/ws/fedora-rpms
|
||||
cd ~/ws/fedora-rpms
|
||||
git clone https://src.fedoraproject.org/rpms/asio.git
|
||||
cd asio
|
||||
spectool -g -R asio.spec
|
||||
rpmbuild -bb asio.spec
|
||||
(it will complain about missing dependencies, so we install them ...)
|
||||
sudo dnf install boost-devel openssl-devel perl-generators
|
||||
rpmbuild -bb asio.spec
|
||||
|
||||
Now you can install the asio-devel package, the exact filename may
|
||||
vary depending on the version you built and your CPU architecture:
|
||||
|
||||
sudo rpm -i ~/rpmbuild/RPMS/x86_64/asio-devel-1.16.1-3.el8.x86_64.rpm
|
||||
|
||||
You may need to repeat this procedure for the cajun-jsonapi package.
|
||||
|
||||
Install Docker (for Podman, alternative to Docker, see below)
|
||||
-------------------------------------------------------------
|
||||
|
||||
If you are planning to use one of the related products that is
|
||||
distributed as a Docker image then you need to install either Docker
|
||||
or Podman. Typical Docker images include the HOMER system for
|
||||
SIP message capture and the Kurento Media Server.
|
||||
|
||||
These are the steps to install Docker:
|
||||
|
||||
sudo dnf config-manager --add-repo=https://download.docker.com/linux/centos/docker-ce.repo
|
||||
|
||||
sudo dnf install docker-ce
|
||||
systemctl is-active docker
|
||||
sudo systemctl enable --now docker
|
||||
systemctl is-active docker
|
||||
systemctl is-enabled docker
|
||||
sudo usermod -aG docker $USER
|
||||
|
||||
and these are the steps to install Podman:
|
||||
|
||||
sudo dnf install podman
|
||||
|
||||
If you like, you can create an alias for the docker command to run
|
||||
Podman, save this in ~/.profile or a similar location:
|
||||
|
||||
alias docker=podman
|
||||
|
||||
Preparing to build the reSIProcate stack
|
||||
----------------------------------------
|
||||
|
||||
You can clone the reSIProcate Git repository or download a copy
|
||||
of the reSIProcate tarball release. Here are the steps to clone
|
||||
the repository:
|
||||
|
||||
mkdir -p ~/ws
|
||||
cd ~/ws
|
||||
git clone https://github.com/resiprocate/resiprocate
|
||||
cd resiprocate
|
||||
|
||||
Configuring the source tree
|
||||
---------------------------
|
||||
|
||||
The project is currently built using CMake. We provide a
|
||||
wrapper script for CMake on each major GNU/Linux distribution.
|
||||
|
||||
The wrapper script for Fedora and RHEL-based systems is:
|
||||
|
||||
build/fedora.sh
|
||||
|
||||
Run the script from the top level of the reSIProcate tree.
|
||||
|
||||
We recommend that you look inside the script and tweak any settings
|
||||
you require. For example, if you are building on RHEL8 or an older
|
||||
system, you need to add the configure switch:
|
||||
|
||||
--with-srtp1
|
||||
|
||||
Compiling the code in the source tree
|
||||
-------------------------------------
|
||||
|
||||
After running the CMake configure command or using the wrapper
|
||||
script described above, it is possible to start compiling the code.
|
||||
To compile with 65 threads, on a system with 64 CPU cores, you could
|
||||
use the following command:
|
||||
|
||||
make -j65
|
||||
|
||||
Running the unit tests
|
||||
----------------------
|
||||
|
||||
The CMake "make test" target is used.
|
||||
|
||||
make test
|
||||
|
||||
Running the binaries or unit tests in the GDB debugger
|
||||
------------------------------------------------------
|
||||
|
||||
Here is an example:
|
||||
|
||||
gdb --args \
|
||||
apps/reConServer/reConServer \
|
||||
apps/reConServer/reConServer.config
|
||||
|
||||
Building reSIProcate RPM packages
|
||||
---------------------------------
|
||||
|
||||
To build packages, it is necessary to configure the tree:
|
||||
|
||||
build/fedora.sh
|
||||
|
||||
Create a reSIProcate release tarball:
|
||||
|
||||
make dist
|
||||
|
||||
Finally, tell rpmbuild to compile the tarball to RPMs. rpmbuild
|
||||
uses the spec file resiprocate.spec inside the tarball:
|
||||
|
||||
rpmbuild -tb resiprocate-1.13.0.tar.gz
|
||||
|
||||
|
||||
106
src/libs/resiprocate/RELEASE-PROCESS.txt
Normal file
106
src/libs/resiprocate/RELEASE-PROCESS.txt
Normal file
@@ -0,0 +1,106 @@
|
||||
|
||||
reSIProcate release process
|
||||
===========================
|
||||
|
||||
This document explains the process for building a release of the
|
||||
reSIProcate software.
|
||||
|
||||
Deliverables
|
||||
------------
|
||||
|
||||
The only official deliverable is the tarball, for example,
|
||||
|
||||
resiprocate-1.8.0.tar.gz
|
||||
|
||||
As a courtesy to users, a contrib tarball is also produced,
|
||||
containing some third party code:
|
||||
|
||||
resiprocate-contrib-1.8.0.tar.gz
|
||||
|
||||
Building of binary packages (e.g. for Debian, RPM, OpenCSW) is
|
||||
done after the tarball release. That is not covered here.
|
||||
|
||||
Workspace
|
||||
---------
|
||||
|
||||
Obtain a release branch from the Git repository.
|
||||
|
||||
git clone -b release/1.8 https://github.com/resiprocate/resiprocate resip-1.8
|
||||
cd resip-1.8
|
||||
|
||||
If this is the beginning of a release branch, manually copy the ChangeLog
|
||||
file from the previous release branch and then add the new entries.
|
||||
|
||||
Version/tag
|
||||
-----------
|
||||
|
||||
Here we give an example for building the release v1.8.5:
|
||||
|
||||
Update version information and tag it:
|
||||
|
||||
vi configure.ac (update the version and ABIVERSION numbers)
|
||||
|
||||
git add configure.ac
|
||||
git commit -m 'release: Update for 1.8.5'
|
||||
git tag -s -m 'release: Tag 1.8.5' resiprocate-1.8.5
|
||||
|
||||
git push (send changes back to Git)
|
||||
|
||||
Bootstrap
|
||||
---------
|
||||
|
||||
The bootstrap must always be done on the same version of CMake
|
||||
for consistency. The currently endorsed version is the CMake
|
||||
distributed in Debian 11.0 (bullseye). If another version is to be used,
|
||||
it should be discussed on the mailing list and noted in this document.
|
||||
|
||||
cmake .
|
||||
|
||||
Make a tarball
|
||||
--------------
|
||||
|
||||
build/release-tarball.sh
|
||||
|
||||
* this script will call cmake . && make dist
|
||||
* it uses a temporary clone from the current working directory
|
||||
to avoid picking up files that are not committed
|
||||
|
||||
Make the contrib tarball
|
||||
------------------------
|
||||
|
||||
build/contrib-tarball.sh
|
||||
|
||||
Sanity check on tarball
|
||||
-----------------------
|
||||
|
||||
Extract the tarball to /tmp/some-folder/resiprocate-1.8.5
|
||||
|
||||
cd /tmp/some-folder/resiprocate-1.8.5
|
||||
./build/debian.sh && make -j 70 check
|
||||
|
||||
Distribute the tarball
|
||||
----------------------
|
||||
|
||||
sha256sum resiprocate-1.8.5.tar.gz
|
||||
|
||||
Upload the tarball to the pre-release section of the web site
|
||||
|
||||
cadaver https://www.resiprocate.org/files/pub/reSIProcate/releases/
|
||||
mput resiprocate-1.8.5.tar.gz resiprocate-1.8.5.zip resiprocate-contrib-1.8.5.tar.gz resiprocate-contrib-1.8.5.zip
|
||||
|
||||
Send a PGP signed email to the developers list announcing that
|
||||
a release candidate has been built. Other developers may test the tarball.
|
||||
|
||||
Include the SHA-256 checksum of each file in the PGP signed email.
|
||||
|
||||
Confirm the release
|
||||
-------------------
|
||||
|
||||
Upload the tarball to the official download page
|
||||
|
||||
Send a PGP signed email to the resip-announce and users lists
|
||||
announcing that the release candidate is now an official release.
|
||||
|
||||
Include the SHA-256 checksum in the PGP signed email.
|
||||
|
||||
|
||||
6
src/libs/resiprocate/apps/.gitignore
vendored
Normal file
6
src/libs/resiprocate/apps/.gitignore
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
|
||||
/Makefile.in
|
||||
/Makefile
|
||||
/.deps
|
||||
/.libs
|
||||
|
||||
23
src/libs/resiprocate/apps/CMakeLists.txt
Normal file
23
src/libs/resiprocate/apps/CMakeLists.txt
Normal file
@@ -0,0 +1,23 @@
|
||||
|
||||
if(BUILD_CLICKTOCALL)
|
||||
add_subdirectory(clicktocall)
|
||||
endif()
|
||||
if(WITH_SSL)
|
||||
add_subdirectory(sipdial)
|
||||
endif()
|
||||
if(BUILD_ICHAT_GW)
|
||||
add_subdirectory(ichat-gw)
|
||||
endif()
|
||||
if(BUILD_TELEPATHY_CM)
|
||||
add_subdirectory(telepathy)
|
||||
endif()
|
||||
if(BUILD_RECONSERVER)
|
||||
add_subdirectory(reConServer)
|
||||
endif()
|
||||
if(NETSNMP_AGENT_FOUND)
|
||||
add_subdirectory(registration-agent)
|
||||
endif()
|
||||
if(USE_GSTREAMER)
|
||||
add_subdirectory(echoTest)
|
||||
endif()
|
||||
|
||||
8
src/libs/resiprocate/apps/clicktocall/.gitignore
vendored
Normal file
8
src/libs/resiprocate/apps/clicktocall/.gitignore
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
|
||||
/Makefile.in
|
||||
/Makefile
|
||||
/.deps
|
||||
/.libs
|
||||
|
||||
/clicktocall
|
||||
|
||||
214
src/libs/resiprocate/apps/clicktocall/AddressTranslator.cxx
Normal file
214
src/libs/resiprocate/apps/clicktocall/AddressTranslator.cxx
Normal file
@@ -0,0 +1,214 @@
|
||||
|
||||
#include "rutil/Logger.hxx"
|
||||
#include "rutil/ParseBuffer.hxx"
|
||||
|
||||
#include "AppSubsystem.hxx"
|
||||
#include "AddressTranslator.hxx"
|
||||
#include "rutil/WinLeakCheck.hxx"
|
||||
|
||||
#define RESIPROCATE_SUBSYSTEM AppSubsystem::CLICKTOCALL
|
||||
|
||||
using namespace clicktocall;
|
||||
using namespace resip;
|
||||
using namespace std;
|
||||
|
||||
namespace clicktocall
|
||||
{
|
||||
|
||||
AddressTranslator::AddressTranslator()
|
||||
{
|
||||
}
|
||||
|
||||
AddressTranslator::~AddressTranslator()
|
||||
{
|
||||
// Destroy all of the filters
|
||||
for(FilterOpList::iterator it = mFilterOperators.begin(); it != mFilterOperators.end(); it++)
|
||||
{
|
||||
if ( it->preq )
|
||||
{
|
||||
delete it->preq;
|
||||
it->preq = 0;
|
||||
}
|
||||
}
|
||||
mFilterOperators.clear();
|
||||
}
|
||||
|
||||
void
|
||||
AddressTranslator::addTranslation(const resip::Data& matchingPattern,
|
||||
const resip::Data& rewriteExpression)
|
||||
{
|
||||
InfoLog( << "Add translation " << matchingPattern << " -> " << rewriteExpression);
|
||||
|
||||
FilterOp filter;
|
||||
filter.mMatchingPattern = matchingPattern;
|
||||
filter.mRewriteExpression = rewriteExpression;
|
||||
|
||||
if( !filter.mMatchingPattern.empty() )
|
||||
{
|
||||
// Note: this code originally used the PCRE (Perl Compatible) regular expression library. The ECMAScript standard is a subset
|
||||
// of the Perl regular expression syntax. Posix regular expression syntax is quite a bit different (ie: std::regex_contacts::basic or
|
||||
// std::regex_contacts::extended). To be as backwards compatible with existing regular expressions as possible, we want to
|
||||
// use the EMCAScript syntax.
|
||||
const std::regex_constants::syntax_option_type flags = std::regex_constants::ECMAScript;
|
||||
if( filter.mRewriteExpression.find("$") == Data::npos )
|
||||
{
|
||||
flags |= std::regex_constants::nosubs;
|
||||
}
|
||||
try
|
||||
{
|
||||
filter.preq = new std::regex(filter.mMatchingPattern.c_str(), flags );
|
||||
}
|
||||
catch (std::regex_error& e)
|
||||
{
|
||||
delete filter.preq;
|
||||
ErrLog( << "Translation has invalid match expression: "
|
||||
<< filter.mMatchingPattern );
|
||||
filter.preq = 0;
|
||||
}
|
||||
}
|
||||
mFilterOperators.push_back( filter );
|
||||
}
|
||||
|
||||
void
|
||||
AddressTranslator::removeTranslation(const resip::Data& matchingPattern )
|
||||
{
|
||||
FilterOpList::iterator it = mFilterOperators.begin();
|
||||
while ( it != mFilterOperators.end() )
|
||||
{
|
||||
if ( it->mMatchingPattern == matchingPattern )
|
||||
{
|
||||
FilterOpList::iterator i = it;
|
||||
it++;
|
||||
if ( i->preq )
|
||||
{
|
||||
delete i->preq;
|
||||
i->preq = 0;
|
||||
}
|
||||
mFilterOperators.erase(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
AddressTranslator::translate(const resip::Data& address, resip::Data& translation, bool failIfNoRule)
|
||||
{
|
||||
bool rc=false;
|
||||
DebugLog( << "Translating "<< address);
|
||||
|
||||
for (FilterOpList::iterator it = mFilterOperators.begin();
|
||||
it != mFilterOperators.end(); it++)
|
||||
{
|
||||
Data rewrite = it->mRewriteExpression;
|
||||
Data& match = it->mMatchingPattern;
|
||||
if ( it->preq )
|
||||
{
|
||||
std::cmatch matches;
|
||||
|
||||
// Note: Using regex_search instead of regex_match, so that we don't need to fully match
|
||||
// the string, this is backwards compatible with the previous regexec PCRE implementation
|
||||
if(!std::regex_search(address.c_str(), matches, *it->preq))
|
||||
{
|
||||
// did not match
|
||||
DebugLog( << " Skipped translation "<< address << " did not match " << match );
|
||||
continue;
|
||||
}
|
||||
|
||||
DebugLog( << " Matched translation "<< address << " matched " << match );
|
||||
translation = rewrite;
|
||||
rc=true;
|
||||
if ( rewrite.find("$") != Data::npos )
|
||||
{
|
||||
for ( int i=1; i<matches.size(); i++)
|
||||
{
|
||||
Data subExp(matches[i]);
|
||||
DebugLog( << " subExpression[" <<i <<"]="<< subExp );
|
||||
|
||||
Data result;
|
||||
{
|
||||
DataStream s(result);
|
||||
|
||||
ParseBuffer pb(translation);
|
||||
|
||||
while (true)
|
||||
{
|
||||
const char* a = pb.position();
|
||||
pb.skipToChars( Data("$") + char('0'+i) );
|
||||
if ( pb.eof() )
|
||||
{
|
||||
s << pb.data(a);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
s << pb.data(a);
|
||||
pb.skipN(2);
|
||||
s << subExp;
|
||||
}
|
||||
}
|
||||
s.flush();
|
||||
}
|
||||
translation = result;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
translation = rewrite;
|
||||
rc = true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If we didn't find a translation and we are not suppossed to fail, then just return address
|
||||
if(!rc && !failIfNoRule)
|
||||
{
|
||||
rc = true;
|
||||
translation = address;
|
||||
}
|
||||
|
||||
InfoLog( << "Translated "<< address << " to " << translation);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* ====================================================================
|
||||
|
||||
Copyright (c) 2009, SIP Spectrum, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of SIP Spectrum nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
==================================================================== */
|
||||
|
||||
75
src/libs/resiprocate/apps/clicktocall/AddressTranslator.hxx
Normal file
75
src/libs/resiprocate/apps/clicktocall/AddressTranslator.hxx
Normal file
@@ -0,0 +1,75 @@
|
||||
#if !defined(AddressTranslator_hxx)
|
||||
#define AddressTranslator_hxx
|
||||
|
||||
#include <list>
|
||||
|
||||
#include <regex>
|
||||
#include "rutil/Data.hxx"
|
||||
|
||||
namespace clicktocall
|
||||
{
|
||||
|
||||
class AddressTranslator
|
||||
{
|
||||
public:
|
||||
AddressTranslator();
|
||||
~AddressTranslator();
|
||||
|
||||
void addTranslation(const resip::Data& matchingPattern,
|
||||
const resip::Data& rewriteExpression);
|
||||
|
||||
void removeTranslation(const resip::Data& matchingPattern);
|
||||
|
||||
bool translate(const resip::Data& address, resip::Data& translation, bool failIfNoRule=false);
|
||||
|
||||
private:
|
||||
class FilterOp
|
||||
{
|
||||
public:
|
||||
resip::Data mMatchingPattern;
|
||||
resip::Data mRewriteExpression;
|
||||
std::regex *preq;
|
||||
};
|
||||
|
||||
typedef std::list<FilterOp> FilterOpList;
|
||||
FilterOpList mFilterOperators;
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* ====================================================================
|
||||
|
||||
Copyright (c) 2009, SIP Spectrum, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of SIP Spectrum nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
==================================================================== */
|
||||
|
||||
38
src/libs/resiprocate/apps/clicktocall/AppSubsystem.cxx
Normal file
38
src/libs/resiprocate/apps/clicktocall/AppSubsystem.cxx
Normal file
@@ -0,0 +1,38 @@
|
||||
#include "AppSubsystem.hxx"
|
||||
|
||||
AppSubsystem AppSubsystem::CLICKTOCALL("CLICKTOCALL");
|
||||
|
||||
/* ====================================================================
|
||||
|
||||
Copyright (c) 2009, SIP Spectrum, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of SIP Spectrum nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
==================================================================== */
|
||||
|
||||
61
src/libs/resiprocate/apps/clicktocall/AppSubsystem.hxx
Normal file
61
src/libs/resiprocate/apps/clicktocall/AppSubsystem.hxx
Normal file
@@ -0,0 +1,61 @@
|
||||
#if !defined(AppSubsystem_hxx)
|
||||
#define AppSubsystem_hxx
|
||||
|
||||
#include <iostream>
|
||||
#include <rutil/Subsystem.hxx>
|
||||
|
||||
/**
|
||||
This class is used in the logging subsystem to identify
|
||||
logging messages generated from the ClickToCall server.
|
||||
|
||||
Author: Scott Godin (sgodin AT SipSpectrum DOT com)
|
||||
*/
|
||||
|
||||
class AppSubsystem : public resip::Subsystem
|
||||
{
|
||||
public:
|
||||
// Add new systems below
|
||||
static AppSubsystem CLICKTOCALL;
|
||||
|
||||
private:
|
||||
explicit AppSubsystem(const char* rhs) : resip::Subsystem(rhs) {};
|
||||
explicit AppSubsystem(const resip::Data& rhs);
|
||||
AppSubsystem& operator=(const resip::Data& rhs);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/* ====================================================================
|
||||
|
||||
Copyright (c) 2009, SIP Spectrum, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of SIP Spectrum nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
==================================================================== */
|
||||
|
||||
995
src/libs/resiprocate/apps/clicktocall/B2BSession.cxx
Normal file
995
src/libs/resiprocate/apps/clicktocall/B2BSession.cxx
Normal file
@@ -0,0 +1,995 @@
|
||||
#include "B2BSession.hxx"
|
||||
#include "Server.hxx"
|
||||
#include "AppSubsystem.hxx"
|
||||
|
||||
#include <resip/stack/PlainContents.hxx>
|
||||
#include <resip/stack/SdpContents.hxx>
|
||||
#include <resip/stack/SipFrag.hxx>
|
||||
#include <resip/dum/ServerInviteSession.hxx>
|
||||
#include <resip/dum/ClientInviteSession.hxx>
|
||||
#include <resip/dum/ClientSubscription.hxx>
|
||||
#include <rutil/DnsUtil.hxx>
|
||||
#include <rutil/Log.hxx>
|
||||
#include <rutil/Logger.hxx>
|
||||
#include <rutil/WinLeakCheck.hxx>
|
||||
|
||||
using namespace clicktocall;
|
||||
using namespace resip;
|
||||
using namespace std;
|
||||
|
||||
#define RESIPROCATE_SUBSYSTEM AppSubsystem::CLICKTOCALL
|
||||
|
||||
#ifdef BRIEF_MSG_LOGGING
|
||||
#define LOG_MSG msg.brief()
|
||||
#define LOG_MSG_WITH_SDP msg.brief() << ", sdp=" << sdp
|
||||
#define LOG_MSGP msg->brief()
|
||||
#else
|
||||
#define LOG_MSG endl << msg
|
||||
#define LOG_MSG_WITH_SDP endl << msg
|
||||
#define LOG_MSGP endl << *msg
|
||||
#endif
|
||||
#define B2BLOG_PREFIX << "B2BSession[" << mHandle << "] "
|
||||
|
||||
namespace clicktocall
|
||||
{
|
||||
|
||||
B2BSession::B2BSession(Server& server) :
|
||||
AppDialogSet(server.getDialogUsageManager()),
|
||||
mServer(server),
|
||||
mDum(server.getDialogUsageManager()),
|
||||
mPeer(0),
|
||||
mUACConnectedDialogId(Data::Empty, Data::Empty, Data::Empty),
|
||||
mWaitingOfferFromPeer(false),
|
||||
mWaitingAnswerFromPeer(false),
|
||||
mWaitingNitAnswerFromPeer(false),
|
||||
mClickToCallState(Undefined),
|
||||
mClickToCallAnchorEnabled(false),
|
||||
mClickToCallInitiator(false)
|
||||
{
|
||||
mHandle = mServer.registerB2BSession(this);
|
||||
}
|
||||
|
||||
B2BSession::~B2BSession()
|
||||
{
|
||||
endPeer();
|
||||
mServer.unregisterB2BSession(mHandle);
|
||||
}
|
||||
|
||||
void
|
||||
B2BSession::setPeer(B2BSession* peer)
|
||||
{
|
||||
mPeer = peer;
|
||||
}
|
||||
|
||||
B2BSession*
|
||||
B2BSession::getPeer()
|
||||
{
|
||||
return mPeer;
|
||||
}
|
||||
|
||||
void
|
||||
B2BSession::stealPeer(B2BSession* victimSession)
|
||||
{
|
||||
// Assume Peer mapping of victim - and copy some settings
|
||||
setPeer(victimSession->getPeer());
|
||||
if(mPeer)
|
||||
{
|
||||
mPeer->setPeer(this);
|
||||
}
|
||||
|
||||
// Clear peer mapping in victim session
|
||||
victimSession->setPeer(0);
|
||||
}
|
||||
|
||||
void
|
||||
B2BSession::startCall(const Uri& destinationUri, const NameAddr& from, const SdpContents *sdp)
|
||||
{
|
||||
// Create a UserProfile for new call
|
||||
auto userProfile = std::make_shared<UserProfile>(mServer.getMasterProfile());
|
||||
|
||||
// Set the From address
|
||||
userProfile->setDefaultFrom(from);
|
||||
userProfile->getDefaultFrom().remove(p_tag); // Remove tag (if it exists)
|
||||
|
||||
// Create the invite message
|
||||
auto invitemsg = mDum.makeInviteSession(
|
||||
NameAddr(destinationUri),
|
||||
userProfile,
|
||||
sdp,
|
||||
this);
|
||||
|
||||
// Send the invite message
|
||||
mDum.send(std::move(invitemsg));
|
||||
}
|
||||
|
||||
void
|
||||
B2BSession::clickToCall(const resip::Uri& initiator, const resip::Uri& destination, bool anchorCall, const XmlRpcInfo& xmlRpcInfo)
|
||||
{
|
||||
resip_assert(mClickToCallState == Undefined);
|
||||
|
||||
// Store Click-To-Call request info
|
||||
mClickToCallInitiator = true;
|
||||
mClickToCallDestination = destination;
|
||||
mClickToCallAnchorEnabled = anchorCall;
|
||||
mXmlRpcInfo = xmlRpcInfo;
|
||||
transitionClickToCallState(Setup);
|
||||
|
||||
// Create local sdp offer
|
||||
SdpContents sdp;
|
||||
if(!buildLocalOffer(sdp))
|
||||
{
|
||||
ErrLog(<< "B2BSession::clickToCall: unable to build local offer.");
|
||||
return;
|
||||
}
|
||||
|
||||
NameAddr from = mServer.getMasterProfile()->getDefaultFrom();
|
||||
from.displayName() = "Click-To-Call: " + destination.user();
|
||||
startCall(initiator, from, &sdp);
|
||||
}
|
||||
|
||||
void
|
||||
B2BSession::startClickToCallAnchorLeg(const NameAddr& initiator, const Uri& destination, const XmlRpcInfo& xmlRpcInfo)
|
||||
{
|
||||
// Create B2BCall
|
||||
InfoLog(B2BLOG_PREFIX << "B2BSession::startClickToCallAnchorLeg: Starting second leg of click to call to " << destination);
|
||||
|
||||
mXmlRpcInfo = xmlRpcInfo;
|
||||
transitionClickToCallState(Setup);
|
||||
startCall(destination, initiator, 0);
|
||||
}
|
||||
|
||||
bool
|
||||
B2BSession::buildLocalOffer(SdpContents& offer)
|
||||
{
|
||||
// Build s=, o=, t=, and c= lines
|
||||
uint64_t currentTime = Timer::getTimeMicroSec();
|
||||
|
||||
unsigned int port=8000; // Placeholder port
|
||||
|
||||
// Note: The outbound decorator will take care of filling in the correct IP address before the message is sent
|
||||
// to the wire.
|
||||
SdpContents::Session::Origin origin("clicktocall", currentTime /* sessionId */, currentTime /* version */, SdpContents::IP4, "0.0.0.0"); // o=
|
||||
SdpContents::Session session(0, origin, "-" /* s= */);
|
||||
session.connection() = SdpContents::Session::Connection(SdpContents::IP4, "0.0.0.0"); // c=
|
||||
session.addTime(SdpContents::Session::Time(0, 0));
|
||||
|
||||
// Build Codecs and media offering
|
||||
SdpContents::Session::Medium medium("audio", port, 1, "RTP/AVP");
|
||||
SdpContents::Session::Codec g711ucodec("PCMU", 8000);
|
||||
g711ucodec.payloadType() = 0; /* RFC3551 */ ;
|
||||
medium.addCodec(g711ucodec);
|
||||
medium.addAttribute("inactive");
|
||||
session.addMedium(medium);
|
||||
|
||||
offer.session() = session;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
B2BSession::endPeer()
|
||||
{
|
||||
if(mPeer)
|
||||
{
|
||||
mPeer->setPeer(0);
|
||||
mPeer->end(); // send cancel or bye appropriately
|
||||
mPeer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
B2BSession::isUACConnected()
|
||||
{
|
||||
return !mUACConnectedDialogId.getCallId().empty();
|
||||
}
|
||||
|
||||
bool
|
||||
B2BSession::isStaleFork(const DialogId& dialogId)
|
||||
{
|
||||
return (!mUACConnectedDialogId.getCallId().empty() && dialogId != mUACConnectedDialogId);
|
||||
}
|
||||
|
||||
void
|
||||
B2BSession::processReferNotify(const SipMessage& notify)
|
||||
{
|
||||
unsigned int code = 400; // Bad Request - default if for some reason a valid sipfrag is not present
|
||||
|
||||
SipFrag* frag = dynamic_cast<SipFrag*>(notify.getContents());
|
||||
if (frag)
|
||||
{
|
||||
// Get StatusCode from SipFrag
|
||||
if (frag->message().isResponse())
|
||||
{
|
||||
code = frag->message().header(h_StatusLine).statusCode();
|
||||
}
|
||||
}
|
||||
|
||||
// If subscription is terminated, due to timeout and we don't have a final response in the SipFrag - treat as error
|
||||
if(notify.exists(h_SubscriptionState) &&
|
||||
isEqualNoCase(notify.header(h_SubscriptionState).value(), Symbols::Terminated) &&
|
||||
notify.header(h_SubscriptionState).exists(p_reason) &&
|
||||
isEqualNoCase(notify.header(h_SubscriptionState).param(p_reason), getTerminateReasonString(Timeout)) &&
|
||||
code < 200)
|
||||
{
|
||||
// failure
|
||||
transitionClickToCallState(ReferToDestinationFailed, 408);
|
||||
end();
|
||||
}
|
||||
// Check if success or failure response code was in SipFrag
|
||||
else if(code >= 180 && code < 200)
|
||||
{
|
||||
// proceeding
|
||||
transitionClickToCallState(ReferToDestinationProceeding);
|
||||
}
|
||||
else if(code >= 200 && code < 300)
|
||||
{
|
||||
// success
|
||||
transitionClickToCallState(ReferToDestinationConnected);
|
||||
end();
|
||||
}
|
||||
else if(code >= 300)
|
||||
{
|
||||
// failure
|
||||
transitionClickToCallState(ReferToDestinationFailed, code);
|
||||
end();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
B2BSession::transitionClickToCallState(ClickToCallState newState, unsigned int statusCode)
|
||||
{
|
||||
if(newState != mClickToCallState)
|
||||
{
|
||||
unsigned int resultCode = 0;
|
||||
Data resultText;
|
||||
Data leg = mClickToCallInitiator ? "Initiator" : "Destination";
|
||||
switch(newState)
|
||||
{
|
||||
case Setup:
|
||||
InfoLog(B2BLOG_PREFIX << "transitionClickToCallState: newState=Setup, initiator=" << mClickToCallInitiator);
|
||||
break;
|
||||
case Proceeding:
|
||||
InfoLog(B2BLOG_PREFIX << "transitionClickToCallState: newState=Proceeding, initiator=" << mClickToCallInitiator);
|
||||
resultCode = 180;
|
||||
resultText = mClickToCallInitiator ? "Ringing initiator" : "Ringing destination";
|
||||
break;
|
||||
case Connected:
|
||||
InfoLog(B2BLOG_PREFIX << "transitionClickToCallState: newState=Connected, initiator=" << mClickToCallInitiator);
|
||||
resultCode = 200;
|
||||
resultText = mClickToCallInitiator ? "Connected to initiator" : "Connected to destination";
|
||||
break;
|
||||
case Failed:
|
||||
InfoLog(B2BLOG_PREFIX << "transitionClickToCallState: newState=Failed, initiator=" << mClickToCallInitiator);
|
||||
resultCode = statusCode;
|
||||
resultText = mClickToCallInitiator ? "Failed to connect to initiator" : "Failed to connect to destination";
|
||||
break;
|
||||
case ReferToDestinationProceeding:
|
||||
InfoLog(B2BLOG_PREFIX << "transitionClickToCallState: newState=ReferToDestinationProceeding, initiator=" << mClickToCallInitiator);
|
||||
leg = "Destination";
|
||||
resultCode = 180;
|
||||
resultText = "Ringing destination";
|
||||
break;
|
||||
case ReferToDestinationConnected:
|
||||
InfoLog(B2BLOG_PREFIX << "transitionClickToCallState: newState=ReferToDestinationConnected, initiator=" << mClickToCallInitiator);
|
||||
leg = "Destination";
|
||||
resultCode = 200;
|
||||
resultText = "Connected to destination";
|
||||
break;
|
||||
case ReferToDestinationFailed:
|
||||
InfoLog(B2BLOG_PREFIX << "transitionClickToCallState: newState=ReferToDestinationFailed, initiator=" << mClickToCallInitiator);
|
||||
leg = "Destination";
|
||||
resultCode = statusCode;
|
||||
resultText = "Failed to connect to destination";
|
||||
break;
|
||||
default:
|
||||
resip_assert(false);
|
||||
}
|
||||
mClickToCallState = newState;
|
||||
|
||||
if(mXmlRpcInfo.mXmlRpcServer && resultCode != 0)
|
||||
{
|
||||
mXmlRpcInfo.mXmlRpcServer->sendResponse(mXmlRpcInfo.mConnectionId, mXmlRpcInfo.mRequestId, Data::Empty, resultCode, resultText, leg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// InviteSessionHandler ///////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void
|
||||
B2BSession::onNewSession(ClientInviteSessionHandle h, InviteSession::OfferAnswerType oat, const SipMessage& msg)
|
||||
{
|
||||
InfoLog(B2BLOG_PREFIX << "onNewSession(ClientInviteSessionHandle): msg=" << LOG_MSG);
|
||||
mInviteSessionHandle = h->getSessionHandle();
|
||||
}
|
||||
|
||||
void
|
||||
B2BSession::onNewSession(ServerInviteSessionHandle h, InviteSession::OfferAnswerType oat, const SipMessage& msg)
|
||||
{
|
||||
WarningLog(B2BLOG_PREFIX << "onNewSession(ServerInviteSessionHandle): ClickToCall server does not accept inbound calls - rejecting.");
|
||||
|
||||
mInviteSessionHandle = h->getSessionHandle();
|
||||
|
||||
h->reject(403 /* Forbidden */);
|
||||
}
|
||||
|
||||
void
|
||||
B2BSession::onFailure(ClientInviteSessionHandle h, const SipMessage& msg)
|
||||
{
|
||||
// Note: Teardown of peer is handled in destructor
|
||||
InfoLog(B2BLOG_PREFIX << "onFailure: msg=" << LOG_MSG);
|
||||
}
|
||||
|
||||
void
|
||||
B2BSession::onEarlyMedia(ClientInviteSessionHandle h, const SipMessage& msg, const SdpContents& sdp)
|
||||
{
|
||||
InfoLog(B2BLOG_PREFIX << "onEarlyMedia: msg=" << LOG_MSG_WITH_SDP);
|
||||
}
|
||||
|
||||
void
|
||||
B2BSession::onProvisional(ClientInviteSessionHandle h, const SipMessage& msg)
|
||||
{
|
||||
InfoLog(B2BLOG_PREFIX << "onProvisional: msg=" << LOG_MSG);
|
||||
|
||||
if(isStaleFork(h->getDialogId())) return;
|
||||
|
||||
if(msg.header(h_StatusLine).responseCode() >= 180 && mClickToCallState == Setup)
|
||||
{
|
||||
transitionClickToCallState(Proceeding);
|
||||
}
|
||||
|
||||
if(mPeer)
|
||||
{
|
||||
if(mPeer->mInviteSessionHandle.isValid())
|
||||
{
|
||||
ServerInviteSession* sis = dynamic_cast<ServerInviteSession*>(mPeer->mInviteSessionHandle.get());
|
||||
if(sis && !sis->isAccepted())
|
||||
{
|
||||
sis->provisional(msg.header(h_StatusLine).responseCode());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
B2BSession::onConnected(ClientInviteSessionHandle h, const SipMessage& msg)
|
||||
{
|
||||
InfoLog(B2BLOG_PREFIX << "onConnected: msg=" << LOG_MSG);
|
||||
if(!isUACConnected())
|
||||
{
|
||||
// It is possible in forking scenarios to get multiple 200 responses, if this is
|
||||
// our first 200 response, then this is the leg we accept, store the connected DialogId
|
||||
mUACConnectedDialogId = h->getDialogId();
|
||||
|
||||
// Note: each forked leg will update mInviteSessionHandle (in onNewSession call) - need to set mInviteSessionHandle for final answering leg on 200
|
||||
mInviteSessionHandle = h->getSessionHandle();
|
||||
|
||||
if(mClickToCallState == Setup || mClickToCallState == Proceeding)
|
||||
{
|
||||
transitionClickToCallState(Connected);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// We already have a connected leg - end this one with a BYE
|
||||
h->end();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
B2BSession::onConnected(InviteSessionHandle h, const SipMessage& msg)
|
||||
{
|
||||
InfoLog(B2BLOG_PREFIX << "onConnected: msg=" << LOG_MSG);
|
||||
if(mClickToCallState == Setup || mClickToCallState == Proceeding)
|
||||
{
|
||||
transitionClickToCallState(Connected);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
B2BSession::onStaleCallTimeout(ClientInviteSessionHandle h)
|
||||
{
|
||||
InfoLog(B2BLOG_PREFIX << "onStaleCallTimeout:");
|
||||
endPeer();
|
||||
}
|
||||
|
||||
void
|
||||
B2BSession::onTerminated(InviteSessionHandle h, InviteSessionHandler::TerminatedReason reason, const SipMessage* msg)
|
||||
{
|
||||
Data reasonData;
|
||||
switch(reason)
|
||||
{
|
||||
case InviteSessionHandler::RemoteBye:
|
||||
reasonData = "received a BYE from peer";
|
||||
break;
|
||||
case InviteSessionHandler::RemoteCancel:
|
||||
reasonData = "received a CANCEL from peer";
|
||||
break;
|
||||
case InviteSessionHandler::Rejected:
|
||||
reasonData = "received a rejection from peer";
|
||||
break;
|
||||
case InviteSessionHandler::LocalBye:
|
||||
reasonData = "ended locally via BYE";
|
||||
break;
|
||||
case InviteSessionHandler::LocalCancel:
|
||||
reasonData = "ended locally via CANCEL";
|
||||
break;
|
||||
case InviteSessionHandler::Replaced:
|
||||
reasonData = "ended due to being replaced";
|
||||
break;
|
||||
case InviteSessionHandler::Referred:
|
||||
reasonData = "ended due to being reffered";
|
||||
break;
|
||||
case InviteSessionHandler::Error:
|
||||
reasonData = "ended due to an error";
|
||||
break;
|
||||
case InviteSessionHandler::Timeout:
|
||||
reasonData = "ended due to a timeout";
|
||||
break;
|
||||
default:
|
||||
resip_assert(false);
|
||||
break;
|
||||
}
|
||||
|
||||
if(msg)
|
||||
{
|
||||
InfoLog(B2BLOG_PREFIX << "onTerminated: reason=" << reasonData << ", msg=" << LOG_MSGP);
|
||||
}
|
||||
else
|
||||
{
|
||||
InfoLog(B2BLOG_PREFIX << "onTerminated: reason=" << reasonData);
|
||||
}
|
||||
|
||||
unsigned int statusCode = 603;
|
||||
if(msg)
|
||||
{
|
||||
if(msg->isResponse())
|
||||
{
|
||||
statusCode = msg->header(h_StatusLine).responseCode();
|
||||
}
|
||||
}
|
||||
|
||||
// If this is a referred call and the refer is still around - then switch back to referrer (ie. failed transfer recovery)
|
||||
if(mReferringAppDialogSet.isValid() && mPeer)
|
||||
{
|
||||
B2BSession* session = (B2BSession*)mReferringAppDialogSet.get();
|
||||
session->stealPeer(this);
|
||||
}
|
||||
|
||||
if(isStaleFork(h->getDialogId())) return;
|
||||
|
||||
// If we have a peer that hasn't been accepted yet - then pass back terminated code, by calling reject now
|
||||
if(mPeer && mPeer->mInviteSessionHandle.isValid())
|
||||
{
|
||||
ServerInviteSession* sis = dynamic_cast<ServerInviteSession*>(mPeer->mInviteSessionHandle.get());
|
||||
if(sis && !sis->isAccepted())
|
||||
{
|
||||
sis->reject(statusCode);
|
||||
}
|
||||
}
|
||||
|
||||
if(mClickToCallState == Setup || mClickToCallState == Proceeding)
|
||||
{
|
||||
transitionClickToCallState(Failed, statusCode);
|
||||
}
|
||||
|
||||
endPeer();
|
||||
}
|
||||
|
||||
void
|
||||
B2BSession::onRedirected(ClientInviteSessionHandle h, const SipMessage& msg)
|
||||
{
|
||||
// We will recurse on redirect requests, so nothing to do here
|
||||
InfoLog(B2BLOG_PREFIX << "onRedirected: msg=" << LOG_MSG);
|
||||
}
|
||||
|
||||
void
|
||||
B2BSession::onAnswer(InviteSessionHandle h, const SipMessage& msg, const SdpContents& sdp)
|
||||
{
|
||||
InfoLog(B2BLOG_PREFIX << "onAnswer: msg=" << LOG_MSG_WITH_SDP);
|
||||
|
||||
if(isStaleFork(h->getDialogId())) return;
|
||||
|
||||
if(mPeer)
|
||||
{
|
||||
if(mPeer->mInviteSessionHandle.isValid())
|
||||
{
|
||||
if(mPeer->mWaitingAnswerFromPeer)
|
||||
{
|
||||
mPeer->mInviteSessionHandle->provideAnswer(sdp);
|
||||
mPeer->mWaitingAnswerFromPeer = false;
|
||||
}
|
||||
else if(mPeer->mWaitingOfferFromPeer)
|
||||
{
|
||||
mPeer->mInviteSessionHandle->provideOffer(sdp);
|
||||
mPeer->mWaitingOfferFromPeer = false;
|
||||
}
|
||||
|
||||
ServerInviteSession* sis = dynamic_cast<ServerInviteSession*>(mPeer->mInviteSessionHandle.get());
|
||||
if(sis && !sis->isAccepted())
|
||||
{
|
||||
sis->accept();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(mClickToCallInitiator && (mClickToCallState == Setup || mClickToCallState == Proceeding))
|
||||
{
|
||||
if(mClickToCallAnchorEnabled)
|
||||
{
|
||||
// We are anchoring (B2B'ing) the call - time to start second leg
|
||||
mPeer = new B2BSession(mServer);
|
||||
mPeer->setPeer(this);
|
||||
mPeer->startClickToCallAnchorLeg(msg.header(h_To), mClickToCallDestination, mXmlRpcInfo);
|
||||
mWaitingOfferFromPeer = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// ClickToCall, but do not anchor call - send REFER here instead
|
||||
h->refer(NameAddr(mClickToCallDestination));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
B2BSession::onOffer(InviteSessionHandle h, const SipMessage& msg, const SdpContents& sdp)
|
||||
{
|
||||
InfoLog(B2BLOG_PREFIX << "onOffer: msg=" << LOG_MSG_WITH_SDP);
|
||||
|
||||
if(isStaleFork(h->getDialogId())) return;
|
||||
|
||||
if(mPeer)
|
||||
{
|
||||
if(mPeer->mInviteSessionHandle.isValid())
|
||||
{
|
||||
mPeer->mInviteSessionHandle->provideOffer(sdp);
|
||||
mPeer->mWaitingOfferFromPeer = false;
|
||||
mWaitingAnswerFromPeer = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
resip_assert(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ErrLog(B2BLOG_PREFIX << "onOffer: No peer, rejecting with 501.");
|
||||
h->reject(501 /* Not Implemented */);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
B2BSession::onOfferRequired(InviteSessionHandle h, const SipMessage& msg)
|
||||
{
|
||||
InfoLog(B2BLOG_PREFIX << "onOfferRequired: msg=" << LOG_MSG);
|
||||
|
||||
if(isStaleFork(h->getDialogId())) return;
|
||||
|
||||
if(mPeer)
|
||||
{
|
||||
if(mPeer->mInviteSessionHandle.isValid())
|
||||
{
|
||||
mPeer->mInviteSessionHandle->requestOffer();
|
||||
mWaitingOfferFromPeer = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
resip_assert(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ErrLog(B2BLOG_PREFIX << "onOfferRequired: No peer, rejecting with 501.");
|
||||
h->reject(501 /* Not Implemented */);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
B2BSession::onOfferRejected(InviteSessionHandle h, const SipMessage* msg)
|
||||
{
|
||||
int statusCode = 488;
|
||||
WarningCategory* warning=0;
|
||||
|
||||
if(isStaleFork(h->getDialogId())) return;
|
||||
|
||||
if(msg)
|
||||
{
|
||||
InfoLog(B2BLOG_PREFIX << "onOfferRejected: msg=" << LOG_MSGP);
|
||||
if(msg->exists(h_Warnings))
|
||||
{
|
||||
warning = (WarningCategory*)&msg->header(h_Warnings).back();
|
||||
}
|
||||
if(msg->isResponse())
|
||||
{
|
||||
statusCode = msg->header(h_StatusLine).responseCode();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
InfoLog(B2BLOG_PREFIX << "onOfferRejected:");
|
||||
}
|
||||
|
||||
if(mPeer)
|
||||
{
|
||||
if(mPeer->mInviteSessionHandle.isValid() && mPeer->mWaitingAnswerFromPeer)
|
||||
{
|
||||
mPeer->mWaitingAnswerFromPeer = false;
|
||||
mPeer->mInviteSessionHandle->reject(statusCode, warning);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
B2BSession::onOfferRequestRejected(InviteSessionHandle h, const SipMessage& msg)
|
||||
{
|
||||
InfoLog(B2BLOG_PREFIX << "onOfferRequestRejected: msg=" << LOG_MSG);
|
||||
// This is called when we are waiting to resend a INVITE with no sdp after a glare condition, and we
|
||||
// instead receive an inbound INVITE or UPDATE
|
||||
if(mPeer)
|
||||
{
|
||||
if(mPeer->mInviteSessionHandle.isValid() && mPeer->mWaitingOfferFromPeer)
|
||||
{
|
||||
// Return glare to peer
|
||||
mPeer->mInviteSessionHandle->reject(491);
|
||||
mPeer->mWaitingOfferFromPeer = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
B2BSession::onRemoteSdpChanged(InviteSessionHandle h, const SipMessage& msg, const SdpContents& sdp)
|
||||
{
|
||||
/// called when a modified SDP is received in a 2xx response to a
|
||||
/// session-timer reINVITE. Under normal circumstances where the response
|
||||
/// SDP is unchanged from current remote SDP no handler is called
|
||||
/// There is not much we can do about this. If session timers are used then they are managed separately per leg
|
||||
/// and we have no real mechanism to notify the other peer of new SDP without starting a new offer/answer negotiation
|
||||
InfoLog(B2BLOG_PREFIX << "onRemoteSdpChanged: msg=" << LOG_MSG_WITH_SDP);
|
||||
}
|
||||
|
||||
void
|
||||
B2BSession::onInfo(InviteSessionHandle h, const SipMessage& msg)
|
||||
{
|
||||
InfoLog(B2BLOG_PREFIX << "onInfo: msg=" << LOG_MSG);
|
||||
if(mPeer)
|
||||
{
|
||||
if(mPeer->mInviteSessionHandle.isValid() && msg.getContents())
|
||||
{
|
||||
mPeer->mInviteSessionHandle->info(*msg.getContents());
|
||||
mWaitingNitAnswerFromPeer = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
h->acceptNIT();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
B2BSession::onInfoSuccess(InviteSessionHandle h, const SipMessage& msg)
|
||||
{
|
||||
InfoLog(B2BLOG_PREFIX << "onInfoSuccess: msg=" << LOG_MSG);
|
||||
if(mPeer)
|
||||
{
|
||||
if(mPeer->mInviteSessionHandle.isValid() && mPeer->mWaitingNitAnswerFromPeer)
|
||||
{
|
||||
mPeer->mInviteSessionHandle->acceptNIT(msg.header(h_StatusLine).responseCode(), msg.getContents());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
B2BSession::onInfoFailure(InviteSessionHandle h, const SipMessage& msg)
|
||||
{
|
||||
InfoLog(B2BLOG_PREFIX << "onInfoFailure: msg=" << LOG_MSG);
|
||||
if(mPeer)
|
||||
{
|
||||
if(mPeer->mInviteSessionHandle.isValid() && mPeer->mWaitingNitAnswerFromPeer)
|
||||
{
|
||||
mPeer->mInviteSessionHandle->rejectNIT(msg.header(h_StatusLine).responseCode());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
B2BSession::onRefer(InviteSessionHandle h, ServerSubscriptionHandle ss, const SipMessage& msg)
|
||||
{
|
||||
InfoLog(B2BLOG_PREFIX << "onRefer: msg=" << LOG_MSG);
|
||||
|
||||
// If no peer (for some reason), then reject request
|
||||
if(!mPeer)
|
||||
{
|
||||
ss->send(ss->reject(403));
|
||||
return;
|
||||
}
|
||||
|
||||
// Recurse on the REFER - do not pass to other leg
|
||||
try
|
||||
{
|
||||
// Accept the Refer
|
||||
ss->send(ss->accept(202 /* Refer Accepted */));
|
||||
|
||||
B2BSession* newPeer = new B2BSession(mServer);
|
||||
|
||||
mPeer->mWaitingOfferFromPeer = true;
|
||||
|
||||
// Map other leg to this new one
|
||||
newPeer->stealPeer(this);
|
||||
newPeer->mReferringAppDialogSet = getHandle();
|
||||
|
||||
auto invitemsg = mDum.makeInviteSessionFromRefer(msg, ss->getHandle(), 0 /* SdpOffer */, newPeer);
|
||||
mDum.send(std::move(invitemsg));
|
||||
}
|
||||
catch(BaseException &e)
|
||||
{
|
||||
WarningLog(B2BLOG_PREFIX << "onRefer exception: " << e);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
WarningLog(B2BLOG_PREFIX << "onRefer unknown exception");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
B2BSession::onReferAccepted(InviteSessionHandle h, ClientSubscriptionHandle csh, const SipMessage& msg)
|
||||
{
|
||||
InfoLog(B2BLOG_PREFIX << "onReferAccepted: msg=" << LOG_MSG);
|
||||
}
|
||||
|
||||
void
|
||||
B2BSession::onReferRejected(InviteSessionHandle h, const SipMessage& msg)
|
||||
{
|
||||
InfoLog(B2BLOG_PREFIX << "onReferRejected: msg=" << LOG_MSG);
|
||||
|
||||
// Endpoint doesn't support REFER - Fallback to anchoring Click-To-Call
|
||||
mClickToCallAnchorEnabled = true;
|
||||
mPeer = new B2BSession(mServer);
|
||||
mPeer->setPeer(this);
|
||||
mPeer->startClickToCallAnchorLeg(msg.header(h_From), mClickToCallDestination, mXmlRpcInfo);
|
||||
mWaitingOfferFromPeer = true;
|
||||
}
|
||||
|
||||
bool
|
||||
B2BSession::doReferNoSub(const SipMessage& msg)
|
||||
{
|
||||
// If no peer (for some reason), then return false
|
||||
if(!mPeer)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
B2BSession* newPeer = new B2BSession(mServer);
|
||||
|
||||
|
||||
mPeer->mWaitingOfferFromPeer = true;
|
||||
|
||||
// Map other leg to this new one
|
||||
newPeer->stealPeer(this);
|
||||
newPeer->mReferringAppDialogSet = getHandle();
|
||||
|
||||
// Build the Invite
|
||||
auto invitemsg = mDum.makeInviteSessionFromRefer(msg, getUserProfile(), 0 /* Sdp Offer */, newPeer);
|
||||
mDum.send(std::move(invitemsg));
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
B2BSession::onReferNoSub(InviteSessionHandle h, const SipMessage& msg)
|
||||
{
|
||||
InfoLog(B2BLOG_PREFIX << "onReferNoSub: msg=" << LOG_MSG);
|
||||
|
||||
// If no peer (for some reason), then reject request
|
||||
if(!mPeer)
|
||||
{
|
||||
h->rejectReferNoSub(403);
|
||||
return;
|
||||
}
|
||||
|
||||
// Accept the Refer
|
||||
h->acceptReferNoSub(202 /* Refer Accepted */);
|
||||
|
||||
doReferNoSub(msg);
|
||||
}
|
||||
|
||||
void
|
||||
B2BSession::onMessage(InviteSessionHandle h, const SipMessage& msg)
|
||||
{
|
||||
InfoLog(B2BLOG_PREFIX << "onMessage: msg=" << LOG_MSG);
|
||||
if(mPeer)
|
||||
{
|
||||
if(mPeer->mInviteSessionHandle.isValid() && msg.getContents())
|
||||
{
|
||||
mPeer->mInviteSessionHandle->message(*msg.getContents());
|
||||
mWaitingNitAnswerFromPeer = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
h->acceptNIT();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
B2BSession::onMessageSuccess(InviteSessionHandle h, const SipMessage& msg)
|
||||
{
|
||||
InfoLog(B2BLOG_PREFIX << "onMessageSuccess: msg=" << LOG_MSG);
|
||||
if(mPeer)
|
||||
{
|
||||
if(mPeer->mInviteSessionHandle.isValid() && mPeer->mWaitingNitAnswerFromPeer)
|
||||
{
|
||||
mPeer->mInviteSessionHandle->acceptNIT(msg.header(h_StatusLine).responseCode(), msg.getContents());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
B2BSession::onMessageFailure(InviteSessionHandle h, const SipMessage& msg)
|
||||
{
|
||||
InfoLog(B2BLOG_PREFIX << "onMessageFailure: msg=" << LOG_MSG);
|
||||
if(mPeer)
|
||||
{
|
||||
if(mPeer->mInviteSessionHandle.isValid() && mPeer->mWaitingNitAnswerFromPeer)
|
||||
{
|
||||
mPeer->mInviteSessionHandle->rejectNIT(msg.header(h_StatusLine).responseCode());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
B2BSession::onForkDestroyed(ClientInviteSessionHandle h)
|
||||
{
|
||||
InfoLog(B2BLOG_PREFIX << "onForkDestroyed:");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// DialogSetHandler ///////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
B2BSession::onTrying(AppDialogSetHandle h, const SipMessage& msg)
|
||||
{
|
||||
InfoLog(B2BLOG_PREFIX << "onTrying: msg=" << LOG_MSG);
|
||||
}
|
||||
|
||||
void
|
||||
B2BSession::onNonDialogCreatingProvisional(AppDialogSetHandle h, const SipMessage& msg)
|
||||
{
|
||||
InfoLog(B2BLOG_PREFIX << "onNonDialogCreatingProvisional: msg=" << LOG_MSG);
|
||||
|
||||
if(isUACConnected()) return;
|
||||
|
||||
if(mPeer)
|
||||
{
|
||||
if(mPeer->mInviteSessionHandle.isValid())
|
||||
{
|
||||
ServerInviteSession* sis = dynamic_cast<ServerInviteSession*>(mPeer->mInviteSessionHandle.get());
|
||||
if(sis && !sis->isAccepted())
|
||||
{
|
||||
sis->provisional(msg.header(h_StatusLine).responseCode());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// ClientSubscriptionHandler ///////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
B2BSession::onUpdatePending(ClientSubscriptionHandle h, const SipMessage& msg, bool outOfOrder)
|
||||
{
|
||||
InfoLog(B2BLOG_PREFIX << "onUpdatePending(ClientSubscriptionHandle): " << LOG_MSG);
|
||||
if (msg.exists(h_Event) && msg.header(h_Event).value() == "refer")
|
||||
{
|
||||
h->acceptUpdate();
|
||||
processReferNotify(msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
h->rejectUpdate(400, Data("Only notifies for refers are allowed."));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
B2BSession::onUpdateActive(ClientSubscriptionHandle h, const SipMessage& msg, bool outOfOrder)
|
||||
{
|
||||
InfoLog(B2BLOG_PREFIX << "onUpdateActive(ClientSubscriptionHandle): " << LOG_MSG);
|
||||
if (msg.exists(h_Event) && msg.header(h_Event).value() == "refer")
|
||||
{
|
||||
h->acceptUpdate();
|
||||
processReferNotify(msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
h->rejectUpdate(400, Data("Only notifies for refers are allowed."));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
B2BSession::onUpdateExtension(ClientSubscriptionHandle h, const SipMessage& msg, bool outOfOrder)
|
||||
{
|
||||
InfoLog(B2BLOG_PREFIX << "onUpdateExtension(ClientSubscriptionHandle): " << LOG_MSG);
|
||||
if (msg.exists(h_Event) && msg.header(h_Event).value() == "refer")
|
||||
{
|
||||
h->acceptUpdate();
|
||||
processReferNotify(msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
h->rejectUpdate(400, Data("Only notifies for refers are allowed."));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
B2BSession::onNotifyNotReceived(resip::ClientSubscriptionHandle h)
|
||||
{
|
||||
InfoLog(B2BLOG_PREFIX << "onNotifyNotReceived(ClientSubscriptionHandle)");
|
||||
transitionClickToCallState(ReferToDestinationFailed, 408);
|
||||
end();
|
||||
}
|
||||
|
||||
void
|
||||
B2BSession::onTerminated(ClientSubscriptionHandle h, const SipMessage* msg)
|
||||
{
|
||||
if(msg)
|
||||
{
|
||||
InfoLog(B2BLOG_PREFIX << "onTerminated(ClientSubscriptionHandle): " << LOG_MSGP);
|
||||
//Note: Final notify is sometimes only passed in the onTerminated callback
|
||||
if (msg->isRequest() && msg->exists(h_Event) && msg->header(h_Event).value() == "refer")
|
||||
{
|
||||
processReferNotify(*msg);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
InfoLog(B2BLOG_PREFIX << "onTerminated(ClientSubscriptionHandle)");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
B2BSession::onNewSubscription(ClientSubscriptionHandle h, const SipMessage& msg)
|
||||
{
|
||||
InfoLog(B2BLOG_PREFIX << "onNewSubscription(ClientSubscriptionHandle): " << LOG_MSG);
|
||||
}
|
||||
|
||||
int
|
||||
B2BSession::onRequestRetry(ClientSubscriptionHandle h, int retryMinimum, const SipMessage& msg)
|
||||
{
|
||||
InfoLog(B2BLOG_PREFIX << "onRequestRetry(ClientSubscriptionHandle): " << LOG_MSG);
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* ====================================================================
|
||||
|
||||
Copyright (c) 2009, SIP Spectrum, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of SIP Spectrum nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
==================================================================== */
|
||||
|
||||
159
src/libs/resiprocate/apps/clicktocall/B2BSession.hxx
Normal file
159
src/libs/resiprocate/apps/clicktocall/B2BSession.hxx
Normal file
@@ -0,0 +1,159 @@
|
||||
#if !defined(B2BSession_hxx)
|
||||
#define B2BSession_hxx
|
||||
|
||||
#include <rutil/Log.hxx>
|
||||
#include <resip/dum/DialogUsageManager.hxx>
|
||||
#include <resip/dum/InviteSessionHandler.hxx>
|
||||
#include <resip/dum/DialogSetHandler.hxx>
|
||||
#include <resip/dum/AppDialogSet.hxx>
|
||||
|
||||
#include "XmlRpcServer.hxx"
|
||||
|
||||
namespace clicktocall
|
||||
{
|
||||
|
||||
class Server;
|
||||
|
||||
typedef unsigned int B2BSessionHandle;
|
||||
|
||||
class B2BSession : public resip::AppDialogSet
|
||||
{
|
||||
public:
|
||||
B2BSession(Server& server);
|
||||
virtual ~B2BSession();
|
||||
|
||||
void setPeer(B2BSession* peer);
|
||||
B2BSession* getPeer();
|
||||
void stealPeer(B2BSession* victimSession);
|
||||
|
||||
B2BSessionHandle getB2BSessionHandle() const { return mHandle; }
|
||||
|
||||
void clickToCall(const resip::Uri& initiator, const resip::Uri& destination, bool anchorCall, const XmlRpcInfo& xmlRpcInfo);
|
||||
void startCall(const resip::Uri& destinationUri, const resip::NameAddr& from, const resip::SdpContents *sdp);
|
||||
|
||||
protected:
|
||||
friend class Server;
|
||||
|
||||
// Invite Session Handler /////////////////////////////////////////////////////
|
||||
virtual void onNewSession(resip::ClientInviteSessionHandle h, resip::InviteSession::OfferAnswerType oat, const resip::SipMessage& msg);
|
||||
virtual void onNewSession(resip::ServerInviteSessionHandle h, resip::InviteSession::OfferAnswerType oat, const resip::SipMessage& msg);
|
||||
virtual void onFailure(resip::ClientInviteSessionHandle h, const resip::SipMessage& msg);
|
||||
virtual void onEarlyMedia(resip::ClientInviteSessionHandle, const resip::SipMessage&, const resip::SdpContents&);
|
||||
virtual void onProvisional(resip::ClientInviteSessionHandle, const resip::SipMessage& msg);
|
||||
virtual void onConnected(resip::ClientInviteSessionHandle h, const resip::SipMessage& msg);
|
||||
virtual void onConnected(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
||||
virtual void onStaleCallTimeout(resip::ClientInviteSessionHandle);
|
||||
virtual void onTerminated(resip::InviteSessionHandle h, resip::InviteSessionHandler::TerminatedReason reason, const resip::SipMessage* msg);
|
||||
virtual void onRedirected(resip::ClientInviteSessionHandle, const resip::SipMessage& msg);
|
||||
virtual void onAnswer(resip::InviteSessionHandle, const resip::SipMessage& msg, const resip::SdpContents&);
|
||||
virtual void onOffer(resip::InviteSessionHandle handle, const resip::SipMessage& msg, const resip::SdpContents& offer);
|
||||
virtual void onOfferRequired(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
||||
virtual void onOfferRejected(resip::InviteSessionHandle, const resip::SipMessage* msg);
|
||||
virtual void onOfferRequestRejected(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
||||
virtual void onRemoteSdpChanged(resip::InviteSessionHandle, const resip::SipMessage& msg, const resip::SdpContents& sdp);
|
||||
virtual void onInfo(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
||||
virtual void onInfoSuccess(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
||||
virtual void onInfoFailure(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
||||
virtual void onRefer(resip::InviteSessionHandle, resip::ServerSubscriptionHandle, const resip::SipMessage& msg);
|
||||
virtual void onReferAccepted(resip::InviteSessionHandle, resip::ClientSubscriptionHandle, const resip::SipMessage& msg);
|
||||
virtual void onReferRejected(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
||||
virtual bool doReferNoSub(const resip::SipMessage& msg);
|
||||
virtual void onReferNoSub(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
||||
virtual void onMessage(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
||||
virtual void onMessageSuccess(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
||||
virtual void onMessageFailure(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
||||
virtual void onForkDestroyed(resip::ClientInviteSessionHandle);
|
||||
|
||||
// DialogSetHandler //////////////////////////////////////////////
|
||||
virtual void onTrying(resip::AppDialogSetHandle, const resip::SipMessage& msg);
|
||||
virtual void onNonDialogCreatingProvisional(resip::AppDialogSetHandle, const resip::SipMessage& msg);
|
||||
|
||||
// ClientSubscriptionHandler ///////////////////////////////////////////////////
|
||||
virtual void onUpdatePending(resip::ClientSubscriptionHandle h, const resip::SipMessage& notify, bool outOfOrder);
|
||||
virtual void onUpdateActive(resip::ClientSubscriptionHandle h, const resip::SipMessage& notify, bool outOfOrder);
|
||||
virtual void onUpdateExtension(resip::ClientSubscriptionHandle h, const resip::SipMessage& notify, bool outOfOrder);
|
||||
virtual void onNotifyNotReceived(resip::ClientSubscriptionHandle h);
|
||||
virtual void onTerminated(resip::ClientSubscriptionHandle h, const resip::SipMessage* notify);
|
||||
virtual void onNewSubscription(resip::ClientSubscriptionHandle h, const resip::SipMessage& notify);
|
||||
virtual int onRequestRetry(resip::ClientSubscriptionHandle h, int retryMinimum, const resip::SipMessage& notify);
|
||||
|
||||
private:
|
||||
bool buildLocalOffer(resip::SdpContents& sdp);
|
||||
void startClickToCallAnchorLeg(const resip::NameAddr& initiator, const resip::Uri& destination, const XmlRpcInfo& xmlRpcInfo);
|
||||
void endPeer();
|
||||
bool isUACConnected();
|
||||
bool isStaleFork(const resip::DialogId& dialogId);
|
||||
void processReferNotify(const resip::SipMessage& notify);
|
||||
|
||||
Server& mServer;
|
||||
resip::DialogUsageManager& mDum;
|
||||
B2BSession* mPeer;
|
||||
resip::InviteSessionHandle mInviteSessionHandle;
|
||||
B2BSessionHandle mHandle;
|
||||
resip::AppDialogSetHandle mReferringAppDialogSet;
|
||||
|
||||
// State information
|
||||
resip::DialogId mUACConnectedDialogId;
|
||||
bool mWaitingOfferFromPeer;
|
||||
bool mWaitingAnswerFromPeer;
|
||||
bool mWaitingNitAnswerFromPeer;
|
||||
|
||||
// Click-to-Call Info
|
||||
typedef enum
|
||||
{
|
||||
Undefined, // Not used
|
||||
Setup,
|
||||
Proceeding,
|
||||
Connected,
|
||||
Failed,
|
||||
ReferToDestinationProceeding,
|
||||
ReferToDestinationConnected,
|
||||
ReferToDestinationFailed
|
||||
} ClickToCallState;
|
||||
ClickToCallState mClickToCallState;
|
||||
void transitionClickToCallState(ClickToCallState newState, unsigned int statusCode=0);
|
||||
|
||||
resip::Uri mClickToCallDestination;
|
||||
bool mClickToCallAnchorEnabled;
|
||||
bool mClickToCallInitiator;
|
||||
XmlRpcInfo mXmlRpcInfo;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* ====================================================================
|
||||
|
||||
Copyright (c) 2009, SIP Spectrum, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of SIP Spectrum nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
==================================================================== */
|
||||
|
||||
42
src/libs/resiprocate/apps/clicktocall/CMakeLists.txt
Normal file
42
src/libs/resiprocate/apps/clicktocall/CMakeLists.txt
Normal file
@@ -0,0 +1,42 @@
|
||||
set(INCLUDES
|
||||
ConfigParser.hxx
|
||||
Version.hxx
|
||||
WebAdminThread.hxx
|
||||
XmlRpcServerBase.hxx
|
||||
HttpBase.hxx
|
||||
XmlRpcConnection.hxx
|
||||
AppSubsystem.hxx
|
||||
XmlRpcServerThread.hxx
|
||||
B2BSession.hxx
|
||||
AddressTranslator.hxx
|
||||
WebAdmin.hxx
|
||||
XmlRpcServer.hxx
|
||||
HttpConnection.hxx
|
||||
Server.hxx
|
||||
ClickToCallCmds.hxx
|
||||
)
|
||||
|
||||
add_executable(clicktocall
|
||||
AddressTranslator.cxx
|
||||
AppSubsystem.cxx
|
||||
B2BSession.cxx
|
||||
clicktocall.cxx
|
||||
ConfigParser.cxx
|
||||
HttpBase.cxx
|
||||
HttpConnection.cxx
|
||||
Server.cxx
|
||||
WebAdmin.cxx
|
||||
WebAdminThread.cxx
|
||||
XmlRpcConnection.cxx
|
||||
XmlRpcServerBase.cxx
|
||||
XmlRpcServer.cxx
|
||||
XmlRpcServerThread.cxx
|
||||
${INCLUDES}
|
||||
)
|
||||
|
||||
target_include_directories(clicktocall PRIVATE ${PCRE_INCLUDE_DIRS})
|
||||
target_link_libraries(clicktocall PUBLIC dum ${PCRE_LIBRARIES})
|
||||
|
||||
install(TARGETS clicktocall DESTINATION ${CMAKE_INSTALL_SBINDIR})
|
||||
|
||||
install_and_preserve_hierarchy(${CMAKE_INSTALL_INCLUDEDIR}/clicktocall ${INCLUDES})
|
||||
80
src/libs/resiprocate/apps/clicktocall/ClickToCallCmds.hxx
Normal file
80
src/libs/resiprocate/apps/clicktocall/ClickToCallCmds.hxx
Normal file
@@ -0,0 +1,80 @@
|
||||
#if !defined(ClickToCallCmds_hxx)
|
||||
#define ClickToCallCmds_hxx
|
||||
|
||||
#include <resip/dum/DumCommand.hxx>
|
||||
|
||||
#include "Server.hxx"
|
||||
#include "B2BSession.hxx"
|
||||
|
||||
#define RESIPROCATE_SUBSYSTEM AppSubsystem::CLICKTOCALL
|
||||
|
||||
namespace clicktocall
|
||||
{
|
||||
|
||||
/**
|
||||
The classes defined here are used to pass commands from the
|
||||
application thread to the DUM thread (process loop).
|
||||
This ensures thread safety of the external Server methods.
|
||||
|
||||
Author: Scott Godin (sgodin AT SipSpectrum DOT com)
|
||||
*/
|
||||
class ClickToCallCmd : public resip::DumCommand
|
||||
{
|
||||
public:
|
||||
ClickToCallCmd(Server& server, const resip::Uri& initiator, const resip::Uri& destination, bool anchorCall,
|
||||
const XmlRpcInfo& xmlRpcInfo)
|
||||
: mServer(server), mInitiator(initiator), mDestination(destination), mAnchorCall(anchorCall),
|
||||
mXmlRpcInfo(xmlRpcInfo) {}
|
||||
virtual void executeCommand()
|
||||
{
|
||||
mServer.clickToCallImpl(mInitiator, mDestination, mAnchorCall, mXmlRpcInfo);
|
||||
}
|
||||
resip::Message* clone() const { resip_assert(0); return 0; }
|
||||
EncodeStream& encode(EncodeStream& strm) const { strm << " ClickToCallCmd: "; return strm; }
|
||||
EncodeStream& encodeBrief(EncodeStream& strm) const { return encode(strm); }
|
||||
private:
|
||||
Server& mServer;
|
||||
resip::Uri mInitiator;
|
||||
resip::Uri mDestination;
|
||||
bool mAnchorCall;
|
||||
XmlRpcInfo mXmlRpcInfo;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* ====================================================================
|
||||
|
||||
Copyright (c) 2009, SIP Spectrum, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of SIP Spectrum nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
==================================================================== */
|
||||
|
||||
333
src/libs/resiprocate/apps/clicktocall/ConfigParser.cxx
Normal file
333
src/libs/resiprocate/apps/clicktocall/ConfigParser.cxx
Normal file
@@ -0,0 +1,333 @@
|
||||
#include "ConfigParser.hxx"
|
||||
#include "Server.hxx"
|
||||
|
||||
#include "AppSubsystem.hxx"
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <iterator>
|
||||
|
||||
#include <rutil/DnsUtil.hxx>
|
||||
#include <rutil/Log.hxx>
|
||||
#include <rutil/Logger.hxx>
|
||||
#include <rutil/WinLeakCheck.hxx>
|
||||
|
||||
using namespace clicktocall;
|
||||
using namespace resip;
|
||||
using namespace std;
|
||||
|
||||
#define RESIPROCATE_SUBSYSTEM AppSubsystem::CLICKTOCALL
|
||||
|
||||
namespace clicktocall
|
||||
{
|
||||
|
||||
ConfigParser::ConfigParser(int argc, char** argv) :
|
||||
// Defaults
|
||||
mSipPort(5072),
|
||||
mTlsPort(5073),
|
||||
mTlsDomain(DnsUtil::getLocalHostName()),
|
||||
mKeepAlives(true),
|
||||
mLogLevel("INFO"),
|
||||
mLogFilename("clicktocall.log"),
|
||||
mLogFileMaxLines(50000), // 50000 is about 5M size
|
||||
mXmlRpcPort(5094),
|
||||
mHttpPort(5095),
|
||||
mHttpAuth(false),
|
||||
mHttpAuthPwd("admin")
|
||||
{
|
||||
// Parse config file first
|
||||
parseConfigFile("clicktocall.config");
|
||||
|
||||
// Parse command line options
|
||||
// Note: command line overrides config file setting
|
||||
parseCommandLine(argc, argv);
|
||||
}
|
||||
|
||||
ConfigParser::~ConfigParser()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ConfigParser::parseCommandLine(int argc, char** argv)
|
||||
{
|
||||
// Loop through command line arguments and process them
|
||||
for(int i = 1; i < argc; i++)
|
||||
{
|
||||
Data commandName(argv[i]);
|
||||
|
||||
// Process all commandNames that don't take values
|
||||
if(isEqualNoCase(commandName, "-?") ||
|
||||
isEqualNoCase(commandName, "--?") ||
|
||||
isEqualNoCase(commandName, "--help") ||
|
||||
isEqualNoCase(commandName, "/?"))
|
||||
{
|
||||
cout << "Command line options are:" << endl;
|
||||
cout << " -a <IP Address> - bind SIP transports to this IP address" << endl;
|
||||
cout << " -d <DNS servers> - comma seperated list of DNS servers, overrides OS detected list" << endl;
|
||||
cout << " -ci <ClickToCall identity> - used in From header of click-to-call requests to initiator" << endl;
|
||||
cout << " -sp <port num> - local port number to use for SIP messaging (UDP/TCP)" << endl;
|
||||
cout << " -tp <port num> - local port number to use for TLS SIP messaging" << endl;
|
||||
cout << " -td <domain name> - domain name to use for TLS server connections" << endl;
|
||||
cout << " -nk - no keepalives, set this to disable sending of keepalives" << endl;
|
||||
cout << " -op <SIP URI> - URI of a proxy server to use a SIP outbound proxy" << endl;
|
||||
cout << " -l <NONE|CRIT|ERR|WARNING|INFO|DEBUG|STACK> - logging level" << endl;
|
||||
cout << endl;
|
||||
cout << "Sample Command line:" << endl;
|
||||
cout << "clicktocall -a 192.168.1.100 -l DEBUG" << endl;
|
||||
exit(0);
|
||||
}
|
||||
else if(isEqualNoCase(commandName, "-nk"))
|
||||
{
|
||||
mKeepAlives = false;
|
||||
}
|
||||
else if(commandName.at(0) == '-')
|
||||
{
|
||||
commandName = commandName.substr(1); // Remove -
|
||||
|
||||
// Process commands that have values
|
||||
Data commandValue(i+1 < argc ? argv[i+1] : Data::Empty);
|
||||
if(commandValue.empty() || commandValue.at(0) == '-')
|
||||
{
|
||||
cerr << "Invalid command line parameters!" << endl;
|
||||
exit(-1);
|
||||
}
|
||||
i++; // increment argument
|
||||
|
||||
//cout << "Command Line Name='" << commandName << "' value='" << commandValue << "'" << endl;
|
||||
if(!processOption(commandName.lowercase(), commandValue))
|
||||
{
|
||||
cerr << "Invalid command line parameters!" << endl;
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cerr << "Invalid command line parameters!" << endl;
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ConfigParser::parseConfigFile(const Data& filename)
|
||||
{
|
||||
ifstream configFile(filename.c_str());
|
||||
|
||||
string sline;
|
||||
while(getline(configFile, sline))
|
||||
{
|
||||
Data line(sline);
|
||||
Data name;
|
||||
Data value;
|
||||
ParseBuffer pb(line);
|
||||
|
||||
pb.skipWhitespace();
|
||||
const char * anchor = pb.position();
|
||||
if(pb.eof() || *anchor == '#') continue; // if line is a comment or blank then skip it
|
||||
// Look for =
|
||||
pb.skipToOneOf("= \t");
|
||||
if(!pb.eof())
|
||||
{
|
||||
pb.data(name,anchor);
|
||||
if(*pb.position()!='=')
|
||||
{
|
||||
pb.skipToChar('=');
|
||||
}
|
||||
pb.skipChar('=');
|
||||
pb.skipWhitespace();
|
||||
anchor = pb.position();
|
||||
if(!pb.eof())
|
||||
{
|
||||
pb.skipToEnd();
|
||||
pb.data(value, anchor);
|
||||
}
|
||||
//cout << "Config file Name='" << name << "' value='" << value << "'" << endl;
|
||||
processOption(name.lowercase(), value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
ConfigParser::processOption(const Data& name, const Data& value)
|
||||
{
|
||||
bool result = true;
|
||||
if(name == "a" || name == "ipaddress")
|
||||
{
|
||||
mAddress = value;
|
||||
}
|
||||
else if(name == "d" || name == "dnsservers")
|
||||
{
|
||||
if(!value.empty()) mDnsServers.clear(); // allow command line to override config file, since list is added to
|
||||
|
||||
// DNS Servers
|
||||
ParseBuffer pb(value);
|
||||
Data dnsServer;
|
||||
while(!value.empty() && !pb.eof())
|
||||
{
|
||||
pb.skipWhitespace();
|
||||
const char *start = pb.position();
|
||||
pb.skipToOneOf(ParseBuffer::Whitespace, ";,"); // allow white space
|
||||
pb.data(dnsServer, start);
|
||||
if(DnsUtil::isIpV4Address(dnsServer))
|
||||
{
|
||||
mDnsServers.push_back(Tuple(dnsServer, 0, UNKNOWN_TRANSPORT).toGenericIPAddress());
|
||||
}
|
||||
else
|
||||
{
|
||||
cerr << "Tried to add dns server, but invalid format: " << value << endl;
|
||||
result = false;
|
||||
}
|
||||
if(!pb.eof())
|
||||
{
|
||||
pb.skipChar();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(name == "ci" || name == "clicktocallidentity")
|
||||
{
|
||||
result = assignNameAddr("click to call identity", value, mClickToCallIdentity);
|
||||
}
|
||||
else if(name == "sp" || name == "udptcpport")
|
||||
{
|
||||
mSipPort = (unsigned short)value.convertUnsignedLong();
|
||||
}
|
||||
else if(name == "tp" || name == "tlsport")
|
||||
{
|
||||
mTlsPort = (unsigned short)value.convertUnsignedLong();
|
||||
}
|
||||
else if(name == "td" || name == "tlsdomain")
|
||||
{
|
||||
mTlsDomain = value;
|
||||
}
|
||||
else if(name == "keepalives")
|
||||
{
|
||||
if(value == "1" || value == "true" || value == "on" || value == "enable")
|
||||
{
|
||||
mKeepAlives = true;
|
||||
}
|
||||
else if(value == "0" || value == "false" || value == "off" || value == "disable")
|
||||
{
|
||||
mKeepAlives = false;
|
||||
}
|
||||
}
|
||||
else if(name == "op" || name == "outboundproxy")
|
||||
{
|
||||
result = assignNameAddr("outbound proxy", value, mOutboundProxy);
|
||||
}
|
||||
else if(name == "l" || name == "loglevel")
|
||||
{
|
||||
mLogLevel = value;
|
||||
}
|
||||
else if(name == "logfilename")
|
||||
{
|
||||
mLogFilename = value;
|
||||
}
|
||||
else if(name == "logfilemaxlines")
|
||||
{
|
||||
mLogFileMaxLines = value.convertUnsignedLong();
|
||||
}
|
||||
else if(name == "xmlrpcport")
|
||||
{
|
||||
mXmlRpcPort = (unsigned short)value.convertUnsignedLong();
|
||||
}
|
||||
else if(name == "httpport")
|
||||
{
|
||||
mHttpPort = (unsigned short)value.convertUnsignedLong();
|
||||
}
|
||||
else if(name == "httpauth")
|
||||
{
|
||||
if(value == "1" || value == "true" || value == "on" || value == "enable")
|
||||
{
|
||||
mHttpAuth = true;
|
||||
}
|
||||
else if(value == "0" || value == "false" || value == "off" || value == "disable")
|
||||
{
|
||||
mHttpAuth = false;
|
||||
}
|
||||
}
|
||||
else if(name == "httpauthpwd")
|
||||
{
|
||||
mHttpAuthPwd = value;
|
||||
}
|
||||
else if(name == "translationpattern")
|
||||
{
|
||||
mAddressTranslations.push_back(std::make_pair(value, Data::Empty));
|
||||
}
|
||||
else if(name == "translationoutput")
|
||||
{
|
||||
if(!mAddressTranslations.empty())
|
||||
{
|
||||
mAddressTranslations.back().second = value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool
|
||||
ConfigParser::assignNameAddr(const Data& settingName, const Data& settingValue, NameAddr& nameAddr)
|
||||
{
|
||||
try
|
||||
{
|
||||
if(!settingValue.empty())
|
||||
{
|
||||
NameAddr tempNameAddr(settingValue);
|
||||
nameAddr = tempNameAddr;
|
||||
}
|
||||
}
|
||||
catch(resip::BaseException& e)
|
||||
{
|
||||
// Try adding sip: to address to see if it will be valid
|
||||
try
|
||||
{
|
||||
NameAddr tempNameAddr(Data("sip:" + settingValue));
|
||||
nameAddr = tempNameAddr;
|
||||
}
|
||||
catch(resip::BaseException&)
|
||||
{
|
||||
cerr << "Invalid " << settingName << " NameAddr format=" << settingValue << ": " << e << endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* ====================================================================
|
||||
|
||||
Copyright (c) 2009, SIP Spectrum, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of SIP Spectrum nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
==================================================================== */
|
||||
|
||||
80
src/libs/resiprocate/apps/clicktocall/ConfigParser.hxx
Normal file
80
src/libs/resiprocate/apps/clicktocall/ConfigParser.hxx
Normal file
@@ -0,0 +1,80 @@
|
||||
#if !defined(ConfigParser_hxx)
|
||||
#define ConfigParser_hxx
|
||||
|
||||
#include <list>
|
||||
#include <resip/dum/MasterProfile.hxx>
|
||||
#include <rutil/dns/DnsStub.hxx>
|
||||
#include <rutil/Log.hxx>
|
||||
|
||||
|
||||
namespace clicktocall
|
||||
{
|
||||
|
||||
class ConfigParser
|
||||
{
|
||||
public:
|
||||
ConfigParser(int argc, char** argv);
|
||||
virtual ~ConfigParser();
|
||||
|
||||
void parseCommandLine(int argc, char** argv);
|
||||
void parseConfigFile(const resip::Data& filename);
|
||||
bool processOption(const resip::Data& name, const resip::Data& value);
|
||||
bool assignNameAddr(const resip::Data& settingName, const resip::Data& settingValue, resip::NameAddr& nameAddr);
|
||||
|
||||
resip::Data mAddress;
|
||||
resip::DnsStub::NameserverList mDnsServers;
|
||||
resip::NameAddr mClickToCallIdentity;
|
||||
unsigned short mSipPort;
|
||||
unsigned short mTlsPort;
|
||||
resip::Data mTlsDomain;
|
||||
resip::NameAddr mOutboundProxy;
|
||||
bool mKeepAlives;
|
||||
resip::Data mLogLevel;
|
||||
resip::Data mLogFilename;
|
||||
unsigned int mLogFileMaxLines;
|
||||
unsigned short mXmlRpcPort;
|
||||
unsigned short mHttpPort;
|
||||
bool mHttpAuth;
|
||||
resip::Data mHttpAuthPwd;
|
||||
typedef std::list<std::pair<resip::Data,resip::Data> > TranslationList;
|
||||
TranslationList mAddressTranslations;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* ====================================================================
|
||||
|
||||
Copyright (c) 2009, SIP Spectrum, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of SIP Spectrum nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
==================================================================== */
|
||||
|
||||
258
src/libs/resiprocate/apps/clicktocall/HttpBase.cxx
Normal file
258
src/libs/resiprocate/apps/clicktocall/HttpBase.cxx
Normal file
@@ -0,0 +1,258 @@
|
||||
#include "rutil/ResipAssert.h"
|
||||
|
||||
#include <rutil/Data.hxx>
|
||||
#include <rutil/Socket.hxx>
|
||||
#include <resip/stack/Symbols.hxx>
|
||||
#include <rutil/TransportType.hxx>
|
||||
#include <rutil/Logger.hxx>
|
||||
#include <resip/stack/Tuple.hxx>
|
||||
#include <rutil/DnsUtil.hxx>
|
||||
#include <rutil/ParseBuffer.hxx>
|
||||
#include <resip/stack/Transport.hxx>
|
||||
|
||||
#include "AppSubsystem.hxx"
|
||||
#include "HttpBase.hxx"
|
||||
#include "HttpConnection.hxx"
|
||||
#include "WebAdmin.hxx"
|
||||
#include <rutil/WinLeakCheck.hxx>
|
||||
|
||||
using namespace clicktocall;
|
||||
using namespace resip;
|
||||
using namespace std;
|
||||
|
||||
#define RESIPROCATE_SUBSYSTEM AppSubsystem::CLICKTOCALL
|
||||
|
||||
|
||||
HttpBase::~HttpBase()
|
||||
{
|
||||
#if defined(WIN32)
|
||||
closesocket(mFd);
|
||||
#else
|
||||
close(mFd);
|
||||
#endif
|
||||
mFd=0;
|
||||
for( int i=0; i<MaxConnections; i++)
|
||||
{
|
||||
if ( mConnection[i] )
|
||||
{
|
||||
delete mConnection[i] ; mConnection[i]=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HttpBase::HttpBase( int port, IpVersion ipVer, const Data& realm ):
|
||||
mRealm(realm),
|
||||
nextConnection(0),
|
||||
mTuple(Data::Empty,port,ipVer,TCP,Data::Empty)
|
||||
{
|
||||
sane = true;
|
||||
|
||||
for ( int i=0 ; i<MaxConnections; i++)
|
||||
{
|
||||
mConnection[i]=0;
|
||||
}
|
||||
|
||||
#ifdef USE_IPV6
|
||||
mFd = ::socket(ipVer == V4 ? PF_INET : PF_INET6, SOCK_STREAM, 0);
|
||||
#else
|
||||
mFd = ::socket(PF_INET, SOCK_STREAM, 0);
|
||||
#endif
|
||||
|
||||
if ( mFd == INVALID_SOCKET )
|
||||
{
|
||||
int e = getErrno();
|
||||
ErrLog (<< "Failed to create socket: " << strerror(e));
|
||||
sane = false;
|
||||
return;
|
||||
}
|
||||
|
||||
DebugLog (<< "Creating fd=" << (int)mFd
|
||||
<< (ipVer == V4 ? " V4/" : " V6/") );
|
||||
|
||||
int on = 1;
|
||||
#if !defined(WIN32)
|
||||
if ( ::setsockopt ( mFd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) )
|
||||
#else
|
||||
if ( ::setsockopt ( mFd, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on)) )
|
||||
#endif
|
||||
{
|
||||
int e = getErrno();
|
||||
ErrLog (<< "Couldn't set sockoptions SO_REUSEPORT | SO_REUSEADDR: " << strerror(e));
|
||||
sane = false;
|
||||
return;
|
||||
}
|
||||
|
||||
DebugLog (<< "Binding to " << Tuple::inet_ntop(mTuple));
|
||||
|
||||
if ( ::bind( mFd, &mTuple.getMutableSockaddr(), mTuple.length()) == SOCKET_ERROR )
|
||||
{
|
||||
int e = getErrno();
|
||||
if ( e == EADDRINUSE )
|
||||
{
|
||||
ErrLog (<< mTuple << " already in use ");
|
||||
}
|
||||
else
|
||||
{
|
||||
ErrLog (<< "Could not bind to " << mTuple);
|
||||
}
|
||||
sane = false;
|
||||
return;
|
||||
}
|
||||
|
||||
bool ok = makeSocketNonBlocking(mFd);
|
||||
if ( !ok )
|
||||
{
|
||||
ErrLog (<< "Could not make HTTP socket non-blocking " << port );
|
||||
sane = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// do the listen, seting the maximum queue size for compeletly established
|
||||
// sockets -- on linux, tcp_max_syn_backlog should be used for the incomplete
|
||||
// queue size(see man listen)
|
||||
int e = listen(mFd,5 );
|
||||
|
||||
if (e != 0 )
|
||||
{
|
||||
int e = getErrno();
|
||||
InfoLog (<< "Failed listen " << strerror(e));
|
||||
sane = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
HttpBase::buildFdSet(FdSet& fdset)
|
||||
{
|
||||
fdset.setRead( mFd );
|
||||
|
||||
for( int i=0; i<MaxConnections; i++)
|
||||
{
|
||||
if ( mConnection[i] )
|
||||
{
|
||||
mConnection[i]->buildFdSet(fdset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
HttpBase::process(FdSet& fdset)
|
||||
{
|
||||
if (fdset.readyToRead(mFd))
|
||||
{
|
||||
Tuple tuple(mTuple);
|
||||
struct sockaddr& peer = tuple.getMutableSockaddr();
|
||||
socklen_t peerLen = tuple.length();
|
||||
Socket sock = accept( mFd, &peer, &peerLen);
|
||||
if ( sock == SOCKET_ERROR )
|
||||
{
|
||||
int e = getErrno();
|
||||
switch (e)
|
||||
{
|
||||
case EWOULDBLOCK:
|
||||
return;
|
||||
default:
|
||||
ErrLog(<< "Some error reading from socket: " << e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
makeSocketNonBlocking(sock);
|
||||
|
||||
int c = nextConnection;
|
||||
nextConnection = ( nextConnection+1 ) % MaxConnections;
|
||||
|
||||
if ( mConnection[c] )
|
||||
{
|
||||
delete mConnection[c]; mConnection[c] = 0;
|
||||
}
|
||||
|
||||
mConnection[c] = new HttpConnection(*this,sock);
|
||||
|
||||
DebugLog (<< "Received TCP connection as connection=" << c << " fd=" << (int)sock);
|
||||
}
|
||||
|
||||
for( int i=0; i<MaxConnections; i++)
|
||||
{
|
||||
if ( mConnection[i] )
|
||||
{
|
||||
bool ok = mConnection[i]->process(fdset);
|
||||
if ( !ok )
|
||||
{
|
||||
delete mConnection[i]; mConnection[i]=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void HttpBase::setPage( const Data& page, int pageNumber, int response, const Mime& type )
|
||||
{
|
||||
for ( int i=0 ; i<MaxConnections; i++)
|
||||
{
|
||||
if ( mConnection[i] )
|
||||
{
|
||||
if ( mConnection[i]->mPageNumber == pageNumber )
|
||||
{
|
||||
mConnection[i]->setPage( page,response,type );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool HttpBase::isSane()
|
||||
{
|
||||
return sane;
|
||||
}
|
||||
|
||||
/* ====================================================================
|
||||
* The Vovida Software License, Version 1.0
|
||||
*
|
||||
* Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. The names "VOCAL", "Vovida Open Communication Application Library",
|
||||
* and "Vovida Open Communication Application Library (VOCAL)" must
|
||||
* not be used to endorse or promote products derived from this
|
||||
* software without prior written permission. For written
|
||||
* permission, please contact vocal@vovida.org.
|
||||
*
|
||||
* 4. Products derived from this software may not be called "VOCAL", nor
|
||||
* may "VOCAL" appear in their name, without prior written
|
||||
* permission of Vovida Networks, Inc.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
|
||||
* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
|
||||
* NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
|
||||
* IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* ====================================================================
|
||||
*
|
||||
* This software consists of voluntary contributions made by Vovida
|
||||
* Networks, Inc. and many individuals on behalf of Vovida Networks,
|
||||
* Inc. For more information on Vovida Networks, Inc., please see
|
||||
* <http://www.vovida.org/>.
|
||||
*
|
||||
*/
|
||||
104
src/libs/resiprocate/apps/clicktocall/HttpBase.hxx
Normal file
104
src/libs/resiprocate/apps/clicktocall/HttpBase.hxx
Normal file
@@ -0,0 +1,104 @@
|
||||
#if !defined(HttpBase_hxx)
|
||||
#define HttpBase_hxx
|
||||
|
||||
#include <rutil/Data.hxx>
|
||||
#include <rutil/Socket.hxx>
|
||||
#include <rutil/TransportType.hxx>
|
||||
#include <resip/stack/Tuple.hxx>
|
||||
#include <resip/stack/Mime.hxx>
|
||||
|
||||
namespace clicktocall
|
||||
{
|
||||
class HttpConnection;
|
||||
|
||||
class HttpBase
|
||||
{
|
||||
friend class HttpConnection;
|
||||
|
||||
public:
|
||||
HttpBase( int port, resip::IpVersion version, const resip::Data& realm );
|
||||
virtual ~HttpBase();
|
||||
|
||||
void buildFdSet(resip::FdSet& fdset);
|
||||
void process(resip::FdSet& fdset);
|
||||
|
||||
bool isSane();
|
||||
|
||||
protected:
|
||||
virtual void buildPage( const resip::Data& uri,
|
||||
int pageNumber,
|
||||
const resip::Data& user,
|
||||
const resip::Data& password )=0;
|
||||
void setPage( const resip::Data& page,
|
||||
int pageNumber,
|
||||
int response=200,
|
||||
const resip::Mime& pType = resip::Mime("text","html") );
|
||||
|
||||
const resip::Data mRealm;
|
||||
|
||||
private:
|
||||
static const int MaxConnections = 30;
|
||||
|
||||
resip::Socket mFd;
|
||||
int nextConnection;
|
||||
resip::Tuple mTuple;
|
||||
|
||||
bool sane;
|
||||
|
||||
HttpConnection* mConnection[MaxConnections];
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* ====================================================================
|
||||
* The Vovida Software License, Version 1.0
|
||||
*
|
||||
* Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. The names "VOCAL", "Vovida Open Communication Application Library",
|
||||
* and "Vovida Open Communication Application Library (VOCAL)" must
|
||||
* not be used to endorse or promote products derived from this
|
||||
* software without prior written permission. For written
|
||||
* permission, please contact vocal@vovida.org.
|
||||
*
|
||||
* 4. Products derived from this software may not be called "VOCAL", nor
|
||||
* may "VOCAL" appear in their name, without prior written
|
||||
* permission of Vovida Networks, Inc.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
|
||||
* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
|
||||
* NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
|
||||
* IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* ====================================================================
|
||||
*
|
||||
* This software consists of voluntary contributions made by Vovida
|
||||
* Networks, Inc. and many individuals on behalf of Vovida Networks,
|
||||
* Inc. For more information on Vovida Networks, Inc., please see
|
||||
* <http://www.vovida.org/>.
|
||||
*
|
||||
*/
|
||||
421
src/libs/resiprocate/apps/clicktocall/HttpConnection.cxx
Normal file
421
src/libs/resiprocate/apps/clicktocall/HttpConnection.cxx
Normal file
@@ -0,0 +1,421 @@
|
||||
#include "rutil/ResipAssert.h"
|
||||
|
||||
#include <rutil/Data.hxx>
|
||||
#include <rutil/Socket.hxx>
|
||||
#include <resip/stack/Symbols.hxx>
|
||||
#include <rutil/TransportType.hxx>
|
||||
#include <rutil/Logger.hxx>
|
||||
#include <resip/stack/Tuple.hxx>
|
||||
#include <rutil/DnsUtil.hxx>
|
||||
#include <rutil/ParseBuffer.hxx>
|
||||
|
||||
#include "Version.hxx"
|
||||
#include "AppSubsystem.hxx"
|
||||
#include "Server.hxx"
|
||||
#include "HttpBase.hxx"
|
||||
#include "HttpConnection.hxx"
|
||||
|
||||
using namespace clicktocall;
|
||||
using namespace resip;
|
||||
using namespace std;
|
||||
|
||||
#define RESIPROCATE_SUBSYSTEM AppSubsystem::CLICKTOCALL
|
||||
|
||||
int HttpConnection::nextPageNumber=1;
|
||||
|
||||
|
||||
HttpConnection::HttpConnection( HttpBase& base, resip::Socket pSock ):
|
||||
mHttpBase( base ),
|
||||
mPageNumber(nextPageNumber++),
|
||||
mSock(pSock),
|
||||
mParsedRequest(false)
|
||||
{
|
||||
resip_assert( mSock > 0 );
|
||||
}
|
||||
|
||||
|
||||
HttpConnection::~HttpConnection()
|
||||
{
|
||||
resip_assert( mSock > 0 );
|
||||
#ifdef WIN32
|
||||
closesocket(mSock); mSock=0;
|
||||
#else
|
||||
close(mSock); mSock=0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
HttpConnection::buildFdSet(FdSet& fdset)
|
||||
{
|
||||
if ( !mTxBuffer.empty() )
|
||||
{
|
||||
fdset.setWrite(mSock);
|
||||
}
|
||||
fdset.setRead(mSock);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
HttpConnection::process(FdSet& fdset)
|
||||
{
|
||||
if ( fdset.hasException(mSock) )
|
||||
{
|
||||
int errNum = 0;
|
||||
int errNumSize = sizeof(errNum);
|
||||
getsockopt(mSock,SOL_SOCKET,SO_ERROR,(char *)&errNum,(socklen_t *)&errNumSize);
|
||||
InfoLog (<< "Exception reading from socket "
|
||||
<< (int)mSock << " code: " << errNum << "; closing connection");
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( fdset.readyToRead( mSock ) )
|
||||
{
|
||||
bool ok = processSomeReads();
|
||||
if ( !ok )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if ( (!mTxBuffer.empty()) && fdset.readyToWrite( mSock ) )
|
||||
{
|
||||
bool ok = processSomeWrites();
|
||||
if ( !ok )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
HttpConnection::setPage(const Data& pPage,int response,const Mime& pType)
|
||||
{
|
||||
Data page(pPage);
|
||||
|
||||
switch (response)
|
||||
{
|
||||
case 401:
|
||||
{
|
||||
mTxBuffer += "HTTP/1.0 401 Unauthorized"; mTxBuffer += Symbols::CRLF;
|
||||
|
||||
page = ("<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">"
|
||||
"<html><head>"
|
||||
"<title>401 Unauthorized</title>"
|
||||
"</head><body>"
|
||||
"<h1>Unauthorized</h1>"
|
||||
"</body></html>" );
|
||||
}
|
||||
break;
|
||||
|
||||
case 404:
|
||||
{
|
||||
mTxBuffer += "HTTP/1.0 404 Not Found"; mTxBuffer += Symbols::CRLF;
|
||||
|
||||
page = ("<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">"
|
||||
"<html><head>"
|
||||
"<title>404 Not Found</title>"
|
||||
"</head><body>"
|
||||
"<h1>Unauthorized</h1>"
|
||||
"</body></html>" );
|
||||
}
|
||||
break;
|
||||
|
||||
case 301:
|
||||
{
|
||||
mTxBuffer += "HTTP/1.0 301 Moved Permanently"; mTxBuffer += Symbols::CRLF;
|
||||
mTxBuffer += "Location: http:/index.html"; mTxBuffer += Symbols::CRLF;
|
||||
|
||||
page = ("<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">"
|
||||
"<html><head>"
|
||||
"<title>301 Moved Permanently</title>"
|
||||
"</head><body>"
|
||||
"<h1>Moved</h1>"
|
||||
"</body></html>" );
|
||||
}
|
||||
break;
|
||||
|
||||
case 200:
|
||||
{
|
||||
mTxBuffer += "HTTP/1.0 200 OK" ; mTxBuffer += Symbols::CRLF;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
resip_assert(0);
|
||||
|
||||
Data resp;
|
||||
{
|
||||
DataStream s(resp);
|
||||
s << response;
|
||||
s.flush();
|
||||
}
|
||||
|
||||
mTxBuffer += "HTTP/1.0 ";
|
||||
mTxBuffer += resp;
|
||||
mTxBuffer += "OK" ; mTxBuffer += Symbols::CRLF;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
Data len;
|
||||
{
|
||||
DataStream s(len);
|
||||
s << page.size();
|
||||
s.flush();
|
||||
}
|
||||
|
||||
mTxBuffer += "WWW-Authenticate: Basic realm=\"";
|
||||
if ( mHttpBase.mRealm.empty() )
|
||||
{
|
||||
mTxBuffer += resip::DnsUtil::getLocalHostName();
|
||||
}
|
||||
else
|
||||
{
|
||||
mTxBuffer += mHttpBase.mRealm;
|
||||
}
|
||||
mTxBuffer += "\" ";
|
||||
mTxBuffer += Symbols::CRLF;
|
||||
|
||||
mTxBuffer += "Server: clicktocall " ;
|
||||
mTxBuffer += Data(CLICKTOCALL_VERSION_STRING);
|
||||
mTxBuffer += Symbols::CRLF;
|
||||
mTxBuffer += "Mime-version: 1.0 " ; mTxBuffer += Symbols::CRLF;
|
||||
mTxBuffer += "Pragma: no-cache " ; mTxBuffer += Symbols::CRLF;
|
||||
mTxBuffer += "Content-Length: "; mTxBuffer += len; mTxBuffer += Symbols::CRLF;
|
||||
|
||||
mTxBuffer += "Content-Type: " ;
|
||||
mTxBuffer += pType.type() ;
|
||||
mTxBuffer +="/" ;
|
||||
mTxBuffer += pType.subType() ; mTxBuffer += Symbols::CRLF;
|
||||
|
||||
mTxBuffer += Symbols::CRLF;
|
||||
|
||||
mTxBuffer += page;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
HttpConnection::processSomeReads()
|
||||
{
|
||||
const int bufSize = 8000;
|
||||
char buf[bufSize];
|
||||
|
||||
|
||||
#if defined(WIN32)
|
||||
int bytesRead = ::recv(mSock, buf, bufSize, 0);
|
||||
#else
|
||||
int bytesRead = ::read(mSock, buf, bufSize);
|
||||
#endif
|
||||
|
||||
if (bytesRead == INVALID_SOCKET)
|
||||
{
|
||||
int e = getErrno();
|
||||
switch (e)
|
||||
{
|
||||
case EAGAIN:
|
||||
InfoLog (<< "No data ready to read");
|
||||
return true;
|
||||
case EINTR:
|
||||
InfoLog (<< "The call was interrupted by a signal before any data was read.");
|
||||
break;
|
||||
case EIO:
|
||||
InfoLog (<< "I/O error");
|
||||
break;
|
||||
case EBADF:
|
||||
InfoLog (<< "fd is not a valid file descriptor or is not open for reading.");
|
||||
break;
|
||||
case EINVAL:
|
||||
InfoLog (<< "fd is attached to an object which is unsuitable for reading.");
|
||||
break;
|
||||
case EFAULT:
|
||||
InfoLog (<< "buf is outside your accessible address space.");
|
||||
break;
|
||||
default:
|
||||
InfoLog (<< "Some other error");
|
||||
break;
|
||||
}
|
||||
InfoLog (<< "Failed read on " << (int)mSock << " " << strerror(e));
|
||||
return false;
|
||||
}
|
||||
else if (bytesRead == 0)
|
||||
{
|
||||
InfoLog (<< "Connection closed by remote " );
|
||||
return false;
|
||||
}
|
||||
|
||||
//DebugLog (<< "HttpConnection::processSomeReads() "
|
||||
// << " read=" << bytesRead);
|
||||
|
||||
mRxBuffer += Data( buf, bytesRead );
|
||||
|
||||
tryParse();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
HttpConnection::tryParse()
|
||||
{
|
||||
//DebugLog (<< "parse " << mRxBuffer );
|
||||
|
||||
ParseBuffer pb(mRxBuffer);
|
||||
|
||||
pb.skipToChar(Symbols::SPACE[0]);
|
||||
const char* start = pb.skipWhitespace();
|
||||
pb.skipToChar(Symbols::SPACE[0]);
|
||||
|
||||
if (pb.eof())
|
||||
{
|
||||
// parse failed - just return
|
||||
return;
|
||||
}
|
||||
|
||||
Data uri;
|
||||
pb.data( uri, start );
|
||||
|
||||
DebugLog (<< "parse found URI " << uri );
|
||||
mParsedRequest = true;
|
||||
|
||||
|
||||
Data user;
|
||||
Data password;
|
||||
|
||||
try
|
||||
{
|
||||
pb.skipToChars( "Authorization" );
|
||||
if ( !pb.eof() )
|
||||
{
|
||||
if ( pb.eof() ) DebugLog( << "Did not find Authorization header" );
|
||||
pb.skipToChars( "Basic" ); pb.skipN(6);
|
||||
if ( pb.eof() ) DebugLog( << "Did not find Authorization basic " );
|
||||
pb.skipWhitespace();
|
||||
if ( pb.eof() ) DebugLog( << "Something weird in Auhtorization header " );
|
||||
if ( !pb.eof() )
|
||||
{
|
||||
const char* a = pb.position();
|
||||
pb.skipNonWhitespace();
|
||||
Data buf = pb.data(a);
|
||||
|
||||
DebugLog (<< "parse found basic base64 auth data of " << buf );
|
||||
Data auth = buf.base64decode();
|
||||
|
||||
//DebugLog (<< "parse found basic auth data of " << auth );
|
||||
|
||||
ParseBuffer p(auth);
|
||||
const char* a1 = p.position();
|
||||
p.skipToChar(':');
|
||||
user = p.data(a1);
|
||||
const char* a2 = p.skipChar(':');
|
||||
p.skipToEnd();
|
||||
password = p.data(a2);
|
||||
|
||||
//DebugLog (<< "parse found basic auth data with user=" << user
|
||||
// << " password=" << password );
|
||||
}
|
||||
}
|
||||
}
|
||||
catch ( ... )
|
||||
{
|
||||
ErrLog (<< "Some problem finding Authorization header in HTTP request" );
|
||||
}
|
||||
|
||||
mHttpBase.buildPage(uri,mPageNumber,user,password);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
HttpConnection::processSomeWrites()
|
||||
{
|
||||
if ( mTxBuffer.empty() )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//DebugLog (<< "Writing " << mTxBuffer );
|
||||
|
||||
#if defined(WIN32)
|
||||
int bytesWritten = ::send( mSock, mTxBuffer.data(), (int)mTxBuffer.size(), 0);
|
||||
#else
|
||||
int bytesWritten = ::write(mSock, mTxBuffer.data(), mTxBuffer.size() );
|
||||
#endif
|
||||
|
||||
if (bytesWritten == INVALID_SOCKET)
|
||||
{
|
||||
int e = getErrno();
|
||||
InfoLog (<< "HttpConnection failed write on " << mSock << " " << strerror(e));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (bytesWritten == (int)mTxBuffer.size() )
|
||||
{
|
||||
DebugLog (<< "Wrote it all" );
|
||||
mTxBuffer = Data::Empty;
|
||||
|
||||
return false; // return false causes connection to close and clean up
|
||||
}
|
||||
else
|
||||
{
|
||||
Data rest = mTxBuffer.substr(bytesWritten);
|
||||
mTxBuffer = rest;
|
||||
DebugLog( << "Wrote " << bytesWritten << " bytes - still need to do " << mTxBuffer );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* ====================================================================
|
||||
* The Vovida Software License, Version 1.0
|
||||
*
|
||||
* Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. The names "VOCAL", "Vovida Open Communication Application Library",
|
||||
* and "Vovida Open Communication Application Library (VOCAL)" must
|
||||
* not be used to endorse or promote products derived from this
|
||||
* software without prior written permission. For written
|
||||
* permission, please contact vocal@vovida.org.
|
||||
*
|
||||
* 4. Products derived from this software may not be called "VOCAL", nor
|
||||
* may "VOCAL" appear in their name, without prior written
|
||||
* permission of Vovida Networks, Inc.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
|
||||
* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
|
||||
* NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
|
||||
* IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* ====================================================================
|
||||
*
|
||||
* This software consists of voluntary contributions made by Vovida
|
||||
* Networks, Inc. and many individuals on behalf of Vovida Networks,
|
||||
* Inc. For more information on Vovida Networks, Inc., please see
|
||||
* <http://www.vovida.org/>.
|
||||
*
|
||||
*/
|
||||
97
src/libs/resiprocate/apps/clicktocall/HttpConnection.hxx
Normal file
97
src/libs/resiprocate/apps/clicktocall/HttpConnection.hxx
Normal file
@@ -0,0 +1,97 @@
|
||||
#if !defined(HttpConnection_hxx)
|
||||
#define HttpConnection_hxx
|
||||
|
||||
#include <rutil/Data.hxx>
|
||||
#include <rutil/Socket.hxx>
|
||||
#include <rutil/TransportType.hxx>
|
||||
#include <resip/stack/Tuple.hxx>
|
||||
#include <resip/stack/Mime.hxx>
|
||||
|
||||
#include "HttpBase.hxx"
|
||||
|
||||
namespace clicktocall
|
||||
{
|
||||
|
||||
class HttpConnection
|
||||
{
|
||||
friend class HttpBase;
|
||||
|
||||
public:
|
||||
HttpConnection( HttpBase& webAdmin, resip::Socket pSock );
|
||||
~HttpConnection();
|
||||
|
||||
void buildFdSet(resip::FdSet& fdset);
|
||||
bool process(resip::FdSet& fdset);
|
||||
|
||||
void setPage(const resip::Data& page,
|
||||
int response,
|
||||
const resip::Mime& pType );
|
||||
|
||||
private:
|
||||
bool processSomeReads();
|
||||
bool processSomeWrites();
|
||||
void tryParse();
|
||||
|
||||
HttpBase& mHttpBase;
|
||||
const int mPageNumber;
|
||||
static int nextPageNumber;
|
||||
|
||||
resip::Socket mSock;
|
||||
resip::Data mRxBuffer;
|
||||
resip::Data mTxBuffer;
|
||||
bool mParsedRequest;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* ====================================================================
|
||||
* The Vovida Software License, Version 1.0
|
||||
*
|
||||
* Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. The names "VOCAL", "Vovida Open Communication Application Library",
|
||||
* and "Vovida Open Communication Application Library (VOCAL)" must
|
||||
* not be used to endorse or promote products derived from this
|
||||
* software without prior written permission. For written
|
||||
* permission, please contact vocal@vovida.org.
|
||||
*
|
||||
* 4. Products derived from this software may not be called "VOCAL", nor
|
||||
* may "VOCAL" appear in their name, without prior written
|
||||
* permission of Vovida Networks, Inc.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
|
||||
* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
|
||||
* NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
|
||||
* IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* ====================================================================
|
||||
*
|
||||
* This software consists of voluntary contributions made by Vovida
|
||||
* Networks, Inc. and many individuals on behalf of Vovida Networks,
|
||||
* Inc. For more information on Vovida Networks, Inc., please see
|
||||
* <http://www.vovida.org/>.
|
||||
*
|
||||
*/
|
||||
1111
src/libs/resiprocate/apps/clicktocall/Server.cxx
Normal file
1111
src/libs/resiprocate/apps/clicktocall/Server.cxx
Normal file
File diff suppressed because it is too large
Load Diff
271
src/libs/resiprocate/apps/clicktocall/Server.hxx
Normal file
271
src/libs/resiprocate/apps/clicktocall/Server.hxx
Normal file
@@ -0,0 +1,271 @@
|
||||
#if !defined(Server_hxx)
|
||||
#define Server_hxx
|
||||
|
||||
#include <map>
|
||||
|
||||
#include <resip/stack/TransactionUser.hxx>
|
||||
#include <resip/stack/EventStackThread.hxx>
|
||||
#include <resip/stack/UdpTransport.hxx>
|
||||
#include <resip/dum/MasterProfile.hxx>
|
||||
#include <resip/dum/DumShutdownHandler.hxx>
|
||||
#include <resip/dum/DialogUsageManager.hxx>
|
||||
#include <resip/dum/InviteSessionHandler.hxx>
|
||||
#include <resip/dum/DialogSetHandler.hxx>
|
||||
#include <resip/dum/OutOfDialogHandler.hxx>
|
||||
#include <resip/dum/RedirectHandler.hxx>
|
||||
#include <resip/dum/SubscriptionHandler.hxx>
|
||||
#include <rutil/Log.hxx>
|
||||
#include <rutil/Mutex.hxx>
|
||||
|
||||
#include "ConfigParser.hxx"
|
||||
#include "B2BSession.hxx"
|
||||
#include "AddressTranslator.hxx"
|
||||
#include "WebAdmin.hxx"
|
||||
#include "WebAdminThread.hxx"
|
||||
#include "XmlRpcServer.hxx"
|
||||
#include "XmlRpcServerThread.hxx"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#ifdef WIN32
|
||||
#define sleepMs(t) Sleep(t)
|
||||
#else
|
||||
#define sleepMs(t) usleep(t*1000)
|
||||
#endif
|
||||
|
||||
namespace clicktocall
|
||||
{
|
||||
|
||||
class ShutdownCmd;
|
||||
class B2BSession;
|
||||
|
||||
class Server : public ConfigParser,
|
||||
public resip::DumShutdownHandler,
|
||||
public resip::InviteSessionHandler,
|
||||
public resip::DialogSetHandler,
|
||||
public resip::OutOfDialogHandler,
|
||||
public resip::RedirectHandler,
|
||||
public resip::ClientSubscriptionHandler,
|
||||
public resip::ServerSubscriptionHandler
|
||||
{
|
||||
public:
|
||||
Server(int argc, char** argv);
|
||||
virtual ~Server();
|
||||
|
||||
/**
|
||||
Starts the SIP stack thread.
|
||||
|
||||
@note This should be called before calling process() in a loop
|
||||
*/
|
||||
void startup();
|
||||
|
||||
/**
|
||||
This should be called in a loop to give process cycles to the server.
|
||||
|
||||
@param timeoutMs Will return after timeoutMs if nothing to do.
|
||||
Application can do some work, but should call
|
||||
process again ASAP.
|
||||
*/
|
||||
void process(int timeoutMs); // call this in a loop
|
||||
|
||||
/**
|
||||
Used to initiate a shutdown of the server. This function blocks
|
||||
until the shutdown is complete.
|
||||
|
||||
@note There should not be an active process request when this
|
||||
is called.
|
||||
*/
|
||||
void shutdown();
|
||||
|
||||
// Utility Methods ////////////////////////////////////////////////////////////
|
||||
typedef enum
|
||||
{
|
||||
SubsystemAll,
|
||||
SubsystemContents,
|
||||
SubsystemDns,
|
||||
SubsystemDum,
|
||||
SubsystemSdp,
|
||||
SubsystemSip,
|
||||
SubsystemTransaction,
|
||||
SubsystemTransport,
|
||||
SubsystemStats,
|
||||
SubsystemClickToCall
|
||||
} LoggingSubsystem;
|
||||
|
||||
/**
|
||||
Static method that sets the logging level for a particular subsystem,
|
||||
or all subsystems.
|
||||
|
||||
@param level Logging level to set
|
||||
@param subsystem Subsystem to set level on
|
||||
|
||||
@note: Use Server::SubsystemAll to set the logging level on all
|
||||
subsystems
|
||||
*/
|
||||
static void setLogLevel(resip::Log::Level level, LoggingSubsystem subsystem=SubsystemAll);
|
||||
|
||||
/**
|
||||
Click-To-Call - Requests server to place a call first to the initiator, once the initiator
|
||||
answers the call the destination is contacted. If anchorCall is true, then the server
|
||||
stays in the call path (B2BUA). If anchorCall is false then a REFER message is sent
|
||||
to the initiator once answered, to direct the endpoint to the destination outside of
|
||||
this server.
|
||||
|
||||
@param initiator First party contacted
|
||||
@param destination Second part contacted
|
||||
@param anchorCall Set to true to keep server in call path
|
||||
@param xmlRpcInfo Set to non-zero if request was received from XML RPC interface - used for progress notification
|
||||
*/
|
||||
void clickToCall(const resip::Uri& initiator, const resip::Uri& destination, bool anchorCall, XmlRpcInfo* xmlRpcServer = 0);
|
||||
|
||||
bool translateAddress(const resip::Data& address, resip::Data& translation, bool failIfNoRule=false);
|
||||
|
||||
protected:
|
||||
std::shared_ptr<resip::MasterProfile>& getMasterProfile() noexcept { return mProfile; }
|
||||
|
||||
// Shutdown Handler ////////////////////////////////////////////////////////////
|
||||
void onDumCanBeDeleted();
|
||||
|
||||
// Invite Session Handler /////////////////////////////////////////////////////
|
||||
virtual void onNewSession(resip::ClientInviteSessionHandle h, resip::InviteSession::OfferAnswerType oat, const resip::SipMessage& msg);
|
||||
virtual void onNewSession(resip::ServerInviteSessionHandle h, resip::InviteSession::OfferAnswerType oat, const resip::SipMessage& msg);
|
||||
virtual void onFailure(resip::ClientInviteSessionHandle h, const resip::SipMessage& msg);
|
||||
virtual void onEarlyMedia(resip::ClientInviteSessionHandle, const resip::SipMessage&, const resip::SdpContents&);
|
||||
virtual void onProvisional(resip::ClientInviteSessionHandle, const resip::SipMessage& msg);
|
||||
virtual void onConnected(resip::ClientInviteSessionHandle h, const resip::SipMessage& msg);
|
||||
virtual void onConnected(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
||||
virtual void onStaleCallTimeout(resip::ClientInviteSessionHandle);
|
||||
virtual void onTerminated(resip::InviteSessionHandle h, resip::InviteSessionHandler::TerminatedReason reason, const resip::SipMessage* msg);
|
||||
virtual void onRedirected(resip::ClientInviteSessionHandle, const resip::SipMessage& msg);
|
||||
virtual void onAnswer(resip::InviteSessionHandle, const resip::SipMessage& msg, const resip::SdpContents&);
|
||||
virtual void onOffer(resip::InviteSessionHandle handle, const resip::SipMessage& msg, const resip::SdpContents& offer);
|
||||
virtual void onOfferRequired(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
||||
virtual void onOfferRejected(resip::InviteSessionHandle, const resip::SipMessage* msg);
|
||||
virtual void onOfferRequestRejected(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
||||
virtual void onRemoteSdpChanged(resip::InviteSessionHandle, const resip::SipMessage& msg, const resip::SdpContents& sdp);
|
||||
virtual void onInfo(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
||||
virtual void onInfoSuccess(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
||||
virtual void onInfoFailure(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
||||
virtual void onRefer(resip::InviteSessionHandle, resip::ServerSubscriptionHandle, const resip::SipMessage& msg);
|
||||
virtual void onReferAccepted(resip::InviteSessionHandle, resip::ClientSubscriptionHandle, const resip::SipMessage& msg);
|
||||
virtual void onReferRejected(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
||||
virtual void onReferNoSub(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
||||
virtual void onMessage(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
||||
virtual void onMessageSuccess(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
||||
virtual void onMessageFailure(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
||||
virtual void onForkDestroyed(resip::ClientInviteSessionHandle);
|
||||
|
||||
// DialogSetHandler //////////////////////////////////////////////
|
||||
virtual void onTrying(resip::AppDialogSetHandle, const resip::SipMessage& msg);
|
||||
virtual void onNonDialogCreatingProvisional(resip::AppDialogSetHandle, const resip::SipMessage& msg);
|
||||
|
||||
// ClientSubscriptionHandler ///////////////////////////////////////////////////
|
||||
virtual void onUpdatePending(resip::ClientSubscriptionHandle h, const resip::SipMessage& notify, bool outOfOrder);
|
||||
virtual void onUpdateActive(resip::ClientSubscriptionHandle h, const resip::SipMessage& notify, bool outOfOrder);
|
||||
virtual void onUpdateExtension(resip::ClientSubscriptionHandle, const resip::SipMessage& notify, bool outOfOrder);
|
||||
virtual void onNotifyNotReceived(resip::ClientSubscriptionHandle h);
|
||||
virtual void onTerminated(resip::ClientSubscriptionHandle h, const resip::SipMessage* notify);
|
||||
virtual void onNewSubscription(resip::ClientSubscriptionHandle h, const resip::SipMessage& notify);
|
||||
virtual int onRequestRetry(resip::ClientSubscriptionHandle h, int retryMinimum, const resip::SipMessage& notify);
|
||||
|
||||
// ServerSubscriptionHandler ///////////////////////////////////////////////////
|
||||
virtual void onNewSubscription(resip::ServerSubscriptionHandle, const resip::SipMessage& sub);
|
||||
virtual void onNewSubscriptionFromRefer(resip::ServerSubscriptionHandle, const resip::SipMessage& sub);
|
||||
virtual void onRefresh(resip::ServerSubscriptionHandle, const resip::SipMessage& sub);
|
||||
virtual void onTerminated(resip::ServerSubscriptionHandle);
|
||||
virtual void onNotifyRejected(resip::ServerSubscriptionHandle, const resip::SipMessage& msg);
|
||||
virtual void onError(resip::ServerSubscriptionHandle, const resip::SipMessage& msg);
|
||||
virtual void onExpiredByClient(resip::ServerSubscriptionHandle, const resip::SipMessage& sub, resip::SipMessage& notify);
|
||||
virtual void onExpired(resip::ServerSubscriptionHandle, resip::SipMessage& notify);
|
||||
virtual bool hasDefaultExpires() const;
|
||||
virtual uint32_t getDefaultExpires() const;
|
||||
|
||||
// OutOfDialogHandler //////////////////////////////////////////////////////////
|
||||
virtual void onSuccess(resip::ClientOutOfDialogReqHandle, const resip::SipMessage& response);
|
||||
virtual void onFailure(resip::ClientOutOfDialogReqHandle, const resip::SipMessage& response);
|
||||
virtual void onReceivedRequest(resip::ServerOutOfDialogReqHandle, const resip::SipMessage& request);
|
||||
|
||||
// RedirectHandler /////////////////////////////////////////////////////////////
|
||||
virtual void onRedirectReceived(resip::AppDialogSetHandle, const resip::SipMessage& response);
|
||||
virtual bool onTryingNextTarget(resip::AppDialogSetHandle, const resip::SipMessage& request);
|
||||
|
||||
private:
|
||||
friend class ShutdownCmd;
|
||||
friend class B2BSession;
|
||||
|
||||
resip::DialogUsageManager& getDialogUsageManager();
|
||||
|
||||
void post(resip::ApplicationMessage& message, unsigned int ms=0);
|
||||
void shutdownImpl();
|
||||
|
||||
friend class ClickToCallCmd;
|
||||
void clickToCallImpl(const resip::Uri& initiator, const resip::Uri& destination, bool anchorCall, const XmlRpcInfo& xmlRpcInfo);
|
||||
|
||||
std::shared_ptr<resip::MasterProfile> mProfile;
|
||||
resip::Security* mSecurity;
|
||||
resip::FdPollGrp *mPollGrp;
|
||||
resip::EventThreadInterruptor *mEventInterruptor;
|
||||
resip::SipStack mStack;
|
||||
resip::DialogUsageManager mDum;
|
||||
resip::EventStackThread mStackThread;
|
||||
volatile bool mDumShutdown;
|
||||
|
||||
typedef std::map<B2BSessionHandle, B2BSession*> B2BSessionMap;
|
||||
B2BSessionMap mB2BSessions;
|
||||
B2BSessionHandle mCurrentB2BSessionHandle;
|
||||
B2BSession* getB2BSession(const B2BSessionHandle& handle) const;
|
||||
B2BSessionHandle registerB2BSession(B2BSession *);
|
||||
void unregisterB2BSession(const B2BSessionHandle& handle);
|
||||
|
||||
bool mIsV6Avail;
|
||||
|
||||
WebAdmin* mWebAdminV4;
|
||||
WebAdmin* mWebAdminV6;
|
||||
WebAdminThread* mWebAdminThread;
|
||||
|
||||
XmlRpcServer* mXmlRpcServerV4;
|
||||
XmlRpcServer* mXmlRpcServerV6;
|
||||
XmlRpcServerThread* mXmlRpcServerThread;
|
||||
|
||||
AddressTranslator mAddressTranslator;
|
||||
std::map<resip::DialogSetId,B2BSession*> mActiveSessions;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* ====================================================================
|
||||
|
||||
Copyright (c) 2009, SIP Spectrum, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of SIP Spectrum nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
==================================================================== */
|
||||
|
||||
36
src/libs/resiprocate/apps/clicktocall/Version.hxx
Normal file
36
src/libs/resiprocate/apps/clicktocall/Version.hxx
Normal file
@@ -0,0 +1,36 @@
|
||||
#define CLICKTOCALL_VERSION_STRING "0.1"
|
||||
|
||||
/* ====================================================================
|
||||
|
||||
Copyright (c) 2009, SIP Spectrum, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of SIP Spectrum nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
==================================================================== */
|
||||
|
||||
331
src/libs/resiprocate/apps/clicktocall/WebAdmin.cxx
Normal file
331
src/libs/resiprocate/apps/clicktocall/WebAdmin.cxx
Normal file
@@ -0,0 +1,331 @@
|
||||
#include "rutil/ResipAssert.h"
|
||||
#include <time.h>
|
||||
|
||||
#include <resip/stack/Symbols.hxx>
|
||||
#include <resip/stack/Tuple.hxx>
|
||||
#include <rutil/Data.hxx>
|
||||
#include <rutil/DnsUtil.hxx>
|
||||
#include <rutil/Logger.hxx>
|
||||
#include <rutil/MD5Stream.hxx>
|
||||
#include <rutil/ParseBuffer.hxx>
|
||||
#include <rutil/Socket.hxx>
|
||||
#include <rutil/Timer.hxx>
|
||||
#include <rutil/TransportType.hxx>
|
||||
|
||||
#include "AppSubsystem.hxx"
|
||||
#include "HttpBase.hxx"
|
||||
#include "HttpConnection.hxx"
|
||||
#include "WebAdmin.hxx"
|
||||
#include "Server.hxx"
|
||||
|
||||
using namespace clicktocall;
|
||||
using namespace resip;
|
||||
using namespace std;
|
||||
|
||||
#define RESIPROCATE_SUBSYSTEM AppSubsystem::CLICKTOCALL
|
||||
|
||||
|
||||
WebAdmin::WebAdmin(Server& server,
|
||||
bool noChal,
|
||||
const Data& realm, // this realm is used for http challenges
|
||||
const Data& adminPassword,
|
||||
int port,
|
||||
IpVersion version ):
|
||||
HttpBase(port, version, realm),
|
||||
mServer(server),
|
||||
mNoWebChallenges(noChal),
|
||||
mAdminPassword(adminPassword)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WebAdmin::buildPage( const Data& uri,
|
||||
int pageNumber,
|
||||
const resip::Data& pUser,
|
||||
const resip::Data& pPassword )
|
||||
{
|
||||
ParseBuffer pb(uri);
|
||||
|
||||
DebugLog (<< "Parsing URL" << uri );
|
||||
|
||||
const char* anchor = pb.skipChar('/');
|
||||
pb.skipToChar('?');
|
||||
Data pageName;
|
||||
pb.data(pageName,anchor);
|
||||
|
||||
DebugLog (<< " got page name: " << pageName );
|
||||
|
||||
// if this is not a valid page, redirect it
|
||||
if (pageName != Data("index.html") &&
|
||||
pageName != Data("clicktocall.html"))
|
||||
{
|
||||
setPage( resip::Data::Empty, pageNumber, 301 );
|
||||
return;
|
||||
}
|
||||
|
||||
// pages anyone can use
|
||||
if ( pageName == Data("index.html") )
|
||||
{
|
||||
setPage( buildDefaultPage(), pageNumber, 200);
|
||||
return;
|
||||
}
|
||||
|
||||
Data authenticatedUser;
|
||||
if (mNoWebChallenges)
|
||||
{
|
||||
// don't do authentication - give everyone admin privilages
|
||||
authenticatedUser = Data("admin");
|
||||
}
|
||||
else
|
||||
{
|
||||
// all pages after this, user must authenticate
|
||||
if ( pUser.empty() )
|
||||
{
|
||||
setPage( resip::Data::Empty, pageNumber,401 );
|
||||
return;
|
||||
}
|
||||
|
||||
MD5Stream dba1;
|
||||
dba1 << "admin" // username
|
||||
<< Symbols::COLON
|
||||
<< Data::Empty // realm
|
||||
<< Symbols::COLON
|
||||
<< mAdminPassword;
|
||||
Data dbA1 = dba1.getHex();
|
||||
|
||||
if ( !dbA1.empty() )
|
||||
{
|
||||
MD5Stream a1;
|
||||
a1 << pUser // username
|
||||
<< Symbols::COLON
|
||||
<< Data::Empty // realm
|
||||
<< Symbols::COLON
|
||||
<< pPassword;
|
||||
Data compA1 = a1.getHex();
|
||||
|
||||
if ( dbA1 == compA1 )
|
||||
{
|
||||
authenticatedUser = pUser;
|
||||
}
|
||||
else
|
||||
{
|
||||
InfoLog( << "user " << pUser << " failed to authenticate to web server" );
|
||||
DebugLog( << " compA1="<<compA1<< " dbA1="<<dbA1 );
|
||||
setPage( resip::Data::Empty, pageNumber,401 );
|
||||
return;
|
||||
}
|
||||
}
|
||||
else //No A1, so we must assume this user does not exist.
|
||||
{
|
||||
setPage( "User does not exist.", pageNumber,401 );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// parse any URI tags from form entry
|
||||
mHttpParams.clear();
|
||||
|
||||
if (!pb.eof())
|
||||
{
|
||||
pb.skipChar('?');
|
||||
|
||||
while ( !pb.eof() )
|
||||
{
|
||||
const char* anchor1 = pb.position();
|
||||
pb.skipToChar('=');
|
||||
Data key;
|
||||
pb.data(key,anchor1);
|
||||
|
||||
const char* anchor2 = pb.skipChar('=');
|
||||
pb.skipToChar('&');
|
||||
Data value;
|
||||
pb.data(value,anchor2);
|
||||
|
||||
if ( !pb.eof() )
|
||||
{
|
||||
pb.skipChar('&');
|
||||
}
|
||||
|
||||
if ( !key.empty() && !value.empty() ) // make sure both exist
|
||||
{
|
||||
DebugLog (<< " key=" << key << " value=" << value << " & unencoded form: " << value.urlDecoded() );
|
||||
mHttpParams[key] = value.urlDecoded(); // add other parameters to the Map
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
DebugLog( << "building page for user=" << authenticatedUser );
|
||||
|
||||
Data page;
|
||||
if ( authenticatedUser == Data("admin") )
|
||||
{
|
||||
DataStream s(page);
|
||||
buildPageOutlinePre(s);
|
||||
|
||||
// admin only pages
|
||||
if ( pageName == Data("clicktocall.html")) buildClickToCallPage(s);
|
||||
|
||||
buildPageOutlinePost(s);
|
||||
s.flush();
|
||||
}
|
||||
|
||||
resip_assert( !authenticatedUser.empty() );
|
||||
resip_assert( !page.empty() );
|
||||
|
||||
setPage( page, pageNumber,200 );
|
||||
}
|
||||
|
||||
|
||||
Data
|
||||
WebAdmin::buildDefaultPage()
|
||||
{
|
||||
Data ret;
|
||||
{
|
||||
DataStream s(ret);
|
||||
|
||||
s <<
|
||||
"<?xml version=\"1.0\" encoding=\"utf-8\"?>" << endl <<
|
||||
"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">" << endl <<
|
||||
"<html xmlns=\"http://www.w3.org/1999/xhtml\">" << endl <<
|
||||
"<head>" << endl <<
|
||||
"<meta http-equiv=\"content-type\" content=\"text/html;charset=utf-8\" />" << endl <<
|
||||
"<title>ClickToCall Server Login</title>" << endl <<
|
||||
"</head>" << endl <<
|
||||
|
||||
"<body bgcolor=\"#ffffff\">" << endl <<
|
||||
" <p>Click-To-Call HTML Server</p>" << endl <<
|
||||
"</body>" << endl <<
|
||||
"</html>" << endl;
|
||||
|
||||
s.flush();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
WebAdmin::buildPageOutlinePre(DataStream& s)
|
||||
{
|
||||
s <<
|
||||
"<?xml version=\"1.0\" encoding=\"utf-8\"?>" << endl <<
|
||||
"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">" << endl <<
|
||||
"<html xmlns=\"http://www.w3.org/1999/xhtml\">" << endl <<
|
||||
"<head>" << endl <<
|
||||
"<meta http-equiv=\"content-type\" content=\"text/html;charset=utf-8\" />" << endl <<
|
||||
"<title>ClickToCall Server</title>" << endl <<
|
||||
"</head>" << endl <<
|
||||
|
||||
"<body bgcolor=\"#ffffff\">" << endl;
|
||||
}
|
||||
|
||||
void
|
||||
WebAdmin::buildPageOutlinePost(DataStream& s)
|
||||
{
|
||||
s << "</body>" << endl <<
|
||||
"</html>" << endl;
|
||||
}
|
||||
|
||||
void
|
||||
WebAdmin::buildClickToCallPage(DataStream& s)
|
||||
{
|
||||
Data initiator;
|
||||
Data destination;
|
||||
bool anchor = false;
|
||||
Dictionary::iterator pos;
|
||||
pos = mHttpParams.find("initiator");
|
||||
if (pos != mHttpParams.end())
|
||||
{
|
||||
initiator = pos->second;
|
||||
}
|
||||
pos = mHttpParams.find("destination");
|
||||
if (pos != mHttpParams.end())
|
||||
{
|
||||
destination = pos->second;
|
||||
}
|
||||
pos = mHttpParams.find("anchor");
|
||||
if (pos != mHttpParams.end())
|
||||
{
|
||||
if(isEqualNoCase(pos->second, "true"))
|
||||
{
|
||||
anchor = true;
|
||||
}
|
||||
}
|
||||
|
||||
s << "<p><em>ClickToCall:</em> initiator=" << initiator << ", destination=" << destination << (anchor ? " (anchored)" : "") << "</p>" << endl;
|
||||
if(!initiator.empty() && !destination.empty())
|
||||
{
|
||||
Data initiatorTranslation;
|
||||
Data destinationTranslation;
|
||||
|
||||
if(mServer.translateAddress(initiator, initiatorTranslation, true /* fail if no rule */) &&
|
||||
mServer.translateAddress(destination, destinationTranslation, true /* fail if no rule */))
|
||||
{
|
||||
try
|
||||
{
|
||||
Uri initiatorUri(initiatorTranslation);
|
||||
Uri destinationUri(destinationTranslation);
|
||||
|
||||
mServer.clickToCall(initiatorUri, destinationUri, anchor);
|
||||
s << "<p>Initiating ClickToCall from " << initiatorUri << "(" << initiator << ") to " << destinationUri << "(" << destination << (anchor ? ") (anchored)" : ") (unanchored)") << "...</p>" << endl;
|
||||
}
|
||||
catch(resip::BaseException& e)
|
||||
{
|
||||
s << "<p>Invalid URI format in initiator " << initiatorTranslation << "(" << initiator << ") or destination " << destinationTranslation << "(" << destination << "): " << e << "</p>" << endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
s << "<p>No translation rule for either initiator " << initiator << " or destination " << destination << ".</p>" << endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
s << "<p>Missing initiator or destination URL parameters.</p>" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ====================================================================
|
||||
* The Vovida Software License, Version 1.0
|
||||
*
|
||||
* Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. The names "VOCAL", "Vovida Open Communication Application Library",
|
||||
* and "Vovida Open Communication Application Library (VOCAL)" must
|
||||
* not be used to endorse or promote products derived from this
|
||||
* software without prior written permission. For written
|
||||
* permission, please contact vocal@vovida.org.
|
||||
*
|
||||
* 4. Products derived from this software may not be called "VOCAL", nor
|
||||
* may "VOCAL" appear in their name, without prior written
|
||||
* permission of Vovida Networks, Inc.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
|
||||
* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
|
||||
* NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
|
||||
* IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* ====================================================================
|
||||
*/
|
||||
106
src/libs/resiprocate/apps/clicktocall/WebAdmin.hxx
Normal file
106
src/libs/resiprocate/apps/clicktocall/WebAdmin.hxx
Normal file
@@ -0,0 +1,106 @@
|
||||
#if !defined(WebAdmin_hxx)
|
||||
#define WebAdmin_hxx
|
||||
|
||||
#include <map>
|
||||
#include <rutil/Data.hxx>
|
||||
#include <rutil/TransportType.hxx>
|
||||
#include <resip/stack/Tuple.hxx>
|
||||
|
||||
#include "HttpBase.hxx"
|
||||
|
||||
namespace resip
|
||||
{
|
||||
class DataStream;
|
||||
}
|
||||
|
||||
namespace clicktocall
|
||||
{
|
||||
class Server;
|
||||
|
||||
typedef std::map<resip::Data, resip::Data> Dictionary;
|
||||
|
||||
class WebAdmin: public HttpBase
|
||||
{
|
||||
public:
|
||||
WebAdmin(Server& server,
|
||||
bool noWebChallenges,
|
||||
const resip::Data& realm,
|
||||
const resip::Data& adminPassword,
|
||||
int port=5090,
|
||||
resip::IpVersion version=resip::V4);
|
||||
|
||||
protected:
|
||||
virtual void buildPage( const resip::Data& uri,
|
||||
int pageNumber,
|
||||
const resip::Data& user,
|
||||
const resip::Data& password);
|
||||
|
||||
private:
|
||||
resip::Data buildDefaultPage();
|
||||
|
||||
void buildPageOutlinePre(resip::DataStream& s);
|
||||
void buildPageOutlinePost(resip::DataStream& s);
|
||||
|
||||
void buildClickToCallPage(resip::DataStream& s);
|
||||
|
||||
Server& mServer;
|
||||
|
||||
bool mNoWebChallenges;
|
||||
resip::Data mAdminPassword;
|
||||
|
||||
Dictionary mHttpParams;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* ====================================================================
|
||||
* The Vovida Software License, Version 1.0
|
||||
*
|
||||
* Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. The names "VOCAL", "Vovida Open Communication Application Library",
|
||||
* and "Vovida Open Communication Application Library (VOCAL)" must
|
||||
* not be used to endorse or promote products derived from this
|
||||
* software without prior written permission. For written
|
||||
* permission, please contact vocal@vovida.org.
|
||||
*
|
||||
* 4. Products derived from this software may not be called "VOCAL", nor
|
||||
* may "VOCAL" appear in their name, without prior written
|
||||
* permission of Vovida Networks, Inc.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
|
||||
* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
|
||||
* NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
|
||||
* IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* ====================================================================
|
||||
*
|
||||
* This software consists of voluntary contributions made by Vovida
|
||||
* Networks, Inc. and many individuals on behalf of Vovida Networks,
|
||||
* Inc. For more information on Vovida Networks, Inc., please see
|
||||
* <http://www.vovida.org/>.
|
||||
*
|
||||
*/
|
||||
99
src/libs/resiprocate/apps/clicktocall/WebAdminThread.cxx
Normal file
99
src/libs/resiprocate/apps/clicktocall/WebAdminThread.cxx
Normal file
@@ -0,0 +1,99 @@
|
||||
#include <rutil/Socket.hxx>
|
||||
#include <rutil/Logger.hxx>
|
||||
|
||||
#include "AppSubsystem.hxx"
|
||||
#include "WebAdmin.hxx"
|
||||
#include "WebAdminThread.hxx"
|
||||
|
||||
#define RESIPROCATE_SUBSYSTEM AppSubsystem::CLICKTOCALL
|
||||
|
||||
using namespace clicktocall;
|
||||
using namespace resip;
|
||||
using namespace std;
|
||||
|
||||
|
||||
WebAdminThread::WebAdminThread(const std::list<WebAdmin*>& webAdminList)
|
||||
: mWebAdminList(webAdminList)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WebAdminThread::thread()
|
||||
{
|
||||
while (!isShutdown())
|
||||
{
|
||||
try
|
||||
{
|
||||
FdSet fdset;
|
||||
|
||||
std::list<WebAdmin*>::iterator it = mWebAdminList.begin();
|
||||
for(;it!=mWebAdminList.end();it++)
|
||||
{
|
||||
(*it)->buildFdSet(fdset);
|
||||
}
|
||||
fdset.selectMilliSeconds( 10*1000 );
|
||||
|
||||
it = mWebAdminList.begin();
|
||||
for(;it!=mWebAdminList.end();it++)
|
||||
{
|
||||
(*it)->process(fdset);
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
ErrLog (<< "Unhandled exception: " );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ====================================================================
|
||||
* The Vovida Software License, Version 1.0
|
||||
*
|
||||
* Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. The names "VOCAL", "Vovida Open Communication Application Library",
|
||||
* and "Vovida Open Communication Application Library (VOCAL)" must
|
||||
* not be used to endorse or promote products derived from this
|
||||
* software without prior written permission. For written
|
||||
* permission, please contact vocal@vovida.org.
|
||||
*
|
||||
* 4. Products derived from this software may not be called "VOCAL", nor
|
||||
* may "VOCAL" appear in their name, without prior written
|
||||
* permission of Vovida Networks, Inc.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
|
||||
* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
|
||||
* NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
|
||||
* IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* ====================================================================
|
||||
*
|
||||
* This software consists of voluntary contributions made by Vovida
|
||||
* Networks, Inc. and many individuals on behalf of Vovida Networks,
|
||||
* Inc. For more information on Vovida Networks, Inc., please see
|
||||
* <http://www.vovida.org/>.
|
||||
*
|
||||
*/
|
||||
77
src/libs/resiprocate/apps/clicktocall/WebAdminThread.hxx
Normal file
77
src/libs/resiprocate/apps/clicktocall/WebAdminThread.hxx
Normal file
@@ -0,0 +1,77 @@
|
||||
#if !defined(WebAdminThread_hxx)
|
||||
#define WebAdminThread_hxx
|
||||
|
||||
#include <list>
|
||||
#include <rutil/ThreadIf.hxx>
|
||||
#include <rutil/Socket.hxx>
|
||||
|
||||
namespace clicktocall
|
||||
{
|
||||
class WebAdmin;
|
||||
|
||||
class WebAdminThread : public resip::ThreadIf
|
||||
{
|
||||
public:
|
||||
WebAdminThread(const std::list<WebAdmin*>& webAdminList);
|
||||
|
||||
protected:
|
||||
|
||||
private:
|
||||
virtual void thread();
|
||||
std::list<WebAdmin*> mWebAdminList;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* ====================================================================
|
||||
* The Vovida Software License, Version 1.0
|
||||
*
|
||||
* Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. The names "VOCAL", "Vovida Open Communication Application Library",
|
||||
* and "Vovida Open Communication Application Library (VOCAL)" must
|
||||
* not be used to endorse or promote products derived from this
|
||||
* software without prior written permission. For written
|
||||
* permission, please contact vocal@vovida.org.
|
||||
*
|
||||
* 4. Products derived from this software may not be called "VOCAL", nor
|
||||
* may "VOCAL" appear in their name, without prior written
|
||||
* permission of Vovida Networks, Inc.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
|
||||
* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
|
||||
* NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
|
||||
* IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* ====================================================================
|
||||
*
|
||||
* This software consists of voluntary contributions made by Vovida
|
||||
* Networks, Inc. and many individuals on behalf of Vovida Networks,
|
||||
* Inc. For more information on Vovida Networks, Inc., please see
|
||||
* <http://www.vovida.org/>.
|
||||
*
|
||||
*/
|
||||
298
src/libs/resiprocate/apps/clicktocall/XmlRpcConnection.cxx
Normal file
298
src/libs/resiprocate/apps/clicktocall/XmlRpcConnection.cxx
Normal file
@@ -0,0 +1,298 @@
|
||||
#include "rutil/ResipAssert.h"
|
||||
|
||||
#include <rutil/Data.hxx>
|
||||
#include <rutil/Socket.hxx>
|
||||
#include <resip/stack/Symbols.hxx>
|
||||
#include <rutil/TransportType.hxx>
|
||||
#include <rutil/Logger.hxx>
|
||||
#include <resip/stack/Tuple.hxx>
|
||||
#include <rutil/DnsUtil.hxx>
|
||||
#include <rutil/ParseBuffer.hxx>
|
||||
|
||||
#include "Version.hxx"
|
||||
#include "AppSubsystem.hxx"
|
||||
#include "Server.hxx"
|
||||
#include "XmlRpcServerBase.hxx"
|
||||
#include "XmlRpcConnection.hxx"
|
||||
|
||||
using namespace clicktocall;
|
||||
using namespace resip;
|
||||
using namespace std;
|
||||
|
||||
#define RESIPROCATE_SUBSYSTEM AppSubsystem::CLICKTOCALL
|
||||
|
||||
unsigned int XmlRpcConnection::NextConnectionId = 1;
|
||||
|
||||
|
||||
XmlRpcConnection::XmlRpcConnection(XmlRpcServerBase& server, resip::Socket sock):
|
||||
mXmlRcpServer(server),
|
||||
mConnectionId(NextConnectionId++),
|
||||
mNextRequestId(1),
|
||||
mSock(sock)
|
||||
{
|
||||
resip_assert(mSock > 0);
|
||||
}
|
||||
|
||||
|
||||
XmlRpcConnection::~XmlRpcConnection()
|
||||
{
|
||||
resip_assert(mSock > 0);
|
||||
#ifdef WIN32
|
||||
closesocket(mSock);
|
||||
#else
|
||||
close(mSock);
|
||||
#endif
|
||||
mSock=0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
XmlRpcConnection::buildFdSet(FdSet& fdset)
|
||||
{
|
||||
if (!mTxBuffer.empty())
|
||||
{
|
||||
fdset.setWrite(mSock);
|
||||
}
|
||||
fdset.setRead(mSock);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
XmlRpcConnection::process(FdSet& fdset)
|
||||
{
|
||||
if (fdset.hasException(mSock))
|
||||
{
|
||||
int errNum = 0;
|
||||
int errNumSize = sizeof(errNum);
|
||||
getsockopt(mSock,SOL_SOCKET,SO_ERROR,(char *)&errNum,(socklen_t *)&errNumSize);
|
||||
InfoLog (<< "XmlRpcConnection::process: Exception reading from socket "
|
||||
<< (int)mSock << " code: " << errNum << "; closing connection");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fdset.readyToRead(mSock))
|
||||
{
|
||||
bool ok = processSomeReads();
|
||||
if (!ok)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if ((!mTxBuffer.empty()) && fdset.readyToWrite(mSock))
|
||||
{
|
||||
bool ok = processSomeWrites();
|
||||
if (!ok)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
XmlRpcConnection::processSomeReads()
|
||||
{
|
||||
const int bufSize = 8000;
|
||||
char buf[bufSize];
|
||||
|
||||
|
||||
#if defined(WIN32)
|
||||
int bytesRead = ::recv(mSock, buf, bufSize, 0);
|
||||
#else
|
||||
int bytesRead = ::read(mSock, buf, bufSize);
|
||||
#endif
|
||||
|
||||
if (bytesRead == INVALID_SOCKET)
|
||||
{
|
||||
int e = getErrno();
|
||||
XmlRpcServerBase::logSocketError(e);
|
||||
InfoLog (<< "XmlRpcConnection::processSomeReads: Failed read on " << (int)mSock);
|
||||
return false;
|
||||
}
|
||||
else if(bytesRead == 0)
|
||||
{
|
||||
InfoLog (<< "XmlRpcConnection::processSomeReads: Connection closed by remote");
|
||||
return false;
|
||||
}
|
||||
|
||||
//DebugLog (<< "XmlRpcConnection::processSomeReads: read=" << bytesRead);
|
||||
|
||||
mRxBuffer += Data( buf, bytesRead );
|
||||
|
||||
while(tryParse());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
XmlRpcConnection::tryParse()
|
||||
{
|
||||
ParseBuffer pb(mRxBuffer);
|
||||
Data initialTag;
|
||||
const char* start = pb.position();
|
||||
pb.skipWhitespace();
|
||||
pb.skipToChar('<');
|
||||
if(!pb.eof())
|
||||
{
|
||||
pb.skipChar();
|
||||
const char* anchor = pb.position();
|
||||
pb.skipToChar('>');
|
||||
if(!pb.eof())
|
||||
{
|
||||
initialTag = pb.data(anchor);
|
||||
// Find end of initial tag
|
||||
pb.skipToChars("</" + initialTag + ">");
|
||||
if (!pb.eof())
|
||||
{
|
||||
pb.skipN(initialTag.size() + 3); // Skip past </InitialTag>
|
||||
mRequests[mNextRequestId] = pb.data(start);
|
||||
mXmlRcpServer.handleRequest(mConnectionId, mNextRequestId, mRequests[mNextRequestId]);
|
||||
mNextRequestId++;
|
||||
|
||||
// Remove processed data from RxBuffer
|
||||
pb.skipWhitespace();
|
||||
if(!pb.eof())
|
||||
{
|
||||
anchor = pb.position();
|
||||
pb.skipToEnd();
|
||||
mRxBuffer = pb.data(anchor);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
mRxBuffer.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
XmlRpcConnection::processSomeWrites()
|
||||
{
|
||||
if (mTxBuffer.empty())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//DebugLog (<< "XmlRpcConnection::processSomeWrites: Writing " << mTxBuffer );
|
||||
|
||||
#if defined(WIN32)
|
||||
int bytesWritten = ::send(mSock, mTxBuffer.data(), (int)mTxBuffer.size(), 0);
|
||||
#else
|
||||
int bytesWritten = ::write(mSock, mTxBuffer.data(), mTxBuffer.size() );
|
||||
#endif
|
||||
|
||||
if (bytesWritten == INVALID_SOCKET)
|
||||
{
|
||||
int e = getErrno();
|
||||
XmlRpcServerBase::logSocketError(e);
|
||||
InfoLog (<< "XmlRpcConnection::processSomeWrites - failed write on " << mSock << " " << strerror(e));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (bytesWritten == (int)mTxBuffer.size())
|
||||
{
|
||||
DebugLog (<< "XmlRpcConnection::processSomeWrites - Wrote it all" );
|
||||
mTxBuffer = Data::Empty;
|
||||
|
||||
//return false; // return false causes connection to close and clean up
|
||||
return true; // keep connection up
|
||||
}
|
||||
else
|
||||
{
|
||||
Data rest = mTxBuffer.substr(bytesWritten);
|
||||
mTxBuffer = rest;
|
||||
DebugLog( << "XmlRpcConnection::processSomeWrites - Wrote " << bytesWritten << " bytes - still need to do " << mTxBuffer );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
XmlRpcConnection::sendResponse(unsigned int requestId, const Data& responseData, bool isFinal)
|
||||
{
|
||||
RequestMap::iterator it = mRequests.find(requestId);
|
||||
if(it != mRequests.end())
|
||||
{
|
||||
Data& request = it->second;
|
||||
Data response(request.size() + responseData.size() + 30, Data::Preallocate);
|
||||
ParseBuffer pb(request);
|
||||
|
||||
// A response is formed by starting with the request and inserting the
|
||||
// ResponseData between <Response> tags at the same level as the <Request> tags
|
||||
const char* start = pb.position();
|
||||
pb.skipToChars("</Request>");
|
||||
if (!pb.eof())
|
||||
{
|
||||
pb.skipN(10); // Skip past </Request>
|
||||
pb.skipWhitespace();
|
||||
|
||||
// Response starts with request message up to end of Request tag
|
||||
response = pb.data(start);
|
||||
|
||||
// Add in response data
|
||||
response += Symbols::CRLF;
|
||||
response += " <Response>" + responseData + " </Response>";
|
||||
response += Symbols::CRLF;
|
||||
|
||||
// Add remainder of request message
|
||||
start = pb.position();
|
||||
pb.skipToEnd();
|
||||
response += pb.data(start);
|
||||
}
|
||||
else
|
||||
{
|
||||
// No Request in message - just send bare response
|
||||
response = "<Response>" + responseData + "</Response>";
|
||||
}
|
||||
mTxBuffer += response;
|
||||
if(isFinal)
|
||||
{
|
||||
mRequests.erase(it);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/* ====================================================================
|
||||
|
||||
Copyright (c) 2009, SIP Spectrum, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of SIP Spectrum nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
==================================================================== */
|
||||
|
||||
84
src/libs/resiprocate/apps/clicktocall/XmlRpcConnection.hxx
Normal file
84
src/libs/resiprocate/apps/clicktocall/XmlRpcConnection.hxx
Normal file
@@ -0,0 +1,84 @@
|
||||
#if !defined(XmlRpcConnection_hxx)
|
||||
#define XmlRpcConnection_hxx
|
||||
|
||||
#include <map>
|
||||
#include <rutil/Data.hxx>
|
||||
#include <rutil/Socket.hxx>
|
||||
#include <rutil/TransportType.hxx>
|
||||
#include <resip/stack/Tuple.hxx>
|
||||
|
||||
#include "XmlRpcServerBase.hxx"
|
||||
|
||||
namespace clicktocall
|
||||
{
|
||||
|
||||
class XmlRpcConnection
|
||||
{
|
||||
friend class XmlRpcServerBase;
|
||||
|
||||
public:
|
||||
XmlRpcConnection(XmlRpcServerBase& server, resip::Socket sock);
|
||||
virtual ~XmlRpcConnection();
|
||||
|
||||
unsigned int getConnectionId() const { return mConnectionId; }
|
||||
void buildFdSet(resip::FdSet& fdset);
|
||||
bool process(resip::FdSet& fdset);
|
||||
|
||||
virtual bool sendResponse(unsigned int requestId, const resip::Data& responseData, bool isFinal);
|
||||
|
||||
private:
|
||||
bool processSomeReads();
|
||||
bool processSomeWrites();
|
||||
bool tryParse(); // returns true if we processed something and there is more data in the buffer
|
||||
|
||||
XmlRpcServerBase& mXmlRcpServer;
|
||||
const unsigned int mConnectionId;
|
||||
static unsigned int NextConnectionId;
|
||||
|
||||
unsigned int mNextRequestId;
|
||||
typedef std::map<unsigned int, resip::Data> RequestMap;
|
||||
RequestMap mRequests;
|
||||
|
||||
resip::Socket mSock;
|
||||
resip::Data mRxBuffer;
|
||||
resip::Data mTxBuffer;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* ====================================================================
|
||||
|
||||
Copyright (c) 2009, SIP Spectrum, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of SIP Spectrum nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
==================================================================== */
|
||||
|
||||
202
src/libs/resiprocate/apps/clicktocall/XmlRpcServer.cxx
Normal file
202
src/libs/resiprocate/apps/clicktocall/XmlRpcServer.cxx
Normal file
@@ -0,0 +1,202 @@
|
||||
#include "rutil/ResipAssert.h"
|
||||
#include <sstream>
|
||||
|
||||
#include <resip/stack/Symbols.hxx>
|
||||
#include <resip/stack/Tuple.hxx>
|
||||
#include <rutil/Data.hxx>
|
||||
#include <rutil/DnsUtil.hxx>
|
||||
#include <rutil/Logger.hxx>
|
||||
#include <rutil/ParseBuffer.hxx>
|
||||
#include <rutil/Socket.hxx>
|
||||
#include <rutil/TransportType.hxx>
|
||||
|
||||
#include "AppSubsystem.hxx"
|
||||
#include "XmlRpcServerBase.hxx"
|
||||
#include "XmlRpcConnection.hxx"
|
||||
#include "XmlRpcServer.hxx"
|
||||
#include "Server.hxx"
|
||||
|
||||
using namespace clicktocall;
|
||||
using namespace resip;
|
||||
using namespace std;
|
||||
|
||||
#define RESIPROCATE_SUBSYSTEM AppSubsystem::CLICKTOCALL
|
||||
|
||||
|
||||
XmlRpcServer::XmlRpcServer(Server& server,
|
||||
int port,
|
||||
IpVersion version ) :
|
||||
XmlRpcServerBase(port, version),
|
||||
mServer(server)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
XmlRpcServer::sendResponse(unsigned int connectionId,
|
||||
unsigned int requestId,
|
||||
const Data& responseData,
|
||||
unsigned int resultCode,
|
||||
const Data& resultText,
|
||||
const Data& leg)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << Symbols::CRLF << responseData << " <Result Code=\"" << resultCode << "\"";
|
||||
if(!leg.empty())
|
||||
{
|
||||
ss << " Leg=\"" << leg << "\"";
|
||||
}
|
||||
ss << ">" << resultText << "</Result>" << Symbols::CRLF;
|
||||
bool isFinal = resultCode >= 300 || (leg=="Destination" && resultCode >= 200);
|
||||
XmlRpcServerBase::sendResponse(connectionId, requestId, ss.str().c_str(), isFinal);
|
||||
}
|
||||
|
||||
void
|
||||
XmlRpcServer::handleRequest(unsigned int connectionId, unsigned int requestId, const resip::Data& request)
|
||||
{
|
||||
InfoLog (<< "XmlRpcServer::handleRequest: connectionId=" << connectionId << ", requestId=" << requestId << ", request=" << request);
|
||||
|
||||
try
|
||||
{
|
||||
ParseBuffer pb(request);
|
||||
XMLCursor xml(pb);
|
||||
|
||||
if(isEqualNoCase(xml.getTag(), "ClickToCall"))
|
||||
{
|
||||
handleClickToCallRequest(connectionId, requestId, xml);
|
||||
}
|
||||
else
|
||||
{
|
||||
InfoLog(<< "XmlRpcServer::handleRequest: Received XML message with unknown method: " << xml.getTag());
|
||||
sendResponse(connectionId, requestId, Data::Empty, 400, "Unknown method");
|
||||
}
|
||||
}
|
||||
catch(resip::BaseException& e)
|
||||
{
|
||||
InfoLog(<< "XmlRpcServer::handleRequest: ParseException: " << e);
|
||||
sendResponse(connectionId, requestId, Data::Empty, 400, "Parse error");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
XmlRpcServer::handleClickToCallRequest(unsigned int connectionId, unsigned int requestId, XMLCursor& xml)
|
||||
{
|
||||
Data initiator;
|
||||
Data destination;
|
||||
bool anchor = false;
|
||||
|
||||
if(xml.firstChild())
|
||||
{
|
||||
if(isEqualNoCase(xml.getTag(), "Request"))
|
||||
{
|
||||
if(xml.firstChild())
|
||||
{
|
||||
do
|
||||
{
|
||||
if(isEqualNoCase(xml.getTag(), "Initiator"))
|
||||
{
|
||||
if(xml.firstChild())
|
||||
{
|
||||
initiator = xml.getValue();
|
||||
xml.parent();
|
||||
}
|
||||
}
|
||||
else if(isEqualNoCase(xml.getTag(), "Destination"))
|
||||
{
|
||||
if(xml.firstChild())
|
||||
{
|
||||
destination = xml.getValue();
|
||||
xml.parent();
|
||||
}
|
||||
}
|
||||
else if(isEqualNoCase(xml.getTag(), "AnchorCall"))
|
||||
{
|
||||
if(xml.firstChild())
|
||||
{
|
||||
if(isEqualNoCase(xml.getValue(), "true"))
|
||||
{
|
||||
anchor = true;
|
||||
}
|
||||
xml.parent();
|
||||
}
|
||||
}
|
||||
} while(xml.nextSibling());
|
||||
xml.parent();
|
||||
}
|
||||
}
|
||||
xml.parent();
|
||||
}
|
||||
|
||||
if(!initiator.empty() && !destination.empty())
|
||||
{
|
||||
Data initiatorTranslation;
|
||||
Data destinationTranslation;
|
||||
|
||||
if(mServer.translateAddress(initiator, initiatorTranslation, true /* fail if no rule */) &&
|
||||
mServer.translateAddress(destination, destinationTranslation, true /* fail if no rule */))
|
||||
{
|
||||
try
|
||||
{
|
||||
Uri initiatorUri(initiatorTranslation);
|
||||
Uri destinationUri(destinationTranslation);
|
||||
XmlRpcInfo info(connectionId, requestId, this);
|
||||
mServer.clickToCall(initiatorUri, destinationUri, anchor, &info);
|
||||
|
||||
std::stringstream ss;
|
||||
ss << " <TranslatedInitiator>" << initiatorUri << "</TranslatedInitiator>" << Symbols::CRLF;
|
||||
ss << " <TranslatedDestination>" << destinationUri << "</TranslatedDestination>" << Symbols::CRLF;
|
||||
sendResponse(connectionId, requestId, ss.str().c_str(), 100, "In progress");
|
||||
}
|
||||
catch(resip::BaseException& e)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "Invalid URI format in initiator " << initiatorTranslation << "(" << initiator << ") or destination " << destinationTranslation << "(" << destination << "): " << e;
|
||||
sendResponse(connectionId, requestId, Data::Empty, 400, ss.str().c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "No translation rule for either initiator " << initiator << " or destination " << destination;
|
||||
sendResponse(connectionId, requestId, Data::Empty, 400, ss.str().c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sendResponse(connectionId, requestId, Data::Empty, 400, "Missing initiator and/or destination tags");
|
||||
}
|
||||
}
|
||||
|
||||
/* ====================================================================
|
||||
|
||||
Copyright (c) 2009, SIP Spectrum, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of SIP Spectrum nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
==================================================================== */
|
||||
|
||||
96
src/libs/resiprocate/apps/clicktocall/XmlRpcServer.hxx
Normal file
96
src/libs/resiprocate/apps/clicktocall/XmlRpcServer.hxx
Normal file
@@ -0,0 +1,96 @@
|
||||
#if !defined(XmlRpcServer_hxx)
|
||||
#define XmlRpcServer_hxx
|
||||
|
||||
#include <rutil/Data.hxx>
|
||||
#include <rutil/TransportType.hxx>
|
||||
#include <resip/stack/Tuple.hxx>
|
||||
#include <rutil/XMLCursor.hxx>
|
||||
|
||||
#include "XmlRpcServerBase.hxx"
|
||||
|
||||
namespace resip
|
||||
{
|
||||
class DataStream;
|
||||
}
|
||||
|
||||
namespace clicktocall
|
||||
{
|
||||
class Server;
|
||||
class XmlRpcServer;
|
||||
|
||||
class XmlRpcInfo
|
||||
{
|
||||
public:
|
||||
XmlRpcInfo(unsigned int connectionId, unsigned int requestId, XmlRpcServer* xmlRpcServer) :
|
||||
mConnectionId(connectionId), mRequestId(requestId), mXmlRpcServer(xmlRpcServer) {}
|
||||
XmlRpcInfo() : mConnectionId(0), mRequestId(0), mXmlRpcServer(0) {}
|
||||
unsigned int mConnectionId;
|
||||
unsigned int mRequestId;
|
||||
XmlRpcServer* mXmlRpcServer;
|
||||
};
|
||||
|
||||
class XmlRpcServer: public XmlRpcServerBase
|
||||
{
|
||||
public:
|
||||
XmlRpcServer(Server& server,
|
||||
int port,
|
||||
resip::IpVersion version);
|
||||
|
||||
// thread safe
|
||||
virtual void sendResponse(unsigned int connectionId,
|
||||
unsigned int requestId,
|
||||
const resip::Data& responseData,
|
||||
unsigned int resultCode,
|
||||
const resip::Data& resultText,
|
||||
const resip::Data& leg = resip::Data::Empty);
|
||||
|
||||
protected:
|
||||
virtual void handleRequest(unsigned int connectionId,
|
||||
unsigned int requestId,
|
||||
const resip::Data& request);
|
||||
|
||||
private:
|
||||
void handleClickToCallRequest(unsigned int connectionId, unsigned int requestId, resip::XMLCursor& xml);
|
||||
|
||||
Server& mServer;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* ====================================================================
|
||||
|
||||
Copyright (c) 2009, SIP Spectrum, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of SIP Spectrum nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
==================================================================== */
|
||||
|
||||
395
src/libs/resiprocate/apps/clicktocall/XmlRpcServerBase.cxx
Normal file
395
src/libs/resiprocate/apps/clicktocall/XmlRpcServerBase.cxx
Normal file
@@ -0,0 +1,395 @@
|
||||
#include "rutil/ResipAssert.h"
|
||||
|
||||
#include <rutil/Data.hxx>
|
||||
#include <rutil/Socket.hxx>
|
||||
#include <resip/stack/Symbols.hxx>
|
||||
#include <rutil/TransportType.hxx>
|
||||
#include <rutil/Logger.hxx>
|
||||
#include <resip/stack/Tuple.hxx>
|
||||
#include <rutil/DnsUtil.hxx>
|
||||
#include <rutil/ParseBuffer.hxx>
|
||||
#include <resip/stack/Transport.hxx>
|
||||
|
||||
#include "AppSubsystem.hxx"
|
||||
#include "XmlRpcServerBase.hxx"
|
||||
#include "XmlRpcConnection.hxx"
|
||||
#include <rutil/WinLeakCheck.hxx>
|
||||
|
||||
using namespace clicktocall;
|
||||
using namespace resip;
|
||||
using namespace std;
|
||||
|
||||
#define RESIPROCATE_SUBSYSTEM AppSubsystem::CLICKTOCALL
|
||||
|
||||
|
||||
XmlRpcServerBase::XmlRpcServerBase(int port, IpVersion ipVer) :
|
||||
mTuple(Data::Empty,port,ipVer,TCP,Data::Empty),
|
||||
mSane(true)
|
||||
{
|
||||
#ifdef USE_IPV6
|
||||
mFd = ::socket(ipVer == V4 ? PF_INET : PF_INET6, SOCK_STREAM, 0);
|
||||
#else
|
||||
mFd = ::socket(PF_INET, SOCK_STREAM, 0);
|
||||
#endif
|
||||
|
||||
if (mFd == INVALID_SOCKET)
|
||||
{
|
||||
int e = getErrno();
|
||||
logSocketError(e);
|
||||
ErrLog(<< "XmlRpcServerBase::XmlRpcServerBase: Failed to create socket: " << strerror(e));
|
||||
mSane = false;
|
||||
return;
|
||||
}
|
||||
|
||||
DebugLog (<< "XmlRpcServerBase::XmlRpcServerBase: Creating fd=" << (int)mFd
|
||||
<< (ipVer == V4 ? " V4/" : " V6/") );
|
||||
|
||||
int on = 1;
|
||||
#if !defined(WIN32)
|
||||
if (::setsockopt(mFd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)))
|
||||
#else
|
||||
if (::setsockopt(mFd, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on)))
|
||||
#endif
|
||||
{
|
||||
int e = getErrno();
|
||||
logSocketError(e);
|
||||
ErrLog(<< "XmlRpcServerBase::XmlRpcServerBase: Couldn't set sockoptions SO_REUSEPORT | SO_REUSEADDR: " << strerror(e));
|
||||
mSane = false;
|
||||
return;
|
||||
}
|
||||
|
||||
DebugLog(<< "XmlRpcServerBase::XmlRpcServerBase: Binding to " << Tuple::inet_ntop(mTuple));
|
||||
|
||||
if (::bind( mFd, &mTuple.getMutableSockaddr(), mTuple.length()) == SOCKET_ERROR)
|
||||
{
|
||||
int e = getErrno();
|
||||
logSocketError(e);
|
||||
if (e == EADDRINUSE)
|
||||
{
|
||||
ErrLog(<< "XmlRpcServerBase::XmlRpcServerBase: " << mTuple << " already in use ");
|
||||
}
|
||||
else
|
||||
{
|
||||
ErrLog(<< "XmlRpcServerBase::XmlRpcServerBase: Could not bind to " << mTuple);
|
||||
}
|
||||
mSane = false;
|
||||
return;
|
||||
}
|
||||
|
||||
bool ok = makeSocketNonBlocking(mFd);
|
||||
if (!ok)
|
||||
{
|
||||
int e = getErrno();
|
||||
logSocketError(e);
|
||||
ErrLog(<< "XmlRpcServerBase::XmlRpcServerBase: Could not make HTTP socket non-blocking " << port);
|
||||
mSane = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// do the listen, seting the maximum queue size for compeletly established
|
||||
// sockets -- on linux, tcp_max_syn_backlog should be used for the incomplete
|
||||
// queue size(see man listen)
|
||||
int e = listen(mFd,5);
|
||||
|
||||
if (e != 0)
|
||||
{
|
||||
int e = getErrno();
|
||||
InfoLog(<< "XmlRpcServerBase::XmlRpcServerBase: Failed listen " << strerror(e));
|
||||
mSane = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
XmlRpcServerBase::~XmlRpcServerBase()
|
||||
{
|
||||
#if defined(WIN32)
|
||||
closesocket(mFd);
|
||||
#else
|
||||
close(mFd);
|
||||
#endif
|
||||
mFd = 0;
|
||||
ConnectionMap::iterator it = mConnections.begin();
|
||||
for(; it != mConnections.end(); it++)
|
||||
{
|
||||
delete it->second;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
XmlRpcServerBase::buildFdSet(FdSet& fdset)
|
||||
{
|
||||
mSelectInterruptor.buildFdSet(fdset);
|
||||
|
||||
fdset.setRead(mFd); // listen socket for server
|
||||
|
||||
ConnectionMap::iterator it = mConnections.begin();
|
||||
for(; it != mConnections.end(); it++)
|
||||
{
|
||||
it->second->buildFdSet(fdset);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
XmlRpcServerBase::process(FdSet& fdset)
|
||||
{
|
||||
// Process Response fifo first
|
||||
while (mResponseFifo.messageAvailable())
|
||||
{
|
||||
ResponseInfo* responseInfo = mResponseFifo.getNext();
|
||||
ConnectionMap::iterator it = mConnections.find(responseInfo->getConnectionId());
|
||||
if(it != mConnections.end())
|
||||
{
|
||||
it->second->sendResponse(responseInfo->getRequestId(), responseInfo->getResponseData(), responseInfo->getIsFinal());
|
||||
delete responseInfo;
|
||||
}
|
||||
}
|
||||
|
||||
mSelectInterruptor.process(fdset);
|
||||
|
||||
if (fdset.readyToRead(mFd))
|
||||
{
|
||||
Tuple tuple(mTuple);
|
||||
struct sockaddr& peer = tuple.getMutableSockaddr();
|
||||
socklen_t peerLen = tuple.length();
|
||||
Socket sock = accept( mFd, &peer, &peerLen);
|
||||
if (sock == SOCKET_ERROR)
|
||||
{
|
||||
int e = getErrno();
|
||||
switch (e)
|
||||
{
|
||||
case EWOULDBLOCK:
|
||||
return;
|
||||
default:
|
||||
logSocketError(e);
|
||||
ErrLog(<< "XmlRpcServerBase::process: Some error reading from socket: " << e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
makeSocketNonBlocking(sock);
|
||||
|
||||
if(mConnections.size() == MaxConnections)
|
||||
{
|
||||
closeOldestConnection();
|
||||
}
|
||||
|
||||
XmlRpcConnection* connection = new XmlRpcConnection(*this,sock);
|
||||
mConnections[connection->getConnectionId()] = connection;
|
||||
|
||||
DebugLog (<< "XmlRpcServerBase::process: Received TCP connection as connection=" << connection->getConnectionId() << " fd=" << (int)sock);
|
||||
}
|
||||
|
||||
// Call process on each connection
|
||||
ConnectionMap::iterator it = mConnections.begin();
|
||||
for(; it != mConnections.end(); )
|
||||
{
|
||||
bool ok = it->second->process(fdset);
|
||||
if (!ok)
|
||||
{
|
||||
delete it->second;
|
||||
mConnections.erase(it++);
|
||||
}
|
||||
else
|
||||
{
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
XmlRpcServerBase::sendResponse(unsigned int connectionId,
|
||||
unsigned int requestId,
|
||||
const Data& responseData,
|
||||
bool isFinal)
|
||||
{
|
||||
mResponseFifo.add(new ResponseInfo(connectionId, requestId, responseData, isFinal));
|
||||
mSelectInterruptor.interrupt();
|
||||
}
|
||||
|
||||
bool
|
||||
XmlRpcServerBase::isSane()
|
||||
{
|
||||
return mSane;
|
||||
}
|
||||
|
||||
void
|
||||
XmlRpcServerBase::closeOldestConnection()
|
||||
{
|
||||
if(mConnections.empty()) return;
|
||||
|
||||
// Oldest Connection is the one with the lowest Id
|
||||
ConnectionMap::iterator lowestConnectionIdIt = mConnections.end();
|
||||
ConnectionMap::iterator it = mConnections.begin();
|
||||
for(; it != mConnections.end(); it++)
|
||||
{
|
||||
if(it->second->getConnectionId() < lowestConnectionIdIt->second->getConnectionId())
|
||||
{
|
||||
lowestConnectionIdIt = it;
|
||||
}
|
||||
}
|
||||
delete lowestConnectionIdIt->second;
|
||||
mConnections.erase(lowestConnectionIdIt);
|
||||
}
|
||||
|
||||
void
|
||||
XmlRpcServerBase::logSocketError(int e)
|
||||
{
|
||||
switch (e)
|
||||
{
|
||||
case EAGAIN:
|
||||
InfoLog (<< "No data ready to read" << strerror(e));
|
||||
break;
|
||||
case EINTR:
|
||||
InfoLog (<< "The call was interrupted by a signal before any data was read : " << strerror(e));
|
||||
break;
|
||||
case EIO:
|
||||
InfoLog (<< "I/O error : " << strerror(e));
|
||||
break;
|
||||
case EBADF:
|
||||
InfoLog (<< "fd is not a valid file descriptor or is not open for reading : " << strerror(e));
|
||||
break;
|
||||
case EINVAL:
|
||||
InfoLog (<< "fd is attached to an object which is unsuitable for reading : " << strerror(e));
|
||||
break;
|
||||
case EFAULT:
|
||||
InfoLog (<< "buf is outside your accessible address space : " << strerror(e));
|
||||
break;
|
||||
|
||||
#if defined(WIN32)
|
||||
case WSAENETDOWN:
|
||||
InfoLog (<<" The network subsystem has failed. ");
|
||||
break;
|
||||
case WSAEFAULT:
|
||||
InfoLog (<<" The buf or from parameters are not part of the user address space, "
|
||||
"or the fromlen parameter is too small to accommodate the peer address. ");
|
||||
break;
|
||||
case WSAEINTR:
|
||||
InfoLog (<<" The (blocking) call was canceled through WSACancelBlockingCall. ");
|
||||
break;
|
||||
case WSAEINPROGRESS:
|
||||
InfoLog (<<" A blocking Windows Sockets 1.1 call is in progress, or the "
|
||||
"service provider is still processing a callback function. ");
|
||||
break;
|
||||
case WSAEINVAL:
|
||||
InfoLog (<<" The socket has not been bound with bind, or an unknown flag was specified, "
|
||||
"or MSG_OOB was specified for a socket with SO_OOBINLINE enabled, "
|
||||
"or (for byte stream-style sockets only) len was zero or negative. ");
|
||||
break;
|
||||
case WSAEISCONN :
|
||||
InfoLog (<<"The socket is connected. This function is not permitted with a connected socket, "
|
||||
"whether the socket is connection-oriented or connectionless. ");
|
||||
break;
|
||||
case WSAENETRESET:
|
||||
InfoLog (<<" The connection has been broken due to the keep-alive activity "
|
||||
"detecting a failure while the operation was in progress. ");
|
||||
break;
|
||||
case WSAENOTSOCK :
|
||||
InfoLog (<<"The descriptor is not a socket. ");
|
||||
break;
|
||||
case WSAEOPNOTSUPP:
|
||||
InfoLog (<<" MSG_OOB was specified, but the socket is not stream-style such as type "
|
||||
"SOCK_STREAM, OOB data is not supported in the communication domain associated with this socket, "
|
||||
"or the socket is unidirectional and supports only send operations. ");
|
||||
break;
|
||||
case WSAESHUTDOWN:
|
||||
InfoLog (<<"The socket has been shut down; it is not possible to recvfrom on a socket after "
|
||||
"shutdown has been invoked with how set to SD_RECEIVE or SD_BOTH. ");
|
||||
break;
|
||||
case WSAEMSGSIZE:
|
||||
InfoLog (<<" The message was too large to fit into the specified buffer and was truncated. ");
|
||||
break;
|
||||
case WSAETIMEDOUT:
|
||||
InfoLog (<<" The connection has been dropped, because of a network failure or because the "
|
||||
"system on the other end went down without notice. ");
|
||||
break;
|
||||
case WSAECONNRESET :
|
||||
InfoLog (<<"Connection reset ");
|
||||
break;
|
||||
|
||||
case WSAEWOULDBLOCK:
|
||||
DebugLog (<<"Would Block ");
|
||||
break;
|
||||
|
||||
case WSAEHOSTUNREACH:
|
||||
InfoLog (<<"A socket operation was attempted to an unreachable host ");
|
||||
break;
|
||||
case WSANOTINITIALISED:
|
||||
InfoLog (<<"Either the application has not called WSAStartup or WSAStartup failed. "
|
||||
"The application may be accessing a socket that the current active task does not own (that is, trying to share a socket between tasks),"
|
||||
"or WSACleanup has been called too many times. ");
|
||||
break;
|
||||
case WSAEACCES:
|
||||
InfoLog (<<"An attempt was made to access a socket in a way forbidden by its access permissions ");
|
||||
break;
|
||||
case WSAENOBUFS:
|
||||
InfoLog (<<"An operation on a socket could not be performed because the system lacked sufficient "
|
||||
"buffer space or because a queue was full");
|
||||
break;
|
||||
case WSAENOTCONN:
|
||||
InfoLog (<<"A request to send or receive data was disallowed because the socket is not connected "
|
||||
"and (when sending on a datagram socket using sendto) no address was supplied");
|
||||
break;
|
||||
case WSAECONNABORTED:
|
||||
InfoLog (<<"An established connection was aborted by the software in your host computer, possibly "
|
||||
"due to a data transmission time-out or protocol error");
|
||||
break;
|
||||
case WSAEADDRNOTAVAIL:
|
||||
InfoLog (<<"The requested address is not valid in its context. This normally results from an attempt to "
|
||||
"bind to an address that is not valid for the local computer");
|
||||
break;
|
||||
case WSAEAFNOSUPPORT:
|
||||
InfoLog (<<"An address incompatible with the requested protocol was used");
|
||||
break;
|
||||
case WSAEDESTADDRREQ:
|
||||
InfoLog (<<"A required address was omitted from an operation on a socket");
|
||||
break;
|
||||
case WSAENETUNREACH:
|
||||
InfoLog (<<"A socket operation was attempted to an unreachable network");
|
||||
break;
|
||||
|
||||
#endif
|
||||
|
||||
default:
|
||||
InfoLog (<< "Some other error (" << e << "): " << strerror(e));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ====================================================================
|
||||
|
||||
Copyright (c) 2009, SIP Spectrum, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of SIP Spectrum nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
==================================================================== */
|
||||
|
||||
119
src/libs/resiprocate/apps/clicktocall/XmlRpcServerBase.hxx
Normal file
119
src/libs/resiprocate/apps/clicktocall/XmlRpcServerBase.hxx
Normal file
@@ -0,0 +1,119 @@
|
||||
#if !defined(XmlRpcServerBase_hxx)
|
||||
#define XmlRpcServerBase_hxx
|
||||
|
||||
#include <map>
|
||||
#include <rutil/Data.hxx>
|
||||
#include <rutil/Socket.hxx>
|
||||
#include <rutil/TransportType.hxx>
|
||||
#include <rutil/Fifo.hxx>
|
||||
#include <resip/stack/Tuple.hxx>
|
||||
#include <rutil/SelectInterruptor.hxx>
|
||||
|
||||
namespace clicktocall
|
||||
{
|
||||
class XmlRpcConnection;
|
||||
|
||||
class ResponseInfo
|
||||
{
|
||||
public:
|
||||
ResponseInfo(unsigned int connectionId,
|
||||
unsigned int requestId,
|
||||
const resip::Data& responseData,
|
||||
bool isFinal) :
|
||||
mConnectionId(connectionId),
|
||||
mRequestId(requestId),
|
||||
mResponseData(responseData),
|
||||
mIsFinal(isFinal) {}
|
||||
|
||||
~ResponseInfo() {}
|
||||
|
||||
unsigned int getConnectionId() const { return mConnectionId; }
|
||||
unsigned int getRequestId() const { return mRequestId; }
|
||||
const resip::Data& getResponseData() const { return mResponseData; }
|
||||
bool getIsFinal() const { return mIsFinal; }
|
||||
|
||||
private:
|
||||
unsigned int mConnectionId;
|
||||
unsigned int mRequestId;
|
||||
resip::Data mResponseData;
|
||||
bool mIsFinal;
|
||||
};
|
||||
|
||||
class XmlRpcServerBase
|
||||
{
|
||||
friend class XmlRpcConnection;
|
||||
|
||||
public:
|
||||
XmlRpcServerBase(int port, resip::IpVersion version);
|
||||
virtual ~XmlRpcServerBase();
|
||||
|
||||
void buildFdSet(resip::FdSet& fdset);
|
||||
void process(resip::FdSet& fdset);
|
||||
|
||||
bool isSane();
|
||||
static void logSocketError(int e);
|
||||
|
||||
// thread safe - uses fifo
|
||||
void sendResponse(unsigned int connectionId,
|
||||
unsigned int requestId,
|
||||
const resip::Data& responseData,
|
||||
bool isFinal=true);
|
||||
|
||||
protected:
|
||||
virtual void handleRequest(unsigned int connectionId,
|
||||
unsigned int requestId,
|
||||
const resip::Data& request) = 0;
|
||||
|
||||
private:
|
||||
static const unsigned int MaxConnections = 60; // Note: use caution if making this any bigger, default fd_set size in windows is 64
|
||||
|
||||
resip::Socket mFd;
|
||||
resip::Tuple mTuple;
|
||||
bool mSane;
|
||||
|
||||
typedef std::map<unsigned int, XmlRpcConnection*> ConnectionMap;
|
||||
ConnectionMap mConnections;
|
||||
void closeOldestConnection();
|
||||
|
||||
resip::Fifo<ResponseInfo> mResponseFifo;
|
||||
resip::SelectInterruptor mSelectInterruptor;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* ====================================================================
|
||||
|
||||
Copyright (c) 2009, SIP Spectrum, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of SIP Spectrum nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
==================================================================== */
|
||||
|
||||
84
src/libs/resiprocate/apps/clicktocall/XmlRpcServerThread.cxx
Normal file
84
src/libs/resiprocate/apps/clicktocall/XmlRpcServerThread.cxx
Normal file
@@ -0,0 +1,84 @@
|
||||
#include <rutil/Socket.hxx>
|
||||
#include <rutil/Logger.hxx>
|
||||
|
||||
#include "AppSubsystem.hxx"
|
||||
#include "XmlRpcServer.hxx"
|
||||
#include "XmlRpcServerThread.hxx"
|
||||
|
||||
#define RESIPROCATE_SUBSYSTEM AppSubsystem::CLICKTOCALL
|
||||
|
||||
using namespace clicktocall;
|
||||
using namespace resip;
|
||||
using namespace std;
|
||||
|
||||
|
||||
XmlRpcServerThread::XmlRpcServerThread(const std::list<XmlRpcServer*>& xmlRpcServerList)
|
||||
: mXmlRpcServerList(xmlRpcServerList)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
XmlRpcServerThread::thread()
|
||||
{
|
||||
while (!isShutdown())
|
||||
{
|
||||
try
|
||||
{
|
||||
FdSet fdset;
|
||||
|
||||
std::list<XmlRpcServer*>::iterator it = mXmlRpcServerList.begin();
|
||||
for(;it!=mXmlRpcServerList.end();it++)
|
||||
{
|
||||
(*it)->buildFdSet(fdset);
|
||||
}
|
||||
fdset.selectMilliSeconds( 10*1000 );
|
||||
|
||||
it = mXmlRpcServerList.begin();
|
||||
for(;it!=mXmlRpcServerList.end();it++)
|
||||
{
|
||||
(*it)->process(fdset);
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
ErrLog (<< "XmlRpcServerThread::thread: Unhandled exception: " );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ====================================================================
|
||||
|
||||
Copyright (c) 2009, SIP Spectrum, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of SIP Spectrum nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
==================================================================== */
|
||||
|
||||
62
src/libs/resiprocate/apps/clicktocall/XmlRpcServerThread.hxx
Normal file
62
src/libs/resiprocate/apps/clicktocall/XmlRpcServerThread.hxx
Normal file
@@ -0,0 +1,62 @@
|
||||
#if !defined(XmlRpcServerThread_hxx)
|
||||
#define XmlRpcServerThread_hxx
|
||||
|
||||
#include <list>
|
||||
#include <rutil/ThreadIf.hxx>
|
||||
#include <rutil/Socket.hxx>
|
||||
|
||||
namespace clicktocall
|
||||
{
|
||||
class XmlRpcServer;
|
||||
|
||||
class XmlRpcServerThread : public resip::ThreadIf
|
||||
{
|
||||
public:
|
||||
XmlRpcServerThread(const std::list<XmlRpcServer*>& xmlRpcServerList);
|
||||
|
||||
protected:
|
||||
|
||||
private:
|
||||
virtual void thread();
|
||||
std::list<XmlRpcServer*> mXmlRpcServerList;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* ====================================================================
|
||||
|
||||
Copyright (c) 2009, SIP Spectrum, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of SIP Spectrum nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
==================================================================== */
|
||||
|
||||
81
src/libs/resiprocate/apps/clicktocall/clicktocall.config
Normal file
81
src/libs/resiprocate/apps/clicktocall/clicktocall.config
Normal file
@@ -0,0 +1,81 @@
|
||||
########################################################
|
||||
# click to call server configuration file
|
||||
########################################################
|
||||
|
||||
|
||||
########################################################
|
||||
# SIP settings
|
||||
########################################################
|
||||
|
||||
# Local IP Address to bind SIP transports to. If left blank
|
||||
# ichat-gw will bind to all adapters.
|
||||
#IPAddress = 192.168.1.106
|
||||
#IPAddress = 2001:5c0:1000:a::6d
|
||||
IPAddress =
|
||||
|
||||
# Comma separated list of DNS servers, overrides default OS detected list (leave blank for default)
|
||||
DNSServers =
|
||||
|
||||
# Used in From header of SIP calls, when calling initiator. Value must be a valid formatted SIP Uri
|
||||
ClickToCallIdentity = sip:click2call@blitzzgod.com
|
||||
|
||||
# Local port to listen on for SIP messages over UDP or TCP
|
||||
UDPTCPPort = 5072
|
||||
|
||||
# Local port to listen on for SIP messages over TLS
|
||||
TLSPort = 5073
|
||||
|
||||
# TLS domain name for this server (note: domain cert for this domain must be present)
|
||||
TLSDomainName =
|
||||
|
||||
# Enable/Disable TCP/UDP CRLFCRLF keepalive packets for SIP endpoints
|
||||
# 1|true|on|enable to enable, 0|false|off|disable to disable
|
||||
KeepAlives = enable
|
||||
|
||||
# URI of a proxy server to use a SIP outbound proxy. This setting should not be required if
|
||||
# proper DNS based SIP routing is operational.
|
||||
OutboundProxy =
|
||||
|
||||
|
||||
########################################################
|
||||
# General settings
|
||||
########################################################
|
||||
|
||||
# Logging level: NONE|CRIT|ERR|WARNING|INFO|DEBUG|STACK
|
||||
LogLevel = INFO
|
||||
|
||||
# Log Filename
|
||||
LogFilename = clicktocall.log
|
||||
|
||||
# Log file Max Lines
|
||||
LogFileMaxLines = 50000
|
||||
|
||||
# Port to listen for XML RPC requests on. Set to 0 to disable.
|
||||
# Note: clicktocall will listen on this port for all interfaces, for both IPv4
|
||||
# and IPv6 (if available).
|
||||
XmlRpcPort = 5094
|
||||
|
||||
# Port to listen on for HTTP messaging (ie. Click-to-call). Set to 0 to disable.
|
||||
# Note: clicktocall will listen on this port for all interfaces, for both IPv4
|
||||
# and IPv6 (if available).
|
||||
HttpPort = 5090
|
||||
|
||||
# Enable/Disable HTTP Digest authentication: 1|true|on to enable
|
||||
# 1|true|on|enable to enable, 0|false|off|disable to disable
|
||||
HttpAuth = enable
|
||||
|
||||
# Password required if HttpAuth is enabled: Note: auth user is always "admin"
|
||||
HttpAuthPwd = admin
|
||||
|
||||
|
||||
########################################################
|
||||
# Address Translation Rules (must be listed in pairs)
|
||||
########################################################
|
||||
|
||||
# Rule for mapping any non-sip address to appropriate SIP URI
|
||||
TranslationPattern=^(.*)$
|
||||
TranslationOutput=sip:$1@blitzzgod.com
|
||||
|
||||
|
||||
|
||||
|
||||
116
src/libs/resiprocate/apps/clicktocall/clicktocall.cxx
Normal file
116
src/libs/resiprocate/apps/clicktocall/clicktocall.cxx
Normal file
@@ -0,0 +1,116 @@
|
||||
#include <signal.h>
|
||||
|
||||
#include "AppSubsystem.hxx"
|
||||
#include "Server.hxx"
|
||||
|
||||
#include <rutil/Log.hxx>
|
||||
#include <rutil/Logger.hxx>
|
||||
#include <rutil/Time.hxx>
|
||||
#include <rutil/DnsUtil.hxx>
|
||||
#include <rutil/BaseException.hxx>
|
||||
#include <resip/stack/NameAddr.hxx>
|
||||
#include <rutil/WinLeakCheck.hxx>
|
||||
|
||||
using namespace clicktocall;
|
||||
using namespace resip;
|
||||
using namespace std;
|
||||
|
||||
#define RESIPROCATE_SUBSYSTEM AppSubsystem::CLICKTOCALL
|
||||
|
||||
static bool finished = false;
|
||||
|
||||
static void
|
||||
signalHandler(int signo)
|
||||
{
|
||||
std::cerr << "Shutting down..." << endl;
|
||||
finished = true;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char** argv)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
if ( signal( SIGPIPE, SIG_IGN) == SIG_ERR)
|
||||
{
|
||||
cerr << "Couldn't install signal handler for SIGPIPE" << endl;
|
||||
exit(-1);
|
||||
}
|
||||
#else
|
||||
#if defined(_DEBUG) && defined(LEAK_CHECK)
|
||||
resip::FindMemoryLeaks fml;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if ( signal( SIGINT, signalHandler ) == SIG_ERR )
|
||||
{
|
||||
cerr << "Couldn't install signal handler for SIGINT" << endl;
|
||||
exit( -1 );
|
||||
}
|
||||
|
||||
if ( signal( SIGTERM, signalHandler ) == SIG_ERR )
|
||||
{
|
||||
cerr << "Couldn't install signal handler for SIGTERM" << endl;
|
||||
exit( -1 );
|
||||
}
|
||||
|
||||
initNetwork();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Create Server
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
{
|
||||
Server server(argc, argv);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Startup and run...
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
server.startup();
|
||||
|
||||
while(true)
|
||||
{
|
||||
server.process(50);
|
||||
if(finished) break;
|
||||
}
|
||||
|
||||
server.shutdown();
|
||||
}
|
||||
|
||||
InfoLog(<< "ClickToCall server is shutdown.");
|
||||
sleepSeconds(2);
|
||||
}
|
||||
|
||||
/* ====================================================================
|
||||
|
||||
Copyright (c) 2009, SIP Spectrum, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of SIP Spectrum nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
==================================================================== */
|
||||
|
||||
67
src/libs/resiprocate/apps/clicktocall/clicktocall_9_0.sln
Normal file
67
src/libs/resiprocate/apps/clicktocall/clicktocall_9_0.sln
Normal file
@@ -0,0 +1,67 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 10.00
|
||||
# Visual Studio 2008
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "clicktocall", "clicktocall_9_0.vcproj", "{8BA87397-9B42-4820-BA53-62FF35C22CAE}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{2A8BE839-6466-4001-B224-8F1C3168D04A} = {2A8BE839-6466-4001-B224-8F1C3168D04A}
|
||||
{12720B4D-F4FC-4502-8FA9-589BF5166216} = {12720B4D-F4FC-4502-8FA9-589BF5166216}
|
||||
{38594885-CF9C-4C5F-B3F0-E4969D7E3F58} = {38594885-CF9C-4C5F-B3F0-E4969D7E3F58}
|
||||
{96CD935E-1951-43B8-AF75-F1C06B3778C1} = {96CD935E-1951-43B8-AF75-F1C06B3778C1}
|
||||
{3D0E5CEB-93DC-4FDB-918B-D08FA369E106} = {3D0E5CEB-93DC-4FDB-918B-D08FA369E106}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rutil", "..\..\rutil\rutil_9_0.vcproj", "{3D0E5CEB-93DC-4FDB-918B-D08FA369E106}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "resiprocate", "..\..\resip\stack\resiprocate_9_0.vcproj", "{2A8BE839-6466-4001-B224-8F1C3168D04A}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dum", "..\..\resip\dum\dum_9_0.vcproj", "{12720B4D-F4FC-4502-8FA9-589BF5166216}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ares", "..\..\rutil\dns\ares\ares_9_0.vcproj", "{96CD935E-1951-43B8-AF75-F1C06B3778C1}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pcre", "..\..\contrib\pcre\pcre_9_0.vcproj", "{38594885-CF9C-4C5F-B3F0-E4969D7E3F58}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "clicktocallxml", "test\clicktocallxml_9_0.vcproj", "{9F820A51-A2FF-4EB6-ACB7-F0402E8D5CEC}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{2A8BE839-6466-4001-B224-8F1C3168D04A} = {2A8BE839-6466-4001-B224-8F1C3168D04A}
|
||||
{8BA87397-9B42-4820-BA53-62FF35C22CAE} = {8BA87397-9B42-4820-BA53-62FF35C22CAE}
|
||||
{96CD935E-1951-43B8-AF75-F1C06B3778C1} = {96CD935E-1951-43B8-AF75-F1C06B3778C1}
|
||||
{3D0E5CEB-93DC-4FDB-918B-D08FA369E106} = {3D0E5CEB-93DC-4FDB-918B-D08FA369E106}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{8BA87397-9B42-4820-BA53-62FF35C22CAE}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{8BA87397-9B42-4820-BA53-62FF35C22CAE}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{8BA87397-9B42-4820-BA53-62FF35C22CAE}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{3D0E5CEB-93DC-4FDB-918B-D08FA369E106}.Debug|Win32.ActiveCfg = SSL-Debug|Win32
|
||||
{3D0E5CEB-93DC-4FDB-918B-D08FA369E106}.Debug|Win32.Build.0 = SSL-Debug|Win32
|
||||
{3D0E5CEB-93DC-4FDB-918B-D08FA369E106}.Release|Win32.ActiveCfg = SSL-Release|Win32
|
||||
{3D0E5CEB-93DC-4FDB-918B-D08FA369E106}.Release|Win32.Build.0 = SSL-Release|Win32
|
||||
{2A8BE839-6466-4001-B224-8F1C3168D04A}.Debug|Win32.ActiveCfg = SSL-Debug|Win32
|
||||
{2A8BE839-6466-4001-B224-8F1C3168D04A}.Debug|Win32.Build.0 = SSL-Debug|Win32
|
||||
{2A8BE839-6466-4001-B224-8F1C3168D04A}.Release|Win32.ActiveCfg = SSL-Release|Win32
|
||||
{2A8BE839-6466-4001-B224-8F1C3168D04A}.Release|Win32.Build.0 = SSL-Release|Win32
|
||||
{12720B4D-F4FC-4502-8FA9-589BF5166216}.Debug|Win32.ActiveCfg = SSL-Debug|Win32
|
||||
{12720B4D-F4FC-4502-8FA9-589BF5166216}.Debug|Win32.Build.0 = SSL-Debug|Win32
|
||||
{12720B4D-F4FC-4502-8FA9-589BF5166216}.Release|Win32.ActiveCfg = SSL-Release|Win32
|
||||
{12720B4D-F4FC-4502-8FA9-589BF5166216}.Release|Win32.Build.0 = SSL-Release|Win32
|
||||
{96CD935E-1951-43B8-AF75-F1C06B3778C1}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{96CD935E-1951-43B8-AF75-F1C06B3778C1}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{96CD935E-1951-43B8-AF75-F1C06B3778C1}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{96CD935E-1951-43B8-AF75-F1C06B3778C1}.Release|Win32.Build.0 = Release|Win32
|
||||
{38594885-CF9C-4C5F-B3F0-E4969D7E3F58}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{38594885-CF9C-4C5F-B3F0-E4969D7E3F58}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{38594885-CF9C-4C5F-B3F0-E4969D7E3F58}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{38594885-CF9C-4C5F-B3F0-E4969D7E3F58}.Release|Win32.Build.0 = Release|Win32
|
||||
{9F820A51-A2FF-4EB6-ACB7-F0402E8D5CEC}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{9F820A51-A2FF-4EB6-ACB7-F0402E8D5CEC}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{9F820A51-A2FF-4EB6-ACB7-F0402E8D5CEC}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{9F820A51-A2FF-4EB6-ACB7-F0402E8D5CEC}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
312
src/libs/resiprocate/apps/clicktocall/clicktocall_9_0.vcproj
Normal file
312
src/libs/resiprocate/apps/clicktocall/clicktocall_9_0.vcproj
Normal file
@@ -0,0 +1,312 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="9.00"
|
||||
Name="clicktocall"
|
||||
ProjectGUID="{8BA87397-9B42-4820-BA53-62FF35C22CAE}"
|
||||
RootNamespace="clicktocall"
|
||||
Keyword="Win32Proj"
|
||||
TargetFrameworkVersion="131072"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""$(ProjectDir)../../";"$(ProjectDir)../../contrib/openssl/include";"$(ProjectDir)../../contrib/openssl/inc32";"$(ProjectDir)../../contrib/pcre""
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;USE_SSL;USE_IPV6;LEAK_CHECK"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="false"
|
||||
DebugInformationFormat="4"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="Ws2_32.lib winmm.lib Dnsapi.lib Iphlpapi.lib crypt32.lib "$(ProjectDir)..\..\contrib\openssl\lib\vc\static\libeay32MDd.lib" "$(ProjectDir)..\..\contrib\openssl\lib\vc\static\ssleay32MDd.lib""
|
||||
LinkIncremental="2"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="1"
|
||||
RandomizedBaseAddress="1"
|
||||
DataExecutionPrevention="0"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories=""$(ProjectDir)../../";"$(ProjectDir)../../contrib/openssl/include";"$(ProjectDir)../../contrib/openssl/inc32";"$(ProjectDir)../../contrib/pcre""
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;USE_SSL;USE_IPV6"
|
||||
RuntimeLibrary="2"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="false"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="Ws2_32.lib winmm.lib Dnsapi.lib Iphlpapi.lib crypt32.lib "$(ProjectDir)..\..\contrib\openssl\lib\vc\static\libeay32MD.lib" "$(ProjectDir)..\..\contrib\openssl\lib\vc\static\ssleay32MD.lib""
|
||||
LinkIncremental="1"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="1"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
RandomizedBaseAddress="1"
|
||||
DataExecutionPrevention="0"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\AddressTranslator.cxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\AppSubsystem.cxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\B2BSession.cxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\clicktocall.cxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\ConfigParser.cxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\HttpBase.cxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\HttpConnection.cxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Server.cxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\WebAdmin.cxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\WebAdminThread.cxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\XmlRpcConnection.cxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\XmlRpcServer.cxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\XmlRpcServerBase.cxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\XmlRpcServerThread.cxx"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\AddressTranslator.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\AppSubsystem.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\B2BSession.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\ClickToCallCmds.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\ConfigParser.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\HttpBase.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\HttpConnection.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Server.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Version.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\WebAdmin.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\WebAdminThread.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\XmlRpcConnection.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\XmlRpcServer.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\XmlRpcServerBase.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\XmlRpcServerThread.hxx"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
|
||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
||||
>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
Binary file not shown.
Binary file not shown.
6
src/libs/resiprocate/apps/clicktocall/test/.gitignore
vendored
Normal file
6
src/libs/resiprocate/apps/clicktocall/test/.gitignore
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
|
||||
/Makefile.in
|
||||
/Makefile
|
||||
/.deps
|
||||
/.libs
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
|
||||
add_executable(clicktocallxml
|
||||
clicktocallxml.cxx
|
||||
)
|
||||
|
||||
target_link_libraries(clicktocallxml PUBLIC rutil)
|
||||
190
src/libs/resiprocate/apps/clicktocall/test/clicktocallxml.cxx
Normal file
190
src/libs/resiprocate/apps/clicktocall/test/clicktocallxml.cxx
Normal file
@@ -0,0 +1,190 @@
|
||||
#include <rutil/Log.hxx>
|
||||
#include <rutil/Logger.hxx>
|
||||
#include <rutil/DnsUtil.hxx>
|
||||
#include <rutil/BaseException.hxx>
|
||||
#include <rutil/XMLCursor.hxx>
|
||||
#include <rutil/WinLeakCheck.hxx>
|
||||
|
||||
using namespace resip;
|
||||
using namespace std;
|
||||
|
||||
#define RESIPROCATE_SUBSYSTEM Subsystem::TEST
|
||||
|
||||
void sleepSeconds(unsigned int seconds)
|
||||
{
|
||||
#ifdef WIN32
|
||||
Sleep(seconds*1000);
|
||||
#else
|
||||
sleep(seconds);
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char** argv)
|
||||
{
|
||||
#ifdef WIN32
|
||||
initNetwork();
|
||||
#endif
|
||||
|
||||
int sd, rc;
|
||||
struct sockaddr_in localAddr, servAddr;
|
||||
struct hostent *h;
|
||||
|
||||
if(argc != 6)
|
||||
{
|
||||
ErrLog(<< "usage: " << argv[0] <<" <server> <port> <initiator> <destination> <anchor 0|1>");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
h = gethostbyname(argv[1]);
|
||||
if(h==0)
|
||||
{
|
||||
ErrLog(<< "unknown host " << argv[1]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
servAddr.sin_family = h->h_addrtype;
|
||||
memcpy((char *) &servAddr.sin_addr.s_addr, h->h_addr_list[0], h->h_length);
|
||||
servAddr.sin_port = htons(atoi(argv[2]));
|
||||
|
||||
// Create TCP Socket
|
||||
sd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if(sd < 0)
|
||||
{
|
||||
ErrLog(<< "cannot open socket");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// bind to any local interface/port
|
||||
localAddr.sin_family = AF_INET;
|
||||
localAddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
localAddr.sin_port = 0;
|
||||
|
||||
rc = bind(sd, (struct sockaddr *) &localAddr, sizeof(localAddr));
|
||||
if(rc < 0)
|
||||
{
|
||||
ErrLog(<<"error binding locally");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Connect to server
|
||||
rc = connect(sd, (struct sockaddr *) &servAddr, sizeof(servAddr));
|
||||
if(rc < 0)
|
||||
{
|
||||
ErrLog(<< "error connecting");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
Data request(
|
||||
"<ClickToCall>\r\n"
|
||||
" <Request>\r\n"
|
||||
" <Initiator>" + Data(argv[3]) + "</Initiator>\r\n"
|
||||
" <Destination>" + Data(argv[4]) + "</Destination>\r\n"
|
||||
" <AnchorCall>" + Data(argv[5][0] == '0' ? "false" : "true") + "</AnchorCall>\r\n"
|
||||
" </Request>\r\n"
|
||||
"</ClickToCall>\r\n");
|
||||
rc = send(sd, request.c_str(), request.size(), 0);
|
||||
if(rc < 0)
|
||||
{
|
||||
ErrLog(<< "error sending");
|
||||
close(sd);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char readBuffer[8000];
|
||||
while(rc > 0)
|
||||
{
|
||||
rc = recv(sd, (char*)&readBuffer, sizeof(readBuffer), 0);
|
||||
if(rc < 0)
|
||||
{
|
||||
ErrLog(<< "error receiving");
|
||||
close(sd);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if(rc > 0)
|
||||
{
|
||||
Data response(Data::Borrow, (const char*)&readBuffer, rc);
|
||||
InfoLog(<< "Received response: \r\n" << response.c_str());
|
||||
ParseBuffer pb(response);
|
||||
XMLCursor xml(pb);
|
||||
if(xml.firstChild())
|
||||
{
|
||||
if(xml.nextSibling())
|
||||
{
|
||||
if(xml.firstChild())
|
||||
{
|
||||
do
|
||||
{
|
||||
if(xml.getTag() == "Result")
|
||||
{
|
||||
XMLCursor::AttributeMap attribs = xml.getAttributes();
|
||||
XMLCursor::AttributeMap::iterator it = attribs.find("Code");
|
||||
if(it != attribs.end())
|
||||
{
|
||||
unsigned long statusCode = it->second.convertUnsignedLong();
|
||||
if(statusCode >= 200 && statusCode < 300)
|
||||
{
|
||||
it = attribs.find("Leg");
|
||||
if(it != attribs.end())
|
||||
{
|
||||
if(it->second == "Destination")
|
||||
{
|
||||
// Successfully connected to destination - break out
|
||||
rc = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(statusCode >=300)
|
||||
{
|
||||
// Failed - break out
|
||||
rc = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
} while(xml.nextSibling());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//sleepSeconds(5);
|
||||
InfoLog(<< "xmlrpcclient done.");
|
||||
}
|
||||
|
||||
/* ====================================================================
|
||||
|
||||
Copyright (c) 2009, SIP Spectrum, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of SIP Spectrum nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
==================================================================== */
|
||||
|
||||
@@ -0,0 +1,201 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="9.00"
|
||||
Name="clicktocallxml"
|
||||
ProjectGUID="{9F820A51-A2FF-4EB6-ACB7-F0402E8D5CEC}"
|
||||
RootNamespace="clicktocallxml"
|
||||
Keyword="Win32Proj"
|
||||
TargetFrameworkVersion="196613"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""$(ProjectDir)../../../""
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="4"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="Ws2_32.lib winmm.lib Dnsapi.lib Iphlpapi.lib crypt32.lib "$(ProjectDir)..\..\..\contrib\openssl\lib\vc\static\libeay32MDd.lib" "$(ProjectDir)..\..\..\contrib\openssl\lib\vc\static\ssleay32MDd.lib""
|
||||
LinkIncremental="2"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="1"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
EnableIntrinsicFunctions="true"
|
||||
AdditionalIncludeDirectories=""$(ProjectDir)../../../""
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
|
||||
RuntimeLibrary="2"
|
||||
EnableFunctionLevelLinking="true"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="Ws2_32.lib winmm.lib Dnsapi.lib Iphlpapi.lib crypt32.lib "$(ProjectDir)..\..\..\contrib\openssl\lib\vc\static\libeay32MD.lib" "$(ProjectDir)..\..\..\contrib\openssl\lib\vc\static\ssleay32MD.lib""
|
||||
LinkIncremental="1"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="1"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\clicktocallxml.cxx"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
|
||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
||||
>
|
||||
</Filter>
|
||||
<File
|
||||
RelativePath=".\ReadMe.txt"
|
||||
>
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
12
src/libs/resiprocate/apps/echoTest/.gitignore
vendored
Normal file
12
src/libs/resiprocate/apps/echoTest/.gitignore
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
*.swp
|
||||
|
||||
*.o
|
||||
*.lo
|
||||
*.la
|
||||
/Makefile
|
||||
/Makefile.in
|
||||
/.deps
|
||||
/.libs
|
||||
|
||||
/echoTest
|
||||
38
src/libs/resiprocate/apps/echoTest/AppSubsystem.cxx
Normal file
38
src/libs/resiprocate/apps/echoTest/AppSubsystem.cxx
Normal file
@@ -0,0 +1,38 @@
|
||||
#include "AppSubsystem.hxx"
|
||||
|
||||
AppSubsystem AppSubsystem::ECHOTEST("ECHOTEST");
|
||||
|
||||
/* ====================================================================
|
||||
*
|
||||
* Copyright 2021 Daniel Pocock http://danielpocock.com All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. Neither the name of the author(s) nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
*/
|
||||
60
src/libs/resiprocate/apps/echoTest/AppSubsystem.hxx
Normal file
60
src/libs/resiprocate/apps/echoTest/AppSubsystem.hxx
Normal file
@@ -0,0 +1,60 @@
|
||||
#if !defined(AppSubsystem_hxx)
|
||||
#define AppSubsystem_hxx
|
||||
|
||||
#include <iostream>
|
||||
#include <rutil/Subsystem.hxx>
|
||||
|
||||
/**
|
||||
This class is used in the logging subsystem to identify
|
||||
logging messages generated from echoTest
|
||||
*/
|
||||
|
||||
class AppSubsystem : public resip::Subsystem
|
||||
{
|
||||
public:
|
||||
// Add new systems below
|
||||
static AppSubsystem ECHOTEST;
|
||||
|
||||
private:
|
||||
explicit AppSubsystem(const char* rhs) : resip::Subsystem(rhs) {};
|
||||
explicit AppSubsystem(const resip::Data& rhs);
|
||||
AppSubsystem& operator=(const resip::Data& rhs);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/* ====================================================================
|
||||
*
|
||||
* Copyright 2021 Daniel Pocock http://danielpocock.com All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. Neither the name of the author(s) nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
17
src/libs/resiprocate/apps/echoTest/CMakeLists.txt
Normal file
17
src/libs/resiprocate/apps/echoTest/CMakeLists.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
set(INCLUDES
|
||||
AppSubsystem.hxx
|
||||
EchoTestConfig.hxx
|
||||
)
|
||||
|
||||
add_executable(echoTest
|
||||
echoTest.cxx
|
||||
AppSubsystem.cxx
|
||||
EchoTestConfig.cxx
|
||||
${INCLUDES}
|
||||
)
|
||||
|
||||
target_include_directories(echoTest PRIVATE ${GSTREAMERMM_1_0_INCLUDE_DIRS})
|
||||
target_link_libraries(echoTest dum gstreamerutils)
|
||||
|
||||
install(TARGETS echoTest DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
|
||||
66
src/libs/resiprocate/apps/echoTest/EchoTestConfig.cxx
Normal file
66
src/libs/resiprocate/apps/echoTest/EchoTestConfig.cxx
Normal file
@@ -0,0 +1,66 @@
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
#include "EchoTestConfig.hxx"
|
||||
|
||||
#include "AppSubsystem.hxx"
|
||||
|
||||
#define RESIPROCATE_SUBSYSTEM AppSubsystem::ECHOTEST
|
||||
|
||||
using namespace std;
|
||||
using namespace resip;
|
||||
using namespace echotest;
|
||||
|
||||
EchoTestConfig::EchoTestConfig()
|
||||
{
|
||||
}
|
||||
|
||||
EchoTestConfig::~EchoTestConfig()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
EchoTestConfig::printHelpText(int argc, char **argv)
|
||||
{
|
||||
cout << "Command line format is:" << endl;
|
||||
cout << " " << removePath(argv[0]) << " [<ConfigFilename>] [--<ConfigValueName>=<ConfigValue>] [--<ConfigValueName>=<ConfigValue>] ..." << endl;
|
||||
cout << "Sample Command lines:" << endl;
|
||||
cout << " " << removePath(argv[0]) << " echoTest.config --IPAddress=192.168.1.100 --SIPUri=sip:1000@myproxy.com --Password=123" << endl;
|
||||
}
|
||||
|
||||
/* ====================================================================
|
||||
*
|
||||
* Copyright 2021, Daniel Pocock https://danielpocock.com
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. Neither the name of the author(s) nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* ====================================================================
|
||||
*
|
||||
*
|
||||
*/
|
||||
66
src/libs/resiprocate/apps/echoTest/EchoTestConfig.hxx
Normal file
66
src/libs/resiprocate/apps/echoTest/EchoTestConfig.hxx
Normal file
@@ -0,0 +1,66 @@
|
||||
#if !defined(ECHOTESTCONFIG_HXX)
|
||||
#define ECHOTESTCONFIG_HXX
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <map>
|
||||
#include <rutil/ConfigParse.hxx>
|
||||
#include <rutil/Data.hxx>
|
||||
#include <rutil/Log.hxx>
|
||||
#include <rutil/BaseException.hxx>
|
||||
#include <resip/stack/SipConfigParse.hxx>
|
||||
|
||||
namespace echotest {
|
||||
|
||||
class EchoTestConfig : public resip::SipConfigParse
|
||||
{
|
||||
public:
|
||||
|
||||
EchoTestConfig();
|
||||
virtual ~EchoTestConfig();
|
||||
|
||||
void printHelpText(int argc, char **argv);
|
||||
using resip::ConfigParse::getConfigValue;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
|
||||
/* ====================================================================
|
||||
*
|
||||
* Copyright 2021, Daniel Pocock https://danielpocock.com
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. Neither the name of the author(s) nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* ====================================================================
|
||||
*
|
||||
*
|
||||
*/
|
||||
57
src/libs/resiprocate/apps/echoTest/README.md
Normal file
57
src/libs/resiprocate/apps/echoTest/README.md
Normal file
@@ -0,0 +1,57 @@
|
||||
|
||||
# Introduction
|
||||
|
||||
Voice and video echo test
|
||||
|
||||
Demonstrates how to use GStreamer C++ bindings (GStreamerMM project)
|
||||
with reSIProcate.
|
||||
|
||||
Currently supports regular RTP devices by using the GStreamer rtpbin element.
|
||||
https://gstreamer.freedesktop.org/documentation/rtpmanager/rtpbin.html
|
||||
|
||||
Could be easily adapted for WebRTC using the GStreamer webrtcbin element.
|
||||
https://gstreamer.freedesktop.org/documentation/webrtc/index.html
|
||||
http://blog.nirbheek.in/2018/02/gstreamer-webrtc.html
|
||||
|
||||
See the configuration file for individual options. In particular, you
|
||||
can select one of these pipelines either through the configuration
|
||||
file or by using the name of the pipeline as the SIP user address,
|
||||
for example, dialing sip:h264v@192.168.1.10 will select h264v
|
||||
|
||||
h264avx - use libav decode and x264 encode
|
||||
h264v - use VAAPI decode/encode
|
||||
h264o - use openh264 decode and openh264 encode
|
||||
h264m - use libav decode and openh264 encode
|
||||
vp8 - use the vp8decode and vp8encode
|
||||
|
||||
# Help and feedback
|
||||
|
||||
https://list.resiprocate.org/mailman/listinfo/resiprocate-users
|
||||
mailto:resiprocate-users@resiprocate.org
|
||||
|
||||
# Dependencies
|
||||
|
||||
GStreamer and plugins
|
||||
https://gstreamer.freedesktop.org/
|
||||
License: LGPL
|
||||
Note: GPL and/or patent restrictions apply to some optional plugins
|
||||
Debian/Ubuntu packages: https://packages.qa.debian.org/gstreamer1.0
|
||||
Fedora/RHEL packages: https://src.fedoraproject.org/rpms/gstreamer1
|
||||
|
||||
GStreamerMM (C++ bindings)
|
||||
https://wiki.gnome.org/Projects/gstreamermm
|
||||
License: LGPL 2.1
|
||||
Debian/Ubuntu packages: https://packages.qa.debian.org/gstreamermm-1.0
|
||||
Fedora/RHEL packages: https://src.fedoraproject.org/rpms/gstreamermm
|
||||
|
||||
# Optional dependencies
|
||||
|
||||
gst-kurento-plugins (for the vp8parse element)
|
||||
https://github.com/KurentoLegacy/gst-kurento-plugins
|
||||
License: LGPL 2.1
|
||||
|
||||
OpenH264
|
||||
http://www.openh264.org/
|
||||
Note: it is necessary to rebuild gst-plugins-bad after install OpenH264
|
||||
|
||||
|
||||
89
src/libs/resiprocate/apps/echoTest/echoTest.config
Normal file
89
src/libs/resiprocate/apps/echoTest/echoTest.config
Normal file
@@ -0,0 +1,89 @@
|
||||
########################################################
|
||||
# echoTest configuration file
|
||||
########################################################
|
||||
|
||||
########################################################
|
||||
# Logging settings
|
||||
########################################################
|
||||
|
||||
# Logging Type: syslog|cerr|cout|file
|
||||
LoggingType = file
|
||||
|
||||
# For syslog, also specify the facility, default is LOG_DAEMON
|
||||
SyslogFacility = LOG_DAEMON
|
||||
|
||||
# Logging level: NONE|CRIT|ERR|WARNING|INFO|DEBUG|STACK
|
||||
LogLevel = STACK
|
||||
|
||||
# Log Filename
|
||||
# The following templates can be used in the filename:
|
||||
# {timestamp} - the number of seconds since the UNIX epoch
|
||||
# {pid} - the PID of the process
|
||||
LogFilename = echoTest.log
|
||||
|
||||
# Log message structure: Unstructured or JSON_CEE
|
||||
#LogMessageStructure = Unstructured
|
||||
LogMessageStructure = JSON_CEE
|
||||
|
||||
# Log file Max Bytes. This setting is only applicable when LoggingType is set to file.
|
||||
LogFileMaxBytes = 0
|
||||
|
||||
# Log file Max Lines
|
||||
LogFileMaxLines = 0
|
||||
|
||||
# Instance name to be shown in logs, very useful when multiple instances
|
||||
# logging to syslog concurrently
|
||||
# If unspecified, no instance name is logged
|
||||
#LoggingInstanceName = echoTest-dev
|
||||
|
||||
# Specify the HOMER SIP capture server hostname
|
||||
# If CaptureHost is commented/not defined, there is no default value and
|
||||
# echoTest doesn't attempt to send any HEP packets.
|
||||
#CaptureHost = localhost
|
||||
|
||||
# Specify the HOMER SIP capture server UDP port
|
||||
# If not defined, the default value, 9060, is used
|
||||
#CapturePort = 9060
|
||||
|
||||
# Specify the HOMER Capture Agent ID
|
||||
# The default value is 2002
|
||||
CaptureAgentID = 2002
|
||||
|
||||
########################################################
|
||||
# Transport settings
|
||||
########################################################
|
||||
|
||||
# Local IP Address to bind SIP transports to.
|
||||
# In general the IP address to bind to is queried from the host OS.This switch allows specification
|
||||
# of the IP address for OS's that cannot be queried, or for machines that have mulitple NICs.
|
||||
IPAddress = 127.0.0.1
|
||||
|
||||
# Local port number to use for SIP messaging over TCP - 0 to disable
|
||||
TCPPort = 12010
|
||||
|
||||
# Local port number to use for SIP messaging over UDP - 0 to disable
|
||||
UDPPort = 12010
|
||||
|
||||
# Default decoder / encoder pipeline to select if not specified in
|
||||
# the URI of an incoming call.
|
||||
DefaultPipelineId = h264avx
|
||||
|
||||
# Local port number to start allocating from for RTP media
|
||||
MediaPortStart = 8002
|
||||
|
||||
# URI of a proxy server to use a SIP outbound proxy.
|
||||
# By default echoTest does not use an outbound proxy. Use this switch to route all
|
||||
# outbound, out-of-dialog requests through a fixed proxy despite the destination URI.
|
||||
OutboundProxyUri =
|
||||
|
||||
# Whether to register with a SIP proxy
|
||||
Register = false
|
||||
|
||||
# This option is used to specify the SIP URI for this instance of echoTest. echoTest uses
|
||||
# this setting (-ip is not specified) in order to find the regisration server. If
|
||||
# nothing is specified, then the default of sip:UAS@<ipaddress> will be used.
|
||||
#SIPUri =
|
||||
|
||||
# SIP password of this SIP user
|
||||
# Use this switch in cases where the proxy digest challenges sip messaging.
|
||||
Password =
|
||||
920
src/libs/resiprocate/apps/echoTest/echoTest.cxx
Normal file
920
src/libs/resiprocate/apps/echoTest/echoTest.cxx
Normal file
@@ -0,0 +1,920 @@
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <regex>
|
||||
#include <sstream>
|
||||
#include <thread>
|
||||
#include <time.h>
|
||||
#include <utility>
|
||||
|
||||
#include "resip/stack/SdpContents.hxx"
|
||||
#include "resip/stack/PlainContents.hxx"
|
||||
#include "resip/stack/SipMessage.hxx"
|
||||
#include "resip/stack/ShutdownMessage.hxx"
|
||||
#include "resip/stack/SipStack.hxx"
|
||||
#include "resip/stack/HEPSipMessageLoggingHandler.hxx"
|
||||
#include "resip/dum/ClientAuthManager.hxx"
|
||||
#include "resip/dum/ClientInviteSession.hxx"
|
||||
#include "resip/dum/ClientRegistration.hxx"
|
||||
#include "resip/dum/DialogUsageManager.hxx"
|
||||
#include "resip/dum/DumShutdownHandler.hxx"
|
||||
#include "resip/dum/InviteSessionHandler.hxx"
|
||||
#include "resip/dum/MasterProfile.hxx"
|
||||
#include "resip/dum/RegistrationHandler.hxx"
|
||||
#include "resip/dum/ServerInviteSession.hxx"
|
||||
#include "resip/dum/ServerOutOfDialogReq.hxx"
|
||||
#include "resip/dum/OutOfDialogHandler.hxx"
|
||||
#include "resip/dum/AppDialog.hxx"
|
||||
#include "resip/dum/AppDialogSet.hxx"
|
||||
#include "resip/dum/AppDialogSetFactory.hxx"
|
||||
#include "rutil/Log.hxx"
|
||||
#include "rutil/Logger.hxx"
|
||||
#include "rutil/Random.hxx"
|
||||
#include "rutil/WinLeakCheck.hxx"
|
||||
#include "media/gstreamer/GStreamerUtils.hxx"
|
||||
#include "media/gstreamer/GstRtpManager.hxx"
|
||||
#include "media/gstreamer/GstRtpSession.hxx"
|
||||
#include "rutil/ServerProcess.hxx"
|
||||
#include "rutil/hep/HepAgent.hxx"
|
||||
|
||||
#include <gstreamermm.h>
|
||||
#include <glibmm/main.h>
|
||||
|
||||
#include "EchoTestConfig.hxx"
|
||||
|
||||
#define RESIPROCATE_SUBSYSTEM Subsystem::TEST
|
||||
|
||||
using namespace echotest;
|
||||
//using namespace resipgst;
|
||||
using namespace Gst;
|
||||
using namespace Glib;
|
||||
using namespace resip;
|
||||
using namespace std;
|
||||
|
||||
Data myIP;
|
||||
|
||||
class GstThread
|
||||
{
|
||||
public:
|
||||
GstThread()
|
||||
{
|
||||
main_loop = Glib::MainLoop::create();
|
||||
mThread = make_shared<thread>([this](){
|
||||
InfoLog(<<"GstThread starting");
|
||||
main_loop->run();
|
||||
});
|
||||
}
|
||||
|
||||
virtual ~GstThread()
|
||||
{
|
||||
InfoLog(<<"GstThread stopping");
|
||||
if(main_loop)
|
||||
{
|
||||
main_loop->quit();
|
||||
}
|
||||
InfoLog(<<"GstThread destroyed");
|
||||
}
|
||||
|
||||
private:
|
||||
Glib::RefPtr<Glib::MainLoop> main_loop;
|
||||
shared_ptr<thread> mThread;
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Classes that provide the mapping between Application Data and DUM
|
||||
// dialogs/dialogsets
|
||||
//
|
||||
// The DUM layer creates an AppDialog/AppDialogSet object for inbound/outbound
|
||||
// SIP Request that results in Dialog creation.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
class TestAppDialog : public AppDialog
|
||||
{
|
||||
public:
|
||||
TestAppDialog(HandleManager& ham, Data &SampleAppData, shared_ptr<resipgst::GstRtpManager> rTPManager)
|
||||
: AppDialog(ham),
|
||||
mSampleAppData(SampleAppData),
|
||||
mRtpSession(make_shared<resipgst::GstRtpSession>(*rTPManager, false)) // FIXME isWebRTC
|
||||
{
|
||||
InfoLog(<< mSampleAppData << ": TestAppDialog: created.");
|
||||
}
|
||||
virtual ~TestAppDialog()
|
||||
{
|
||||
InfoLog(<< mSampleAppData << ": TestAppDialog: destroyed.");
|
||||
}
|
||||
|
||||
bool
|
||||
isWebRTCSession()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
onMediaSourceAdded(const RefPtr<Pad>& pad)
|
||||
{
|
||||
Glib::ustring padName = pad->get_name();
|
||||
DebugLog(<<"onMediaSourceAdded: on-pad-added, padName: " << padName << " stream ID: " << pad->get_stream_id().raw());
|
||||
if(pad->get_direction() == PAD_SRC)
|
||||
{
|
||||
RefPtr<Caps> caps = pad->get_current_caps();
|
||||
MediaTypeName mediaTypeName = deduceKeyForPadName(padName);
|
||||
int streamId = getStreamIdFromPadName(padName);
|
||||
if(streamId < 0)
|
||||
{
|
||||
ErrLog(<<"unable to find encoder for " << padName);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto sink = mRtpSession->getOutgoingPads()[streamId];
|
||||
|
||||
if(!sink)
|
||||
{
|
||||
ErrLog(<<"no encoder configured for stream " << streamId);
|
||||
return;
|
||||
}
|
||||
|
||||
bool loopback = !isWebRTCSession();
|
||||
|
||||
if(sink->is_linked())
|
||||
{
|
||||
StackLog(<<"unlinking existing src");
|
||||
RefPtr<Pad> src = sink->get_peer();
|
||||
if(src->unlink(sink))
|
||||
{
|
||||
loopback = true;
|
||||
|
||||
// FIXME - destroy the unlinked test source
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
ErrLog(<<"failed to unlink existing src");
|
||||
resip_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
if(loopback)
|
||||
{
|
||||
StackLog(<<"attempting loopback configuration");
|
||||
RefPtr<Element> proxy;
|
||||
if(mediaTypeName == "video")
|
||||
{
|
||||
proxy = Gst::VideoConvert::create();
|
||||
}
|
||||
else if(mediaTypeName == "audio")
|
||||
{
|
||||
proxy = Gst::AudioConvert::create();
|
||||
}
|
||||
else
|
||||
{
|
||||
CritLog(<<"unexpected streamKey: " << mediaTypeName);
|
||||
resip_assert(0);
|
||||
}
|
||||
mPipeline->add(proxy);
|
||||
// convert->link(enc);
|
||||
proxy->get_static_pad("src")->link(sink);
|
||||
pad->link(proxy->get_static_pad("sink"));
|
||||
proxy->sync_state_with_parent();
|
||||
|
||||
mMediaBin->sync_state_with_parent();
|
||||
|
||||
DebugLog(<<"completed connection from incoming to outgoing stream");
|
||||
}
|
||||
else
|
||||
{
|
||||
// FIXME - disconnect the test sources and do the loopback
|
||||
ErrLog(<<"not doing loopback for WebRTC");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
StackLog(<<"not a source pad: " << padName);
|
||||
}
|
||||
}
|
||||
|
||||
void prepareStream(unsigned int streamId, bool loopbackMode)
|
||||
{
|
||||
resipgst::GstRtpSession::CapsVector capsV = mRtpSession->getOutgoingCaps();
|
||||
RefPtr<Caps> caps;
|
||||
if(capsV.size() > streamId && capsV[streamId])
|
||||
{
|
||||
caps = capsV[streamId];
|
||||
}
|
||||
|
||||
if(!caps)
|
||||
{
|
||||
ErrLog(<<"caps not specified");
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<Pad> mediaSink = mRtpSession->getOutgoingPads()[streamId];
|
||||
|
||||
MediaTypeName mediaTypeName = getMediaTypeName(caps);
|
||||
resip_assert(mediaTypeName.size());
|
||||
|
||||
if(loopbackMode)
|
||||
{
|
||||
// FIXME - move this logic to GstRtpSession
|
||||
//sendCapsEvent(bin, caps);
|
||||
}
|
||||
else
|
||||
{
|
||||
RefPtr<Element> testSrc = buildTestSource(mediaTypeName);
|
||||
resip_assert(testSrc);
|
||||
mPipeline->add(testSrc);
|
||||
testSrc->get_static_pad("src")->link(mediaSink);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Data mSampleAppData;
|
||||
shared_ptr<resipgst::GstRtpSession> mRtpSession;
|
||||
|
||||
Glib::RefPtr<Gst::Pipeline> mPipeline;
|
||||
Glib::RefPtr<Gst::Element> mMediaBin;
|
||||
Glib::RefPtr<Gst::Element> mRtpTransportElement;
|
||||
|
||||
};
|
||||
|
||||
class TestAppDialogSet : public AppDialogSet
|
||||
{
|
||||
public:
|
||||
TestAppDialogSet(DialogUsageManager& dum, Data SampleAppData, shared_ptr<resipgst::GstRtpManager> rTPManager) : AppDialogSet(dum), mSampleAppData(SampleAppData), mRtpManager(rTPManager)
|
||||
{
|
||||
InfoLog(<< mSampleAppData << ": TestAppDialogSet: created.");
|
||||
}
|
||||
virtual ~TestAppDialogSet()
|
||||
{
|
||||
InfoLog(<< mSampleAppData << ": TestAppDialogSet: destroyed.");
|
||||
}
|
||||
virtual AppDialog* createAppDialog(const SipMessage& msg)
|
||||
{
|
||||
return new TestAppDialog(mDum, mSampleAppData, mRtpManager);
|
||||
}
|
||||
virtual std::shared_ptr<UserProfile> selectUASUserProfile(const SipMessage& msg)
|
||||
{
|
||||
InfoLog(<< mSampleAppData << ": TestAppDialogSet: UAS UserProfile requested for msg: " << msg.brief());
|
||||
return mDum.getMasterUserProfile();
|
||||
}
|
||||
Data mSampleAppData;
|
||||
shared_ptr<resipgst::GstRtpManager> mRtpManager;
|
||||
};
|
||||
|
||||
class TestAppDialogSetFactory : public AppDialogSetFactory
|
||||
{
|
||||
public:
|
||||
TestAppDialogSetFactory(shared_ptr<resipgst::GstRtpManager> rTPManager) : mRtpManager(rTPManager) {}
|
||||
|
||||
virtual AppDialogSet* createAppDialogSet(DialogUsageManager& dum, const SipMessage& msg)
|
||||
{ return new TestAppDialogSet(dum, Data("UAS") + Data("(") + getMethodName(msg.header(h_RequestLine).getMethod()) + Data(")"), mRtpManager); }
|
||||
// For a UAS the testAppDialogSet will be created by DUM using this function. If you want to set
|
||||
// Application Data, then one approach is to wait for onNewSession(ServerInviteSessionHandle ...)
|
||||
// to be called, then use the ServerInviteSessionHandle to get at the AppDialogSet or AppDialog,
|
||||
// then cast to your derived class and set the desired application data.
|
||||
|
||||
private:
|
||||
shared_ptr<resipgst::GstRtpManager> mRtpManager;
|
||||
};
|
||||
|
||||
|
||||
// Generic InviteSessionHandler
|
||||
class TestInviteSessionHandler : public InviteSessionHandler, public ClientRegistrationHandler, public OutOfDialogHandler
|
||||
{
|
||||
public:
|
||||
Data name;
|
||||
bool registered;
|
||||
ClientRegistrationHandle registerHandle;
|
||||
|
||||
TestInviteSessionHandler(const Data& n) : name(n), registered(false)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~TestInviteSessionHandler()
|
||||
{
|
||||
}
|
||||
|
||||
virtual void onSuccess(ClientRegistrationHandle h, const SipMessage& response)
|
||||
{
|
||||
registerHandle = h;
|
||||
resip_assert(registerHandle.isValid());
|
||||
InfoLog(<< name << ": ClientRegistration-onSuccess - " << response.brief());
|
||||
registered = true;
|
||||
}
|
||||
|
||||
virtual void onFailure(ClientRegistrationHandle, const SipMessage& msg)
|
||||
{
|
||||
InfoLog(<< name << ": ClientRegistration-onFailure - " << msg.brief());
|
||||
throw; // Ungracefully end
|
||||
}
|
||||
|
||||
virtual void onRemoved(ClientRegistrationHandle, const SipMessage& response)
|
||||
{
|
||||
InfoLog(<< name << ": ClientRegistration-onRemoved");
|
||||
}
|
||||
|
||||
virtual int onRequestRetry(ClientRegistrationHandle, int retrySeconds, const SipMessage& response)
|
||||
{
|
||||
InfoLog(<< name << ": ClientRegistration-onRequestRetry (" << retrySeconds << ") - " << response.brief());
|
||||
return -1;
|
||||
}
|
||||
|
||||
virtual void onNewSession(ClientInviteSessionHandle, InviteSession::OfferAnswerType oat, const SipMessage& msg)
|
||||
{
|
||||
InfoLog(<< name << ": ClientInviteSession-onNewSession - " << msg.brief());
|
||||
}
|
||||
|
||||
virtual void onNewSession(ServerInviteSessionHandle, InviteSession::OfferAnswerType oat, const SipMessage& msg)
|
||||
{
|
||||
InfoLog(<< name << ": ServerInviteSession-onNewSession - " << msg.brief());
|
||||
}
|
||||
|
||||
virtual void onFailure(ClientInviteSessionHandle, const SipMessage& msg)
|
||||
{
|
||||
InfoLog(<< name << ": ClientInviteSession-onFailure - " << msg.brief());
|
||||
}
|
||||
|
||||
virtual void onProvisional(ClientInviteSessionHandle, const SipMessage& msg)
|
||||
{
|
||||
InfoLog(<< name << ": ClientInviteSession-onProvisional - " << msg.brief());
|
||||
}
|
||||
|
||||
virtual void onConnected(ClientInviteSessionHandle, const SipMessage& msg)
|
||||
{
|
||||
InfoLog(<< name << ": ClientInviteSession-onConnected - " << msg.brief());
|
||||
}
|
||||
|
||||
virtual void onStaleCallTimeout(ClientInviteSessionHandle handle)
|
||||
{
|
||||
InfoLog(<< name << ": ClientInviteSession-onStaleCallTimeout");
|
||||
}
|
||||
|
||||
virtual void onConnected(InviteSessionHandle, const SipMessage& msg)
|
||||
{
|
||||
InfoLog(<< name << ": InviteSession-onConnected - " << msg.brief());
|
||||
}
|
||||
|
||||
virtual void onRedirected(ClientInviteSessionHandle, const SipMessage& msg)
|
||||
{
|
||||
InfoLog(<< name << ": ClientInviteSession-onRedirected - " << msg.brief());
|
||||
}
|
||||
|
||||
virtual void onTerminated(InviteSessionHandle, InviteSessionHandler::TerminatedReason reason, const SipMessage* msg)
|
||||
{
|
||||
InfoLog(<< name << ": InviteSession-onTerminated - " << msg->brief());
|
||||
resip_assert(0); // This is overriden in UAS and UAC specific handlers
|
||||
}
|
||||
|
||||
virtual void onAnswer(InviteSessionHandle, const SipMessage& msg, const SdpContents& sdp)
|
||||
{
|
||||
InfoLog(<< name << ": InviteSession-onAnswer(SDP)");
|
||||
//sdp->encode(cout);
|
||||
}
|
||||
|
||||
virtual void onOffer(InviteSessionHandle is, const SipMessage& msg, const SdpContents& sdp)
|
||||
{
|
||||
InfoLog(<< name << ": InviteSession-onOffer(SDP)");
|
||||
//sdp->encode(cout);
|
||||
}
|
||||
|
||||
virtual void onEarlyMedia(ClientInviteSessionHandle, const SipMessage& msg, const SdpContents& sdp)
|
||||
{
|
||||
InfoLog(<< name << ": InviteSession-onEarlyMedia(SDP)");
|
||||
//sdp->encode(cout);
|
||||
}
|
||||
|
||||
virtual void onOfferRequired(InviteSessionHandle, const SipMessage& msg)
|
||||
{
|
||||
InfoLog(<< name << ": InviteSession-onOfferRequired - " << msg.brief());
|
||||
}
|
||||
|
||||
virtual void onOfferRejected(InviteSessionHandle, const SipMessage* msg)
|
||||
{
|
||||
InfoLog(<< name << ": InviteSession-onOfferRejected");
|
||||
}
|
||||
|
||||
virtual void onRefer(InviteSessionHandle, ServerSubscriptionHandle, const SipMessage& msg)
|
||||
{
|
||||
InfoLog(<< name << ": InviteSession-onRefer - " << msg.brief());
|
||||
}
|
||||
|
||||
virtual void onReferAccepted(InviteSessionHandle, ClientSubscriptionHandle, const SipMessage& msg)
|
||||
{
|
||||
InfoLog(<< name << ": InviteSession-onReferAccepted - " << msg.brief());
|
||||
}
|
||||
|
||||
virtual void onReferRejected(InviteSessionHandle, const SipMessage& msg)
|
||||
{
|
||||
InfoLog(<< name << ": InviteSession-onReferRejected - " << msg.brief());
|
||||
}
|
||||
|
||||
virtual void onReferNoSub(InviteSessionHandle, const SipMessage& msg)
|
||||
{
|
||||
InfoLog(<< name << ": InviteSession-onReferNoSub - " << msg.brief());
|
||||
}
|
||||
|
||||
virtual void onInfo(InviteSessionHandle, const SipMessage& msg)
|
||||
{
|
||||
InfoLog(<< name << ": InviteSession-onInfo - " << msg.brief());
|
||||
}
|
||||
|
||||
virtual void onInfoSuccess(InviteSessionHandle, const SipMessage& msg)
|
||||
{
|
||||
InfoLog(<< name << ": InviteSession-onInfoSuccess - " << msg.brief());
|
||||
}
|
||||
|
||||
virtual void onInfoFailure(InviteSessionHandle, const SipMessage& msg)
|
||||
{
|
||||
InfoLog(<< name << ": InviteSession-onInfoFailure - " << msg.brief());
|
||||
}
|
||||
|
||||
virtual void onMessage(InviteSessionHandle, const SipMessage& msg)
|
||||
{
|
||||
InfoLog(<< name << ": InviteSession-onMessage - " << msg.brief());
|
||||
}
|
||||
|
||||
virtual void onMessageSuccess(InviteSessionHandle, const SipMessage& msg)
|
||||
{
|
||||
InfoLog(<< name << ": InviteSession-onMessageSuccess - " << msg.brief());
|
||||
}
|
||||
|
||||
virtual void onMessageFailure(InviteSessionHandle, const SipMessage& msg)
|
||||
{
|
||||
InfoLog(<< name << ": InviteSession-onMessageFailure - " << msg.brief());
|
||||
}
|
||||
|
||||
virtual void onForkDestroyed(ClientInviteSessionHandle)
|
||||
{
|
||||
InfoLog(<< name << ": ClientInviteSession-onForkDestroyed");
|
||||
}
|
||||
|
||||
// Out-of-Dialog Callbacks
|
||||
virtual void onSuccess(ClientOutOfDialogReqHandle, const SipMessage& successResponse)
|
||||
{
|
||||
InfoLog(<< name << ": ClientOutOfDialogReq-onSuccess - " << successResponse.brief());
|
||||
}
|
||||
virtual void onFailure(ClientOutOfDialogReqHandle, const SipMessage& errorResponse)
|
||||
{
|
||||
InfoLog(<< name << ": ClientOutOfDialogReq-onFailure - " << errorResponse.brief());
|
||||
}
|
||||
virtual void onReceivedRequest(ServerOutOfDialogReqHandle ood, const SipMessage& request)
|
||||
{
|
||||
InfoLog(<< name << ": ServerOutOfDialogReq-onReceivedRequest - " << request.brief());
|
||||
// Add SDP to response here if required
|
||||
InfoLog(<< name << ": Sending 200 response to OPTIONS.");
|
||||
ood->send(ood->answerOptions());
|
||||
}
|
||||
};
|
||||
|
||||
class TestUas : public TestInviteSessionHandler
|
||||
{
|
||||
|
||||
public:
|
||||
bool done;
|
||||
bool requestedOffer;
|
||||
|
||||
typedef std::map<DialogId, shared_ptr<GstThread>> MediaThreads;
|
||||
MediaThreads mMediaThreads;
|
||||
|
||||
std::shared_ptr<HepAgent> mHepAgent;
|
||||
|
||||
TestUas(const Data& pipelineId, std::shared_ptr<HepAgent> agent)
|
||||
: TestInviteSessionHandler("UAS"),
|
||||
done(false),
|
||||
requestedOffer(false),
|
||||
mHepAgent(agent)
|
||||
{
|
||||
}
|
||||
|
||||
~TestUas()
|
||||
{
|
||||
}
|
||||
|
||||
using TestInviteSessionHandler::onNewSession;
|
||||
virtual void
|
||||
onNewSession(ServerInviteSessionHandle sis, InviteSession::OfferAnswerType oat, const SipMessage& msg)
|
||||
{
|
||||
InfoLog(<< name << ": ServerInviteSession-onNewSession - " << msg.brief());
|
||||
InfoLog(<< name << ": Sending 180 response.");
|
||||
mSis = sis;
|
||||
sis->provisional(180);
|
||||
}
|
||||
|
||||
virtual void onTerminated(InviteSessionHandle is, InviteSessionHandler::TerminatedReason reason, const SipMessage* msg)
|
||||
{
|
||||
InfoLog(<< name << ": InviteSession-onTerminated - ");
|
||||
mMediaThreads.erase(is->getDialogId());
|
||||
done = true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
onGstBusMessage(const RefPtr<Gst::Bus>&, const RefPtr<Gst::Message>& message)
|
||||
{
|
||||
switch(message->get_message_type())
|
||||
{
|
||||
case Gst::MESSAGE_EOS:
|
||||
ErrLog(<< "End of stream");
|
||||
//main_loop->quit(); // FIXME - from echoTest
|
||||
return false;
|
||||
case Gst::MESSAGE_ERROR:
|
||||
{
|
||||
Glib::Error error;
|
||||
std::string debug_message;
|
||||
RefPtr<MessageError>::cast_static(message)->parse(error, debug_message);
|
||||
ErrLog(<< "Error: " << error.what() << std::endl << debug_message);
|
||||
// main_loop->quit(); // FIXME - from echoTest
|
||||
return false;
|
||||
}
|
||||
case Gst::MESSAGE_STATE_CHANGED:
|
||||
DebugLog(<< "state changed");
|
||||
return true;
|
||||
case Gst::MESSAGE_NEW_CLOCK:
|
||||
DebugLog(<< "new clock");
|
||||
return true;
|
||||
case Gst::MESSAGE_STREAM_STATUS:
|
||||
DebugLog(<< "stream status");
|
||||
return true;
|
||||
|
||||
default:
|
||||
ErrLog(<<"unhandled Bus Message: " << message->get_message_type());
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void onOffer(InviteSessionHandle is, const SipMessage& msg, const SdpContents& sdp)
|
||||
{
|
||||
InfoLog(<< name << ": InviteSession-onOffer(SDP)");
|
||||
TestAppDialog* d = dynamic_cast<TestAppDialog*>(is->getAppDialog().get());
|
||||
const Data& callee = msg.header(h_RequestLine).uri().user();
|
||||
InfoLog(<< name << ": call is for: " << callee);
|
||||
std::shared_ptr<SdpContents> offer(dynamic_cast<SdpContents*>(sdp.clone()));
|
||||
shared_ptr<SdpContents> mSdp = d->mRtpSession->buildAnswer(offer);
|
||||
//sdp->encode(cout);
|
||||
InfoLog(<< name << ": starting GStreamer media thread");
|
||||
d->mRtpSession->initHomer(msg.header(h_CallId).value(), mHepAgent);
|
||||
|
||||
if(d->mPipeline)
|
||||
{
|
||||
DebugLog(<<"mPipeline already exists");
|
||||
}
|
||||
else
|
||||
{
|
||||
d->mPipeline = Gst::Pipeline::create();
|
||||
d->mMediaBin = d->mRtpSession->getMediaBin();
|
||||
resip_assert(d->mMediaBin);
|
||||
d->mRtpTransportElement = d->mRtpSession->getRtpTransportBin();
|
||||
resip_assert(d->mRtpTransportElement);
|
||||
d->mPipeline->add(d->mMediaBin);
|
||||
d->mRtpSession->initOutgoingBins();
|
||||
bool isWebRTC = d->isWebRTCSession();
|
||||
bool loopbackMode = !isWebRTC;
|
||||
|
||||
unsigned int streamCount = d->mRtpSession->getOutgoingCaps().size();
|
||||
if(streamCount == 0)
|
||||
{
|
||||
// sending an offer
|
||||
InfoLog(<<"creating streams for SDP offer");
|
||||
// FIXME - these are currently hardcoded in GstRtpSession::buildOffer
|
||||
//mRtpSession->addStream(Gst::Caps::create_from_string(GST_RTP_CAPS_PCMA));
|
||||
//mRtpSession->addStream(Gst::Caps::create_from_string(GST_RTP_CAPS_H264));
|
||||
}
|
||||
else
|
||||
{
|
||||
// received an offer
|
||||
InfoLog(<<"creating streams for SDP answer");
|
||||
for(unsigned int streamId = 0; streamId < streamCount; streamId++)
|
||||
{
|
||||
d->prepareStream(streamId, loopbackMode);
|
||||
}
|
||||
}
|
||||
// FIXME
|
||||
RefPtr<Bus> bus = d->mPipeline->get_bus();
|
||||
bus->add_watch(sigc::mem_fun(*this, &TestUas::onGstBusMessage));
|
||||
|
||||
DebugLog(<<"mPipeline and mRtpTransportElement created");
|
||||
|
||||
DebugLog(<<"going to STATE_READY");
|
||||
d->mPipeline->set_state(STATE_READY);
|
||||
|
||||
d->mMediaBin->signal_pad_added().connect(sigc::mem_fun(*d, &TestAppDialog::onMediaSourceAdded));
|
||||
|
||||
DebugLog(<<"going to STATE_PLAYING");
|
||||
StateChangeReturn ret = d->mPipeline->set_state(STATE_PLAYING);
|
||||
if (ret == STATE_CHANGE_FAILURE)
|
||||
{
|
||||
ErrLog(<<"pipeline fail");
|
||||
d->mPipeline.reset();
|
||||
is->reject(606);
|
||||
return;
|
||||
}
|
||||
|
||||
d->mRtpSession->onPlaying(); // FIXME - use a signal in GstRtpSession
|
||||
|
||||
mSdp = make_shared<SdpContents>(*d->mRtpSession->getLocalSdp());
|
||||
|
||||
mMediaThreads[is->getDialogId()] = make_shared<GstThread>();
|
||||
}
|
||||
|
||||
|
||||
InfoLog(<< name << ": Sending 200 response with SDP answer.");
|
||||
is->provideAnswer(*mSdp);
|
||||
mSis->accept();
|
||||
}
|
||||
|
||||
virtual void onOfferRequired(InviteSessionHandle is, const SipMessage& msg)
|
||||
{
|
||||
InfoLog(<< name << ": InviteSession-onOfferRequired - " << msg.brief());
|
||||
shared_ptr<SdpContents> mSdp;
|
||||
if(!mSdp)
|
||||
{
|
||||
TestAppDialog* d = dynamic_cast<TestAppDialog*>(is->getAppDialog().get());
|
||||
mSdp = d->mRtpSession->buildOffer(true, true);
|
||||
}
|
||||
is->provideOffer(*mSdp);
|
||||
}
|
||||
|
||||
virtual void onConnected(InviteSessionHandle is, const SipMessage& msg)
|
||||
{
|
||||
InfoLog(<< name << ": InviteSession-onConnected - " << msg.brief());
|
||||
|
||||
// At this point no NIT should have been sent
|
||||
resip_assert(!is->getLastSentNITRequest());
|
||||
}
|
||||
|
||||
virtual void onInfoSuccess(InviteSessionHandle is, const SipMessage& msg)
|
||||
{
|
||||
InfoLog(<< name << ": InviteSession-onInfoSuccess - " << msg.brief());
|
||||
}
|
||||
|
||||
virtual void onMessage(InviteSessionHandle is, const SipMessage& msg)
|
||||
{
|
||||
InfoLog(<< name << ": InviteSession-onMessage - " << msg.brief());
|
||||
|
||||
is->acceptNIT();
|
||||
}
|
||||
|
||||
// Normal people wouldn't put this functionality in the handler
|
||||
// it's a kludge for this test for right now
|
||||
void hangup()
|
||||
{
|
||||
if (mSis.isValid())
|
||||
{
|
||||
InfoLog(<< name << ": Sending BYE.");
|
||||
mSis->end();
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
private:
|
||||
ServerInviteSessionHandle mSis;
|
||||
};
|
||||
|
||||
class TestShutdownHandler : public DumShutdownHandler
|
||||
{
|
||||
public:
|
||||
TestShutdownHandler(const Data& n) : name(n), dumShutDown(false) { }
|
||||
virtual ~TestShutdownHandler(){}
|
||||
|
||||
Data name;
|
||||
bool dumShutDown;
|
||||
virtual void onDumCanBeDeleted()
|
||||
{
|
||||
InfoLog(<< name << ": onDumCanBeDeleted.");
|
||||
dumShutDown = true;
|
||||
}
|
||||
};
|
||||
|
||||
class EchoTestServer : public resip::ServerProcess
|
||||
{
|
||||
private:
|
||||
SipStack* stackUas;
|
||||
DialogUsageManager* dumUas;
|
||||
|
||||
std::shared_ptr<resipgst::GstRtpManager> mRtpManager;
|
||||
|
||||
public:
|
||||
EchoTestServer() :
|
||||
stackUas(nullptr),
|
||||
dumUas(nullptr)
|
||||
{
|
||||
};
|
||||
|
||||
~EchoTestServer()
|
||||
{
|
||||
delete dumUas;
|
||||
delete stackUas;
|
||||
};
|
||||
|
||||
int
|
||||
main (int argc, char** argv)
|
||||
{
|
||||
installSignalHandler();
|
||||
|
||||
Data defaultConfigFilename("echoTest.config");
|
||||
EchoTestConfig echoTestConfig;
|
||||
try
|
||||
{
|
||||
echoTestConfig.parseConfig(argc, argv, defaultConfigFilename);
|
||||
}
|
||||
catch(std::exception& e)
|
||||
{
|
||||
ErrLog(<< "Exception parsing configuration: " << e.what());
|
||||
return -1;
|
||||
}
|
||||
|
||||
Log::initialize(echoTestConfig, argv[0]);
|
||||
|
||||
Data captureHost = echoTestConfig.getConfigData("CaptureHost", "");
|
||||
int capturePort = echoTestConfig.getConfigInt("CapturePort", 9060);
|
||||
int captureAgentID = echoTestConfig.getConfigInt("CaptureAgentID", 2002);
|
||||
|
||||
// For GStreamer
|
||||
const char* _argv[] = { argv[0], "--gst-debug", "5", NULL };
|
||||
int _argc = 3;
|
||||
char** __argv = (char**)_argv;
|
||||
// FIXME: are there C++ equivalents of these functions?
|
||||
gst_debug_remove_log_function (gst_debug_log_default);
|
||||
gst_debug_add_log_function(gst2resip_log_function, nullptr, nullptr);
|
||||
Gst::init(_argc, __argv);
|
||||
|
||||
#if defined(WIN32) && defined(_DEBUG) && defined(LEAK_CHECK)
|
||||
FindMemoryLeaks fml;
|
||||
{
|
||||
#endif
|
||||
bool doReg = echoTestConfig.getConfigBool("Register", false);
|
||||
Data uasPasswd;
|
||||
int uasUdpPort = echoTestConfig.getConfigInt("UDPPort", 12010);
|
||||
int uasTcpPort = echoTestConfig.getConfigInt("TCPPort", 12010);
|
||||
Uri outboundUri = echoTestConfig.getConfigUri("OutboundProxyUri", Uri());
|
||||
bool useOutbound = (outboundUri != Uri());
|
||||
myIP = echoTestConfig.getConfigData("IPAddress", "127.0.0.1");
|
||||
|
||||
uasPasswd = echoTestConfig.getConfigData("Password", Data::Empty);
|
||||
|
||||
//set up UAS
|
||||
stackUas = new SipStack();
|
||||
std::shared_ptr<HepAgent> agent;
|
||||
if(!captureHost.empty())
|
||||
{
|
||||
agent = std::make_shared<HepAgent>(captureHost, capturePort, captureAgentID);
|
||||
stackUas->setTransportSipMessageLoggingHandler(std::make_shared<HEPSipMessageLoggingHandler>(agent));
|
||||
}
|
||||
|
||||
dumUas = new DialogUsageManager(*stackUas);
|
||||
NameAddr uasAor;
|
||||
Uri uasContact;
|
||||
if(uasUdpPort)
|
||||
{
|
||||
stackUas->addTransport(UDP, uasUdpPort);
|
||||
uasContact = Uri("sip:" + myIP + ":" + Data(uasUdpPort));
|
||||
}
|
||||
if(uasTcpPort)
|
||||
{
|
||||
stackUas->addTransport(TCP, uasTcpPort);
|
||||
if(uasContact.port() == 0)
|
||||
{
|
||||
uasContact = Uri("sip:" + myIP + ":" + Data(uasTcpPort) + ";transport=tcp");
|
||||
}
|
||||
}
|
||||
if(uasContact.port() == 0)
|
||||
{
|
||||
uasContact = Uri("sip:" + myIP);
|
||||
ErrLog(<<"no port for uasContact");
|
||||
resip_assert(0);
|
||||
}
|
||||
uasAor = echoTestConfig.getConfigNameAddr("SIPUri", NameAddr("sip:UAS@" + myIP + ":" + Data(uasContact.port())));
|
||||
|
||||
auto uasMasterProfile = std::make_shared<MasterProfile>();
|
||||
std::unique_ptr<ClientAuthManager> uasAuth(new ClientAuthManager);
|
||||
dumUas->setMasterProfile(uasMasterProfile);
|
||||
dumUas->setClientAuthManager(std::move(uasAuth));
|
||||
uasMasterProfile->setOverrideHostAndPort(uasContact);
|
||||
|
||||
if(doReg)
|
||||
{
|
||||
dumUas->getMasterProfile()->setDigestCredential(uasAor.uri().host(), uasAor.uri().user(), uasPasswd);
|
||||
}
|
||||
if(useOutbound)
|
||||
{
|
||||
dumUas->getMasterProfile()->setOutboundProxy(outboundUri);
|
||||
dumUas->getMasterProfile()->addSupportedOptionTag(Token(Symbols::Outbound));
|
||||
}
|
||||
|
||||
dumUas->getMasterProfile()->setDefaultFrom(uasAor);
|
||||
dumUas->getMasterProfile()->addSupportedMethod(INFO);
|
||||
dumUas->getMasterProfile()->addSupportedMethod(MESSAGE);
|
||||
dumUas->getMasterProfile()->addSupportedMimeType(INFO, PlainContents::getStaticType());
|
||||
dumUas->getMasterProfile()->addSupportedMimeType(MESSAGE, PlainContents::getStaticType());
|
||||
dumUas->getMasterProfile()->setDefaultRegistrationTime(70);
|
||||
|
||||
Data pipelineId = echoTestConfig.getConfigData("DefaultPipelineId", "h264avx");
|
||||
int mediaPortStart = echoTestConfig.getConfigInt("MediaPortStart", 8002);
|
||||
|
||||
// FIXME - IPv6 needed
|
||||
mRtpManager = make_shared<resipgst::GstRtpManager>(myIP, mediaPortStart, mediaPortStart + 100);
|
||||
mRtpManager->setApplicationName("reSIProcate GStreamer Echo Test");
|
||||
|
||||
TestUas uas(pipelineId, agent);
|
||||
dumUas->setClientRegistrationHandler(&uas);
|
||||
dumUas->setInviteSessionHandler(&uas);
|
||||
dumUas->addOutOfDialogHandler(OPTIONS, &uas);
|
||||
|
||||
std::unique_ptr<AppDialogSetFactory> uas_dsf(new TestAppDialogSetFactory(mRtpManager));
|
||||
dumUas->setAppDialogSetFactory(std::move(uas_dsf));
|
||||
|
||||
if (!doReg)
|
||||
{
|
||||
uas.registered = true;
|
||||
}
|
||||
|
||||
TestShutdownHandler uasShutdownHandler("UAS");
|
||||
|
||||
mainLoop();
|
||||
|
||||
// FIXME: shutdown the DUM and SipStack
|
||||
|
||||
#if defined(WIN32) && defined(_DEBUG) && defined(LEAK_CHECK)
|
||||
} // FindMemoryLeaks fml
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
doWait()
|
||||
{
|
||||
stackUas->process(50);
|
||||
}
|
||||
|
||||
void
|
||||
onLoop()
|
||||
{
|
||||
while(dumUas->process());
|
||||
}
|
||||
|
||||
void
|
||||
onReload()
|
||||
{
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
EchoTestServer proc;
|
||||
return proc.main(argc, argv);
|
||||
}
|
||||
|
||||
/* ====================================================================
|
||||
* The Vovida Software License, Version 1.0
|
||||
*
|
||||
* Copyright (c) 2022, Software Freedom Institute https://softwarefreedom.institute
|
||||
* Copyright (c) 2021-2022, Daniel Pocock https://danielpocock.com
|
||||
* Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. The names "VOCAL", "Vovida Open Communication Application Library",
|
||||
* and "Vovida Open Communication Application Library (VOCAL)" must
|
||||
* not be used to endorse or promote products derived from this
|
||||
* software without prior written permission. For written
|
||||
* permission, please contact vocal@vovida.org.
|
||||
*
|
||||
* 4. Products derived from this software may not be called "VOCAL", nor
|
||||
* may "VOCAL" appear in their name, without prior written
|
||||
* permission of Vovida Networks, Inc.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
|
||||
* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
|
||||
* NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
|
||||
* IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* ====================================================================
|
||||
*
|
||||
* This software consists of voluntary contributions made by Vovida
|
||||
* Networks, Inc. and many individuals on behalf of Vovida Networks,
|
||||
* Inc. For more snformation on Vovida Networks, Inc., please see
|
||||
* <http://www.vovida.org/>.
|
||||
*
|
||||
*/
|
||||
9
src/libs/resiprocate/apps/ichat-gw/.gitignore
vendored
Normal file
9
src/libs/resiprocate/apps/ichat-gw/.gitignore
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
|
||||
/Makefile.in
|
||||
/Makefile
|
||||
/.deps
|
||||
/.libs
|
||||
/.dirstamp
|
||||
|
||||
/ichat-gw
|
||||
|
||||
214
src/libs/resiprocate/apps/ichat-gw/AddressTranslator.cxx
Normal file
214
src/libs/resiprocate/apps/ichat-gw/AddressTranslator.cxx
Normal file
@@ -0,0 +1,214 @@
|
||||
|
||||
#include "rutil/Logger.hxx"
|
||||
#include "rutil/ParseBuffer.hxx"
|
||||
|
||||
#include "AppSubsystem.hxx"
|
||||
#include "AddressTranslator.hxx"
|
||||
#include "rutil/WinLeakCheck.hxx"
|
||||
|
||||
#define RESIPROCATE_SUBSYSTEM AppSubsystem::GATEWAY
|
||||
|
||||
using namespace gateway;
|
||||
using namespace resip;
|
||||
using namespace std;
|
||||
|
||||
namespace gateway
|
||||
{
|
||||
|
||||
AddressTranslator::AddressTranslator()
|
||||
{
|
||||
}
|
||||
|
||||
AddressTranslator::~AddressTranslator()
|
||||
{
|
||||
// Destroy all of the filters
|
||||
for(FilterOpList::iterator it = mFilterOperators.begin(); it != mFilterOperators.end(); it++)
|
||||
{
|
||||
if ( it->preq )
|
||||
{
|
||||
delete it->preq;
|
||||
it->preq = 0;
|
||||
}
|
||||
}
|
||||
mFilterOperators.clear();
|
||||
}
|
||||
|
||||
void
|
||||
AddressTranslator::addTranslation(const resip::Data& matchingPattern,
|
||||
const resip::Data& rewriteExpression)
|
||||
{
|
||||
InfoLog( << "Add translation " << matchingPattern << " -> " << rewriteExpression);
|
||||
|
||||
FilterOp filter;
|
||||
filter.mMatchingPattern = matchingPattern;
|
||||
filter.mRewriteExpression = rewriteExpression;
|
||||
|
||||
if( !filter.mMatchingPattern.empty() )
|
||||
{
|
||||
// Note: this code originally used the PCRE (Perl Compatible) regular expression library. The ECMAScript standard is a subset
|
||||
// of the Perl regular expression syntax. Posix regular expression syntax is quite a bit different (ie: std::regex_contacts::basic or
|
||||
// std::regex_contacts::extended). To be as backwards compatible with existing regular expressions as possible, we want to
|
||||
// use the EMCAScript syntax.
|
||||
const std::regex_constants::syntax_option_type flags = std::regex_constants::ECMAScript;
|
||||
if( filter.mRewriteExpression.find("$") == Data::npos )
|
||||
{
|
||||
flags |= std::regex_constants::nosubs;
|
||||
}
|
||||
try
|
||||
{
|
||||
filter.preq = new std::regex(filter.mMatchingPattern.c_str(), flags);
|
||||
}
|
||||
catch (std::regex_error& ex)
|
||||
{
|
||||
delete filter.preq;
|
||||
ErrLog( << "Translation has invalid match expression: "
|
||||
<< filter.mMatchingPattern );
|
||||
filter.preq = 0;
|
||||
}
|
||||
}
|
||||
mFilterOperators.push_back( filter );
|
||||
}
|
||||
|
||||
void
|
||||
AddressTranslator::removeTranslation(const resip::Data& matchingPattern )
|
||||
{
|
||||
FilterOpList::iterator it = mFilterOperators.begin();
|
||||
while ( it != mFilterOperators.end() )
|
||||
{
|
||||
if ( it->mMatchingPattern == matchingPattern )
|
||||
{
|
||||
FilterOpList::iterator i = it;
|
||||
it++;
|
||||
if ( i->preq )
|
||||
{
|
||||
delete i->preq;
|
||||
i->preq = 0;
|
||||
}
|
||||
mFilterOperators.erase(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
AddressTranslator::translate(const resip::Data& address, resip::Data& translation, bool failIfNoRule)
|
||||
{
|
||||
bool rc=false;
|
||||
DebugLog( << "Translating "<< address);
|
||||
|
||||
for (FilterOpList::iterator it = mFilterOperators.begin();
|
||||
it != mFilterOperators.end(); it++)
|
||||
{
|
||||
Data rewrite = it->mRewriteExpression;
|
||||
Data& match = it->mMatchingPattern;
|
||||
if ( it->preq )
|
||||
{
|
||||
std::cmatch matches;
|
||||
|
||||
// Note: Using regex_search instead of regex_match, so that we don't need to fully match
|
||||
// the string, this is backwards compatible with the previous regexec PCRE implementation
|
||||
if(!std::regex_search(address.c_str(), matches, *it->preq))
|
||||
{
|
||||
// did not match
|
||||
DebugLog( << " Skipped translation "<< address << " did not match " << match );
|
||||
continue;
|
||||
}
|
||||
|
||||
DebugLog( << " Matched translation "<< address << " matched " << match );
|
||||
translation = rewrite;
|
||||
rc=true;
|
||||
if ( rewrite.find("$") != Data::npos )
|
||||
{
|
||||
for ( int i=1; i<matches.size(); i++)
|
||||
{
|
||||
Data subExp(matches[i]);
|
||||
DebugLog( << " subExpression[" <<i <<"]="<< subExp );
|
||||
|
||||
Data result;
|
||||
{
|
||||
DataStream s(result);
|
||||
|
||||
ParseBuffer pb(translation);
|
||||
|
||||
while (true)
|
||||
{
|
||||
const char* a = pb.position();
|
||||
pb.skipToChars( Data("$") + char('0'+i) );
|
||||
if ( pb.eof() )
|
||||
{
|
||||
s << pb.data(a);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
s << pb.data(a);
|
||||
pb.skipN(2);
|
||||
s << subExp;
|
||||
}
|
||||
}
|
||||
s.flush();
|
||||
}
|
||||
translation = result;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
translation = rewrite;
|
||||
rc = true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If we didn't find a translation and we are not suppossed to fail, then just return address
|
||||
if(!rc && !failIfNoRule)
|
||||
{
|
||||
rc = true;
|
||||
translation = address;
|
||||
}
|
||||
|
||||
InfoLog( << "Translated "<< address << " to " << translation);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* ====================================================================
|
||||
|
||||
Copyright (c) 2009, SIP Spectrum, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of SIP Spectrum nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
==================================================================== */
|
||||
|
||||
74
src/libs/resiprocate/apps/ichat-gw/AddressTranslator.hxx
Normal file
74
src/libs/resiprocate/apps/ichat-gw/AddressTranslator.hxx
Normal file
@@ -0,0 +1,74 @@
|
||||
#if !defined(AddressTranslator_hxx)
|
||||
#define AddressTranslator_hxx
|
||||
|
||||
#include <list>
|
||||
|
||||
#include <regex>
|
||||
|
||||
namespace gateway
|
||||
{
|
||||
|
||||
class AddressTranslator
|
||||
{
|
||||
public:
|
||||
AddressTranslator();
|
||||
~AddressTranslator();
|
||||
|
||||
void addTranslation(const resip::Data& matchingPattern,
|
||||
const resip::Data& rewriteExpression);
|
||||
|
||||
void removeTranslation(const resip::Data& matchingPattern);
|
||||
|
||||
bool translate(const resip::Data& address, resip::Data& translation, bool failIfNoRule=false);
|
||||
|
||||
private:
|
||||
class FilterOp
|
||||
{
|
||||
public:
|
||||
resip::Data mMatchingPattern;
|
||||
resip::Data mRewriteExpression;
|
||||
std::regex *preq;
|
||||
};
|
||||
|
||||
typedef std::list<FilterOp> FilterOpList;
|
||||
FilterOpList mFilterOperators;
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* ====================================================================
|
||||
|
||||
Copyright (c) 2009, SIP Spectrum, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of SIP Spectrum nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
==================================================================== */
|
||||
|
||||
38
src/libs/resiprocate/apps/ichat-gw/AppSubsystem.cxx
Normal file
38
src/libs/resiprocate/apps/ichat-gw/AppSubsystem.cxx
Normal file
@@ -0,0 +1,38 @@
|
||||
#include "AppSubsystem.hxx"
|
||||
|
||||
AppSubsystem AppSubsystem::GATEWAY("GATEWAY");
|
||||
|
||||
/* ====================================================================
|
||||
|
||||
Copyright (c) 2009, SIP Spectrum, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of SIP Spectrum nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
==================================================================== */
|
||||
|
||||
61
src/libs/resiprocate/apps/ichat-gw/AppSubsystem.hxx
Normal file
61
src/libs/resiprocate/apps/ichat-gw/AppSubsystem.hxx
Normal file
@@ -0,0 +1,61 @@
|
||||
#if !defined(AppSubsystem_hxx)
|
||||
#define AppSubsystem_hxx
|
||||
|
||||
#include <iostream>
|
||||
#include <rutil/Subsystem.hxx>
|
||||
|
||||
/**
|
||||
This class is used in the logging subsystem to identify
|
||||
logging messages generated from the iChat Gateway.
|
||||
|
||||
Author: Scott Godin (sgodin AT SipSpectrum DOT com)
|
||||
*/
|
||||
|
||||
class AppSubsystem : public resip::Subsystem
|
||||
{
|
||||
public:
|
||||
// Add new systems below
|
||||
static AppSubsystem GATEWAY;
|
||||
|
||||
private:
|
||||
explicit AppSubsystem(const char* rhs) : resip::Subsystem(rhs) {};
|
||||
explicit AppSubsystem(const resip::Data& rhs);
|
||||
AppSubsystem& operator=(const resip::Data& rhs);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/* ====================================================================
|
||||
|
||||
Copyright (c) 2009, SIP Spectrum, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of SIP Spectrum nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
==================================================================== */
|
||||
|
||||
1699
src/libs/resiprocate/apps/ichat-gw/B2BSession.cxx
Normal file
1699
src/libs/resiprocate/apps/ichat-gw/B2BSession.cxx
Normal file
File diff suppressed because it is too large
Load Diff
176
src/libs/resiprocate/apps/ichat-gw/B2BSession.hxx
Normal file
176
src/libs/resiprocate/apps/ichat-gw/B2BSession.hxx
Normal file
@@ -0,0 +1,176 @@
|
||||
#if !defined(B2BSession_hxx)
|
||||
#define B2BSession_hxx
|
||||
|
||||
#include <rutil/Log.hxx>
|
||||
#include <resip/dum/DialogUsageManager.hxx>
|
||||
#include <resip/dum/InviteSessionHandler.hxx>
|
||||
#include <resip/dum/DialogSetHandler.hxx>
|
||||
#include <resip/dum/AppDialogSet.hxx>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace gateway
|
||||
{
|
||||
|
||||
class Server;
|
||||
class IChatIPPortData;
|
||||
|
||||
typedef unsigned int B2BSessionHandle;
|
||||
|
||||
class B2BSession : public resip::AppDialogSet
|
||||
{
|
||||
public:
|
||||
B2BSession(Server& server, bool hasDialogSet=true);
|
||||
virtual ~B2BSession();
|
||||
|
||||
virtual void end();
|
||||
|
||||
void setPeer(B2BSession* peer);
|
||||
B2BSession* getPeer();
|
||||
void stealPeer(B2BSession* victimSession);
|
||||
|
||||
B2BSessionHandle getB2BSessionHandle() const { return mHandle; }
|
||||
|
||||
void initiateIChatCallRequest(const std::string& to, const std::string& from);
|
||||
bool createNewPeer(const resip::Uri& destinationUri, const resip::NameAddr& from, const resip::SdpContents *sdp);
|
||||
void startIChatCall(const resip::Uri& destinationUri, const resip::NameAddr& from, const resip::SdpContents *sdp);
|
||||
void startSIPCall(const resip::Uri& destinationUri, const resip::NameAddr& from, const resip::SdpContents *sdp);
|
||||
bool checkIChatCallMatch(const resip::SipMessage& msg);
|
||||
|
||||
// iChat call notifications from Jabber Component
|
||||
void notifyIChatCallCancelled();
|
||||
void notifyIChatCallProceeding(const std::string& to);
|
||||
void notifyIChatCallFailed(unsigned int statusCode);
|
||||
void continueIChatCall(const std::string& remoteIPPortListBlob);
|
||||
void timeoutIChatCall();
|
||||
|
||||
// IPC messages for Jabber Component
|
||||
void initiateIChatCall();
|
||||
void cancelIChatCall();
|
||||
void proceedingIChatCall();
|
||||
void acceptIChatCall();
|
||||
void rejectIChatCall();
|
||||
|
||||
protected:
|
||||
friend class Server;
|
||||
|
||||
virtual std::shared_ptr<resip::UserProfile> selectUASUserProfile(const resip::SipMessage& msg);
|
||||
|
||||
// Invite Session Handler /////////////////////////////////////////////////////
|
||||
virtual void onNewSession(resip::ClientInviteSessionHandle h, resip::InviteSession::OfferAnswerType oat, const resip::SipMessage& msg);
|
||||
virtual void onNewSession(resip::ServerInviteSessionHandle h, resip::InviteSession::OfferAnswerType oat, const resip::SipMessage& msg);
|
||||
virtual void onFailure(resip::ClientInviteSessionHandle h, const resip::SipMessage& msg);
|
||||
virtual void onEarlyMedia(resip::ClientInviteSessionHandle, const resip::SipMessage&, const resip::SdpContents&);
|
||||
virtual void onProvisional(resip::ClientInviteSessionHandle, const resip::SipMessage& msg);
|
||||
virtual void onConnected(resip::ClientInviteSessionHandle h, const resip::SipMessage& msg);
|
||||
virtual void onConnected(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
||||
virtual void onStaleCallTimeout(resip::ClientInviteSessionHandle);
|
||||
virtual void onTerminated(resip::InviteSessionHandle h, resip::InviteSessionHandler::TerminatedReason reason, const resip::SipMessage* msg);
|
||||
virtual void onRedirected(resip::ClientInviteSessionHandle, const resip::SipMessage& msg);
|
||||
virtual void onAnswer(resip::InviteSessionHandle, const resip::SipMessage& msg, const resip::SdpContents&);
|
||||
virtual void onOffer(resip::InviteSessionHandle handle, const resip::SipMessage& msg, const resip::SdpContents& offer);
|
||||
virtual void onOfferRequired(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
||||
virtual void onOfferRejected(resip::InviteSessionHandle, const resip::SipMessage* msg);
|
||||
virtual void onOfferRequestRejected(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
||||
virtual void onRemoteSdpChanged(resip::InviteSessionHandle, const resip::SipMessage& msg, const resip::SdpContents& sdp);
|
||||
virtual void onInfo(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
||||
virtual void onInfoSuccess(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
||||
virtual void onInfoFailure(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
||||
virtual void onRefer(resip::InviteSessionHandle, resip::ServerSubscriptionHandle, const resip::SipMessage& msg);
|
||||
virtual void onReferAccepted(resip::InviteSessionHandle, resip::ClientSubscriptionHandle, const resip::SipMessage& msg);
|
||||
virtual void onReferRejected(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
||||
virtual bool doReferNoSub(const resip::SipMessage& msg);
|
||||
virtual void onReferNoSub(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
||||
virtual void onMessage(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
||||
virtual void onMessageSuccess(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
||||
virtual void onMessageFailure(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
||||
virtual void onForkDestroyed(resip::ClientInviteSessionHandle);
|
||||
|
||||
// DialogSetHandler //////////////////////////////////////////////
|
||||
virtual void onTrying(resip::AppDialogSetHandle, const resip::SipMessage& msg);
|
||||
virtual void onNonDialogCreatingProvisional(resip::AppDialogSetHandle, const resip::SipMessage& msg);
|
||||
|
||||
// ClientSubscriptionHandler ///////////////////////////////////////////////////
|
||||
virtual void onUpdatePending(resip::ClientSubscriptionHandle h, const resip::SipMessage& notify, bool outOfOrder);
|
||||
virtual void onUpdateActive(resip::ClientSubscriptionHandle h, const resip::SipMessage& notify, bool outOfOrder);
|
||||
virtual void onUpdateExtension(resip::ClientSubscriptionHandle, const resip::SipMessage& notify, bool outOfOrder);
|
||||
virtual void onTerminated(resip::ClientSubscriptionHandle h, const resip::SipMessage* notify);
|
||||
virtual void onNewSubscription(resip::ClientSubscriptionHandle h, const resip::SipMessage& notify);
|
||||
virtual int onRequestRetry(resip::ClientSubscriptionHandle h, int retryMinimum, const resip::SipMessage& notify);
|
||||
|
||||
private:
|
||||
bool buildLocalOffer(resip::SdpContents& sdp);
|
||||
bool buildLocalAnswer(resip::SdpContents& sdp);
|
||||
bool provideLocalAnswer(void);
|
||||
void endPeer();
|
||||
bool isUACConnected();
|
||||
bool isStaleFork(const resip::DialogId& dialogId);
|
||||
void fixupSdp(const resip::SdpContents& origSdp, resip::SdpContents& fixedSdp);
|
||||
unsigned int mapRejectionCodeForIChat(unsigned int statusCode);
|
||||
|
||||
Server& mServer;
|
||||
bool mHasDialogSet;
|
||||
resip::DialogUsageManager& mDum;
|
||||
B2BSession* mPeer;
|
||||
resip::InviteSessionHandle mInviteSessionHandle;
|
||||
B2BSessionHandle mHandle;
|
||||
resip::AppDialogSetHandle mReferringAppDialogSet;
|
||||
|
||||
// State information
|
||||
resip::DialogId mUACConnectedDialogId;
|
||||
bool mWaitingOfferFromPeer;
|
||||
bool mWaitingAnswerFromPeer;
|
||||
bool mWaitingNitAnswerFromPeer;
|
||||
bool mAnchorMedia;
|
||||
unsigned short mMediaRelayPort;
|
||||
|
||||
// IChat specific endpoint info
|
||||
bool mIChatEndpoint;
|
||||
bool mIChatWaitingToAccept;
|
||||
bool mIChatWaitingToProceed;
|
||||
bool mIChatWaitingToContinue;
|
||||
resip::Uri mIChatDestination;
|
||||
resip::NameAddr mIChatFrom;
|
||||
resip::SdpContents* mIChatSdp;
|
||||
std::string mIChatCallToJID;
|
||||
std::string mIChatCallFromJID;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* ====================================================================
|
||||
|
||||
Copyright (c) 2009, SIP Spectrum, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of SIP Spectrum nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
==================================================================== */
|
||||
|
||||
40
src/libs/resiprocate/apps/ichat-gw/CMakeLists.txt
Normal file
40
src/libs/resiprocate/apps/ichat-gw/CMakeLists.txt
Normal file
@@ -0,0 +1,40 @@
|
||||
set(INCLUDES
|
||||
AddressTranslator.hxx
|
||||
AppSubsystem.hxx
|
||||
B2BSession.hxx
|
||||
ConfigParser.hxx
|
||||
IChatGatewayCmds.hxx
|
||||
IChatIPPortData.hxx
|
||||
IPCThread.hxx
|
||||
MediaRelay.hxx
|
||||
MediaRelayPort.hxx
|
||||
Server.hxx
|
||||
SipRegistration.hxx
|
||||
Thread.hxx
|
||||
Version.hxx
|
||||
)
|
||||
|
||||
add_executable(ichat-gw
|
||||
AddressTranslator.cxx
|
||||
AppSubsystem.cxx
|
||||
B2BSession.cxx
|
||||
ConfigParser.cxx
|
||||
ichat-gw.cxx
|
||||
IChatIPPortData.cxx
|
||||
IPCThread.cxx
|
||||
MediaRelay.cxx
|
||||
MediaRelayPort.cxx
|
||||
Server.cxx
|
||||
SipRegistration.cxx
|
||||
Thread.cxx
|
||||
${INCLUDES}
|
||||
)
|
||||
|
||||
target_include_directories(ichat-gw PRIVATE ${PCRE_INCLUDE_DIRS})
|
||||
target_link_libraries(ichat-gw PUBLIC dum ${PCRE_LIBRARIES})
|
||||
|
||||
install(TARGETS ichat-gw DESTINATION ${CMAKE_INSTALL_SBINDIR})
|
||||
|
||||
install_and_preserve_hierarchy(${CMAKE_INSTALL_INCLUDEDIR}/ichat-gw ${INCLUDES})
|
||||
|
||||
add_subdirectory(jabberconnector)
|
||||
443
src/libs/resiprocate/apps/ichat-gw/ConfigParser.cxx
Executable file
443
src/libs/resiprocate/apps/ichat-gw/ConfigParser.cxx
Executable file
@@ -0,0 +1,443 @@
|
||||
#include "ConfigParser.hxx"
|
||||
#include "Server.hxx"
|
||||
|
||||
#include "AppSubsystem.hxx"
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <iterator>
|
||||
|
||||
#include <rutil/DnsUtil.hxx>
|
||||
#include <rutil/Log.hxx>
|
||||
#include <rutil/Logger.hxx>
|
||||
#include <rutil/WinLeakCheck.hxx>
|
||||
|
||||
using namespace gateway;
|
||||
using namespace resip;
|
||||
using namespace std;
|
||||
|
||||
#define RESIPROCATE_SUBSYSTEM AppSubsystem::GATEWAY
|
||||
|
||||
namespace gateway
|
||||
{
|
||||
|
||||
ConfigParser::ConfigParser(int argc, char** argv) :
|
||||
// Defaults
|
||||
mSipPort(5070),
|
||||
mTlsPort(5071),
|
||||
mTlsDomain(DnsUtil::getLocalHostName()),
|
||||
mRegistrationTime(3600),
|
||||
mRegistrationRetryTime(120),
|
||||
mKeepAlives(true),
|
||||
mLogLevel("INFO"),
|
||||
mLogFilename("ichat-gw.log"),
|
||||
mLogFileMaxLines(50000), // 50000 is about 5M size
|
||||
mGatewayIPCPort(2078),
|
||||
mJabberConnectorIPCPort(2079),
|
||||
mHttpPort(5090),
|
||||
mHttpAuth(false),
|
||||
mHttpAuthPwd("admin"),
|
||||
mIChatProceedingTimeout(5000),
|
||||
mAlwaysRelayIChatMedia(true),
|
||||
mPreferIPv6(false),
|
||||
mSkipFirstIChatAddress(false),
|
||||
mMediaRelayPortRangeMin(8000),
|
||||
mMediaRelayPortRangeMax(9999),
|
||||
mJabberComponentPort(5275),
|
||||
mJabberServerPingDuration(60) // 1 min
|
||||
{
|
||||
// Parse config file first
|
||||
parseConfigFile("ichat-gw.config");
|
||||
|
||||
// Parse command line options
|
||||
// Note: command line overrides config file setting
|
||||
parseCommandLine(argc, argv);
|
||||
}
|
||||
|
||||
ConfigParser::~ConfigParser()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ConfigParser::parseCommandLine(int argc, char** argv)
|
||||
{
|
||||
// Loop through command line arguments and process them
|
||||
for(int i = 1; i < argc; i++)
|
||||
{
|
||||
Data commandName(argv[i]);
|
||||
|
||||
// Process all commandNames that don't take values
|
||||
if(isEqualNoCase(commandName, "-?") ||
|
||||
isEqualNoCase(commandName, "--?") ||
|
||||
isEqualNoCase(commandName, "--help") ||
|
||||
isEqualNoCase(commandName, "/?"))
|
||||
{
|
||||
cout << "Command line options are:" << endl;
|
||||
cout << " -a <IP Address> - bind SIP transports to this IP address" << endl;
|
||||
cout << " -d <DNS servers> - comma seperated list of DNS servers, overrides OS detected list" << endl;
|
||||
cout << " -gi <Gateway identity> - used in From header of click-to-call requests to initiator" << endl;
|
||||
cout << " -sp <port num> - local port number to use for SIP messaging (UDP/TCP)" << endl;
|
||||
cout << " -tp <port num> - local port number to use for TLS SIP messaging" << endl;
|
||||
cout << " -td <domain name> - domain name to use for TLS server connections" << endl;
|
||||
cout << " -nk - no keepalives, set this to disable sending of keepalives" << endl;
|
||||
cout << " -op <SIP URI> - URI of a proxy server to use a SIP outbound proxy" << endl;
|
||||
cout << " -l <NONE|CRIT|ERR|WARNING|INFO|DEBUG|STACK> - logging level" << endl;
|
||||
cout << endl;
|
||||
cout << "Sample Command line:" << endl;
|
||||
cout << "ichat-gw -a 192.168.1.100 -l DEBUG" << endl;
|
||||
exit(0);
|
||||
}
|
||||
else if(isEqualNoCase(commandName, "-nk"))
|
||||
{
|
||||
mKeepAlives = false;
|
||||
}
|
||||
else if(commandName.at(0) == '-')
|
||||
{
|
||||
commandName = commandName.substr(1); // Remove -
|
||||
|
||||
// Process commands that have values
|
||||
Data commandValue(i+1 < argc ? argv[i+1] : Data::Empty);
|
||||
if(commandValue.empty() || commandValue.at(0) == '-')
|
||||
{
|
||||
cerr << "Invalid command line parameters!" << endl;
|
||||
exit(-1);
|
||||
}
|
||||
i++; // increment argument
|
||||
|
||||
//cout << "Command Line Name='" << commandName << "' value='" << commandValue << "'" << endl;
|
||||
if(!processOption(commandName.lowercase(), commandValue))
|
||||
{
|
||||
cerr << "Invalid command line parameters!" << endl;
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cerr << "Invalid command line parameters!" << endl;
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ConfigParser::parseConfigFile(const Data& filename)
|
||||
{
|
||||
ifstream configFile(filename.c_str());
|
||||
|
||||
string sline;
|
||||
while(getline(configFile, sline))
|
||||
{
|
||||
Data line(sline);
|
||||
Data name;
|
||||
Data value;
|
||||
ParseBuffer pb(line);
|
||||
|
||||
pb.skipWhitespace();
|
||||
const char * anchor = pb.position();
|
||||
if(pb.eof() || *anchor == '#') continue; // if line is a comment or blank then skip it
|
||||
// Look for =
|
||||
pb.skipToOneOf("= \t");
|
||||
if(!pb.eof())
|
||||
{
|
||||
pb.data(name,anchor);
|
||||
if(*pb.position()!='=')
|
||||
{
|
||||
pb.skipToChar('=');
|
||||
}
|
||||
pb.skipChar('=');
|
||||
pb.skipWhitespace();
|
||||
anchor = pb.position();
|
||||
if(!pb.eof())
|
||||
{
|
||||
pb.skipToEnd();
|
||||
pb.data(value, anchor);
|
||||
}
|
||||
//cout << "Config file Name='" << name << "' value='" << value << "'" << endl;
|
||||
processOption(name.lowercase(), value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
ConfigParser::assignOnOffSetting(const Data& value, bool& setting)
|
||||
{
|
||||
if(value == "1" || value == "true" || value == "on" || value == "enable")
|
||||
{
|
||||
setting = true;
|
||||
return true;
|
||||
}
|
||||
else if(value == "0" || value == "false" || value == "off" || value == "disable")
|
||||
{
|
||||
setting = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
ConfigParser::processOption(const Data& name, const Data& value)
|
||||
{
|
||||
bool result = true;
|
||||
if(name == "a" || name == "ipaddress")
|
||||
{
|
||||
mAddress = value;
|
||||
}
|
||||
else if(name == "d" || name == "dnsservers")
|
||||
{
|
||||
if(!value.empty()) mDnsServers.clear(); // allow command line to override config file, since list is added to
|
||||
|
||||
// DNS Servers
|
||||
ParseBuffer pb(value);
|
||||
Data dnsServer;
|
||||
while(!value.empty() && !pb.eof())
|
||||
{
|
||||
pb.skipWhitespace();
|
||||
const char *start = pb.position();
|
||||
pb.skipToOneOf(ParseBuffer::Whitespace, ";,"); // allow white space
|
||||
pb.data(dnsServer, start);
|
||||
if(DnsUtil::isIpV4Address(dnsServer))
|
||||
{
|
||||
mDnsServers.push_back(Tuple(dnsServer, 0, UNKNOWN_TRANSPORT).toGenericIPAddress());
|
||||
}
|
||||
else
|
||||
{
|
||||
cerr << "Tried to add dns server, but invalid format: " << value << endl;
|
||||
result = false;
|
||||
}
|
||||
if(!pb.eof())
|
||||
{
|
||||
pb.skipChar();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(name == "gi" || name == "sipgatewayidentity")
|
||||
{
|
||||
result = assignNameAddr("sip gateway identity", value, mGatewayIdentity);
|
||||
}
|
||||
else if(name == "sp" || name == "udptcpport")
|
||||
{
|
||||
mSipPort = (unsigned short)value.convertUnsignedLong();
|
||||
}
|
||||
else if(name == "tp" || name == "tlsport")
|
||||
{
|
||||
mTlsPort = (unsigned short)value.convertUnsignedLong();
|
||||
}
|
||||
else if(name == "td" || name == "tlsdomain")
|
||||
{
|
||||
mTlsDomain = value;
|
||||
}
|
||||
else if(name == "keepalives")
|
||||
{
|
||||
assignOnOffSetting(value, mKeepAlives);
|
||||
}
|
||||
else if(name == "op" || name == "outboundproxy")
|
||||
{
|
||||
result = assignNameAddr("outbound proxy", value, mOutboundProxy);
|
||||
}
|
||||
else if(name == "registrationtime")
|
||||
{
|
||||
mRegistrationTime = value.convertUnsignedLong();
|
||||
}
|
||||
else if(name == "registrationretrytime")
|
||||
{
|
||||
mRegistrationRetryTime = value.convertUnsignedLong();
|
||||
}
|
||||
else if(name == "l" || name == "loglevel")
|
||||
{
|
||||
mLogLevel = value;
|
||||
}
|
||||
else if(name == "logfilename")
|
||||
{
|
||||
mLogFilename = value;
|
||||
}
|
||||
else if(name == "logfilemaxlines")
|
||||
{
|
||||
mLogFileMaxLines = value.convertUnsignedLong();
|
||||
}
|
||||
else if(name == "gatewayipcport")
|
||||
{
|
||||
mGatewayIPCPort = (unsigned short)value.convertUnsignedLong();
|
||||
}
|
||||
else if(name == "jabberconnectoripcport")
|
||||
{
|
||||
mJabberConnectorIPCPort = (unsigned short)value.convertUnsignedLong();
|
||||
}
|
||||
else if(name == "httpport")
|
||||
{
|
||||
mHttpPort = (unsigned short)value.convertUnsignedLong();
|
||||
}
|
||||
else if(name == "httpauth")
|
||||
{
|
||||
assignOnOffSetting(value, mHttpAuth);
|
||||
}
|
||||
else if(name == "httpauthpwd")
|
||||
{
|
||||
mHttpAuthPwd = value;
|
||||
}
|
||||
else if(name == "ichatproceedingtimeout")
|
||||
{
|
||||
mIChatProceedingTimeout = value.convertUnsignedLong();
|
||||
}
|
||||
else if(name == "alwaysrelayichatmedia")
|
||||
{
|
||||
assignOnOffSetting(value, mAlwaysRelayIChatMedia);
|
||||
}
|
||||
else if(name == "preferipv6")
|
||||
{
|
||||
assignOnOffSetting(value, mPreferIPv6);
|
||||
}
|
||||
else if(name == "skipfirstichataddress")
|
||||
{
|
||||
assignOnOffSetting(value, mSkipFirstIChatAddress);
|
||||
}
|
||||
else if(name == "codecidfilterlist")
|
||||
{
|
||||
ParseBuffer pb(value);
|
||||
Data codecId;
|
||||
while(!value.empty() && !pb.eof())
|
||||
{
|
||||
pb.skipWhitespace();
|
||||
const char *start = pb.position();
|
||||
pb.skipToOneOf(ParseBuffer::Whitespace, ";,"); // allow white space
|
||||
pb.data(codecId, start);
|
||||
mCodecIdFilterList.insert((unsigned short)codecId.convertUnsignedLong());
|
||||
if(!pb.eof())
|
||||
{
|
||||
pb.skipChar();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(name == "mediarelayportrangemin")
|
||||
{
|
||||
mMediaRelayPortRangeMin = (unsigned short)value.convertUnsignedLong();
|
||||
}
|
||||
else if(name == "mediarelayportrangemax")
|
||||
{
|
||||
mMediaRelayPortRangeMax = (unsigned short)value.convertUnsignedLong();
|
||||
}
|
||||
else if(name == "translationpattern")
|
||||
{
|
||||
mAddressTranslations.push_back(std::make_pair(value, Data::Empty));
|
||||
}
|
||||
else if(name == "translationoutput")
|
||||
{
|
||||
if(!mAddressTranslations.empty())
|
||||
{
|
||||
mAddressTranslations.back().second = value;
|
||||
}
|
||||
}
|
||||
else if(name == "jabberserver")
|
||||
{
|
||||
mJabberServer = value;
|
||||
}
|
||||
else if(name == "jabbercomponentname")
|
||||
{
|
||||
mJabberComponentName = value;
|
||||
}
|
||||
else if(name == "jabbercomponentpassword")
|
||||
{
|
||||
mJabberComponentPassword = value;
|
||||
}
|
||||
else if(name == "jabbercomponentport")
|
||||
{
|
||||
mJabberComponentPort = (unsigned short)value.convertUnsignedLong();
|
||||
}
|
||||
else if(name == "jabberserverpingduration")
|
||||
{
|
||||
mJabberServerPingDuration = value.convertUnsignedLong();
|
||||
}
|
||||
else if(name == "jabbercontrolusername")
|
||||
{
|
||||
mJabberControlUsername = value;
|
||||
}
|
||||
else if(name == "tlsdhparamsfilename")
|
||||
{
|
||||
mTLSDHParamsFilename = value;
|
||||
}
|
||||
else if(name == "tlscertificate")
|
||||
{
|
||||
mTLSCertificate = value;
|
||||
}
|
||||
else if(name == "tlsprivateKey")
|
||||
{
|
||||
mTLSPrivateKey = value;
|
||||
}
|
||||
else if(name == "tlsprivatekeypassphrase")
|
||||
{
|
||||
mTLSPrivateKeyPassPhrase = value;
|
||||
}
|
||||
else if(name == "ichatjabberconnectorpath")
|
||||
{
|
||||
mIchatJabberConnectorPath = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool
|
||||
ConfigParser::assignNameAddr(const Data& settingName, const Data& settingValue, NameAddr& nameAddr)
|
||||
{
|
||||
try
|
||||
{
|
||||
if(!settingValue.empty())
|
||||
{
|
||||
NameAddr tempNameAddr(settingValue);
|
||||
nameAddr = tempNameAddr;
|
||||
}
|
||||
}
|
||||
catch(resip::BaseException& e)
|
||||
{
|
||||
// Try adding sip: to address to see if it will be valid
|
||||
try
|
||||
{
|
||||
NameAddr tempNameAddr(Data("sip:" + settingValue));
|
||||
nameAddr = tempNameAddr;
|
||||
}
|
||||
catch(resip::BaseException&)
|
||||
{
|
||||
cerr << "Invalid " << settingName << " NameAddr format=" << settingValue << ": " << e << endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* ====================================================================
|
||||
|
||||
Copyright (c) 2009, SIP Spectrum, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of SIP Spectrum nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
==================================================================== */
|
||||
|
||||
110
src/libs/resiprocate/apps/ichat-gw/ConfigParser.hxx
Executable file
110
src/libs/resiprocate/apps/ichat-gw/ConfigParser.hxx
Executable file
@@ -0,0 +1,110 @@
|
||||
#if !defined(ConfigParser_hxx)
|
||||
#define ConfigParser_hxx
|
||||
|
||||
#include <list>
|
||||
#include <resip/dum/MasterProfile.hxx>
|
||||
#include <rutil/dns/DnsStub.hxx>
|
||||
#include <rutil/Log.hxx>
|
||||
|
||||
|
||||
namespace gateway
|
||||
{
|
||||
|
||||
class ConfigParser
|
||||
{
|
||||
public:
|
||||
ConfigParser(int argc, char** argv);
|
||||
virtual ~ConfigParser();
|
||||
|
||||
resip::Data mAddress;
|
||||
resip::DnsStub::NameserverList mDnsServers;
|
||||
resip::NameAddr mGatewayIdentity;
|
||||
unsigned short mSipPort;
|
||||
unsigned short mTlsPort;
|
||||
resip::Data mTlsDomain;
|
||||
resip::NameAddr mOutboundProxy;
|
||||
unsigned int mRegistrationTime;
|
||||
unsigned int mRegistrationRetryTime;
|
||||
bool mKeepAlives;
|
||||
resip::Data mLogLevel;
|
||||
resip::Data mLogFilename;
|
||||
unsigned int mLogFileMaxLines;
|
||||
unsigned short mGatewayIPCPort;
|
||||
unsigned short mJabberConnectorIPCPort;
|
||||
unsigned short mHttpPort;
|
||||
bool mHttpAuth;
|
||||
resip::Data mHttpAuthPwd;
|
||||
unsigned int mIChatProceedingTimeout;
|
||||
bool mAlwaysRelayIChatMedia;
|
||||
bool mPreferIPv6;
|
||||
bool mSkipFirstIChatAddress; // (for testing): skipping the first IPV4 NAT mapped address (on systems with one interface) causes the local address to be used
|
||||
typedef std::set<unsigned short> CodecIdList;
|
||||
CodecIdList mCodecIdFilterList;
|
||||
unsigned short mMediaRelayPortRangeMin;
|
||||
unsigned short mMediaRelayPortRangeMax;
|
||||
typedef std::list<std::pair<resip::Data,resip::Data> > TranslationList;
|
||||
TranslationList mAddressTranslations;
|
||||
|
||||
// Jabber specific settings
|
||||
resip::Data mJabberServer;
|
||||
resip::Data mJabberComponentName;
|
||||
resip::Data mJabberComponentPassword;
|
||||
unsigned short mJabberComponentPort;
|
||||
unsigned int mJabberServerPingDuration;
|
||||
resip::Data mJabberControlUsername;
|
||||
|
||||
// TLS specific settings
|
||||
resip::Data mTLSDHParamsFilename;
|
||||
resip::Data mTLSCertificate;
|
||||
resip::Data mTLSPrivateKey;
|
||||
resip::Data mTLSPrivateKeyPassPhrase;
|
||||
|
||||
// iChat Jabber Connector file path
|
||||
resip::Data mIchatJabberConnectorPath;
|
||||
|
||||
private:
|
||||
void parseCommandLine(int argc, char** argv);
|
||||
void parseConfigFile(const resip::Data& filename);
|
||||
bool processOption(const resip::Data& name, const resip::Data& value);
|
||||
bool assignNameAddr(const resip::Data& settingName, const resip::Data& settingValue, resip::NameAddr& nameAddr);
|
||||
bool assignOnOffSetting(const resip::Data& value, bool& setting);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* ====================================================================
|
||||
|
||||
Copyright (c) 2009, SIP Spectrum, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of SIP Spectrum nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
==================================================================== */
|
||||
|
||||
182
src/libs/resiprocate/apps/ichat-gw/IChatGatewayCmds.hxx
Normal file
182
src/libs/resiprocate/apps/ichat-gw/IChatGatewayCmds.hxx
Normal file
@@ -0,0 +1,182 @@
|
||||
#if !defined(IChatGatewayCmds_hxx)
|
||||
#define IChatGatewayCmds_hxx
|
||||
|
||||
#include <resip/dum/DumCommand.hxx>
|
||||
|
||||
#include "Server.hxx"
|
||||
#include "B2BSession.hxx"
|
||||
|
||||
#define RESIPROCATE_SUBSYSTEM AppSubsystem::GATEWAY
|
||||
|
||||
namespace gateway
|
||||
{
|
||||
|
||||
/**
|
||||
The classes defined here are used to pass commands from the
|
||||
application thread to the DUM thread (process loop).
|
||||
This ensures thread safety of the external Server methods.
|
||||
|
||||
Author: Scott Godin (sgodin AT SipSpectrum DOT com)
|
||||
*/
|
||||
|
||||
class NotifyIChatCallRequestCmd : public resip::DumCommand
|
||||
{
|
||||
public:
|
||||
NotifyIChatCallRequestCmd(Server& server, const std::string& to, const std::string& from)
|
||||
: mServer(server), mTo(to), mFrom(from) {}
|
||||
virtual void executeCommand()
|
||||
{
|
||||
mServer.notifyIChatCallRequestImpl(mTo, mFrom);
|
||||
}
|
||||
resip::Message* clone() const { resip_assert(0); return 0; }
|
||||
EncodeStream& encode(EncodeStream& strm) const { strm << " NotifyIChatCallRequestCmd: "; return strm; }
|
||||
EncodeStream& encodeBrief(EncodeStream& strm) const { return encode(strm); }
|
||||
private:
|
||||
Server& mServer;
|
||||
std::string mTo;
|
||||
std::string mFrom;
|
||||
};
|
||||
|
||||
class NotifyIChatCallCancelledCmd : public resip::DumCommand
|
||||
{
|
||||
public:
|
||||
NotifyIChatCallCancelledCmd(Server& server, const B2BSessionHandle& handle)
|
||||
: mServer(server), mHandle(handle) {}
|
||||
virtual void executeCommand()
|
||||
{
|
||||
mServer.notifyIChatCallCancelledImpl(mHandle);
|
||||
}
|
||||
resip::Message* clone() const { resip_assert(0); return 0; }
|
||||
EncodeStream& encode(EncodeStream& strm) const { strm << " NotifyIChatCallCancelledCmd: "; return strm; }
|
||||
EncodeStream& encodeBrief(EncodeStream& strm) const { return encode(strm); }
|
||||
private:
|
||||
Server& mServer;
|
||||
B2BSessionHandle mHandle;
|
||||
};
|
||||
|
||||
class NotifyIChatCallProceedingCmd : public resip::DumCommand
|
||||
{
|
||||
public:
|
||||
NotifyIChatCallProceedingCmd(Server& server, const B2BSessionHandle& handle, const std::string& to)
|
||||
: mServer(server), mHandle(handle), mTo(to) {}
|
||||
virtual void executeCommand()
|
||||
{
|
||||
mServer.notifyIChatCallProceedingImpl(mHandle, mTo);
|
||||
}
|
||||
resip::Message* clone() const { resip_assert(0); return 0; }
|
||||
EncodeStream& encode(EncodeStream& strm) const { strm << " NotifyIChatCallProceedingCmd: "; return strm; }
|
||||
EncodeStream& encodeBrief(EncodeStream& strm) const { return encode(strm); }
|
||||
private:
|
||||
Server& mServer;
|
||||
B2BSessionHandle mHandle;
|
||||
std::string mTo;
|
||||
};
|
||||
|
||||
class NotifyIChatCallFailedCmd : public resip::DumCommand
|
||||
{
|
||||
public:
|
||||
NotifyIChatCallFailedCmd(Server& server, const B2BSessionHandle& handle, unsigned int statusCode)
|
||||
: mServer(server), mHandle(handle), mStatusCode(statusCode) {}
|
||||
virtual void executeCommand()
|
||||
{
|
||||
mServer.notifyIChatCallFailedImpl(mHandle, mStatusCode);
|
||||
}
|
||||
resip::Message* clone() const { resip_assert(0); return 0; }
|
||||
EncodeStream& encode(EncodeStream& strm) const { strm << " NotifyIChatCallFailedCmd: "; return strm; }
|
||||
EncodeStream& encodeBrief(EncodeStream& strm) const { return encode(strm); }
|
||||
private:
|
||||
Server& mServer;
|
||||
B2BSessionHandle mHandle;
|
||||
unsigned int mStatusCode;
|
||||
};
|
||||
|
||||
class ContinueIChatCallCmd : public resip::DumCommand
|
||||
{
|
||||
public:
|
||||
ContinueIChatCallCmd(Server& server, const B2BSessionHandle& handle, const std::string& remoteIPPortListBlob)
|
||||
: mServer(server), mHandle(handle), mRemoteIPPortListBlob(remoteIPPortListBlob) {}
|
||||
virtual void executeCommand()
|
||||
{
|
||||
mServer.continueIChatCallImpl(mHandle, mRemoteIPPortListBlob);
|
||||
}
|
||||
resip::Message* clone() const { resip_assert(0); return 0; }
|
||||
EncodeStream& encode(EncodeStream& strm) const { strm << " ContinueIChatCallCmd: "; return strm; }
|
||||
EncodeStream& encodeBrief(EncodeStream& strm) const { return encode(strm); }
|
||||
private:
|
||||
Server& mServer;
|
||||
B2BSessionHandle mHandle;
|
||||
std::string mRemoteIPPortListBlob;
|
||||
};
|
||||
|
||||
class SipRegisterJabberUserCmd : public resip::DumCommand
|
||||
{
|
||||
public:
|
||||
SipRegisterJabberUserCmd(Server& server, const std::string& jidToRegister)
|
||||
: mServer(server), mJidToRegister(jidToRegister) {}
|
||||
virtual void executeCommand()
|
||||
{
|
||||
mServer.sipRegisterJabberUserImpl(mJidToRegister);
|
||||
}
|
||||
resip::Message* clone() const { resip_assert(0); return 0; }
|
||||
EncodeStream& encode(EncodeStream& strm) const { strm << " SipRegisterJabberUserCmd: "; return strm; }
|
||||
EncodeStream& encodeBrief(EncodeStream& strm) const { return encode(strm); }
|
||||
private:
|
||||
Server& mServer;
|
||||
std::string mJidToRegister;
|
||||
};
|
||||
|
||||
class SipUnregisterJabberUserCmd : public resip::DumCommand
|
||||
{
|
||||
public:
|
||||
SipUnregisterJabberUserCmd(Server& server, const std::string& jidToUnregister)
|
||||
: mServer(server), mJidToUnregister(jidToUnregister) {}
|
||||
virtual void executeCommand()
|
||||
{
|
||||
mServer.sipUnregisterJabberUserImpl(mJidToUnregister);
|
||||
}
|
||||
resip::Message* clone() const { resip_assert(0); return 0; }
|
||||
EncodeStream& encode(EncodeStream& strm) const { strm << " SipUnregisterJabberUserCmd: "; return strm; }
|
||||
EncodeStream& encodeBrief(EncodeStream& strm) const { return encode(strm); }
|
||||
private:
|
||||
Server& mServer;
|
||||
std::string mJidToUnregister;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* ====================================================================
|
||||
|
||||
Copyright (c) 2009, SIP Spectrum, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of SIP Spectrum nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
==================================================================== */
|
||||
|
||||
169
src/libs/resiprocate/apps/ichat-gw/IChatIPPortData.cxx
Normal file
169
src/libs/resiprocate/apps/ichat-gw/IChatIPPortData.cxx
Normal file
@@ -0,0 +1,169 @@
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <rutil/Logger.hxx>
|
||||
#include <resip/stack/Helper.hxx>
|
||||
|
||||
#include "AppSubsystem.hxx"
|
||||
#include "IChatIPPortData.hxx"
|
||||
#include <rutil/WinLeakCheck.hxx>
|
||||
|
||||
#define RESIPROCATE_SUBSYSTEM AppSubsystem::GATEWAY
|
||||
|
||||
using namespace gateway;
|
||||
using namespace resip;
|
||||
using namespace std;
|
||||
|
||||
namespace gateway
|
||||
{
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned short initialPad;
|
||||
unsigned short family;
|
||||
char interfaceName[16];
|
||||
char ipAddress[16];
|
||||
unsigned short port;
|
||||
unsigned short finalPad;
|
||||
} IPPortDataBlob;
|
||||
|
||||
IChatIPPortData::IChatIPPortData()
|
||||
{
|
||||
}
|
||||
|
||||
IChatIPPortData::IChatIPPortData(const std::string& hexblob) : mHexBlob(hexblob)
|
||||
{
|
||||
unsigned int pad = 0;
|
||||
// Note: gloox passes us an initial line feed, so be tollerant of this
|
||||
if(hexblob.at(0) == 0xa)
|
||||
{
|
||||
pad = 1;
|
||||
}
|
||||
|
||||
// Convert hexblob to binary blob
|
||||
if(((hexblob.size()-pad) % 40) != 0)
|
||||
{
|
||||
ErrLog(<< "Data size provided for IChatIPPortData is not correct, size=" << hexblob.size());
|
||||
return;
|
||||
}
|
||||
Data blob((unsigned int)hexblob.size()-1 / 2, Data::Preallocate);
|
||||
for(unsigned int i = pad; i < hexblob.size(); i=i+8)
|
||||
{
|
||||
unsigned int block = ntohl(Helper::hex2integer(&hexblob.at(i)));
|
||||
blob.append((const char*)&block, 4);
|
||||
}
|
||||
|
||||
for(unsigned int j = 0; j < blob.size(); j=j+40)
|
||||
{
|
||||
IPPortDataBlob* ipPortDataBlob = (IPPortDataBlob*)(blob.data()+j);
|
||||
|
||||
if(ipPortDataBlob->family == V4)
|
||||
{
|
||||
in_addr addr;
|
||||
memcpy(&addr, ipPortDataBlob->ipAddress, 4);
|
||||
addIPPortData(Data(ipPortDataBlob->interfaceName), Tuple(addr,ntohs(ipPortDataBlob->port),UDP));
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef USE_IPV6
|
||||
in6_addr addr;
|
||||
memcpy(&addr, ipPortDataBlob->ipAddress, 16);
|
||||
addIPPortData(Data(ipPortDataBlob->interfaceName), Tuple(addr,ntohs(ipPortDataBlob->port),UDP));
|
||||
#else
|
||||
ErrLog(<< "IPv6 support not enabled at compile time.");
|
||||
resip_assert(0);
|
||||
#endif
|
||||
}
|
||||
InfoLog(<< "IChatIPPortData: name=" << mIPPortDataList.back().first << " addr=" << mIPPortDataList.back().second);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
IChatIPPortData::addIPPortData(const Data& name, const Tuple& ipPortData)
|
||||
{
|
||||
mIPPortDataList.push_back(std::make_pair(name, ipPortData));
|
||||
mHexBlob.clear(); // clear any existing blob string - it will now need to be re-generated if requested
|
||||
}
|
||||
|
||||
std::string&
|
||||
IChatIPPortData::hexBlob()
|
||||
{
|
||||
if(mHexBlob.empty())
|
||||
{
|
||||
Data dataBlob((int)mIPPortDataList.size() * sizeof(IPPortDataBlob), Data::Preallocate);
|
||||
IPPortDataList::const_iterator it;
|
||||
for(it = mIPPortDataList.begin(); it != mIPPortDataList.end(); it++)
|
||||
{
|
||||
IPPortDataBlob ipPortDataBlob;
|
||||
memset(&ipPortDataBlob, 0, sizeof(ipPortDataBlob));
|
||||
memcpy(ipPortDataBlob.interfaceName, it->first.data(), it->first.size() < 16 ? it->first.size() : 16);
|
||||
ipPortDataBlob.port = htons(it->second.getPort());
|
||||
if(it->second.ipVersion() == V4)
|
||||
{
|
||||
ipPortDataBlob.family = V4;
|
||||
memcpy(ipPortDataBlob.ipAddress, &reinterpret_cast<const sockaddr_in&>(it->second.getSockaddr()).sin_addr, 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
ipPortDataBlob.family = V6;
|
||||
memcpy(ipPortDataBlob.ipAddress, &reinterpret_cast<const sockaddr_in6&>(it->second.getSockaddr()).sin6_addr, 16);
|
||||
}
|
||||
dataBlob.append((const char*)&ipPortDataBlob, sizeof(ipPortDataBlob));
|
||||
}
|
||||
|
||||
// Hexify
|
||||
for(unsigned int i = 0; i < dataBlob.size(); i=i+4)
|
||||
{
|
||||
unsigned int block;
|
||||
memcpy(&block, dataBlob.data()+i, 4);
|
||||
char hexBlock[8];
|
||||
Helper::integer2hex(hexBlock, htonl(block));
|
||||
mHexBlob.append(hexBlock, 8);
|
||||
}
|
||||
}
|
||||
return mHexBlob;
|
||||
}
|
||||
|
||||
const IChatIPPortData::IPPortDataList&
|
||||
IChatIPPortData::getIPPortDataList() const
|
||||
{
|
||||
return mIPPortDataList;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* ====================================================================
|
||||
|
||||
Copyright (c) 2009, SIP Spectrum, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of SIP Spectrum nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
==================================================================== */
|
||||
|
||||
66
src/libs/resiprocate/apps/ichat-gw/IChatIPPortData.hxx
Normal file
66
src/libs/resiprocate/apps/ichat-gw/IChatIPPortData.hxx
Normal file
@@ -0,0 +1,66 @@
|
||||
#if !defined(IChatIPPortData_hxx)
|
||||
#define IChatIPPortData_hxx
|
||||
|
||||
#include <list>
|
||||
#include <string>
|
||||
|
||||
#include "rutil/Data.hxx"
|
||||
#include "resip/stack/Tuple.hxx"
|
||||
|
||||
namespace gateway
|
||||
{
|
||||
|
||||
class IChatIPPortData
|
||||
{
|
||||
public:
|
||||
typedef std::list<std::pair<resip::Data,resip::Tuple> > IPPortDataList;
|
||||
|
||||
IChatIPPortData();
|
||||
IChatIPPortData(const std::string& hexblob);
|
||||
|
||||
void addIPPortData(const resip::Data& name, const resip::Tuple& ipPortData);
|
||||
std::string& hexBlob();
|
||||
const IPPortDataList& getIPPortDataList() const;
|
||||
|
||||
private:
|
||||
IPPortDataList mIPPortDataList;
|
||||
std::string mHexBlob;
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ====================================================================
|
||||
|
||||
Copyright (c) 2009, SIP Spectrum, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of SIP Spectrum nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
==================================================================== */
|
||||
|
||||
281
src/libs/resiprocate/apps/ichat-gw/IPCThread.cxx
Normal file
281
src/libs/resiprocate/apps/ichat-gw/IPCThread.cxx
Normal file
@@ -0,0 +1,281 @@
|
||||
#include "rutil/ResipAssert.h"
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <WS2tcpip.h>
|
||||
#else
|
||||
#include <sys/fcntl.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "IPCThread.hxx"
|
||||
|
||||
using namespace gateway;
|
||||
using namespace std;
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
#define EADDRINUSE WSAEADDRINUSE
|
||||
#define EWOULDBLOCK WSAEWOULDBLOCK
|
||||
#define sleepMs(t) Sleep(t)
|
||||
#else
|
||||
#define sleepMs(t) usleep(t*1000)
|
||||
#endif
|
||||
|
||||
|
||||
IPCThread::IPCThread(unsigned short localPort, unsigned short remotePort, IPCHandler* handler, IPCMutex* mutex) :
|
||||
mLocalPort(localPort),
|
||||
mRemotePort(remotePort),
|
||||
mHandler(handler),
|
||||
mMutex(mutex)
|
||||
{
|
||||
resip_assert(handler!=0);
|
||||
mSocket = createIPCSocket("127.0.0.1",mLocalPort);
|
||||
if(mSocket == INVALID_SOCKET)
|
||||
{
|
||||
cerr << "IPCThread::IPCThread - could not create IPC udp socket on port=" << mLocalPort << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set RemoteSockaddr to be same as local but with remote port
|
||||
memcpy(&mRemoteSockaddr, &mLocalSockaddr, sizeof(mRemoteSockaddr));
|
||||
sockaddr_in* anonv4 = (sockaddr_in*)&mRemoteSockaddr;
|
||||
anonv4->sin_port = htons(remotePort);
|
||||
|
||||
cout << "IPCThread::IPCThread: local port=" << mLocalPort << ", remote port=" << remotePort << endl;
|
||||
}
|
||||
}
|
||||
|
||||
IPCThread::~IPCThread()
|
||||
{
|
||||
#if defined(WIN32)
|
||||
closesocket(mSocket);
|
||||
#else
|
||||
close(mSocket);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
IPCThread::sendIPCMsg(IPCMsg& msg)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
msg.encode(oss);
|
||||
mMutex->lock();
|
||||
mDataToSend.push(oss.str());
|
||||
mMutex->unlock();
|
||||
}
|
||||
|
||||
Socket
|
||||
IPCThread::createIPCSocket(const std::string& printableAddr, unsigned int port)
|
||||
{
|
||||
Socket fd;
|
||||
sockaddr_in* anonv4 = (sockaddr_in*)&mLocalSockaddr;
|
||||
|
||||
fd = ::socket(PF_INET, SOCK_DGRAM, 0);
|
||||
|
||||
if ( fd == INVALID_SOCKET )
|
||||
{
|
||||
int e = getErrno();
|
||||
cerr << "IPCThread::createIPCSocket - Failed to create socket: error=" << e << endl;
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
|
||||
memset(anonv4, 0, sizeof(mLocalSockaddr));
|
||||
anonv4->sin_family = AF_INET;
|
||||
anonv4->sin_port = htons(port);
|
||||
if (printableAddr.empty())
|
||||
{
|
||||
anonv4->sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
}
|
||||
else
|
||||
{
|
||||
anonv4->sin_addr.s_addr = inet_addr(printableAddr.c_str());
|
||||
}
|
||||
|
||||
//cout << "IPCThread::createIPCSocket - Creating fd=" << (int)fd
|
||||
// << ", Binding to " << printableAddr << ":" << port << endl;
|
||||
|
||||
if ( ::bind( fd, &mLocalSockaddr, sizeof(mLocalSockaddr)) == SOCKET_ERROR )
|
||||
{
|
||||
int e = getErrno();
|
||||
if ( e == EADDRINUSE )
|
||||
{
|
||||
cerr << "IPCThread::createIPCSocket - " << printableAddr << ":" << port << " already in use" << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
cerr << "IPCThread::createIPCSocket - Could not bind to " << printableAddr << ":" << port << ", error=" << e << endl;
|
||||
}
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
|
||||
if(port == 0)
|
||||
{
|
||||
// If we used port 0, then query what port the OS allocated for us
|
||||
socklen_t len = sizeof(mLocalSockaddr);
|
||||
if(::getsockname(fd, &mLocalSockaddr, &len) == SOCKET_ERROR)
|
||||
{
|
||||
int e = getErrno();
|
||||
cerr <<"IPCThread::createIPCSocket - getsockname failed, error=" << e << endl;
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(WIN32)
|
||||
unsigned long noBlock = 1;
|
||||
int errNoBlock = ioctlsocket( fd, FIONBIO , &noBlock );
|
||||
if ( errNoBlock != 0 )
|
||||
{
|
||||
cerr << "IPCThread::createIPCSocket - Could not make socket non-blocking" << endl;
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
#else
|
||||
int flags = fcntl( fd, F_GETFL, 0);
|
||||
int errNoBlock = fcntl(fd, F_SETFL, flags | O_NONBLOCK );
|
||||
if ( errNoBlock != 0 )
|
||||
{
|
||||
cerr << "IPCThread::createIPCSocket - Could not make socket non-blocking" << endl;
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
#endif
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
void
|
||||
IPCThread::thread()
|
||||
{
|
||||
fd_set read;
|
||||
fd_set write;
|
||||
fd_set except;
|
||||
struct timeval tv;
|
||||
|
||||
if(mSocket == INVALID_SOCKET) return;
|
||||
|
||||
while (!isShutdown())
|
||||
{
|
||||
tv.tv_sec = 1; // Note: calling select on linux based systems can cause the contents of the passed in timeval struct to be modified, so we need to reset the time on each loop iteration
|
||||
tv.tv_usec = 0;
|
||||
|
||||
FD_ZERO(&read);
|
||||
FD_ZERO(&write);
|
||||
FD_ZERO(&except);
|
||||
|
||||
FD_SET(mSocket, &read);
|
||||
FD_SET(mSocket, &except);
|
||||
|
||||
if(!mDataToSend.empty())
|
||||
{
|
||||
FD_SET(mSocket, &write);
|
||||
}
|
||||
|
||||
int ret = ::select(mSocket+1, &read, &write, &except, &tv);
|
||||
if (ret > 0)
|
||||
{
|
||||
process(read, write);
|
||||
}
|
||||
}
|
||||
cout << "IPCThread::thread - IPCThread shutdown." << endl;
|
||||
}
|
||||
|
||||
void
|
||||
IPCThread::process(fd_set& read_fdset, fd_set& write_fdset)
|
||||
{
|
||||
// If data to send and write has signalled
|
||||
if(!mDataToSend.empty() && (FD_ISSET(mSocket, &write_fdset) != 0))
|
||||
{
|
||||
int count;
|
||||
mMutex->lock();
|
||||
std::string& dataToSend = mDataToSend.front();
|
||||
count = sendto(mSocket,
|
||||
dataToSend.data(),
|
||||
dataToSend.size(),
|
||||
0, // flags
|
||||
&mRemoteSockaddr, sizeof(mRemoteSockaddr));
|
||||
mDataToSend.pop();
|
||||
mMutex->unlock();
|
||||
if ( count == SOCKET_ERROR )
|
||||
{
|
||||
int e = getErrno();
|
||||
cerr << "IPCThread::process - Failed (" << e << ") sending." << endl;
|
||||
}
|
||||
}
|
||||
if((FD_ISSET(mSocket, &read_fdset) != 0))
|
||||
{
|
||||
sockaddr readAddr;
|
||||
bool success = true;
|
||||
|
||||
socklen_t slen = sizeof(readAddr);
|
||||
int len = recvfrom(mSocket,
|
||||
mReadBuffer,
|
||||
UDP_IPC_BUFFER_SIZE,
|
||||
0 /*flags */,
|
||||
&readAddr,
|
||||
&slen);
|
||||
if ( len == SOCKET_ERROR )
|
||||
{
|
||||
int err = getErrno();
|
||||
if ( err != EWOULDBLOCK )
|
||||
{
|
||||
cerr << "IPCThread::process - Error calling recvfrom: " << err << endl;
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (len == 0 || len == SOCKET_ERROR)
|
||||
{
|
||||
cerr << "IPCThread::process - No data calling recvfrom: len=" << len << endl;
|
||||
success = false;
|
||||
}
|
||||
|
||||
if (len+1 >= UDP_IPC_BUFFER_SIZE)
|
||||
{
|
||||
cerr << "IPCThread::process - Datagram exceeded max length "<<UDP_IPC_BUFFER_SIZE << endl;
|
||||
success = false;
|
||||
}
|
||||
|
||||
if(success)
|
||||
{
|
||||
//cout << "IPCThread::process - Received a datagram of size=" << len << endl;
|
||||
IPCMsg msg(std::string(mReadBuffer, len));
|
||||
mHandler->onNewIPCMsg(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ====================================================================
|
||||
|
||||
Copyright (c) 2009, SIP Spectrum, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of SIP Spectrum nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
==================================================================== */
|
||||
|
||||
156
src/libs/resiprocate/apps/ichat-gw/IPCThread.hxx
Normal file
156
src/libs/resiprocate/apps/ichat-gw/IPCThread.hxx
Normal file
@@ -0,0 +1,156 @@
|
||||
#if !defined(IPCThread_hxx)
|
||||
#define IPCThread_hxx
|
||||
|
||||
#include <queue>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <errno.h>
|
||||
|
||||
#ifndef WIN32
|
||||
# include <sys/socket.h>
|
||||
# include <sys/select.h>
|
||||
# include <netinet/in.h>
|
||||
# include <arpa/inet.h>
|
||||
# include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#include "Thread.hxx"
|
||||
|
||||
#define UDP_IPC_BUFFER_SIZE 4192
|
||||
|
||||
namespace gateway
|
||||
{
|
||||
|
||||
#ifndef WIN32
|
||||
typedef int Socket;
|
||||
#define INVALID_SOCKET (-1)
|
||||
#define SOCKET_ERROR (-1)
|
||||
inline int getErrno() { return errno; }
|
||||
#else
|
||||
typedef SOCKET Socket;
|
||||
inline int getErrno() { return WSAGetLastError(); }
|
||||
#endif
|
||||
|
||||
class IPCMutex
|
||||
{
|
||||
public:
|
||||
IPCMutex() {}
|
||||
virtual ~IPCMutex() {}
|
||||
virtual void lock() = 0;
|
||||
virtual void unlock() = 0;
|
||||
};
|
||||
|
||||
class IPCMsg
|
||||
{
|
||||
public:
|
||||
IPCMsg() {};
|
||||
IPCMsg(const std::string& msg)
|
||||
{
|
||||
unsigned int start = 0;
|
||||
for(unsigned int i = 0; i < msg.size(); i++)
|
||||
{
|
||||
if(msg.at(i) == '\r')
|
||||
{
|
||||
mArgs.push_back(msg.substr(start,i-start));
|
||||
start = i+1;
|
||||
}
|
||||
}
|
||||
}
|
||||
void addArg(const std::string& arg) { mArgs.push_back(arg); }
|
||||
void addArg(unsigned int arg)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << arg;
|
||||
mArgs.push_back(oss.str());
|
||||
}
|
||||
std::ostream& encode(std::ostream& strm) const
|
||||
{
|
||||
std::vector<std::string>::const_iterator it = mArgs.begin();
|
||||
for(;it != mArgs.end();it++)
|
||||
{
|
||||
strm << *it << "\r"; // Note: using /r since there is a /n character at the start of the iChat call blob
|
||||
}
|
||||
strm.flush();
|
||||
return strm;
|
||||
}
|
||||
const std::vector<std::string>& getArgs() const { return mArgs; }
|
||||
private:
|
||||
std::vector<std::string> mArgs;
|
||||
};
|
||||
|
||||
class IPCHandler
|
||||
{
|
||||
public:
|
||||
virtual ~IPCHandler() {}
|
||||
virtual void onNewIPCMsg(const IPCMsg& msg) = 0;
|
||||
};
|
||||
|
||||
class IPCThread : public Thread
|
||||
{
|
||||
public:
|
||||
IPCThread(unsigned short localPort, unsigned short remotePort, IPCHandler* handler, IPCMutex* mutex);
|
||||
virtual ~IPCThread();
|
||||
|
||||
void sendIPCMsg(IPCMsg& msg);
|
||||
|
||||
protected:
|
||||
|
||||
private:
|
||||
virtual void thread();
|
||||
|
||||
void process(fd_set& read_fdset, fd_set& write_fdset);
|
||||
|
||||
Socket createIPCSocket(const std::string& printableAddr, unsigned int port);
|
||||
char mReadBuffer[UDP_IPC_BUFFER_SIZE+1];
|
||||
|
||||
sockaddr mLocalSockaddr;
|
||||
sockaddr mRemoteSockaddr;
|
||||
Socket mSocket;
|
||||
unsigned short mLocalPort;
|
||||
unsigned short mRemotePort;
|
||||
//resip::Mutex mIPCMutex;
|
||||
std::queue<std::string> mDataToSend;
|
||||
|
||||
IPCHandler* mHandler;
|
||||
IPCMutex* mMutex;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* ====================================================================
|
||||
|
||||
Copyright (c) 2009, SIP Spectrum, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of SIP Spectrum nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
==================================================================== */
|
||||
|
||||
653
src/libs/resiprocate/apps/ichat-gw/MediaRelay.cxx
Normal file
653
src/libs/resiprocate/apps/ichat-gw/MediaRelay.cxx
Normal file
@@ -0,0 +1,653 @@
|
||||
#include "rutil/ResipAssert.h"
|
||||
|
||||
#include <rutil/Data.hxx>
|
||||
#include <rutil/Socket.hxx>
|
||||
#include <rutil/Timer.hxx>
|
||||
#include <resip/stack/Symbols.hxx>
|
||||
#include <rutil/TransportType.hxx>
|
||||
#include <rutil/Logger.hxx>
|
||||
#include <resip/stack/Tuple.hxx>
|
||||
#include <rutil/Random.hxx>
|
||||
#include <rutil/DnsUtil.hxx>
|
||||
#include <rutil/ParseBuffer.hxx>
|
||||
#include <resip/stack/Transport.hxx>
|
||||
|
||||
#include "AppSubsystem.hxx"
|
||||
#include "MediaRelay.hxx"
|
||||
#include <rutil/WinLeakCheck.hxx>
|
||||
|
||||
#include <utility>
|
||||
|
||||
using namespace gateway;
|
||||
using namespace resip;
|
||||
using namespace std;
|
||||
|
||||
#define RESIPROCATE_SUBSYSTEM AppSubsystem::GATEWAY
|
||||
|
||||
#ifdef WIN32
|
||||
#define sleepMs(t) Sleep(t)
|
||||
#else
|
||||
#define sleepMs(t) usleep(t*1000)
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned short versionExtPayloadTypeAndMarker;
|
||||
unsigned short sequenceNumber;
|
||||
unsigned int timestamp;
|
||||
unsigned int ssrc;
|
||||
} RtpHeader;
|
||||
|
||||
|
||||
MediaRelay::MediaRelay(bool isV6Avail, unsigned short portRangeMin, unsigned short portRangeMax) :
|
||||
mIsV6Avail(isV6Avail)
|
||||
{
|
||||
if(portRangeMax < portRangeMin) portRangeMax = portRangeMin; // saftey check
|
||||
for(unsigned int i = portRangeMin; i <= portRangeMax; i++)
|
||||
{
|
||||
mFreeRelayPortList.push_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
MediaRelay::~MediaRelay()
|
||||
{
|
||||
Lock lock(mRelaysMutex);
|
||||
RelayPortList::iterator it = mRelays.begin();
|
||||
for(;it != mRelays.end(); it++)
|
||||
{
|
||||
delete it->second;
|
||||
}
|
||||
}
|
||||
|
||||
#define NUM_CREATE_TRIES 10 // Number of times to try to allocate a port, since port may be in use by another application
|
||||
bool
|
||||
MediaRelay::createRelay(unsigned short& port)
|
||||
{
|
||||
for(unsigned int i = 0; i < NUM_CREATE_TRIES; i++)
|
||||
{
|
||||
if(createRelayImpl(port)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
MediaRelay::createRelayImpl(unsigned short& port)
|
||||
{
|
||||
Lock lock(mRelaysMutex);
|
||||
|
||||
if(mFreeRelayPortList.empty()) return false;
|
||||
|
||||
unsigned short trialPort = mFreeRelayPortList.front();
|
||||
mFreeRelayPortList.pop_front();
|
||||
|
||||
Tuple v4tuple(Data::Empty,trialPort,V4,UDP,Data::Empty);
|
||||
resip::Socket v4fd = createRelaySocket(v4tuple);
|
||||
|
||||
if(v4fd == INVALID_SOCKET)
|
||||
{
|
||||
mFreeRelayPortList.push_back(trialPort);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(mIsV6Avail)
|
||||
{
|
||||
Tuple v6tuple(Data::Empty,trialPort,V6,UDP,Data::Empty);
|
||||
resip::Socket v6fd = createRelaySocket(v6tuple);
|
||||
|
||||
if(v6fd != INVALID_SOCKET)
|
||||
{
|
||||
port = trialPort;
|
||||
|
||||
mRelays[port] = new MediaRelayPort(v4fd, v4tuple, v6fd, v6tuple);
|
||||
InfoLog(<< "MediaRelay::createRelayImpl - Media relay started for port " << port);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined(WIN32)
|
||||
closesocket(v4fd);
|
||||
#else
|
||||
close(v4fd);
|
||||
#endif
|
||||
|
||||
mFreeRelayPortList.push_back(trialPort);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Only V4 is available
|
||||
port = trialPort;
|
||||
|
||||
mRelays[port] = new MediaRelayPort(v4fd, v4tuple);
|
||||
InfoLog(<< "MediaRelay::createRelayImpl - Media relay started for port " << port);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MediaRelay::destroyRelay(unsigned short port)
|
||||
{
|
||||
Lock lock(mRelaysMutex);
|
||||
RelayPortList::iterator it = mRelays.find(port);
|
||||
if(it != mRelays.end())
|
||||
{
|
||||
InfoLog(<< "MediaRelay::destroyRelay - port=" << port);
|
||||
delete it->second;
|
||||
mRelays.erase(it);
|
||||
mFreeRelayPortList.push_back(port);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MediaRelay::primeNextEndpoint(unsigned short& port, resip::Tuple& destinationIPPort)
|
||||
{
|
||||
Lock lock(mRelaysMutex);
|
||||
RelayPortList::iterator it = mRelays.find(port);
|
||||
if(it != mRelays.end())
|
||||
{
|
||||
if(it->second->mFirstEndpoint.mTuple.getPort() == 0)
|
||||
{
|
||||
InfoLog(<< "MediaRelay::primeNextEndpoint - sender=first, port=" << port << ", addr=" << destinationIPPort);
|
||||
it->second->mFirstEndpoint.mTuple = destinationIPPort;
|
||||
}
|
||||
else
|
||||
{
|
||||
InfoLog(<< "MediaRelay::primeNextEndpoint - sender=second, port=" << port << ", addr=" << destinationIPPort);
|
||||
it->second->mSecondEndpoint.mTuple = destinationIPPort;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resip::Socket
|
||||
MediaRelay::createRelaySocket(resip::Tuple& tuple)
|
||||
{
|
||||
resip::Socket fd;
|
||||
|
||||
#ifdef USE_IPV6
|
||||
fd = ::socket(tuple.ipVersion() == V4 ? PF_INET : PF_INET6, SOCK_DGRAM, 0);
|
||||
#else
|
||||
fd = ::socket(PF_INET, SOCK_DGRAM, 0);
|
||||
#endif
|
||||
|
||||
if ( fd == INVALID_SOCKET )
|
||||
{
|
||||
int e = getErrno();
|
||||
ErrLog (<< "MediaRelay::createRelaySocket - Failed to create socket: " << strerror(e));
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
|
||||
DebugLog (<< "MediaRelay::createRelaySocket - Creating fd=" << (int)fd
|
||||
<< (tuple.ipVersion() == V4 ? " V4" : " V6")
|
||||
<< ", Binding to " << Tuple::inet_ntop(tuple));
|
||||
|
||||
if ( ::bind( fd, &tuple.getSockaddr(), tuple.length()) == SOCKET_ERROR )
|
||||
{
|
||||
int e = getErrno();
|
||||
if ( e == EADDRINUSE )
|
||||
{
|
||||
ErrLog (<< "MediaRelay::createRelaySocket - " << tuple << " already in use ");
|
||||
}
|
||||
else
|
||||
{
|
||||
ErrLog (<< "MediaRelay::createRelaySocket - Could not bind to " << tuple << ", error=" << e);
|
||||
}
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
|
||||
if(tuple.getPort() == 0)
|
||||
{
|
||||
// If we used port 0, then query what port the OS allocated for us
|
||||
socklen_t len = tuple.length();
|
||||
if(::getsockname(fd, &tuple.getMutableSockaddr(), &len) == SOCKET_ERROR)
|
||||
{
|
||||
int e = getErrno();
|
||||
ErrLog (<<"MediaRelay::createRelaySocket - getsockname failed, error=" << e);
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
}
|
||||
|
||||
bool ok = makeSocketNonBlocking(fd);
|
||||
if ( !ok )
|
||||
{
|
||||
ErrLog (<< "MediaRelay::createRelaySocket - Could not make socket non-blocking");
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
void
|
||||
MediaRelay::thread()
|
||||
{
|
||||
while (!isShutdown())
|
||||
{
|
||||
try
|
||||
{
|
||||
if(mRelays.size() == 0)
|
||||
{
|
||||
// No relays yet - just wait
|
||||
sleepMs(50);
|
||||
}
|
||||
else
|
||||
{
|
||||
resip::FdSet fdset;
|
||||
buildFdSet(fdset);
|
||||
int ret = fdset.selectMilliSeconds(50);
|
||||
if (ret > 0)
|
||||
{
|
||||
process(fdset);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (BaseException& e)
|
||||
{
|
||||
ErrLog (<< "MediaRelay::thread - Unhandled exception: " << e);
|
||||
}
|
||||
}
|
||||
WarningLog (<< "MediaRelay::thread - shutdown");
|
||||
}
|
||||
|
||||
void
|
||||
MediaRelay::buildFdSet(FdSet& fdset)
|
||||
{
|
||||
Lock lock(mRelaysMutex);
|
||||
|
||||
RelayPortList::iterator it = mRelays.begin();
|
||||
for(;it != mRelays.end(); it++)
|
||||
{
|
||||
// Add read fd's
|
||||
fdset.setRead(it->second->mV4Fd);
|
||||
if(mIsV6Avail) fdset.setRead(it->second->mV6Fd);
|
||||
fdset.setExcept(it->second->mV4Fd);
|
||||
if(mIsV6Avail) fdset.setExcept(it->second->mV6Fd);
|
||||
|
||||
checkKeepalives(it->second);
|
||||
|
||||
// Add write fd's if there is data to write
|
||||
if((it->second->mFirstEndpoint.mRelayDatagram.get() != 0 && it->second->mFirstEndpoint.mTuple.ipVersion() == V4) ||
|
||||
(it->second->mSecondEndpoint.mRelayDatagram.get() != 0 && it->second->mSecondEndpoint.mTuple.ipVersion() == V4))
|
||||
{
|
||||
fdset.setWrite(it->second->mV4Fd);
|
||||
}
|
||||
if(mIsV6Avail &&
|
||||
((it->second->mFirstEndpoint.mRelayDatagram.get() != 0 && it->second->mFirstEndpoint.mTuple.ipVersion() == V6) ||
|
||||
(it->second->mSecondEndpoint.mRelayDatagram.get() != 0 && it->second->mSecondEndpoint.mTuple.ipVersion() == V6)))
|
||||
{
|
||||
fdset.setWrite(it->second->mV6Fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define KEEPALIVETIMEOUTMS 1000
|
||||
#define KEEPALIVEMS 20
|
||||
#define STALEENDPOINTTIMEOUTMS 2000
|
||||
void
|
||||
MediaRelay::checkKeepalives(MediaRelayPort* relayPort)
|
||||
{
|
||||
uint64_t now = Timer::getTimeMs();
|
||||
|
||||
// See if First Endpoint is stale (ie. hasn't received data in STALEENDPOINTTIMEOUTMS ms)
|
||||
if(relayPort->mFirstEndpoint.mTuple.getPort() != 0 &&
|
||||
(now - relayPort->mFirstEndpoint.mRecvTimeMs) > STALEENDPOINTTIMEOUTMS)
|
||||
{
|
||||
relayPort->mFirstEndpoint.reset();
|
||||
InfoLog(<< "MediaRelay::checkKeepalives: port=" << relayPort->mLocalV4Tuple.getPort() << ", haven't recevied data from first endpoint in " << STALEENDPOINTTIMEOUTMS << "ms - reseting endpoint.");
|
||||
}
|
||||
|
||||
// See if Second Endpoint is stale (ie. hasn't received data in STALEENDPOINTTIMEOUTMS ms)
|
||||
if(relayPort->mSecondEndpoint.mTuple.getPort() != 0 &&
|
||||
(now - relayPort->mSecondEndpoint.mRecvTimeMs) > STALEENDPOINTTIMEOUTMS)
|
||||
{
|
||||
relayPort->mSecondEndpoint.reset();
|
||||
InfoLog(<< "MediaRelay::checkKeepalives: port=" << relayPort->mLocalV4Tuple.getPort() << ", haven't recevied data from second endpoint in " << STALEENDPOINTTIMEOUTMS << "ms - reseting endpoint.");
|
||||
}
|
||||
|
||||
//if(relayPort->mFirstEndpoint.mTuple.getPort() != 0)
|
||||
//{
|
||||
//InfoLog(<< "MediaRelay::checkKeepalives - port=" << relayPort->mFirstEndpoint.mTuple.getPort() << ", dataToSend=" <<
|
||||
// (relayPort->mFirstEndpoint.mRelayDatagram.get() == 0 ? "no" : "yes") << ", time since last send=" <<
|
||||
// (now - relayPort->mFirstEndpoint.mSendTimeMs));
|
||||
//}
|
||||
|
||||
// See if keepalive needs to be sent to First Endpoint
|
||||
if(relayPort->mFirstEndpoint.mTuple.getPort() != 0 &&
|
||||
relayPort->mFirstEndpoint.mRelayDatagram.get() == 0 &&
|
||||
((!relayPort->mFirstEndpoint.mKeepaliveMode && (now - relayPort->mFirstEndpoint.mSendTimeMs) > KEEPALIVETIMEOUTMS) ||
|
||||
(relayPort->mFirstEndpoint.mKeepaliveMode && (now - relayPort->mFirstEndpoint.mSendTimeMs) > KEEPALIVEMS)))
|
||||
{
|
||||
RtpHeader keepalive; // Create an empty G711 packet to keep iChat happy
|
||||
keepalive.versionExtPayloadTypeAndMarker = htons(0x8000);
|
||||
keepalive.sequenceNumber = 0;
|
||||
keepalive.timestamp = 0;
|
||||
keepalive.ssrc = relayPort->mFirstEndpoint.mSsrc;
|
||||
|
||||
if(!relayPort->mFirstEndpoint.mKeepaliveMode)
|
||||
{
|
||||
InfoLog(<< "MediaRelay::checkKeepalives: port=" << relayPort->mLocalV4Tuple.getPort() << ", dispatching initial RTP keepalive to first sender!");
|
||||
relayPort->mFirstEndpoint.mKeepaliveMode = true;
|
||||
}
|
||||
//else
|
||||
//{
|
||||
// InfoLog(<< "MediaRelay::checkKeepalives: port=" << relayPort->mLocalV4Tuple.getPort() << ", dispatching subsequent RTP keepalive to first sender!");
|
||||
//}
|
||||
|
||||
// Add message to buffer
|
||||
std::unique_ptr<char[]> buffer(new char[sizeof(RtpHeader)]);
|
||||
memcpy(buffer.get(), &keepalive, sizeof(RtpHeader));
|
||||
|
||||
relayPort->mFirstEndpoint.mRelayDatagram = std::move(buffer);
|
||||
relayPort->mFirstEndpoint.mRelayDatagramLen = sizeof(RtpHeader);
|
||||
}
|
||||
|
||||
// See if keepalive needs to be sent to Second Endpoint
|
||||
if(relayPort->mSecondEndpoint.mTuple.getPort() != 0 &&
|
||||
relayPort->mSecondEndpoint.mRelayDatagram.get() == 0 &&
|
||||
((!relayPort->mSecondEndpoint.mKeepaliveMode && (now - relayPort->mSecondEndpoint.mSendTimeMs) > KEEPALIVETIMEOUTMS) ||
|
||||
(relayPort->mSecondEndpoint.mKeepaliveMode && (now - relayPort->mSecondEndpoint.mSendTimeMs) > KEEPALIVEMS)))
|
||||
{
|
||||
RtpHeader keepalive; // Create an empty G711 packet to keep iChat happy
|
||||
keepalive.versionExtPayloadTypeAndMarker = htons(0x8000);
|
||||
keepalive.sequenceNumber = 0;
|
||||
keepalive.timestamp = 0;
|
||||
keepalive.ssrc = relayPort->mSecondEndpoint.mSsrc;
|
||||
|
||||
if(!relayPort->mSecondEndpoint.mKeepaliveMode)
|
||||
{
|
||||
InfoLog(<< "MediaRelay::checkKeepalives: port=" << relayPort->mLocalV4Tuple.getPort() << ", dispatching initial RTP keepalive to second sender!");
|
||||
relayPort->mSecondEndpoint.mKeepaliveMode = true;
|
||||
}
|
||||
//else
|
||||
//{
|
||||
// InfoLog(<< "MediaRelay::checkKeepalives: port=" << relayPort->mLocalV4Tuple.getPort() << ", dispatching subsequent RTP keepalive to second sender!");
|
||||
//}
|
||||
|
||||
// Add message to buffer
|
||||
std::unique_ptr<char[]> buffer(new char[sizeof(RtpHeader)]);
|
||||
memcpy(buffer.get(), &keepalive, sizeof(RtpHeader));
|
||||
|
||||
relayPort->mSecondEndpoint.mRelayDatagram = std::move(buffer);
|
||||
relayPort->mSecondEndpoint.mRelayDatagramLen = sizeof(RtpHeader);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MediaRelay::process(FdSet& fdset)
|
||||
{
|
||||
Lock lock(mRelaysMutex);
|
||||
|
||||
RelayPortList::iterator it = mRelays.begin();
|
||||
for(;it != mRelays.end(); it++)
|
||||
{
|
||||
if(processWrites(fdset, it->second))
|
||||
{
|
||||
// If all writes have been processed, process reads
|
||||
processReads(fdset, it->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
MediaRelay::processWrites(FdSet& fdset, MediaRelayPort* relayPort)
|
||||
{
|
||||
resip::Socket fd = INVALID_SOCKET;
|
||||
Tuple tuple;
|
||||
std::unique_ptr<char[]> buffer;
|
||||
int len;
|
||||
|
||||
// If we have data to write to first sender then check if readyToWrite
|
||||
if(relayPort->mFirstEndpoint.mRelayDatagram.get() != 0)
|
||||
{
|
||||
if(relayPort->mFirstEndpoint.mTuple.ipVersion() == V4 &&
|
||||
fdset.readyToWrite(relayPort->mV4Fd))
|
||||
{
|
||||
fd = relayPort->mV4Fd;
|
||||
tuple = relayPort->mFirstEndpoint.mTuple;
|
||||
buffer = std::move(relayPort->mFirstEndpoint.mRelayDatagram);
|
||||
len = relayPort->mFirstEndpoint.mRelayDatagramLen;
|
||||
}
|
||||
else if(mIsV6Avail &&
|
||||
relayPort->mFirstEndpoint.mTuple.ipVersion() == V6 &&
|
||||
fdset.readyToWrite(relayPort->mV6Fd))
|
||||
{
|
||||
fd = relayPort->mV6Fd;
|
||||
tuple = relayPort->mFirstEndpoint.mTuple;
|
||||
buffer = std::move(relayPort->mFirstEndpoint.mRelayDatagram);
|
||||
len = relayPort->mFirstEndpoint.mRelayDatagramLen;
|
||||
}
|
||||
}
|
||||
|
||||
// If anything to send to first sender then do it
|
||||
if (fd != INVALID_SOCKET)
|
||||
{
|
||||
int count;
|
||||
count = sendto(fd,
|
||||
buffer.get(),
|
||||
len,
|
||||
0, // flags
|
||||
&tuple.getMutableSockaddr(), tuple.length());
|
||||
if ( count == SOCKET_ERROR )
|
||||
{
|
||||
int e = getErrno();
|
||||
InfoLog (<< "MediaRelay::processWrites: port=" << relayPort->mLocalV4Tuple.getPort() << ", Failed (" << e << ") sending to " << tuple);
|
||||
}
|
||||
else
|
||||
{
|
||||
// InfoLog(<< len << " bytes of data sent to " << tuple);
|
||||
relayPort->mFirstEndpoint.mSendTimeMs = Timer::getTimeMs();
|
||||
}
|
||||
}
|
||||
|
||||
// check if we have data to write to second sender then check if readyToWrite
|
||||
fd = INVALID_SOCKET; // reset
|
||||
if(relayPort->mSecondEndpoint.mRelayDatagram.get() != 0)
|
||||
{
|
||||
if(relayPort->mSecondEndpoint.mTuple.ipVersion() == V4 &&
|
||||
fdset.readyToWrite(relayPort->mV4Fd))
|
||||
{
|
||||
fd = relayPort->mV4Fd;
|
||||
tuple = relayPort->mSecondEndpoint.mTuple;
|
||||
buffer = std::move(relayPort->mSecondEndpoint.mRelayDatagram);
|
||||
len = relayPort->mSecondEndpoint.mRelayDatagramLen;
|
||||
}
|
||||
else if(mIsV6Avail &&
|
||||
relayPort->mSecondEndpoint.mTuple.ipVersion() == V6 &&
|
||||
fdset.readyToWrite(relayPort->mV6Fd))
|
||||
{
|
||||
fd = relayPort->mV6Fd;
|
||||
tuple = relayPort->mSecondEndpoint.mTuple;
|
||||
buffer = std::move(relayPort->mSecondEndpoint.mRelayDatagram);
|
||||
len = relayPort->mSecondEndpoint.mRelayDatagramLen;
|
||||
}
|
||||
}
|
||||
|
||||
// If anything to send to sender sender then do it
|
||||
if (fd != INVALID_SOCKET)
|
||||
{
|
||||
int count;
|
||||
count = sendto(fd,
|
||||
buffer.get(),
|
||||
len,
|
||||
0, // flags
|
||||
&tuple.getMutableSockaddr(), tuple.length());
|
||||
if ( count == SOCKET_ERROR )
|
||||
{
|
||||
int e = getErrno();
|
||||
InfoLog (<< "MediaRelay::processWrites: port=" << relayPort->mLocalV4Tuple.getPort() << ", Failed (" << e << ") sending to " << tuple);
|
||||
}
|
||||
else
|
||||
{
|
||||
//InfoLog(<< len << " bytes of data sent to " << tuple);
|
||||
relayPort->mSecondEndpoint.mSendTimeMs = Timer::getTimeMs();
|
||||
}
|
||||
}
|
||||
|
||||
return relayPort->mFirstEndpoint.mRelayDatagram.get() == 0 &&
|
||||
relayPort->mSecondEndpoint.mRelayDatagram.get() == 0;
|
||||
}
|
||||
|
||||
#define UDP_BUFFER_SIZE 1000
|
||||
void
|
||||
MediaRelay::processReads(FdSet& fdset, MediaRelayPort* relayPort)
|
||||
{
|
||||
resip::Socket fd = INVALID_SOCKET;
|
||||
Tuple tuple;
|
||||
|
||||
if(fdset.readyToRead(relayPort->mV4Fd))
|
||||
{
|
||||
//InfoLog(<<"V4 socket is ready to read.");
|
||||
fd = relayPort->mV4Fd;
|
||||
tuple = relayPort->mLocalV4Tuple;
|
||||
}
|
||||
else if(mIsV6Avail && fdset.readyToRead(relayPort->mV6Fd))
|
||||
{
|
||||
//InfoLog(<<"V6 socket is ready to read.");
|
||||
fd = relayPort->mV6Fd;
|
||||
tuple = relayPort->mLocalV6Tuple;
|
||||
}
|
||||
if (fd != INVALID_SOCKET)
|
||||
{
|
||||
std::unique_ptr<char[]> buffer(new char[UDP_BUFFER_SIZE+1]);
|
||||
|
||||
socklen_t slen = tuple.length();
|
||||
int len = recvfrom( fd,
|
||||
buffer.get(),
|
||||
UDP_BUFFER_SIZE,
|
||||
0 /*flags */,
|
||||
&tuple.getMutableSockaddr(),
|
||||
&slen);
|
||||
if ( len == SOCKET_ERROR )
|
||||
{
|
||||
int err = getErrno();
|
||||
if ( err != EWOULDBLOCK )
|
||||
{
|
||||
ErrLog (<< "MediaRelay::processReads: port=" << relayPort->mLocalV4Tuple.getPort() << ", Error calling recvfrom: " << err);
|
||||
}
|
||||
buffer.reset();
|
||||
}
|
||||
|
||||
if (len == 0)
|
||||
{
|
||||
ErrLog (<< "MediaRelay::processReads: port=" << relayPort->mLocalV4Tuple.getPort() << ", No data calling recvfrom: len=" << len);
|
||||
buffer.reset();
|
||||
}
|
||||
|
||||
if (len+1 >= UDP_BUFFER_SIZE)
|
||||
{
|
||||
InfoLog(<<"MediaRelay::processReads: port=" << relayPort->mLocalV4Tuple.getPort() << ", Datagram exceeded max length "<<UDP_BUFFER_SIZE);
|
||||
buffer.reset();
|
||||
}
|
||||
|
||||
if(buffer.get() != 0)
|
||||
{
|
||||
uint64_t now = Timer::getTimeMs();
|
||||
RtpHeader* rtpHeader = (RtpHeader*)buffer.get();
|
||||
//InfoLog(<< "Received a datagram of size=" << len << " from=" << tuple);
|
||||
MediaEndpoint* pReceivingEndpoint = 0;
|
||||
MediaEndpoint* pSendingEndpoint = 0;
|
||||
|
||||
// First check if packet is from first endpoint
|
||||
if(tuple == relayPort->mFirstEndpoint.mTuple)
|
||||
{
|
||||
pReceivingEndpoint = &relayPort->mFirstEndpoint;
|
||||
pSendingEndpoint = &relayPort->mSecondEndpoint;
|
||||
}
|
||||
// Next check if packet is from second endpoint
|
||||
else if(tuple == relayPort->mSecondEndpoint.mTuple)
|
||||
{
|
||||
pReceivingEndpoint = &relayPort->mSecondEndpoint;
|
||||
pSendingEndpoint = &relayPort->mFirstEndpoint;
|
||||
}
|
||||
else
|
||||
{
|
||||
// See if we can store this new sender in First Endpoint
|
||||
if(relayPort->mFirstEndpoint.mTuple.getPort() == 0)
|
||||
{
|
||||
InfoLog(<< "MediaRelay::processReads: port=" << relayPort->mLocalV4Tuple.getPort() << ", First packet received from First Endpoint " << tuple);
|
||||
pReceivingEndpoint = &relayPort->mFirstEndpoint;
|
||||
pSendingEndpoint = &relayPort->mSecondEndpoint;
|
||||
}
|
||||
else if(relayPort->mSecondEndpoint.mTuple.getPort() == 0)
|
||||
{
|
||||
InfoLog(<< "MediaRelay::processReads: port=" << relayPort->mLocalV4Tuple.getPort() << ", First packet received from Second Endpoint " << tuple);
|
||||
pReceivingEndpoint = &relayPort->mSecondEndpoint;
|
||||
pSendingEndpoint = &relayPort->mFirstEndpoint;
|
||||
}
|
||||
else // We already have 2 endpoints - this would be a third
|
||||
{
|
||||
// We have a third sender - for now drop, if one of the other senders stops sending data for 2 seconds then we will start picking up this sender
|
||||
WarningLog(<< "MediaRelay::processReads: port=" << relayPort->mLocalV4Tuple.getPort() << ", MediaRelay on " << relayPort->mLocalV4Tuple.getPort() << " has seen a third sender " << tuple << " - not implemented yet - ignoring packet");
|
||||
}
|
||||
if(pReceivingEndpoint)
|
||||
{
|
||||
pReceivingEndpoint->mTuple = tuple;
|
||||
pReceivingEndpoint->mSendTimeMs = now;
|
||||
pReceivingEndpoint->mRecvTimeMs = now;
|
||||
}
|
||||
}
|
||||
|
||||
if(pReceivingEndpoint)
|
||||
{
|
||||
pReceivingEndpoint->mRecvTimeMs = now;
|
||||
if(pSendingEndpoint && pSendingEndpoint->mTuple.getPort() != 0)
|
||||
{
|
||||
if(ntohs(rtpHeader->versionExtPayloadTypeAndMarker) & 0x8000) // RTP Version 2
|
||||
{
|
||||
// Adjust ssrc
|
||||
rtpHeader->ssrc = pSendingEndpoint->mSsrc;
|
||||
|
||||
// relay packet to second sender
|
||||
resip_assert(pSendingEndpoint->mRelayDatagram.get() == 0);
|
||||
pSendingEndpoint->mRelayDatagram = std::move(buffer);
|
||||
pSendingEndpoint->mRelayDatagramLen = len;
|
||||
if(pSendingEndpoint->mKeepaliveMode)
|
||||
{
|
||||
InfoLog(<< "MediaRelay::processReads: port=" << relayPort->mLocalV4Tuple.getPort() << ", received packet to forward, turning off keepalive mode for " << pSendingEndpoint->mTuple);
|
||||
pSendingEndpoint->mKeepaliveMode = false;
|
||||
}
|
||||
|
||||
//InfoLog(<< "Relaying packet from=" << tuple << " to " << pSendingEndpoint->mTuple);
|
||||
}
|
||||
//else
|
||||
//{
|
||||
// InfoLog(<< "MediaRelay::processReads: port=" << relayPort->mLocalV4Tuple.getPort() << ", discarding received packet with unknown RTP version from " << tuple);
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ====================================================================
|
||||
|
||||
Copyright (c) 2009, SIP Spectrum, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of SIP Spectrum nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
==================================================================== */
|
||||
|
||||
87
src/libs/resiprocate/apps/ichat-gw/MediaRelay.hxx
Normal file
87
src/libs/resiprocate/apps/ichat-gw/MediaRelay.hxx
Normal file
@@ -0,0 +1,87 @@
|
||||
#if !defined(MediaRelay_hxx)
|
||||
#define MediaRelay_hxx
|
||||
|
||||
#include <map>
|
||||
#include <deque>
|
||||
#include <rutil/Data.hxx>
|
||||
#include <rutil/Socket.hxx>
|
||||
#include <rutil/ThreadIf.hxx>
|
||||
#include <rutil/TransportType.hxx>
|
||||
#include <resip/stack/Tuple.hxx>
|
||||
|
||||
#include "MediaRelayPort.hxx"
|
||||
|
||||
namespace gateway
|
||||
{
|
||||
|
||||
class MediaRelay : public resip::ThreadIf
|
||||
{
|
||||
public:
|
||||
MediaRelay(bool isV6Avail, unsigned short portRangeMin, unsigned short portRangeMax);
|
||||
virtual ~MediaRelay();
|
||||
|
||||
bool createRelay(unsigned short& port);
|
||||
void destroyRelay(unsigned short port);
|
||||
|
||||
void primeNextEndpoint(unsigned short& port, resip::Tuple& destinationIPPort);
|
||||
|
||||
protected:
|
||||
|
||||
private:
|
||||
virtual void thread();
|
||||
|
||||
void buildFdSet(resip::FdSet& fdset);
|
||||
void checkKeepalives(MediaRelayPort* relayPort);
|
||||
void process(resip::FdSet& fdset);
|
||||
bool processWrites(resip::FdSet& fdset, MediaRelayPort* relayPort); // return true if all writes are complete
|
||||
void processReads(resip::FdSet& fdset, MediaRelayPort* relayPort);
|
||||
|
||||
bool createRelayImpl(unsigned short& port);
|
||||
resip::Socket createRelaySocket(resip::Tuple& tuple);
|
||||
|
||||
typedef std::map<unsigned short, MediaRelayPort*> RelayPortList;
|
||||
RelayPortList mRelays;
|
||||
resip::Mutex mRelaysMutex;
|
||||
bool mIsV6Avail;
|
||||
|
||||
std::deque<unsigned int> mFreeRelayPortList;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* ====================================================================
|
||||
|
||||
Copyright (c) 2009, SIP Spectrum, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of SIP Spectrum nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
==================================================================== */
|
||||
|
||||
84
src/libs/resiprocate/apps/ichat-gw/MediaRelayPort.cxx
Normal file
84
src/libs/resiprocate/apps/ichat-gw/MediaRelayPort.cxx
Normal file
@@ -0,0 +1,84 @@
|
||||
#include "rutil/ResipAssert.h"
|
||||
|
||||
#include <rutil/Data.hxx>
|
||||
#include <rutil/Socket.hxx>
|
||||
#include <resip/stack/Symbols.hxx>
|
||||
#include <rutil/TransportType.hxx>
|
||||
#include <rutil/Logger.hxx>
|
||||
#include <resip/stack/Tuple.hxx>
|
||||
//#include <rutil/DnsUtil.hxx>
|
||||
//#include <rutil/ParseBuffer.hxx>
|
||||
#include <resip/stack/Transport.hxx>
|
||||
|
||||
#include "AppSubsystem.hxx"
|
||||
#include "MediaRelayPort.hxx"
|
||||
#include <rutil/WinLeakCheck.hxx>
|
||||
|
||||
using namespace gateway;
|
||||
using namespace resip;
|
||||
using namespace std;
|
||||
|
||||
#define RESIPROCATE_SUBSYSTEM AppSubsystem::GATEWAY
|
||||
|
||||
MediaRelayPort::MediaRelayPort() : mV4Fd(INVALID_SOCKET), mV6Fd(INVALID_SOCKET)
|
||||
{
|
||||
}
|
||||
|
||||
MediaRelayPort::MediaRelayPort(resip::Socket& v4fd, resip::Tuple& v4tuple, resip::Socket& v6fd, resip::Tuple& v6tuple) :
|
||||
mV4Fd(v4fd), mLocalV4Tuple(v4tuple),
|
||||
mV6Fd(v6fd), mLocalV6Tuple(v6tuple)
|
||||
{
|
||||
}
|
||||
|
||||
MediaRelayPort::MediaRelayPort(resip::Socket& v4fd, resip::Tuple& v4tuple) :
|
||||
mV4Fd(v4fd), mLocalV4Tuple(v4tuple),
|
||||
mV6Fd(INVALID_SOCKET)
|
||||
{
|
||||
}
|
||||
|
||||
MediaRelayPort::~MediaRelayPort()
|
||||
{
|
||||
#if defined(WIN32)
|
||||
if(mV4Fd != INVALID_SOCKET) closesocket(mV4Fd);
|
||||
if(mV6Fd != INVALID_SOCKET) closesocket(mV6Fd);
|
||||
#else
|
||||
if(mV4Fd != INVALID_SOCKET) close(mV4Fd);
|
||||
if(mV6Fd != INVALID_SOCKET) close(mV6Fd);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* ====================================================================
|
||||
|
||||
Copyright (c) 2009, SIP Spectrum, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of SIP Spectrum nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
==================================================================== */
|
||||
|
||||
94
src/libs/resiprocate/apps/ichat-gw/MediaRelayPort.hxx
Normal file
94
src/libs/resiprocate/apps/ichat-gw/MediaRelayPort.hxx
Normal file
@@ -0,0 +1,94 @@
|
||||
#if !defined(MediaRelayPort_hxx)
|
||||
#define MediaRelayPort_hxx
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <rutil/Data.hxx>
|
||||
#include <rutil/Random.hxx>
|
||||
#include <rutil/Socket.hxx>
|
||||
#include <rutil/TransportType.hxx>
|
||||
#include <resip/stack/Tuple.hxx>
|
||||
|
||||
namespace gateway
|
||||
{
|
||||
|
||||
class MediaEndpoint
|
||||
{
|
||||
public:
|
||||
MediaEndpoint() : mSsrc(resip::Random::getRandom()), mRelayDatagramLen(0), mSendTimeMs(0), mRecvTimeMs(0), mKeepaliveMode(false) {}
|
||||
|
||||
resip::Tuple mTuple;
|
||||
unsigned int mSsrc;
|
||||
std::unique_ptr<char[]> mRelayDatagram;
|
||||
int mRelayDatagramLen;
|
||||
uint64_t mSendTimeMs;
|
||||
uint64_t mRecvTimeMs;
|
||||
bool mKeepaliveMode;
|
||||
|
||||
void reset()
|
||||
{
|
||||
mTuple = resip::Tuple();
|
||||
mRelayDatagram.release();
|
||||
mRelayDatagramLen = 0;
|
||||
mKeepaliveMode = false;
|
||||
}
|
||||
};
|
||||
|
||||
class MediaRelayPort
|
||||
{
|
||||
public:
|
||||
MediaRelayPort();
|
||||
MediaRelayPort(resip::Socket& v4fd, resip::Tuple& v4tuple, resip::Socket& v6fd, resip::Tuple& v6tuple);
|
||||
MediaRelayPort(resip::Socket& v4fd, resip::Tuple& v4tuple);
|
||||
~MediaRelayPort();
|
||||
|
||||
// V4 and V6 fd's and tuples
|
||||
resip::Socket mV4Fd;
|
||||
resip::Tuple mLocalV4Tuple;
|
||||
|
||||
resip::Socket mV6Fd;
|
||||
resip::Tuple mLocalV6Tuple;
|
||||
|
||||
// Sender data
|
||||
MediaEndpoint mFirstEndpoint;
|
||||
MediaEndpoint mSecondEndpoint;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* ====================================================================
|
||||
|
||||
Copyright (c) 2009, SIP Spectrum, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of SIP Spectrum nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
==================================================================== */
|
||||
|
||||
1508
src/libs/resiprocate/apps/ichat-gw/Server.cxx
Normal file
1508
src/libs/resiprocate/apps/ichat-gw/Server.cxx
Normal file
File diff suppressed because it is too large
Load Diff
362
src/libs/resiprocate/apps/ichat-gw/Server.hxx
Normal file
362
src/libs/resiprocate/apps/ichat-gw/Server.hxx
Normal file
@@ -0,0 +1,362 @@
|
||||
#if !defined(Server_hxx)
|
||||
#define Server_hxx
|
||||
|
||||
#include <map>
|
||||
|
||||
#include <resip/stack/TransactionUser.hxx>
|
||||
#include <resip/stack/EventStackThread.hxx>
|
||||
#include <rutil/SelectInterruptor.hxx>
|
||||
#include <resip/stack/UdpTransport.hxx>
|
||||
#include <resip/dum/MasterProfile.hxx>
|
||||
#include <resip/dum/DumShutdownHandler.hxx>
|
||||
#include <resip/dum/DialogUsageManager.hxx>
|
||||
#include <resip/dum/InviteSessionHandler.hxx>
|
||||
#include <resip/dum/DialogSetHandler.hxx>
|
||||
#include <resip/dum/OutOfDialogHandler.hxx>
|
||||
#include <resip/dum/RedirectHandler.hxx>
|
||||
#include <resip/dum/SubscriptionHandler.hxx>
|
||||
#include <resip/dum/RegistrationHandler.hxx>
|
||||
#include <rutil/Log.hxx>
|
||||
#include <rutil/Mutex.hxx>
|
||||
|
||||
#include "ConfigParser.hxx"
|
||||
#include "B2BSession.hxx"
|
||||
#include "SipRegistration.hxx"
|
||||
#include "AddressTranslator.hxx"
|
||||
#include "MediaRelay.hxx"
|
||||
#include "IChatIPPortData.hxx"
|
||||
#include "IPCThread.hxx"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#ifdef WIN32
|
||||
#define sleepMs(t) Sleep(t)
|
||||
#else
|
||||
#define sleepMs(t) usleep(t*1000)
|
||||
#endif
|
||||
|
||||
#define SDP_ICHATGW_ORIGIN_USER "iChat-gw"
|
||||
|
||||
namespace gateway
|
||||
{
|
||||
|
||||
class ShutdownCmd;
|
||||
class B2BSession;
|
||||
|
||||
class Server : public ConfigParser,
|
||||
public IPCHandler,
|
||||
public resip::DumShutdownHandler,
|
||||
public resip::InviteSessionHandler,
|
||||
public resip::DialogSetHandler,
|
||||
public resip::OutOfDialogHandler,
|
||||
public resip::RedirectHandler,
|
||||
public resip::ClientSubscriptionHandler,
|
||||
public resip::ServerSubscriptionHandler,
|
||||
public resip::ClientRegistrationHandler,
|
||||
public resip::ExternalUnknownDatagramHandler
|
||||
{
|
||||
public:
|
||||
Server(int argc, char** argv);
|
||||
virtual ~Server();
|
||||
|
||||
/**
|
||||
Starts the SIP stack thread.
|
||||
|
||||
@note This should be called before calling process() in a loop
|
||||
*/
|
||||
void startup();
|
||||
|
||||
/**
|
||||
This should be called in a loop to give process cycles to the server.
|
||||
|
||||
@param timeoutMs Will return after timeoutMs if nothing to do.
|
||||
Application can do some work, but should call
|
||||
process again ASAP.
|
||||
*/
|
||||
void process(int timeoutMs); // call this in a loop
|
||||
|
||||
/**
|
||||
Used to initiate a shutdown of the server. This function blocks
|
||||
until the shutdown is complete.
|
||||
|
||||
@note There should not be an active process request when this
|
||||
is called.
|
||||
*/
|
||||
void shutdown();
|
||||
|
||||
// Utility Methods ////////////////////////////////////////////////////////////
|
||||
typedef enum
|
||||
{
|
||||
SubsystemAll,
|
||||
SubsystemContents,
|
||||
SubsystemDns,
|
||||
SubsystemDum,
|
||||
SubsystemSdp,
|
||||
SubsystemSip,
|
||||
SubsystemTransaction,
|
||||
SubsystemTransport,
|
||||
SubsystemStats,
|
||||
SubsystemGateway
|
||||
} LoggingSubsystem;
|
||||
|
||||
/**
|
||||
Static method that sets the logging level for a particular subsystem,
|
||||
or all subsystems.
|
||||
|
||||
@param level Logging level to set
|
||||
@param subsystem Subsystem to set level on
|
||||
|
||||
@note: Use Server::SubsystemAll to set the logging level on all
|
||||
subsystems
|
||||
*/
|
||||
static void setLogLevel(resip::Log::Level level, LoggingSubsystem subsystem=SubsystemAll);
|
||||
|
||||
/**
|
||||
Called by Jabber side of gateway to notify SIP side of iChat call request.
|
||||
|
||||
@param to Bare JID of endpoint we are proceeding to ring
|
||||
@param from Full JID of endpoint requesting the call
|
||||
*/
|
||||
void notifyIChatCallRequest(const std::string& to, const std::string& from);
|
||||
|
||||
/**
|
||||
Called by Jabber side of gateway to notify SIP side of cancelled iChat call request.
|
||||
|
||||
@param handle Handle of the B2BSession object for the call
|
||||
*/
|
||||
void notifyIChatCallCancelled(const B2BSessionHandle& handle);
|
||||
|
||||
/**
|
||||
Called by Jabber side of gateway to notify B2BSession that iChat call is proceeding.
|
||||
This call will cause a timeout timer to be deactiviated.
|
||||
|
||||
@param handle Handle of the B2BSession object for the call
|
||||
@param to Full JID of endpoint we are proceeding to ring
|
||||
*/
|
||||
void notifyIChatCallProceeding(const B2BSessionHandle& handle, const std::string& to);
|
||||
|
||||
/**
|
||||
Called by Jabber side of gateway to notify B2BSession that iChat call has failed.
|
||||
|
||||
@param handle Handle of the B2BSession object for the call
|
||||
@param statusCode Code representing the reason for the failure
|
||||
*/
|
||||
void notifyIChatCallFailed(const B2BSessionHandle& handle, unsigned int statusCode);
|
||||
|
||||
/**
|
||||
Called by Jabber side of gateway to notify B2BSession that iChat call setup
|
||||
has completed on the Jabber side, and that it now needs to continue via SIP.
|
||||
|
||||
@param handle Handle of the B2BSession object for the call
|
||||
@param remoteIPPortListBlob List of transports received from the iChat client via
|
||||
Jabber messaging - in proprietary iChat blob format
|
||||
*/
|
||||
void continueIChatCall(const B2BSessionHandle& handle, const std::string& remoteIPPortListBlob);
|
||||
|
||||
/**
|
||||
Called by Jabber side of gateway to request that a jabber user be registered on the
|
||||
configured SIP server. Note: The jabber user's JID is first transformed into a
|
||||
SIP URI using the configured translation rules. Note: calling this multiple times
|
||||
with the same jidToRegister is safe and will result in a no op.
|
||||
|
||||
@param jidToRegister - Jabber user's JID to register on the SIP server.
|
||||
*/
|
||||
void sipRegisterJabberUser(const std::string& jidToRegister);
|
||||
|
||||
/**
|
||||
Called by Jabber side of gateway to request that a jabber user be unregistered from the
|
||||
configured SIP server. Note: The jabber user's JID is first transformed into a
|
||||
SIP URI using the configured translation rules.
|
||||
|
||||
@param jidToUnregister - Jabber user's JID to unregister from the SIP server.
|
||||
*/
|
||||
void sipUnregisterJabberUser(const std::string& jidToUnregister);
|
||||
|
||||
/**
|
||||
Called by Jabber side of gateway to check if the JID to be subscribed will pass the
|
||||
translation rules.
|
||||
|
||||
@param to - JID of address being subscribed to
|
||||
@param from - JID of subscriber
|
||||
*/
|
||||
void checkSubscription(const std::string& to, const std::string& from);
|
||||
|
||||
B2BSession* findMatchingIChatB2BSession(const resip::SipMessage& msg);
|
||||
|
||||
protected:
|
||||
std::shared_ptr<resip::MasterProfile>& getMasterProfile() noexcept { return mProfile; }
|
||||
bool translateAddress(const resip::Data& address, resip::Data& translation, bool failIfNoRule=false);
|
||||
|
||||
// IPC Handler
|
||||
virtual void onNewIPCMsg(const IPCMsg& msg);
|
||||
|
||||
// External Unknown Packet Handler//////////////////////////////////////////////
|
||||
virtual void operator()(resip::UdpTransport* transport, const resip::Tuple& source, std::unique_ptr<resip::Data> unknownPacket);
|
||||
|
||||
// Shutdown Handler ////////////////////////////////////////////////////////////
|
||||
void onDumCanBeDeleted();
|
||||
|
||||
// Invite Session Handler /////////////////////////////////////////////////////
|
||||
virtual void onNewSession(resip::ClientInviteSessionHandle h, resip::InviteSession::OfferAnswerType oat, const resip::SipMessage& msg);
|
||||
virtual void onNewSession(resip::ServerInviteSessionHandle h, resip::InviteSession::OfferAnswerType oat, const resip::SipMessage& msg);
|
||||
virtual void onFailure(resip::ClientInviteSessionHandle h, const resip::SipMessage& msg);
|
||||
virtual void onEarlyMedia(resip::ClientInviteSessionHandle, const resip::SipMessage&, const resip::SdpContents&);
|
||||
virtual void onProvisional(resip::ClientInviteSessionHandle, const resip::SipMessage& msg);
|
||||
virtual void onConnected(resip::ClientInviteSessionHandle h, const resip::SipMessage& msg);
|
||||
virtual void onConnected(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
||||
virtual void onStaleCallTimeout(resip::ClientInviteSessionHandle);
|
||||
virtual void onTerminated(resip::InviteSessionHandle h, resip::InviteSessionHandler::TerminatedReason reason, const resip::SipMessage* msg);
|
||||
virtual void onRedirected(resip::ClientInviteSessionHandle, const resip::SipMessage& msg);
|
||||
virtual void onAnswer(resip::InviteSessionHandle, const resip::SipMessage& msg, const resip::SdpContents&);
|
||||
virtual void onOffer(resip::InviteSessionHandle handle, const resip::SipMessage& msg, const resip::SdpContents& offer);
|
||||
virtual void onOfferRequired(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
||||
virtual void onOfferRejected(resip::InviteSessionHandle, const resip::SipMessage* msg);
|
||||
virtual void onOfferRequestRejected(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
||||
virtual void onRemoteSdpChanged(resip::InviteSessionHandle, const resip::SipMessage& msg, const resip::SdpContents& sdp);
|
||||
virtual void onInfo(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
||||
virtual void onInfoSuccess(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
||||
virtual void onInfoFailure(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
||||
virtual void onRefer(resip::InviteSessionHandle, resip::ServerSubscriptionHandle, const resip::SipMessage& msg);
|
||||
virtual void onReferAccepted(resip::InviteSessionHandle, resip::ClientSubscriptionHandle, const resip::SipMessage& msg);
|
||||
virtual void onReferRejected(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
||||
virtual void onReferNoSub(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
||||
virtual void onMessage(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
||||
virtual void onMessageSuccess(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
||||
virtual void onMessageFailure(resip::InviteSessionHandle, const resip::SipMessage& msg);
|
||||
virtual void onForkDestroyed(resip::ClientInviteSessionHandle);
|
||||
|
||||
// DialogSetHandler //////////////////////////////////////////////
|
||||
virtual void onTrying(resip::AppDialogSetHandle, const resip::SipMessage& msg);
|
||||
virtual void onNonDialogCreatingProvisional(resip::AppDialogSetHandle, const resip::SipMessage& msg);
|
||||
|
||||
// ClientSubscriptionHandler ///////////////////////////////////////////////////
|
||||
virtual void onUpdatePending(resip::ClientSubscriptionHandle h, const resip::SipMessage& notify, bool outOfOrder);
|
||||
virtual void onUpdateActive(resip::ClientSubscriptionHandle h, const resip::SipMessage& notify, bool outOfOrder);
|
||||
virtual void onUpdateExtension(resip::ClientSubscriptionHandle, const resip::SipMessage& notify, bool outOfOrder);
|
||||
virtual void onTerminated(resip::ClientSubscriptionHandle h, const resip::SipMessage* notify);
|
||||
virtual void onNewSubscription(resip::ClientSubscriptionHandle h, const resip::SipMessage& notify);
|
||||
virtual int onRequestRetry(resip::ClientSubscriptionHandle h, int retryMinimum, const resip::SipMessage& notify);
|
||||
|
||||
// ServerSubscriptionHandler ///////////////////////////////////////////////////
|
||||
virtual void onNewSubscription(resip::ServerSubscriptionHandle, const resip::SipMessage& sub);
|
||||
virtual void onNewSubscriptionFromRefer(resip::ServerSubscriptionHandle, const resip::SipMessage& sub);
|
||||
virtual void onRefresh(resip::ServerSubscriptionHandle, const resip::SipMessage& sub);
|
||||
virtual void onTerminated(resip::ServerSubscriptionHandle);
|
||||
virtual void onReadyToSend(resip::ServerSubscriptionHandle, resip::SipMessage&);
|
||||
virtual void onNotifyRejected(resip::ServerSubscriptionHandle, const resip::SipMessage& msg);
|
||||
virtual void onError(resip::ServerSubscriptionHandle, const resip::SipMessage& msg);
|
||||
virtual void onExpiredByClient(resip::ServerSubscriptionHandle, const resip::SipMessage& sub, resip::SipMessage& notify);
|
||||
virtual void onExpired(resip::ServerSubscriptionHandle, resip::SipMessage& notify);
|
||||
virtual bool hasDefaultExpires() const;
|
||||
virtual uint32_t getDefaultExpires() const;
|
||||
|
||||
// OutOfDialogHandler //////////////////////////////////////////////////////////
|
||||
virtual void onSuccess(resip::ClientOutOfDialogReqHandle, const resip::SipMessage& response);
|
||||
virtual void onFailure(resip::ClientOutOfDialogReqHandle, const resip::SipMessage& response);
|
||||
virtual void onReceivedRequest(resip::ServerOutOfDialogReqHandle, const resip::SipMessage& request);
|
||||
|
||||
// RedirectHandler /////////////////////////////////////////////////////////////
|
||||
virtual void onRedirectReceived(resip::AppDialogSetHandle, const resip::SipMessage& response);
|
||||
virtual bool onTryingNextTarget(resip::AppDialogSetHandle, const resip::SipMessage& request);
|
||||
|
||||
// Registration Handler ////////////////////////////////////////////////////////
|
||||
virtual void onSuccess(resip::ClientRegistrationHandle h, const resip::SipMessage& response);
|
||||
virtual void onFailure(resip::ClientRegistrationHandle h, const resip::SipMessage& response);
|
||||
virtual void onRemoved(resip::ClientRegistrationHandle h, const resip::SipMessage& response);
|
||||
virtual int onRequestRetry(resip::ClientRegistrationHandle h, int retryMinimum, const resip::SipMessage& msg);
|
||||
|
||||
private:
|
||||
friend class ShutdownCmd;
|
||||
friend class B2BSession;
|
||||
friend class IChatCallTimeout;
|
||||
|
||||
resip::DialogUsageManager& getDialogUsageManager();
|
||||
|
||||
void post(resip::ApplicationMessage& message, unsigned int ms=0);
|
||||
void shutdownImpl();
|
||||
|
||||
friend class NotifyIChatCallRequestCmd;
|
||||
void notifyIChatCallRequestImpl(const std::string& to, const std::string& from);
|
||||
friend class NotifyIChatCallCancelledCmd;
|
||||
void notifyIChatCallCancelledImpl(const B2BSessionHandle& handle);
|
||||
friend class NotifyIChatCallProceedingCmd;
|
||||
void notifyIChatCallProceedingImpl(const B2BSessionHandle& handle, const std::string& to);
|
||||
friend class NotifyIChatCallFailedCmd;
|
||||
void notifyIChatCallFailedImpl(const B2BSessionHandle& handle, unsigned int statusCode);
|
||||
friend class ContinueIChatCallCmd;
|
||||
void continueIChatCallImpl(const B2BSessionHandle& handle, const std::string& remoteIPPortListBlob);
|
||||
friend class SipRegisterJabberUserCmd;
|
||||
void sipRegisterJabberUserImpl(const std::string& jidToRegister);
|
||||
friend class SipUnregisterJabberUserCmd;
|
||||
void sipUnregisterJabberUserImpl(const std::string& jidToUnregister);
|
||||
|
||||
std::shared_ptr<resip::MasterProfile> mProfile;
|
||||
resip::Security* mSecurity;
|
||||
resip::FdPollGrp *mPollGrp;
|
||||
resip::EventThreadInterruptor *mEventInterruptor;
|
||||
resip::SipStack mStack;
|
||||
resip::DialogUsageManager mDum;
|
||||
resip::EventStackThread mStackThread;
|
||||
volatile bool mDumShutdown;
|
||||
|
||||
typedef std::map<B2BSessionHandle, B2BSession*> B2BSessionMap;
|
||||
B2BSessionMap mB2BSessions;
|
||||
B2BSessionHandle mCurrentB2BSessionHandle;
|
||||
B2BSession* getB2BSession(const B2BSessionHandle& handle) const;
|
||||
B2BSessionHandle registerB2BSession(B2BSession *);
|
||||
void unregisterB2BSession(const B2BSessionHandle& handle);
|
||||
|
||||
friend class SipRegistration;
|
||||
typedef std::map<resip::Uri, SipRegistration*> RegistrationMap;
|
||||
RegistrationMap mRegistrations;
|
||||
void registerRegistration(SipRegistration *);
|
||||
void unregisterRegistration(SipRegistration *);
|
||||
|
||||
bool mIsV6Avail;
|
||||
IChatIPPortData mLocalIPPortData;
|
||||
|
||||
MediaRelay* mMediaRelay;
|
||||
|
||||
IPCThread* mIPCThread;
|
||||
|
||||
AddressTranslator mAddressTranslator;
|
||||
std::map<resip::DialogSetId,B2BSession*> mActiveSessions;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* ====================================================================
|
||||
|
||||
Copyright (c) 2009, SIP Spectrum, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of SIP Spectrum nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
==================================================================== */
|
||||
165
src/libs/resiprocate/apps/ichat-gw/SipRegistration.cxx
Normal file
165
src/libs/resiprocate/apps/ichat-gw/SipRegistration.cxx
Normal file
@@ -0,0 +1,165 @@
|
||||
#include "Server.hxx"
|
||||
#include "AppSubsystem.hxx"
|
||||
#include "SipRegistration.hxx"
|
||||
|
||||
#include <rutil/Log.hxx>
|
||||
#include <rutil/Logger.hxx>
|
||||
#include <resip/dum/DialogUsageManager.hxx>
|
||||
#include <resip/dum/ClientRegistration.hxx>
|
||||
|
||||
using namespace gateway;
|
||||
using namespace resip;
|
||||
using namespace std;
|
||||
|
||||
#define RESIPROCATE_SUBSYSTEM AppSubsystem::GATEWAY
|
||||
|
||||
SipRegistration::SipRegistration(Server& server, DialogUsageManager& dum, Uri& aor)
|
||||
: AppDialogSet(dum),
|
||||
mServer(server),
|
||||
mDum(dum),
|
||||
mAor(aor),
|
||||
mEnded(false)
|
||||
{
|
||||
mServer.registerRegistration(this);
|
||||
}
|
||||
|
||||
SipRegistration::~SipRegistration()
|
||||
{
|
||||
mServer.unregisterRegistration(this);
|
||||
}
|
||||
|
||||
const resip::Uri&
|
||||
SipRegistration::getAor()
|
||||
{
|
||||
return mAor;
|
||||
}
|
||||
|
||||
void
|
||||
SipRegistration::end()
|
||||
{
|
||||
if(!mEnded)
|
||||
{
|
||||
mEnded = true;
|
||||
if(mRegistrationHandle.isValid())
|
||||
{
|
||||
try
|
||||
{
|
||||
// If ended - then just shutdown registration - likely due to shutdown
|
||||
mRegistrationHandle->end();
|
||||
}
|
||||
catch(BaseException&)
|
||||
{
|
||||
// If end() call is nested - it will throw - catch here so that processing continues normally
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const NameAddrs&
|
||||
SipRegistration::getContactAddresses()
|
||||
{
|
||||
static NameAddrs empty;
|
||||
if(mRegistrationHandle.isValid())
|
||||
{
|
||||
return mRegistrationHandle->allContacts(); // .slg. note: myContacts is not sufficient, since they do not contain the stack populated transport address
|
||||
}
|
||||
else
|
||||
{
|
||||
return empty;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Registration Handler ////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
SipRegistration::onSuccess(ClientRegistrationHandle h, const SipMessage& msg)
|
||||
{
|
||||
InfoLog(<< "onSuccess(ClientRegistrationHandle): aor=" << mAor << ", msg=" << msg.brief());
|
||||
if(!mEnded)
|
||||
{
|
||||
mRegistrationHandle = h;
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
// If ended - then just shutdown registration - likely due to shutdown
|
||||
h->end();
|
||||
}
|
||||
catch(BaseException&)
|
||||
{
|
||||
// If end() call is nested - it will throw - catch here so that processing continues normally
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SipRegistration::onFailure(ClientRegistrationHandle h, const SipMessage& msg)
|
||||
{
|
||||
InfoLog(<< "onFailure(ClientRegistrationHandle): aor=" << mAor << ", msg=" << msg.brief());
|
||||
if(!mEnded)
|
||||
{
|
||||
mRegistrationHandle = h;
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
// If we don't have a handle - then just shutdown registration - likely due to shutdown
|
||||
h->end();
|
||||
}
|
||||
catch(BaseException&)
|
||||
{
|
||||
// If end() call is nested - it will throw - catch here so that processing continues normally
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SipRegistration::onRemoved(ClientRegistrationHandle h, const SipMessage&msg)
|
||||
{
|
||||
InfoLog(<< "onRemoved(ClientRegistrationHandle): aor=" << mAor << ", msg=" << msg.brief());
|
||||
}
|
||||
|
||||
int
|
||||
SipRegistration::onRequestRetry(ClientRegistrationHandle h, int retryMinimum, const SipMessage& msg)
|
||||
{
|
||||
InfoLog(<< "onRequestRetry(ClientRegistrationHandle): aor=" << mAor << ", msg=" << msg.brief());
|
||||
return -1; // Let Profile retry setting take effect
|
||||
}
|
||||
|
||||
/* ====================================================================
|
||||
|
||||
Copyright (c) 2009, SIP Spectrum, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of SIP Spectrum nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
==================================================================== */
|
||||
|
||||
89
src/libs/resiprocate/apps/ichat-gw/SipRegistration.hxx
Normal file
89
src/libs/resiprocate/apps/ichat-gw/SipRegistration.hxx
Normal file
@@ -0,0 +1,89 @@
|
||||
#if !defined(SipRegistration_hxx)
|
||||
#define SipRegistration_hxx
|
||||
|
||||
#include <resip/dum/AppDialogSet.hxx>
|
||||
#include <resip/dum/InviteSessionHandler.hxx>
|
||||
#include <resip/dum/DialogSetHandler.hxx>
|
||||
#include <resip/dum/SubscriptionHandler.hxx>
|
||||
|
||||
#include "Server.hxx"
|
||||
|
||||
namespace resip
|
||||
{
|
||||
class DialogUsageManager;
|
||||
class SipMessage;
|
||||
}
|
||||
|
||||
namespace gateway
|
||||
{
|
||||
class Server;
|
||||
|
||||
/**
|
||||
This class is used to manage active SIP registrations.
|
||||
|
||||
Author: Scott Godin (sgodin AT SipSpectrum DOT com)
|
||||
*/
|
||||
|
||||
class SipRegistration : public resip::AppDialogSet
|
||||
{
|
||||
public:
|
||||
SipRegistration(Server& server, resip::DialogUsageManager& dum, resip::Uri& aor);
|
||||
virtual ~SipRegistration();
|
||||
|
||||
virtual void end();
|
||||
|
||||
const resip::Uri& getAor();
|
||||
const resip::NameAddrs& getContactAddresses();
|
||||
|
||||
// Registration Handler ////////////////////////////////////////////////////////
|
||||
virtual void onSuccess(resip::ClientRegistrationHandle h, const resip::SipMessage& response);
|
||||
virtual void onFailure(resip::ClientRegistrationHandle h, const resip::SipMessage& response);
|
||||
virtual void onRemoved(resip::ClientRegistrationHandle h, const resip::SipMessage& response);
|
||||
virtual int onRequestRetry(resip::ClientRegistrationHandle h, int retryMinimum, const resip::SipMessage& msg);
|
||||
|
||||
private:
|
||||
Server &mServer;
|
||||
resip::DialogUsageManager &mDum;
|
||||
resip::Uri mAor;
|
||||
bool mEnded;
|
||||
resip::ClientRegistrationHandle mRegistrationHandle;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* ====================================================================
|
||||
|
||||
Copyright (c) 2009, SIP Spectrum, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of SIP Spectrum nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
==================================================================== */
|
||||
|
||||
176
src/libs/resiprocate/apps/ichat-gw/Thread.cxx
Normal file
176
src/libs/resiprocate/apps/ichat-gw/Thread.cxx
Normal file
@@ -0,0 +1,176 @@
|
||||
#include "rutil/ResipAssert.h"
|
||||
|
||||
#include "Thread.hxx"
|
||||
|
||||
using namespace gateway;
|
||||
using namespace std;
|
||||
|
||||
#if defined(WIN32)
|
||||
#include <stdio.h>
|
||||
#include <tchar.h>
|
||||
#include <time.h>
|
||||
#include <process.h> // for _beginthreadex()
|
||||
typedef unsigned(__stdcall *THREAD_START_ROUTINE)(void*);
|
||||
#endif
|
||||
|
||||
#include "rutil/ResipAssert.h"
|
||||
#include <iostream>
|
||||
|
||||
extern "C"
|
||||
{
|
||||
static void*
|
||||
#ifdef WIN32
|
||||
__stdcall
|
||||
#endif
|
||||
threadWrapper( void* parm )
|
||||
{
|
||||
resip_assert( parm );
|
||||
Thread* t = static_cast < Thread* > ( parm );
|
||||
|
||||
resip_assert( t );
|
||||
t->thread();
|
||||
#ifdef WIN32
|
||||
_endthreadex(0);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
Thread::Thread() :
|
||||
#ifdef WIN32
|
||||
mThread(0),
|
||||
#endif
|
||||
mId(0), mShutdown(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Thread::~Thread()
|
||||
{
|
||||
shutdown();
|
||||
join();
|
||||
}
|
||||
|
||||
void
|
||||
Thread::run()
|
||||
{
|
||||
resip_assert(mId == 0);
|
||||
|
||||
#if defined(WIN32)
|
||||
mThread =
|
||||
(HANDLE)_beginthreadex
|
||||
(
|
||||
NULL, // LPSECURITY_ATTRIBUTES lpThreadAttributes, // pointer to security attributes
|
||||
0, // DWORD dwStackSize, // initial thread stack size
|
||||
THREAD_START_ROUTINE
|
||||
(threadWrapper), // LPTHREAD_START_ROUTINE lpStartAddress, // pointer to thread function
|
||||
this, //LPVOID lpParameter, // argument for new thread
|
||||
0, //DWORD dwCreationFlags, // creation flags
|
||||
&mId// LPDWORD lpThreadId // pointer to receive thread ID
|
||||
);
|
||||
resip_assert( mThread != 0 );
|
||||
#else
|
||||
// spawn the thread
|
||||
if ( int retval = pthread_create( &mId, 0, threadWrapper, this) )
|
||||
{
|
||||
std::cerr << "Failed to spawn thread: " << retval << std::endl;
|
||||
resip_assert(0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
Thread::join()
|
||||
{
|
||||
if (mId == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(WIN32)
|
||||
DWORD exitCode;
|
||||
while (true)
|
||||
{
|
||||
if (GetExitCodeThread(mThread,&exitCode) != 0)
|
||||
{
|
||||
if (exitCode != STILL_ACTIVE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
WaitForSingleObject(mThread,INFINITE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CloseHandle(mThread);
|
||||
mThread=0;
|
||||
#else
|
||||
void* stat;
|
||||
if (mId != pthread_self())
|
||||
{
|
||||
int r = pthread_join( mId , &stat );
|
||||
if ( r != 0 )
|
||||
{
|
||||
cerr << "Internal error: pthread_join() returned " << r << endl;
|
||||
resip_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
mId = 0;
|
||||
}
|
||||
|
||||
void
|
||||
Thread::shutdown()
|
||||
{
|
||||
mShutdown = true;
|
||||
}
|
||||
|
||||
bool
|
||||
Thread::isShutdown() const
|
||||
{
|
||||
return mShutdown;
|
||||
}
|
||||
|
||||
|
||||
/* ====================================================================
|
||||
|
||||
Copyright (c) 2009, SIP Spectrum, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of SIP Spectrum nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
==================================================================== */
|
||||
|
||||
85
src/libs/resiprocate/apps/ichat-gw/Thread.hxx
Normal file
85
src/libs/resiprocate/apps/ichat-gw/Thread.hxx
Normal file
@@ -0,0 +1,85 @@
|
||||
#if !defined(Thread_hxx)
|
||||
#define Thread_hxx
|
||||
|
||||
#ifdef WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
# include <windows.h>
|
||||
# include <winsock2.h>
|
||||
#undef WIN32_LEAN_AND_MEAN
|
||||
#else
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
|
||||
namespace gateway
|
||||
{
|
||||
|
||||
class Thread
|
||||
{
|
||||
public:
|
||||
Thread();
|
||||
virtual ~Thread();
|
||||
|
||||
virtual void run();
|
||||
void join();
|
||||
virtual void shutdown();
|
||||
bool isShutdown() const;
|
||||
|
||||
#ifdef WIN32
|
||||
typedef unsigned int Id;
|
||||
#else
|
||||
typedef pthread_t Id;
|
||||
#endif
|
||||
|
||||
virtual void thread() = 0;
|
||||
|
||||
protected:
|
||||
#ifdef WIN32
|
||||
HANDLE mThread;
|
||||
#endif
|
||||
Id mId;
|
||||
volatile bool mShutdown;
|
||||
|
||||
private:
|
||||
// Suppress copying
|
||||
Thread(const Thread &);
|
||||
const Thread & operator=(const Thread &);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* ====================================================================
|
||||
|
||||
Copyright (c) 2009, SIP Spectrum, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of SIP Spectrum nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
==================================================================== */
|
||||
|
||||
36
src/libs/resiprocate/apps/ichat-gw/Version.hxx
Normal file
36
src/libs/resiprocate/apps/ichat-gw/Version.hxx
Normal file
@@ -0,0 +1,36 @@
|
||||
#define ICHATGW_VERSION_STRING "0.1"
|
||||
|
||||
/* ====================================================================
|
||||
|
||||
Copyright (c) 2009, SIP Spectrum, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of SIP Spectrum nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
==================================================================== */
|
||||
|
||||
Binary file not shown.
Binary file not shown.
154
src/libs/resiprocate/apps/ichat-gw/ichat-gw.config
Normal file
154
src/libs/resiprocate/apps/ichat-gw/ichat-gw.config
Normal file
@@ -0,0 +1,154 @@
|
||||
########################################################
|
||||
# ichat-gw configuration file
|
||||
########################################################
|
||||
|
||||
|
||||
########################################################
|
||||
# SIP settings
|
||||
########################################################
|
||||
|
||||
# Local IP Address to bind SIP transports to. If left blank
|
||||
# ichat-gw will bind to all adapters.
|
||||
#IPAddress = 192.168.1.106
|
||||
#IPAddress = 2001:5c0:1000:a::6d
|
||||
IPAddress =
|
||||
|
||||
# Comma separated list of DNS servers, overrides default OS detected list (leave blank for default)
|
||||
DNSServers =
|
||||
|
||||
# Used in From header of SIP calls, when caller is unknown. Value must be a valid formatted SIP
|
||||
# NameAddr. Ie. “{displayname}” <{SIP URI}>. Currently this setting is only used when
|
||||
# calling iChat endpoints and is never displayed to the end user.
|
||||
SIPGatewayIdentity = "iChat-gw" <sip:ichat-gw@blitzzgod.com>
|
||||
|
||||
# Local port to listen on for SIP messages over UDP or TCP
|
||||
UDPTCPPort = 5070
|
||||
|
||||
# Local port to listen on for SIP messages over TLS
|
||||
TLSPort = 5071
|
||||
|
||||
# TLS domain name for this server (note: domain cert for this domain must be present)
|
||||
TLSDomain =
|
||||
|
||||
# Enable/Disable TCP/UDP CRLFCRLF keepalive packets for SIP endpoints
|
||||
# 1|true|on|enable to enable, 0|false|off|disable to disable
|
||||
KeepAlives = enable
|
||||
|
||||
# URI of a proxy server to use a SIP outbound proxy. This setting should not be required if
|
||||
# proper DNS based SIP routing is operational.
|
||||
OutboundProxy =
|
||||
|
||||
# SIP Registration Time - the requested amount of seconds between SIP re-registration requests
|
||||
# Set to 0, to instruct the iChat gateway not to perform any registrations
|
||||
RegistrationTime = 3600
|
||||
|
||||
# SIP Registration Retry Time - the requested amount of seconds between retrying SIP registration
|
||||
# requests after a registration failure.
|
||||
RegistrationRetryTime = 120
|
||||
|
||||
|
||||
########################################################
|
||||
# General settings
|
||||
########################################################
|
||||
|
||||
# Logging level: NONE|CRIT|ERR|WARNING|INFO|DEBUG|STACK
|
||||
LogLevel = INFO
|
||||
|
||||
# Log Filename
|
||||
LogFilename = ichat-gw.log
|
||||
|
||||
# Log file Max Lines
|
||||
LogFileMaxLines = 50000
|
||||
|
||||
# Gateway IPC Port - for IPC UDP socket bound to 127.0.0.1
|
||||
GatewayIPCPort = 2078
|
||||
|
||||
# Jabber Connector IPC Port - for IPC UDP socket bound to 127.0.0.1
|
||||
JabberConnectorIPCPort = 2079
|
||||
|
||||
# Timeout for obtaining iChat Resources when an iChat user is called.
|
||||
IChatProceedingTimeout = 5000
|
||||
|
||||
# If enabled then any time an IChat endpoint is involved then the media relay will be used.
|
||||
# If disabled then the media relay is only used if iChat is originator of a Click-to-dial call.
|
||||
# Note: The media relay MUST be used to perform RTP IPV4<->IPV6 translation and to avoid
|
||||
# media stream timeout during a SIP phone hold.
|
||||
# 1|true|on|enable to enable, 0|false|off|disable to disable
|
||||
AlwaysRelayIChatMedia = true
|
||||
|
||||
# Prefer IPv6 over IPv4 - this setting controls which IP address we select when presented
|
||||
# with the list of IP addresses for an iChat endpoint
|
||||
PreferIPv6 = true
|
||||
|
||||
# Comma separated codec ID filter list - specifies non-interopable codecs that should
|
||||
# be filtered from Sdp Offers.
|
||||
# Note: Default is 3 (GSM), since it has proven non-interopable between iChat and SNOM phones
|
||||
CodecIdFilterList = 3
|
||||
|
||||
# Media relay port range min/max settings. These settings define the range of ports that will be used
|
||||
# by the media relay.
|
||||
MediaRelayPortRangeMin = 8000
|
||||
MediaRelayPortRangeMax = 9999
|
||||
|
||||
|
||||
########################################################
|
||||
# Jabber settings
|
||||
########################################################
|
||||
|
||||
# Hostname or IP address of the Jabber server to connect to
|
||||
JabberServer = jabber.blitzzgod.com
|
||||
|
||||
# Identity of this component - note: domain suffix should match Jabber server domain
|
||||
JabberComponentName = ichat-gw.jabber.blitzzgod.com
|
||||
|
||||
# Jabber Component Password required in order to connect to Jabber server as a component
|
||||
JabberComponentPassword = password
|
||||
|
||||
# Jabber Component Port - port on Jabber server that accepts component connections
|
||||
JabberComponentPort = 5275
|
||||
|
||||
# Duration between Jabber ping messages sent to the server, in order to keep the component connection alive
|
||||
JabberServerPingDuration = 60
|
||||
|
||||
# Username for the iChat Gateway control user - Note: iChat users of the Gateway must add this user to their roster
|
||||
JabberControlUsername = control
|
||||
|
||||
|
||||
########################################################
|
||||
# Address Translation Rules (must be listed in pairs)
|
||||
########################################################
|
||||
|
||||
# Rule for mapping any sip address to appropriate jabber JID/domain
|
||||
TranslationPattern=^sip:(.*)@(.*)$
|
||||
TranslationOutput=xmpp:$1@jabber.blitzzgod.com
|
||||
|
||||
#Rule for mapping any xmpp address to appropriate SIP URI/domain
|
||||
TranslationPattern=^xmpp:(.*)@(.*)$
|
||||
TranslationOutput=sip:$1@blitzzgod.com
|
||||
|
||||
|
||||
########################################################
|
||||
# TLS Configurations
|
||||
########################################################
|
||||
|
||||
#Local path to DH Parameters file
|
||||
TLSDHParamsFilename =
|
||||
|
||||
# Local path to TLS Certificate
|
||||
TLSCertificate =
|
||||
|
||||
# Local path to Private key file
|
||||
TLSPrivateKey =
|
||||
|
||||
# Pass phrase of private key file (can be left blank)
|
||||
TLSPrivateKeyPassPhrase =
|
||||
|
||||
########################################################
|
||||
# iChat Jabber Connector Settings
|
||||
########################################################
|
||||
|
||||
# Path to iChat jabber connector (ichat-gw-jc) executable
|
||||
IchatJabberConnectorPath = ichat-gw-jc
|
||||
|
||||
#For Windows
|
||||
#IchatJabberConnectorPath = ichat-gw-jc.exe
|
||||
115
src/libs/resiprocate/apps/ichat-gw/ichat-gw.cxx
Normal file
115
src/libs/resiprocate/apps/ichat-gw/ichat-gw.cxx
Normal file
@@ -0,0 +1,115 @@
|
||||
#include <signal.h>
|
||||
|
||||
#include "AppSubsystem.hxx"
|
||||
#include "Server.hxx"
|
||||
|
||||
#include <rutil/Log.hxx>
|
||||
#include <rutil/Logger.hxx>
|
||||
#include <rutil/DnsUtil.hxx>
|
||||
#include <rutil/BaseException.hxx>
|
||||
#include <resip/stack/NameAddr.hxx>
|
||||
#include <rutil/WinLeakCheck.hxx>
|
||||
|
||||
using namespace gateway;
|
||||
using namespace resip;
|
||||
using namespace std;
|
||||
|
||||
#define RESIPROCATE_SUBSYSTEM AppSubsystem::GATEWAY
|
||||
|
||||
static bool finished = false;
|
||||
|
||||
static void
|
||||
signalHandler(int signo)
|
||||
{
|
||||
//std::cerr << "Shutting down..." << endl;
|
||||
finished = true;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char** argv)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
if ( signal( SIGPIPE, SIG_IGN) == SIG_ERR)
|
||||
{
|
||||
cerr << "Couldn't install signal handler for SIGPIPE" << endl;
|
||||
exit(-1);
|
||||
}
|
||||
#else
|
||||
#if defined(_DEBUG) && defined(LEAK_CHECK)
|
||||
resip::FindMemoryLeaks fml;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if ( signal( SIGINT, signalHandler ) == SIG_ERR )
|
||||
{
|
||||
cerr << "Couldn't install signal handler for SIGINT" << endl;
|
||||
exit( -1 );
|
||||
}
|
||||
|
||||
if ( signal( SIGTERM, signalHandler ) == SIG_ERR )
|
||||
{
|
||||
cerr << "Couldn't install signal handler for SIGTERM" << endl;
|
||||
exit( -1 );
|
||||
}
|
||||
|
||||
initNetwork();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Create Server
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
{
|
||||
Server server(argc, argv);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Startup and run...
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
server.startup();
|
||||
|
||||
while(true)
|
||||
{
|
||||
server.process(50);
|
||||
if(finished) break;
|
||||
}
|
||||
|
||||
server.shutdown();
|
||||
}
|
||||
|
||||
InfoLog(<< "ichat-gw is shutdown.");
|
||||
sleepSeconds(2);
|
||||
}
|
||||
|
||||
/* ====================================================================
|
||||
|
||||
Copyright (c) 2009, SIP Spectrum, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of SIP Spectrum nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
==================================================================== */
|
||||
|
||||
72
src/libs/resiprocate/apps/ichat-gw/ichat-gw_9_0.sln
Normal file
72
src/libs/resiprocate/apps/ichat-gw/ichat-gw_9_0.sln
Normal file
@@ -0,0 +1,72 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 10.00
|
||||
# Visual Studio 2008
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ichat-gw", "ichat-gw_9_0.vcproj", "{8BA87397-9B42-4820-BA53-62FF35C22CAD}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{A77DCD34-20CA-4602-B185-EE3EAD97713D} = {A77DCD34-20CA-4602-B185-EE3EAD97713D}
|
||||
{2A8BE839-6466-4001-B224-8F1C3168D04A} = {2A8BE839-6466-4001-B224-8F1C3168D04A}
|
||||
{12720B4D-F4FC-4502-8FA9-589BF5166216} = {12720B4D-F4FC-4502-8FA9-589BF5166216}
|
||||
{38594885-CF9C-4C5F-B3F0-E4969D7E3F58} = {38594885-CF9C-4C5F-B3F0-E4969D7E3F58}
|
||||
{96CD935E-1951-43B8-AF75-F1C06B3778C1} = {96CD935E-1951-43B8-AF75-F1C06B3778C1}
|
||||
{3D0E5CEB-93DC-4FDB-918B-D08FA369E106} = {3D0E5CEB-93DC-4FDB-918B-D08FA369E106}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rutil", "..\..\rutil\rutil_9_0.vcproj", "{3D0E5CEB-93DC-4FDB-918B-D08FA369E106}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "resiprocate", "..\..\resip\stack\resiprocate_9_0.vcproj", "{2A8BE839-6466-4001-B224-8F1C3168D04A}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dum", "..\..\resip\dum\dum_9_0.vcproj", "{12720B4D-F4FC-4502-8FA9-589BF5166216}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ares", "..\..\rutil\dns\ares\ares_9_0.vcproj", "{96CD935E-1951-43B8-AF75-F1C06B3778C1}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pcre", "..\..\contrib\pcre\pcre_9_0.vcproj", "{38594885-CF9C-4C5F-B3F0-E4969D7E3F58}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jabberconnector", "jabberconnector\jabberconnector_9_0.vcproj", "{A77DCD34-20CA-4602-B185-EE3EAD97713D}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{EEDA9797-BEAA-4377-96FC-C4B41E063290} = {EEDA9797-BEAA-4377-96FC-C4B41E063290}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gloox", "..\..\contrib\gloox\gloox.vcproj", "{EEDA9797-BEAA-4377-96FC-C4B41E063290}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{8BA87397-9B42-4820-BA53-62FF35C22CAD}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{8BA87397-9B42-4820-BA53-62FF35C22CAD}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{8BA87397-9B42-4820-BA53-62FF35C22CAD}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{8BA87397-9B42-4820-BA53-62FF35C22CAD}.Release|Win32.Build.0 = Release|Win32
|
||||
{3D0E5CEB-93DC-4FDB-918B-D08FA369E106}.Debug|Win32.ActiveCfg = SSL-Debug|Win32
|
||||
{3D0E5CEB-93DC-4FDB-918B-D08FA369E106}.Debug|Win32.Build.0 = SSL-Debug|Win32
|
||||
{3D0E5CEB-93DC-4FDB-918B-D08FA369E106}.Release|Win32.ActiveCfg = SSL-Release|Win32
|
||||
{3D0E5CEB-93DC-4FDB-918B-D08FA369E106}.Release|Win32.Build.0 = SSL-Release|Win32
|
||||
{2A8BE839-6466-4001-B224-8F1C3168D04A}.Debug|Win32.ActiveCfg = SSL-Debug|Win32
|
||||
{2A8BE839-6466-4001-B224-8F1C3168D04A}.Debug|Win32.Build.0 = SSL-Debug|Win32
|
||||
{2A8BE839-6466-4001-B224-8F1C3168D04A}.Release|Win32.ActiveCfg = SSL-Release|Win32
|
||||
{2A8BE839-6466-4001-B224-8F1C3168D04A}.Release|Win32.Build.0 = SSL-Release|Win32
|
||||
{12720B4D-F4FC-4502-8FA9-589BF5166216}.Debug|Win32.ActiveCfg = SSL-Debug|Win32
|
||||
{12720B4D-F4FC-4502-8FA9-589BF5166216}.Debug|Win32.Build.0 = SSL-Debug|Win32
|
||||
{12720B4D-F4FC-4502-8FA9-589BF5166216}.Release|Win32.ActiveCfg = SSL-Release|Win32
|
||||
{12720B4D-F4FC-4502-8FA9-589BF5166216}.Release|Win32.Build.0 = SSL-Release|Win32
|
||||
{96CD935E-1951-43B8-AF75-F1C06B3778C1}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{96CD935E-1951-43B8-AF75-F1C06B3778C1}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{96CD935E-1951-43B8-AF75-F1C06B3778C1}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{96CD935E-1951-43B8-AF75-F1C06B3778C1}.Release|Win32.Build.0 = Release|Win32
|
||||
{38594885-CF9C-4C5F-B3F0-E4969D7E3F58}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{38594885-CF9C-4C5F-B3F0-E4969D7E3F58}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{38594885-CF9C-4C5F-B3F0-E4969D7E3F58}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{38594885-CF9C-4C5F-B3F0-E4969D7E3F58}.Release|Win32.Build.0 = Release|Win32
|
||||
{A77DCD34-20CA-4602-B185-EE3EAD97713D}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{A77DCD34-20CA-4602-B185-EE3EAD97713D}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{A77DCD34-20CA-4602-B185-EE3EAD97713D}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{A77DCD34-20CA-4602-B185-EE3EAD97713D}.Release|Win32.Build.0 = Release|Win32
|
||||
{EEDA9797-BEAA-4377-96FC-C4B41E063290}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{EEDA9797-BEAA-4377-96FC-C4B41E063290}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{EEDA9797-BEAA-4377-96FC-C4B41E063290}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{EEDA9797-BEAA-4377-96FC-C4B41E063290}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
300
src/libs/resiprocate/apps/ichat-gw/ichat-gw_9_0.vcproj
Normal file
300
src/libs/resiprocate/apps/ichat-gw/ichat-gw_9_0.vcproj
Normal file
@@ -0,0 +1,300 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="9.00"
|
||||
Name="ichat-gw"
|
||||
ProjectGUID="{8BA87397-9B42-4820-BA53-62FF35C22CAD}"
|
||||
RootNamespace="ichatgw"
|
||||
Keyword="Win32Proj"
|
||||
TargetFrameworkVersion="131072"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""$(ProjectDir)../../";"$(ProjectDir)../../contrib/openssl/include";"$(ProjectDir)../../contrib/openssl/inc32";"$(ProjectDir)../../contrib/pcre""
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;USE_SSL;USE_IPV6"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="false"
|
||||
DebugInformationFormat="4"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="Ws2_32.lib winmm.lib Dnsapi.lib Iphlpapi.lib crypt32.lib "$(ProjectDir)..\..\contrib\openssl\lib\vc\static\libeay32MDd.lib" "$(ProjectDir)..\..\contrib\openssl\lib\vc\static\ssleay32MDd.lib""
|
||||
LinkIncremental="2"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="1"
|
||||
RandomizedBaseAddress="1"
|
||||
DataExecutionPrevention="0"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories=""$(ProjectDir)../../";"$(ProjectDir)../../contrib/openssl/include";"$(ProjectDir)../../contrib/openssl/inc32";"$(ProjectDir)../../contrib/pcre""
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;USE_SSL;USE_IPV6"
|
||||
RuntimeLibrary="2"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="false"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="Ws2_32.lib winmm.lib Dnsapi.lib Iphlpapi.lib crypt32.lib "$(ProjectDir)..\..\contrib\openssl\lib\vc\static\libeay32MD.lib" "$(ProjectDir)..\..\contrib\openssl\lib\vc\static\ssleay32MD.lib""
|
||||
LinkIncremental="1"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="1"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
RandomizedBaseAddress="1"
|
||||
DataExecutionPrevention="0"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\AddressTranslator.cxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\AppSubsystem.cxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\B2BSession.cxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\ConfigParser.cxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\ichat-gw.cxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\IChatIPPortData.cxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\IPCThread.cxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\MediaRelay.cxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\MediaRelayPort.cxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Server.cxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\SipRegistration.cxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Thread.cxx"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\AddressTranslator.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\AppSubsystem.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\B2BSession.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\ConfigParser.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\IChatGatewayCmds.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\IChatIPPortData.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\IPCThread.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\MediaRelay.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\MediaRelayPort.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Server.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\SipRegistration.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Thread.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Version.hxx"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
|
||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
||||
>
|
||||
</Filter>
|
||||
<File
|
||||
RelativePath=".\ichat-gw.config"
|
||||
>
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user