Compare commits

..

4 Commits

Author SHA1 Message Date
sauwming ac39c675a3 Fixed UAS tsx tp error handling and PJSIP test 2024-01-02 12:08:26 +08:00
sauwming f396cd4788 Merge branch 'master' into tsx-tp-error 2024-01-02 12:05:40 +08:00
sauwming b5be1717cd Add doc 2023-12-18 12:00:55 +08:00
sauwming d931d78ffe Prevent immediate tsx termination upon transport error 2023-12-15 12:07:57 +08:00
113 changed files with 672 additions and 7595 deletions

View File

@ -23,11 +23,11 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: install dependencies
run: brew install openssl opencore-amr swig sipp
run: brew install openssl@1.1 opencore-amr swig sipp
- name: config site
run: cd pjlib/include/pj && cp config_site_test.h config_site.h
- name: configure
run: CFLAGS="-g $(pkg-config --cflags openssl) $(pkg-config --cflags opencore-amrnb) -fPIC" LDFLAGS="$(pkg-config --libs-only-L openssl) $(pkg-config --libs-only-L openssl)/lib $(pkg-config --libs-only-L opencore-amrnb)" CXXFLAGS="-g -fPIC" ./configure
run: CFLAGS="-g -I/usr/local/include -I/usr/local/opt/openssl@1.1/include -fPIC" LDFLAGS="-L/usr/local/lib -L/usr/local/opt/openssl@1.1/lib" CXXFLAGS="-g -fPIC" ./configure
- name: make
run: make
- name: set up Python
@ -47,11 +47,11 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: install dependencies
run: brew install openssl opencore-amr
run: brew install openssl@1.1 opencore-amr
- name: config site
run: cd pjlib/include/pj && cp config_site_test.h config_site.h
- name: configure
run: CFLAGS="-g $(pkg-config --cflags openssl) $(pkg-config --cflags opencore-amrnb)" LDFLAGS="$(pkg-config --libs-only-L openssl) $(pkg-config --libs-only-L openssl)/lib $(pkg-config --libs-only-L opencore-amrnb)" ./configure
run: CFLAGS="-g -I/usr/local/include -I/usr/local/opt/openssl@1.1/include" LDFLAGS="-L/usr/local/lib -L/usr/local/opt/openssl@1.1/lib" ./configure
- name: make
run: make
- name: disable firewall
@ -65,11 +65,11 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: install dependencies
run: brew install openssl opencore-amr
run: brew install openssl@1.1 opencore-amr
- name: config site
run: cd pjlib/include/pj && cp config_site_test.h config_site.h
- name: configure
run: CFLAGS="-g $(pkg-config --cflags openssl) $(pkg-config --cflags opencore-amrnb)" LDFLAGS="$(pkg-config --libs-only-L openssl) $(pkg-config --libs-only-L openssl)/lib $(pkg-config --libs-only-L opencore-amrnb)" ./configure
run: CFLAGS="-g -I/usr/local/include -I/usr/local/opt/openssl@1.1/include" LDFLAGS="-L/usr/local/lib -L/usr/local/opt/openssl@1.1/lib" ./configure
- name: make
run: make
- name: disable firewall
@ -86,9 +86,9 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: install dependencies
run: brew install openssl swig
run: brew install openssl@1.1 swig
- name: configure
run: CFLAGS="$(pkg-config --cflags openssl) -fPIC" LDFLAGS="$(pkg-config --libs-only-L openssl) $(pkg-config --libs-only-L openssl)/lib" CXXFLAGS="-fPIC" ./configure
run: CFLAGS="-I/usr/local/include -I/usr/local/opt/openssl@1.1/include -fPIC" LDFLAGS="-L/usr/local/lib -L/usr/local/opt/openssl@1.1/lib" CXXFLAGS="-fPIC" ./configure
- name: make
run: make
- name: set up Python
@ -123,11 +123,11 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: install dependencies
run: brew install openssl openh264 libvpx opencore-amr swig sipp
run: brew install openssl@1.1 openh264 libvpx opencore-amr swig sipp
- name: config site
run: cd pjlib/include/pj && cp config_site_test.h config_site.h && echo "#define PJMEDIA_HAS_VIDEO 1" >> config_site.h
- name: configure
run: CFLAGS="-g $(pkg-config --cflags openssl) $(pkg-config --cflags opencore-amrnb) -DHAS_VID_CODEC_TEST=0 -fPIC" LDFLAGS="$(pkg-config --libs-only-L openssl) $(pkg-config --libs-only-L openssl)/lib $(pkg-config --libs-only-L opencore-amrnb)" CXXFLAGS="-g -fPIC" ./configure
run: CFLAGS="-g -I/usr/local/include -I/usr/local/opt/openssl@1.1/include -DHAS_VID_CODEC_TEST=0 -fPIC" LDFLAGS="-L/usr/local/lib -L/usr/local/opt/openssl@1.1/lib" CXXFLAGS="-g -fPIC" ./configure
- name: make
run: make
- name: set up Python
@ -147,11 +147,11 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: install dependencies
run: brew install openssl openh264 libvpx opencore-amr
run: brew install openssl@1.1 openh264 libvpx opencore-amr
- name: config site
run: cd pjlib/include/pj && cp config_site_test.h config_site.h && echo "#define PJMEDIA_HAS_VIDEO 1" >> config_site.h
- name: configure
run: CFLAGS="-g $(pkg-config --cflags openssl) $(pkg-config --cflags opencore-amrnb)" LDFLAGS="$(pkg-config --libs-only-L openssl) $(pkg-config --libs-only-L openssl)/lib $(pkg-config --libs-only-L opencore-amrnb)" ./configure
run: CFLAGS="-g -I/usr/local/include -I/usr/local/opt/openssl@1.1/include" LDFLAGS="-L/usr/local/lib -L/usr/local/opt/openssl@1.1/lib" ./configure
- name: make
run: make
- name: disable firewall
@ -165,11 +165,11 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: install dependencies
run: brew install openssl openh264 libvpx opencore-amr
run: brew install openssl@1.1 openh264 libvpx opencore-amr
- name: config site
run: cd pjlib/include/pj && cp config_site_test.h config_site.h && echo "#define PJMEDIA_HAS_VIDEO 1" >> config_site.h
- name: configure
run: CFLAGS="-g $(pkg-config --cflags openssl) $(pkg-config --cflags opencore-amrnb)" LDFLAGS="$(pkg-config --libs-only-L openssl) $(pkg-config --libs-only-L openssl)/lib $(pkg-config --libs-only-L opencore-amrnb)" ./configure
run: CFLAGS="-g -I/usr/local/include -I/usr/local/opt/openssl@1.1/include" LDFLAGS="-L/usr/local/lib -L/usr/local/opt/openssl@1.1/lib" ./configure
- name: make
run: make
- name: disable firewall
@ -183,17 +183,17 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: install dependencies
run: brew install openssl x264 libvpx nasm swig
run: brew install openssl@1.1 x264 libvpx nasm swig
- name: get ffmpeg
run: git clone --single-branch --branch release/7.0 https://github.com/FFmpeg/FFmpeg.git
run: git clone --single-branch --branch release/4.2 https://github.com/FFmpeg/FFmpeg.git
- name: configure ffmpeg
run: cd FFmpeg && LDFLAGS="-Wl,-ld_classic" ./configure --enable-shared --disable-static --enable-gpl --enable-libx264
run: cd FFmpeg && ./configure --enable-shared --disable-static --enable-gpl --enable-libx264
- name: build ffmpeg
run: cd FFmpeg && make -j10 && sudo make install
- name: config site
run: echo -e "#define PJMEDIA_HAS_VIDEO 1\n" > pjlib/include/pj/config_site.h
- name: configure
run: CFLAGS="$(pkg-config --cflags openssl) -fPIC" LDFLAGS="$(pkg-config --libs-only-L openssl) $(pkg-config --libs-only-L openssl)/lib" CXXFLAGS="-fPIC" ./configure
run: CFLAGS="-I/usr/local/include -I/usr/local/opt/openssl@1.1/include -fPIC" LDFLAGS="-L/usr/local/lib -L/usr/local/opt/openssl@1.1/lib" CXXFLAGS="-fPIC" ./configure
- name: make
run: make
- name: set up Python
@ -209,11 +209,11 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: install dependencies
run: brew install openssl libvpx swig
run: brew install openssl@1.1 libvpx swig
- name: config site
run: echo -e "#define PJMEDIA_HAS_VIDEO 1\n#define PJMEDIA_HAS_VID_TOOLBOX_CODEC 1\n" > pjlib/include/pj/config_site.h
- name: configure
run: CFLAGS="$(pkg-config --cflags openssl) -fPIC" LDFLAGS="$(pkg-config --libs-only-L openssl) $(pkg-config --libs-only-L openssl)/lib" CXXFLAGS="-fPIC" ./configure
run: CFLAGS="-I/usr/local/include -I/usr/local/opt/openssl@1.1/include -fPIC" LDFLAGS="-L/usr/local/lib -L/usr/local/opt/openssl@1.1/lib" CXXFLAGS="-fPIC" ./configure
- name: make
run: make
- name: set up Python

View File

@ -178,10 +178,25 @@ jobs:
msbuild pjproject-vs14.sln /p:PlatformToolset=v143 /p:Configuration=Release /p:Platform=win32 /p:UseEnv=true
shell: cmd
windows-with-video-libvpx-schannel-unit-test-1:
windows-with-video-libvpx-unit-test-1:
runs-on: windows-latest
steps:
- uses: actions/checkout@master
- name: get openssl
run: Invoke-WebRequest -Uri "https://github.com/pjsip/third_party_libs/raw/main/openssl-1.1.1s-win.zip" -OutFile ".\openssl.zip"
shell: powershell
- name: expand openssl
run: |
Expand-Archive -LiteralPath .\openssl.zip -DestinationPath .; pwd
cd openssl_build
Add-Content ..\openssl_dir.txt $pwd.Path
shell: powershell
- name: check openssl folder
run: |
set /P OPENSSL_DIR=<openssl_dir.txt
dir "%OPENSSL_DIR%\include"
dir "%OPENSSL_DIR%\lib"
shell: cmd
- name: get vpx
run: Invoke-WebRequest -Uri "https://github.com/pjsip/third_party_libs/raw/main/vpx-1.12-win.zip" -Outfile "vpx.zip"
shell: powershell
@ -216,8 +231,6 @@ jobs:
run: |
cd pjlib/include/pj; cp config_site_test.h config_site.h
Add-Content config_site.h "#define PJ_HAS_SSL_SOCK 1"
Add-Content config_site.h "#define PJ_SSL_SOCK_IMP PJ_SSL_SOCK_IMP_SCHANNEL"
Add-Content config_site.h "#undef PJMEDIA_SRTP_HAS_DTLS"
Add-Content config_site.h "#define PJMEDIA_HAS_VIDEO 1"
Add-Content config_site.h "#define PJMEDIA_VIDEO_DEV_HAS_DSHOW 1"
Add-Content config_site.h "#define PJMEDIA_HAS_LIBYUV 1"
@ -245,7 +258,7 @@ jobs:
set /P SDL_DIR=<sdl_dir.txt
cd tests/pjsua/tools
set INCLUDE=%INCLUDE%;%OPENSSL_DIR%\include;%VPX_DIR%\include;%SDL_DIR%\include
set LIB=%LIB%;%VPX_DIR%\lib;%SDL_DIR%\lib\x86
set LIB=%LIB%;%OPENSSL_DIR%\lib;%VPX_DIR%\lib;%SDL_DIR%\lib\x86
call "%PROGRAMFILES%\Microsoft Visual Studio\2022\Enterprise\Common7\Tools\VsDevCmd.bat"
msbuild cmp_wav.vcxproj /p:PlatformToolset=v143 /p:Configuration=Release /p:Platform=win32 /p:UseEnv=true
shell: cmd
@ -255,8 +268,9 @@ jobs:
python-version: '3.10'
- name: unit tests
run: |
$env:OPENSSL_DIR = Get-Content .\openssl_dir.txt
$env:SDL_DIR = Get-Content .\sdl_dir.txt
$env:PATH+=";$env:SDL_DIR\lib\x86;"
$env:PATH+=";$env:OPENSSL_DIR\bin;$env:SDL_DIR\lib\x86;"
cd tests/pjsua; python runall.py
cd ../../pjlib/bin; ./pjlib-test-i386-Win32-vc14-Release.exe --ci-mode
cd ../../pjlib-util/bin; ./pjlib-util-test-i386-Win32-vc14-Release.exe

View File

@ -17,50 +17,50 @@ Encrypt sensitive information using our PGP public key below.
```
-----BEGIN PGP PUBLIC KEY BLOCK-----
Comment: User-ID: Teluu <security@pjsip.org>
Comment: Created: 1/24/2024 10:05 AM
Comment: Expires: 12/31/2029 12:00 PM
Comment: Created: 7/29/2021 8:24 AM
Comment: Expires: 7/29/2023 12:00 PM
Comment: Type: 3,072-bit RSA (secret key available)
Comment: Usage: Signing, Encryption, Certifying User-IDs
Comment: Fingerprint: BCCC7ADEFFABAAB10FA4CDC027E875D43D995460
Comment: Fingerprint: C2A9D29D94D131466D8832AE15BA5B3B5DAE8B36
mQGNBGWwfm8BDACpBBGoBkkxgkm6hao9Fk63iEt3mJ6Ycg2BabeA7ZeHAA1IMkMG
6247Y08Mk5DkqS+SeDu//44I6MQ/3tEDHqr59/F1qqhsu4zvPDOSgcfCET9kL7u0
XhCrJC0DbEpTNmY9prnvNnzJOTzvbDQVysUII6b4UwhWC+Y+qhl6csVhoHUphwMs
XZDtMR3EPpNbIrkXgUWRhEkcR2iuuLxnmdGTH8gDrtiq+IBcANkzojIEEQPulv6r
IrrGbVx8hFRgbk5mJwIy6xRfr+5ah5gUeNM8fV/BwCUOP++qtY3c491I499XXdWa
OpSRTSYgqY0kI0rl8B75FLG0qjnB1ySbmek++bWzK6sCJWmJxJJGjzVr3sccHOQZ
hDUoK82OFkvde0em8HU1WnshRbSJhchrL6bO4uDMrGCYdO9uE2XHb/UiKFE9mCrw
JKZlDg6PPUf8Gkqf594S3raekrvwWEmq/JWsk3WtNancMUQRd1pQR6ouXU0mHIih
+1qf6hvXITxzDccAEQEAAbQaVGVsdXUgPHNlY3VyaXR5QHBqc2lwLm9yZz6JAdcE
EwEIAEEWIQS8zHre/6uqsQ+kzcAn6HXUPZlUYAUCZbB+bwIbAwUJCypO4QULCQgH
AgIiAgYVCgkICwIEFgIDAQIeBwIXgAAKCRAn6HXUPZlUYJmfDACLT86rTd+JMpUY
iqYbELpOBfMkY0ebXVWQE/1FjmE5itS6XgHb3BWwXq99wtn9yKgwqbG8F2A/PVZd
4Ga/EI0jyfJN85tjbk+bEqAkKIhzVljuLl6qkDqOOr6EzGAVAHLIJ1NgPLOOZKF8
WM4t3WBTKRTJmGL9uNE/yblbRqrtsLAbtLcyZk0f8E8UYCIrWHKV7teop0VeBUw3
+a0ISa9NHCLH35FYGROPL3s1CieWrYOSS/B8ncChqB8sfCE3UkcTTWvPSvCpYEIY
mZjQa975HFcvYaD+sYJ+ZwJJGg5fm1jLaGFrL5zTvPpx53Y3u/SBXTeGEmal/tvp
s5hz/3ZZeSmTLLcWjG1xcxVGnQF7EK4h1EmvcTz7mZrTY+ZHohnv7a50G3C5eo2s
tNkf0E0ajfmgLXClxWMue+TzhwnnMQN7jdbTRU8SLgooG4LJeww7TiLI2eiyZC7L
wOhNsbOyofnIfT0q/xWHKGJFe7Sffk6+cT/Jw0EWrt+34ATEUmC5AY0EZbB+bwEM
AKan7Fo7Y2PDLh+hMb4KrPfQyypBIv8+//Ln4oEZLcYFcNzdWWVc4z54YfqkSu8j
vGhjYKk5JK1l9RBHPoFGPV4pmG2hf/wSeNoYcs7Tz4wQapCYLNL6ouA9hJIezG5S
BYs74njIrFtycJXlXhOlqzsJQ7dcMWlYjeXyiOFVYWyzcfwZWGJQ7i6YotmRxx6j
IfJ3abRJtgTeUXqUNUagetpOjno+R8uYhm6r1sgajyi/WE8QMixVNoWgUo94jhk4
ZAcAAw/gBN+pGQawf9TOC4llle8g0YENf39m/GtQ6PD6ks1pSnjXNLhiIHkrv5eD
+I8td0RSbsHqgWjO1F4/h1eH4yQXbV5QTIcVgE5yLqIQaoScEFsOokLFm8NDWrVA
eI0TBbOm1qtHaPpJROrEQkTyJBBFCFKRuC5u7LCirlN+O21lZDgKg/bPNe6tV4zr
30FEsVy0njusY5ZSapbLemAOQldIwphgp8WBMFxq1tb86n6dOLYYte1A8DF3ryHM
iQARAQABiQG8BBgBCAAmFiEEvMx63v+rqrEPpM3AJ+h11D2ZVGAFAmWwfm8CGwwF
CQsqTuEACgkQJ+h11D2ZVGAcLAv+JB0iNqrtVG/cqBz44VC2+zJ6rAuGYuiR1sNL
Ejvk9D483ZUKUpsZOjpVkgEJ88Fw73RoAiuEvF78mN6CloIIxQtJCFRs66PECjJP
m9pjzx5wer2TqC+7l6fNp8pXFuLoeirvYTPisdUM+cqJ9N37BekqqiE0LSdGWcmK
GqlO3DjPgyWfjE5rSGy9Bu4l9HKmv8AUtFiw3g65cwDC/23LFYK+HJB8gelLytkp
kLSC6HbNg6lpnFoqhIJYBr3TK8IKXhD62dO4B3IyWnqMnKFJ2fv1ILj42LlzWgZo
ULnZUI/EUpV3+5ELVmNKJiWGB1OgVsaJalN5TMqnr2iXPg1qnJzvzvvuwwDfA6g0
EeR5H7yOK5WvQvGDJrUaESXRMZgubJmv42EmfT048Ajq1/SaWTdQqRK9CoFIJTOY
lQAakbU2ukwSJRdwd+PDRFWB8c4geIAtiYJw+LseTKtjo4++hADQBoRkqgnKB1o7
oUbFbwQAAHfNE3xFJespnLA/KbbO
=Oiwu
mQGNBGECAzwBDADjloGXRtTaSoTj+Nz4uy5Ei8e9CpIe0kEXLUykdr0bxWh7EiUX
EqkZnFXbt3bWcFTVp7CQMn1as8/AUSteRbKuweLVyx/fFFtxrOQIBNqrwJhwwbmx
SKLc4Pe/RqT8HmJb+MRnU3rkuzJ4ak0Nh5fLUFL/gBmped8MqBmF8OobJt0U/z/d
opqVGfnHPablA3nJUcbMW97GJ8FH4cX5ZT+46cbpoJo/L7WbMUpbZcnz+iPiQFFO
/oO7AbVihdvFNd0SoXi7aE8i8BFIhOYa9nLJId/PMRqG9aFTRP8dOwbOL+EekQ7d
5x81bQLgjpXogORDxiUns0cFgPBDz5P1Y1qXlQ+HYa8m/vIKnEZMo1mnNhBR40cM
XyrapeA9WcXiYNo4FBEt6rHoCKpGbMG5Rfpk5u5KljDGxg3tdbuXNfbJPFAOp3IB
hQ72zhT4rWV31J8IEmoBOT8smf04cEr+jfrjs/ejYJh//Ez7AzMhyoDm1m1ELWwW
Mzvm5QPtm1pwHakAEQEAAbQaVGVsdXUgPHNlY3VyaXR5QHBqc2lwLm9yZz6JAdQE
EwEIAD4WIQTCqdKdlNExRm2IMq4Vuls7Xa6LNgUCYQIDPAIbAwUJA8KZlAULCQgH
AgYVCgkICwIEFgIDAQIeAQIXgAAKCRAVuls7Xa6LNhEGC/4p9GiArgRF0DgVa40O
JeH8mObjpweBvQc1zpHX2cA9DhkEs/vP0lg29v1248HnnZFz0HBnXKGQVq599jZX
blm1IphNJSWfkutfjIIH80fqDCuqHOHLhrf0qzDxIAWaSSr0Bh/rGHlsPo2+s35f
3EMwpkDzETnoLeJMShxAwJOocZBqIieWK2/MZKdLnwn2Evb40BJ63UftFOCf7LuQ
tbZQ/w2op3Capt+6BL5aNAwnhz5uTgzUE2dLA31YCpWPDJbE1vMy05suzbEqGLu1
aAFAKocdw1gbFrvEj2nDhH3dD10kQeMtXNPXqtQfRcmQCi8HCetfmFjfB8n5J6YW
G6dtmiC9RfDgUlrhfTcHRL7ioD2g8jZt2LE2yXulS+8AD10/WQTWkEHYmly0bHAE
sbAtwNA1asVsuVNUreTirZA0KgTJRySe/WbCyaCXStlTHy2X2aKR0jaNhm56Snpz
K+aRPTsc6ZFOQOzBMys7hBCAQlCQ0CQyzucMfV3Egl83Qxm5AY0EYQIDPAEMALRb
OcHPuJ77J+jZGtNAp27/QDXsA1AwvyxDVP+BhZUS3gKXqoyXS3THNEQoqL8GhvZz
j/sDQo7Hs6p3oEj+HXF2LzlOjiaqObZsYaEBrMo/OS6p/8YvVOa39eTtuvgNVeDB
EitlH8/pjk5bsZ0KFWqijcqsu0i4ye758UyERZ1ruXHNMB4auow4ZAwqn0vNN0CH
f1hP/2qMLw5krCgHx1QowMk7S83ljFF5J36ojOuVQjzrCd96eWMHCdUpXbBJv7dd
firVH9JIOAMDRAEoeX/EjWqeHlPVoOElGUWqAVKveQ0GNdN10hT+1gg0lxqR8f5G
QDz7u6pDHJHhDQeMH6HYpRLXiXN23AEYnwpzFyw7p22WihV/6rKzGAP7JECZGDsD
w5x2/YWRcg04MWcnY25f79JM/QWfRGfX6cxdKPxDDgZKUREzESy8/VeefF+xLklg
O8t9xASz7dU4iSzwdyT5AJX7hIjyJxij8EroQ+4rn4m/zwVE9I9vUNn139kIaQAR
AQABiQG8BBgBCAAmFiEEwqnSnZTRMUZtiDKuFbpbO12uizYFAmECAzwCGwwFCQPC
mZQACgkQFbpbO12uizZQHwwAkActQzy2bb6naSAAVgxvobrNuXzO+HygJLgBa37l
NdFxbBnN0YjYYrjA5PJJZYTcEaedz8Uec2onqTDpsaMDRwouCRayo19WizmSQd34
DdygKA2CecQdXxKUf/2vxE//Jxq1/Sq0+facynhTygG24aSI44F/iw2h+9Z9JPcM
BwtNLdGcuWEU2slHcN24sBveBHbTyCe4h52OMr/HBPldAREa2zojF4J8fxTPD6ES
wx8mWc79sr50EPejw2r3ipKjrbxiB1yDtiry/eZatidb0slGWLzBhawOkZAUrVJh
DODKf+upkfP8V/MayqRdNNH8FDxYUgxYwnX9+VbtJr7BrvnoyGgOwIuxN5TV+EQt
+Bf7Kzzsqz2/bzsPtnd/F3faAAoOEzby//fdLWUpKcubf7kVq0EQ9bMKwC56rLpd
BnLaAfcL/676JS3bjJMc3ij3T2doC3IFwj84kNoBk+ArgBFlKjcB84Uket+rj23e
SjwjgsVZsFg9w1+m0F72hyAQ
=rD28
-----END PGP PUBLIC KEY BLOCK-----
```

View File

@ -712,7 +712,6 @@ ac_pjmedia_video_has_qt
ac_darwin_cflags
ac_pjmedia_video_has_ios_opengl
ac_pjmedia_video_has_vtoolbox
ac_pjmedia_video_has_metal
ac_pjmedia_video_has_darwin
ac_dshow_ldflags
ac_dshow_cflags
@ -6518,26 +6517,19 @@ rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking ioqueue backend" >&5
printf %s "checking ioqueue backend... " >&6; }
ac_os_objs=ioqueue_select.o
ac_linux_poll=select
case $target in
*darwin* | *bsd*)
# Check whether --enable-kqueue was given.
if test ${enable_kqueue+y}
then :
enableval=$enable_kqueue;
if test "$enable_kqueue" = "yes"; then
ac_os_objs=ioqueue_kqueue.o
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: kqueue()" >&5
ac_os_objs=ioqueue_kqueue.o
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: kqueue()" >&5
printf "%s\n" "kqueue()" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: select()" >&5
printf "%s\n" "select()" >&6; }
fi
else $as_nop
ac_os_objs=ioqueue_select.o
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: select()" >&5
printf "%s\n" "select()" >&6; }
@ -6549,22 +6541,19 @@ fi
if test ${enable_epoll+y}
then :
enableval=$enable_epoll;
if test "$enable_epoll" = "yes"; then
ac_os_objs=ioqueue_epoll.o
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: /dev/epoll" >&5
ac_os_objs=ioqueue_epoll.o
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: /dev/epoll" >&5
printf "%s\n" "/dev/epoll" >&6; }
printf "%s\n" "#define PJ_HAS_LINUX_EPOLL 1" >>confdefs.h
printf "%s\n" "#define PJ_HAS_LINUX_EPOLL 1" >>confdefs.h
ac_linux_poll=epoll
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: select()" >&5
printf "%s\n" "select()" >&6; }
fi
ac_linux_poll=epoll
else $as_nop
ac_os_objs=ioqueue_select.o
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: select()" >&5
printf "%s\n" "select()" >&6; }
ac_linux_poll=select
fi
@ -7480,7 +7469,6 @@ printf "%s\n" "Checking if OpenGL ES 2 is available... no" >&6; }
SAVED_LIBS="$LIBS"
LIBS="-framework AVFoundation -framework CoreGraphics -framework QuartzCore -framework CoreVideo -framework CoreMedia"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@ -7520,26 +7508,6 @@ then :
else $as_nop
ac_pjmedia_video_has_vtoolbox=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS="-framework Metal"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
main (void)
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
ac_pjmedia_video_has_metal=yes
else $as_nop
ac_pjmedia_video_has_metal=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS="-framework OpenGLES"
@ -7571,15 +7539,6 @@ printf "%s\n" "Checking if AVFoundation framework is available... yes" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: Checking if AVFoundation framework is available... no" >&5
printf "%s\n" "Checking if AVFoundation framework is available... no" >&6; }
fi
if test "$ac_pjmedia_video_has_metal" = "yes"; then
ac_darwin_cflags+=" -DPJMEDIA_VIDEO_DEV_HAS_METAL=1"
LIBS="$LIBS -framework Metal -framework MetalKit"
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: Checking if Metal framework is available... yes" >&5
printf "%s\n" "Checking if Metal framework is available... yes" >&6; }
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: Checking if Metal framework is available... no" >&5
printf "%s\n" "Checking if Metal framework is available... no" >&6; }
fi
if test "$ac_pjmedia_video_has_vtoolbox" = "yes"; then
#ac_darwin_cflags+=" -DPJMEDIA_HAS_VID_TOOLBOX_CODEC=1"

View File

@ -467,23 +467,17 @@ AC_SUBST(ac_os_objs)
AC_SUBST(ac_linux_poll)
AC_MSG_CHECKING([ioqueue backend])
ac_os_objs=ioqueue_select.o
ac_linux_poll=select
case $target in
*darwin* | *bsd*)
AC_ARG_ENABLE(kqueue,
AS_HELP_STRING([--enable-kqueue],
[Use kqueue ioqueue on macos/BSD (experimental)]),
[
if test "$enable_kqueue" = "yes"; then
ac_os_objs=ioqueue_kqueue.o
AC_MSG_RESULT([kqueue()])
else
AC_MSG_RESULT([select()])
fi
ac_os_objs=ioqueue_kqueue.o
AC_MSG_RESULT([kqueue()])
],
[
ac_os_objs=ioqueue_select.o
AC_MSG_RESULT([select()])
])
;;
@ -492,17 +486,15 @@ case $target in
AS_HELP_STRING([--enable-epoll],
[Use /dev/epoll ioqueue on Linux (experimental)]),
[
if test "$enable_epoll" = "yes"; then
ac_os_objs=ioqueue_epoll.o
AC_MSG_RESULT([/dev/epoll])
AC_DEFINE(PJ_HAS_LINUX_EPOLL,1)
ac_linux_poll=epoll
else
AC_MSG_RESULT([select()])
fi
ac_os_objs=ioqueue_epoll.o
AC_MSG_RESULT([/dev/epoll])
AC_DEFINE(PJ_HAS_LINUX_EPOLL,1)
ac_linux_poll=epoll
],
[
ac_os_objs=ioqueue_select.o
AC_MSG_RESULT([select()])
ac_linux_poll=select
])
;;
esac
@ -1055,7 +1047,6 @@ else
*darwin*)
ac_pjmedia_video=darwin_os
AC_SUBST(ac_pjmedia_video_has_darwin)
AC_SUBST(ac_pjmedia_video_has_metal)
AC_SUBST(ac_pjmedia_video_has_vtoolbox)
AC_SUBST(ac_pjmedia_video_has_ios_opengl)
AC_SUBST(ac_darwin_cflags)
@ -1068,10 +1059,6 @@ else
AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [])],
[ac_pjmedia_video_has_vtoolbox=yes],
[ac_pjmedia_video_has_vtoolbox=no])
LIBS="-framework Metal"
AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [])],
[ac_pjmedia_video_has_metal=yes],
[ac_pjmedia_video_has_metal=no])
LIBS="-framework OpenGLES"
AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [])],
[ac_pjmedia_video_has_ios_opengl=yes],
@ -1084,13 +1071,6 @@ else
else
AC_MSG_RESULT([Checking if AVFoundation framework is available... no])
fi
if test "$ac_pjmedia_video_has_metal" = "yes"; then
ac_darwin_cflags+=" -DPJMEDIA_VIDEO_DEV_HAS_METAL=1"
LIBS="$LIBS -framework Metal -framework MetalKit"
AC_MSG_RESULT([Checking if Metal framework is available... yes])
else
AC_MSG_RESULT([Checking if Metal framework is available... no])
fi
if test "$ac_pjmedia_video_has_vtoolbox" = "yes"; then
#ac_darwin_cflags+=" -DPJMEDIA_HAS_VID_TOOLBOX_CODEC=1"
LIBS="$LIBS -framework VideoToolbox"

View File

@ -204,7 +204,6 @@ AC_PJMEDIA_VIDEO_HAS_QT = @ac_pjmedia_video_has_qt@
# Darwin (Mac and iOS)
AC_PJMEDIA_VIDEO_HAS_DARWIN = @ac_pjmedia_video_has_darwin@
AC_PJMEDIA_VIDEO_HAS_METAL = @ac_pjmedia_video_has_metal@
AC_PJMEDIA_VIDEO_HAS_VTOOLBOX = @ac_pjmedia_video_has_vtoolbox@
AC_PJMEDIA_VIDEO_HAS_IOS_OPENGL = @ac_pjmedia_video_has_ios_opengl@
DARWIN_CFLAGS = @ac_darwin_cflags@

View File

@ -20,8 +20,8 @@ if test "$*" = "--help" -o "$*" = "-h"; then
echo " ARCH Optional flags to specify target architecture, e.g."
echo " ARCH=\"-arch armv7\". Default is arm64."
echo " MIN_IOS Optional flags to specify minimum supported iOS"
echo " versions, e.g. MIN_IOS=\"-miphoneos-version-min=11.0\". "
echo " Default is 11.0."
echo " versions, e.g. MIN_IOS=\"-miphoneos-version-min=10.0\". "
echo " Default is 7.0."
echo ""
exit 0
fi
@ -123,7 +123,7 @@ if test "${ARCH_VAL}" = "arm64e"; then
fi
if test "${MIN_IOS}" = ""; then
MIN_IOS_VER="11.0"
MIN_IOS_VER="7.0"
echo "$F: MIN_IOS is not specified, choosing ${MIN_IOS_VER}"
MIN_IOS="-miphoneos-version-min=${MIN_IOS_VER}"
fi

View File

@ -1840,15 +1840,15 @@ PJ_DEF(pj_status_t) pj_dns_resolver_add_entry( pj_dns_resolver *resolver,
pj_bzero(&key, sizeof(struct res_key));
if (pkt->hdr.anscount) {
/* Make sure name is not too long. */
PJ_ASSERT_ON_FAIL(pkt->ans[0].name.slen < PJ_MAX_HOSTNAME,
{ pj_grp_lock_release(resolver->grp_lock); return PJ_ENAMETOOLONG; });
PJ_ASSERT_RETURN(pkt->ans[0].name.slen < PJ_MAX_HOSTNAME,
PJ_ENAMETOOLONG);
init_res_key(&key, pkt->ans[0].type, &pkt->ans[0].name);
} else {
/* Make sure name is not too long. */
PJ_ASSERT_ON_FAIL(pkt->q[0].name.slen < PJ_MAX_HOSTNAME,
{ pj_grp_lock_release(resolver->grp_lock); return PJ_ENAMETOOLONG; });
PJ_ASSERT_RETURN(pkt->q[0].name.slen < PJ_MAX_HOSTNAME,
PJ_ENAMETOOLONG);
init_res_key(&key, pkt->q[0].type, &pkt->q[0].name);
}

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug-Dynamic|ARM">
@ -998,7 +998,6 @@
</ClCompile>
<ClCompile Include="..\src\pj\ssl_sock_ossl.c" />
<ClCompile Include="..\src\pj\ssl_sock_gtls.c" />
<ClCompile Include="..\src\pj\ssl_sock_schannel.c" />
<ClCompile Include="..\src\pj\string.c" />
<ClCompile Include="..\src\pj\symbols.c">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug-Dynamic|Win32'">true</ExcludedFromBuild>

View File

@ -1077,9 +1077,6 @@
/** Using Apple's Network framework */
#define PJ_SSL_SOCK_IMP_APPLE 4
/** Using Windows's Schannel */
#define PJ_SSL_SOCK_IMP_SCHANNEL 5
/**
* Select which SSL socket implementation to use. Currently pjlib supports
* PJ_SSL_SOCK_IMP_OPENSSL, which uses OpenSSL, and PJ_SSL_SOCK_IMP_GNUTLS,

View File

@ -170,27 +170,6 @@ PJ_IDECL(void) pj_list_insert_nodes_after(pj_list_type *lst,
pj_list_type *nodes);
/**
* Insert a list to another list before the specified element position.
*
* @param pos The element to which the node will be inserted before.
* @param lst The list to be inserted.
*/
PJ_IDECL(void) pj_list_insert_list_before(pj_list_type *pos,
pj_list_type *lst);
/**
* Insert a list to another list after the specified element position.
*
* @param pos The element in the list which will precede the inserted
* list.
* @param lst The list to be inserted.
*/
PJ_IDECL(void) pj_list_insert_list_after(pj_list_type *pos,
pj_list_type *lst);
/**
* Remove elements from the source list, and insert them to the destination
* list. The elements of the source list will occupy the

View File

@ -54,23 +54,6 @@ PJ_IDEF(void) pj_list_insert_nodes_before(pj_list_type *pos, pj_list_type *lst)
pj_list_insert_nodes_after(((pj_list*)pos)->prev, lst);
}
PJ_IDEF(void) pj_list_insert_list_after(pj_list_type *pos, pj_list_type *lst)
{
if (!pj_list_empty(lst)) {
pj_list *lst_last = (pj_list *) ((pj_list*)lst)->prev;
pj_list *pos_next = (pj_list *) ((pj_list*)pos)->next;
pj_link_node(pos, (pj_list *) ((pj_list*)lst)->next);
pj_link_node(lst_last, pos_next);
pj_list_init(lst);
}
}
PJ_IDEF(void) pj_list_insert_list_before(pj_list_type *pos, pj_list_type *lst)
{
pj_list_insert_list_after(((pj_list*)pos)->prev, lst);
}
PJ_IDEF(void) pj_list_merge_last(pj_list_type *lst1, pj_list_type *lst2)
{
if (!pj_list_empty(lst2)) {

View File

@ -849,16 +849,12 @@ struct pj_caching_pool
/**
* Total size of memory currently used by application.
*
* This field is deprecated.
*/
pj_size_t used_size;
/**
* The maximum size of memory used by application throughout the life
* of the caching pool.
*
* This field is deprecated.
*/
pj_size_t peak_used_size;

View File

@ -117,11 +117,6 @@ typedef enum pj_ssl_cert_verify_flag_t
*/
PJ_SSL_CERT_ECHAIN_TOO_LONG = (1 << 8),
/**
* The certificate signature is created using a weak hashing algorithm.
*/
PJ_SSL_CERT_EWEAK_SIGNATURE = (1 << 9),
/**
* The server identity does not match to any identities specified in
* the certificate, e.g: subjectAltName extension, subject common name.
@ -150,59 +145,6 @@ typedef enum pj_ssl_cert_name_type
PJ_SSL_CERT_NAME_IP
} pj_ssl_cert_name_type;
/**
* Field type for looking up SSL certificate in the certificate stores.
*/
typedef enum pj_ssl_cert_lookup_type
{
/**
* No certificate to be looked up.
*/
PJ_SSL_CERT_LOOKUP_NONE,
/**
* Lookup by subject, this will lookup any first certificate whose
* subject containing the specified keyword. Note that subject may not
* be unique in the store, so the lookup may end up selecting a wrong
* certificate.
*/
PJ_SSL_CERT_LOOKUP_SUBJECT,
/**
* Lookup by fingerprint/thumbprint (SHA1 hash), this will lookup
* any first certificate whose fingerprint matching the specified
* keyword. The keyword is an array of hash octets.
*/
PJ_SSL_CERT_LOOKUP_FINGERPRINT,
/**
* Lookup by friendly name, this will lookup any first certificate
* whose friendly name containing the specified keyword. Note that
* friendly name may not be unique in the store, so the lookup may end up
* selecting a wrong certificate.
*/
PJ_SSL_CERT_LOOKUP_FRIENDLY_NAME
} pj_ssl_cert_lookup_type;
/**
* Describe structure of certificate lookup criteria.
*/
typedef struct pj_ssl_cert_lookup_criteria
{
/**
* Certificate field type to look.
*/
pj_ssl_cert_lookup_type type;
/*
* Keyword to match on the field specified in \a type.
*/
pj_str_t keyword;
} pj_ssl_cert_lookup_criteria;
/**
* Describe structure of certificate info.
*/
@ -331,30 +273,6 @@ PJ_DECL(pj_status_t) pj_ssl_cert_load_from_buffer(pj_pool_t *pool,
const pj_str_t *privkey_pass,
pj_ssl_cert_t **p_cert);
/**
* Create credential from OS certificate store, this function will lookup
* certificate using the specified criterias.
*
* Currently this is used by Windows Schannel backend only, it will lookup
* in the Current User store first, if no certificate with the specified
* criteria is not found, it will lookup in the Local Machine store.
*
* Note that for manual verification (e.g: when pj_ssl_sock_param.verify_peer
* is disabled), the backend will provide pre-verification result against
* trusted CA certificates in Current User store only (will not check CA
* certificates in the Local Machine store).
*
* @param pool The pool.
* @param criteria The lookup criteria.
* @param p_cert Pointer to credential instance to be created.
*
* @return PJ_SUCCESS when successful.
*/
PJ_DECL(pj_status_t) pj_ssl_cert_load_from_store(
pj_pool_t *pool,
const pj_ssl_cert_lookup_criteria *criteria,
pj_ssl_cert_t **p_cert);
/**
* Dump SSL certificate info.
*

View File

@ -143,9 +143,6 @@ static void activesock_destroy_iphone_os_stream(pj_activesock_t *asock)
static void activesock_create_iphone_os_stream(pj_activesock_t *asock)
{
#if (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && \
__IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_9_0)
if (ios_bg_support && asock->bg_setting && asock->stream_oriented) {
activesock_destroy_iphone_os_stream(asock);
@ -167,8 +164,6 @@ static void activesock_create_iphone_os_stream(pj_activesock_t *asock)
activesock_destroy_iphone_os_stream(asock);
}
}
#endif
}
@ -513,8 +508,7 @@ static void ioqueue_on_read_complete(pj_ioqueue_key_t *key,
ret = (*asock->cb.on_data_read)(asock, r->pkt, r->size,
PJ_SUCCESS, &remainder);
PJ_ASSERT_ON_FAIL(
!ret || !asock->stream_oriented || remainder <= r->size,
{
!asock->stream_oriented || remainder <= r->size, {
PJ_LOG(2, ("",
"App bug! Invalid remainder length from "
"activesock on_data_read()."));
@ -590,8 +584,7 @@ static void ioqueue_on_read_complete(pj_ioqueue_key_t *key,
ret = (*asock->cb.on_data_read)(asock, r->pkt, r->size,
status, &remainder);
PJ_ASSERT_ON_FAIL(
!ret || !asock->stream_oriented || remainder <= r->size,
{
!asock->stream_oriented || remainder <= r->size, {
PJ_LOG(2, ("",
"App bug! Invalid remainder length from "
"activesock on_data_read()."));

View File

@ -1056,7 +1056,7 @@ retry_on_restart:
/*
* Check that address storage can hold the address parameter.
*/
PJ_ASSERT_RETURN(addrlen <= (int)sizeof(pj_sockaddr), PJ_EBUG);
PJ_ASSERT_RETURN(addrlen <= (int)sizeof(pj_sockaddr_in), PJ_EBUG);
/*
* Schedule asynchronous send.

View File

@ -63,7 +63,7 @@ struct write_operation
pj_size_t size;
pj_ssize_t written;
unsigned flags;
pj_sockaddr rmt_addr;
pj_sockaddr_in rmt_addr;
int rmt_addrlen;
};

View File

@ -495,7 +495,6 @@ PJ_DEF(pj_status_t) pj_ioqueue_destroy( pj_ioqueue_t *ioqueue )
}
#endif
pj_lock_release(ioqueue->lock);
if (ioqueue->auto_delete_lock)
pj_lock_destroy(ioqueue->lock);

View File

@ -91,7 +91,6 @@ PJ_DEF(int) pj_run_app(pj_main_func_ptr main_func, int argc, char *argv[],
param.main_func = main_func;
if (pthread_create(&thread, NULL, &main_thread, &param) == 0) {
CFRunLoopRun();
pthread_join(thread, NULL);
}
PJ_UNUSED_ARG(pool);

View File

@ -75,12 +75,8 @@ PJ_DEF(void) pj_caching_pool_init( pj_caching_pool *cp,
cp->factory.create_pool = &cpool_create_pool;
cp->factory.release_pool = &cpool_release_pool;
cp->factory.dump_status = &cpool_dump_status;
/* Deprecated, these callbacks are only used for updating cp.used_size &
* cp.peak_used_size which are no longer used.
*/
//cp->factory.on_block_alloc = &cpool_on_block_alloc;
//cp->factory.on_block_free = &cpool_on_block_free;
cp->factory.on_block_alloc = &cpool_on_block_alloc;
cp->factory.on_block_free = &cpool_on_block_free;
pool = pj_pool_create_on_buf("cachingpool", cp->pool_buf, sizeof(cp->pool_buf));
status = pj_lock_create_simple_mutex(pool, "cachingpool", &cp->lock);
@ -224,7 +220,6 @@ static void cpool_release_pool( pj_pool_factory *pf, pj_pool_t *pool)
#if PJ_SAFE_POOL
/* Make sure pool is still in our used list */
if (pj_list_find_node(&cp->used_list, pool) != pool) {
pj_lock_release(cp->lock);
pj_assert(!"Attempt to destroy pool that has been destroyed before");
return;
}

View File

@ -173,10 +173,6 @@ PJ_DEF(pj_status_t) pj_ssl_cert_get_verify_status_strings(
case PJ_SSL_CERT_ECHAIN_TOO_LONG:
p = "The certificate chain length is too long";
break;
case PJ_SSL_CERT_EWEAK_SIGNATURE:
p = "The certificate signature is created using a weak hashing "
"algorithm";
break;
case PJ_SSL_CERT_EIDENTITY_NOT_MATCH:
p = "The server identity does not match to any identities "
"specified in the certificate";

View File

@ -52,22 +52,9 @@ static pj_bool_t asock_on_data_sent (pj_activesock_t *asock,
*******************************************************************
*/
static pj_size_t next_pow2(pj_size_t n)
{
/* Next 32-bit power of two */
pj_size_t power = 1;
while (power < n && power < 0x8000000) {
power <<= 1;
}
return power;
}
static pj_status_t circ_init(pj_pool_factory *factory,
circ_buf_t *cb, pj_size_t cap)
{
/* Round-up cap */
cap = next_pow2(cap);
cb->cap = cap;
cb->readp = 0;
cb->writep = 0;
@ -81,24 +68,17 @@ static pj_status_t circ_init(pj_pool_factory *factory,
/* Allocate circular buffer */
cb->buf = pj_pool_alloc(cb->pool, cap);
if (!cb->buf) {
pj_pool_secure_release(&cb->pool);
pj_pool_release(cb->pool);
return PJ_ENOMEM;
}
return PJ_SUCCESS;
}
static void circ_reset(circ_buf_t* cb)
{
cb->readp = 0;
cb->writep = 0;
cb->size = 0;
}
static void circ_deinit(circ_buf_t *cb)
{
if (cb->pool) {
pj_pool_secure_release(&cb->pool);
pj_pool_release(cb->pool);
cb->pool = NULL;
}
}
@ -124,8 +104,6 @@ static void circ_read(circ_buf_t *cb, pj_uint8_t *dst, pj_size_t len)
pj_size_t tbc = PJ_MIN(size_after, len);
pj_size_t rem = len - tbc;
pj_assert(cb->size >= len);
pj_memcpy(dst, cb->buf + cb->readp, tbc);
pj_memcpy(dst + tbc, cb->buf, rem);
@ -135,21 +113,6 @@ static void circ_read(circ_buf_t *cb, pj_uint8_t *dst, pj_size_t len)
cb->size -= len;
}
/* Cancel previous read, partially or fully.
* Should be called in the same mutex block as circ_read().
*/
static void circ_read_cancel(circ_buf_t* cb, pj_size_t len)
{
pj_assert(cb->cap - cb->size >= len);
if (cb->readp < len)
cb->readp = cb->cap - (len - cb->readp);
else
cb->readp -= len;
cb->size += len;
}
static pj_status_t circ_write(circ_buf_t *cb,
const pj_uint8_t *src, pj_size_t len)
{
@ -158,8 +121,14 @@ static pj_status_t circ_write(circ_buf_t *cb,
/* Minimum required capacity */
pj_size_t min_cap = len + cb->size;
/* Round-up minimum capacity */
min_cap = next_pow2(min_cap);
/* Next 32-bit power of two */
min_cap--;
min_cap |= min_cap >> 1;
min_cap |= min_cap >> 2;
min_cap |= min_cap >> 4;
min_cap |= min_cap >> 8;
min_cap |= min_cap >> 16;
min_cap++;
/* Create a new pool to hold a bigger buffer, using the same factory */
pj_pool_t *pool = pj_pool_create(cb->pool->factory, "tls-circ%p",
@ -184,7 +153,7 @@ static pj_status_t circ_write(circ_buf_t *cb,
cb->size = old_size;
/* Release the previous pool */
pj_pool_secure_release(&cb->pool);
pj_pool_release(cb->pool);
/* Update circular buffer members */
cb->pool = pool;
@ -1768,7 +1737,7 @@ static pj_status_t ssl_send (pj_ssl_sock_t *ssock,
unsigned flags)
{
pj_status_t status;
int nwritten = 0;
int nwritten;
/* Write the plain data to SSL, after SSL encrypts it, the buffer will
* contain the secured data to be sent via socket. Note that re-
@ -2272,9 +2241,8 @@ static void wipe_buf(pj_str_t *buf)
}
PJ_DEF(void) pj_ssl_cert_wipe_keys(pj_ssl_cert_t *cert)
{
{
if (cert) {
#if (PJ_SSL_SOCK_IMP != PJ_SSL_SOCK_IMP_SCHANNEL)
wipe_buf(&cert->CA_file);
wipe_buf(&cert->CA_path);
wipe_buf(&cert->cert_file);
@ -2283,10 +2251,6 @@ PJ_DEF(void) pj_ssl_cert_wipe_keys(pj_ssl_cert_t *cert)
wipe_buf(&cert->CA_buf);
wipe_buf(&cert->cert_buf);
wipe_buf(&cert->privkey_buf);
#else
cert->criteria.type = PJ_SSL_CERT_LOOKUP_NONE;
wipe_buf(&cert->criteria.keyword);
#endif
}
}
@ -2310,7 +2274,6 @@ PJ_DEF(pj_status_t) pj_ssl_cert_load_from_files2(pj_pool_t *pool,
const pj_str_t *privkey_pass,
pj_ssl_cert_t **p_cert)
{
#if (PJ_SSL_SOCK_IMP != PJ_SSL_SOCK_IMP_SCHANNEL)
pj_ssl_cert_t *cert;
PJ_ASSERT_RETURN(pool && (CA_file || CA_path) && cert_file &&
@ -2331,16 +2294,6 @@ PJ_DEF(pj_status_t) pj_ssl_cert_load_from_files2(pj_pool_t *pool,
*p_cert = cert;
return PJ_SUCCESS;
#else
PJ_UNUSED_ARG(pool);
PJ_UNUSED_ARG(CA_file);
PJ_UNUSED_ARG(CA_path);
PJ_UNUSED_ARG(cert_file);
PJ_UNUSED_ARG(privkey_file);
PJ_UNUSED_ARG(privkey_pass);
PJ_UNUSED_ARG(p_cert);
return PJ_ENOTSUP;
#endif
}
PJ_DEF(pj_status_t) pj_ssl_cert_load_from_buffer(pj_pool_t *pool,
@ -2350,7 +2303,6 @@ PJ_DEF(pj_status_t) pj_ssl_cert_load_from_buffer(pj_pool_t *pool,
const pj_str_t *privkey_pass,
pj_ssl_cert_t **p_cert)
{
#if (PJ_SSL_SOCK_IMP != PJ_SSL_SOCK_IMP_SCHANNEL)
pj_ssl_cert_t *cert;
PJ_ASSERT_RETURN(pool && CA_buf && cert_buf && privkey_buf, PJ_EINVAL);
@ -2364,44 +2316,8 @@ PJ_DEF(pj_status_t) pj_ssl_cert_load_from_buffer(pj_pool_t *pool,
*p_cert = cert;
return PJ_SUCCESS;
#else
PJ_UNUSED_ARG(pool);
PJ_UNUSED_ARG(CA_buf);
PJ_UNUSED_ARG(cert_buf);
PJ_UNUSED_ARG(privkey_buf);
PJ_UNUSED_ARG(privkey_pass);
PJ_UNUSED_ARG(p_cert);
return PJ_ENOTSUP;
#endif
}
PJ_DEF(pj_status_t) pj_ssl_cert_load_from_store(
pj_pool_t *pool,
const pj_ssl_cert_lookup_criteria *criteria,
pj_ssl_cert_t **p_cert)
{
#if (PJ_SSL_SOCK_IMP == PJ_SSL_SOCK_IMP_SCHANNEL)
pj_ssl_cert_t *cert;
PJ_ASSERT_RETURN(pool && criteria && p_cert, PJ_EINVAL);
cert = PJ_POOL_ZALLOC_T(pool, pj_ssl_cert_t);
pj_memcpy(&cert->criteria, criteria, sizeof(*criteria));
pj_strdup_with_null(pool, &cert->criteria.keyword, &criteria->keyword);
*p_cert = cert;
return PJ_SUCCESS;
#else
PJ_UNUSED_ARG(pool);
PJ_UNUSED_ARG(criteria);
PJ_UNUSED_ARG(p_cert);
return PJ_ENOTSUP;
#endif
}
/* Set SSL socket credentials. */
PJ_DEF(pj_status_t) pj_ssl_sock_set_certificate(
pj_ssl_sock_t *ssock,
@ -2414,8 +2330,6 @@ PJ_DEF(pj_status_t) pj_ssl_sock_set_certificate(
cert_ = PJ_POOL_ZALLOC_T(pool, pj_ssl_cert_t);
pj_memcpy(cert_, cert, sizeof(pj_ssl_cert_t));
#if (PJ_SSL_SOCK_IMP != PJ_SSL_SOCK_IMP_SCHANNEL)
pj_strdup_with_null(pool, &cert_->CA_file, &cert->CA_file);
pj_strdup_with_null(pool, &cert_->CA_path, &cert->CA_path);
pj_strdup_with_null(pool, &cert_->cert_file, &cert->cert_file);
@ -2425,10 +2339,6 @@ PJ_DEF(pj_status_t) pj_ssl_sock_set_certificate(
pj_strdup(pool, &cert_->CA_buf, &cert->CA_buf);
pj_strdup(pool, &cert_->cert_buf, &cert->cert_buf);
pj_strdup(pool, &cert_->privkey_buf, &cert->privkey_buf);
#else
pj_strdup_with_null(pool, &cert_->criteria.keyword,
&cert->criteria.keyword);
#endif
ssock->cert = cert_;

View File

@ -152,7 +152,6 @@ struct pj_ssl_sock_t
*/
struct pj_ssl_cert_t
{
#if (PJ_SSL_SOCK_IMP != PJ_SSL_SOCK_IMP_SCHANNEL)
pj_str_t CA_file;
pj_str_t CA_path;
pj_str_t cert_file;
@ -163,9 +162,6 @@ struct pj_ssl_cert_t
pj_ssl_cert_buffer CA_buf;
pj_ssl_cert_buffer cert_buf;
pj_ssl_cert_buffer privkey_buf;
#else
pj_ssl_cert_lookup_criteria criteria;
#endif
};
/* ssl available ciphers */
@ -209,11 +205,9 @@ static pj_status_t flush_delayed_send(pj_ssl_sock_t *ssock);
static pj_status_t circ_init(pj_pool_factory *factory,
circ_buf_t *cb, pj_size_t cap);
static void circ_deinit(circ_buf_t *cb);
static void circ_reset(circ_buf_t* cb);
static pj_bool_t circ_empty(const circ_buf_t *cb);
static pj_size_t circ_size(const circ_buf_t *cb);
static void circ_read(circ_buf_t *cb, pj_uint8_t *dst, pj_size_t len);
static void circ_read_cancel(circ_buf_t* cb, pj_size_t len);
static pj_status_t circ_write(circ_buf_t *cb,
const pj_uint8_t *src, pj_size_t len);

View File

@ -161,7 +161,7 @@ static void update_certs_info(pj_ssl_sock_t* ssock,
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
# define OPENSSL_NO_SSL2 /* seems to be removed in 1.1.0 */
# ifndef M_ASN1_STRING_data
# if !USING_LIBRESSL
# define M_ASN1_STRING_data(x) ASN1_STRING_get0_data(x)
# define M_ASN1_STRING_length(x) ASN1_STRING_length(x)
# endif
@ -483,12 +483,11 @@ static pj_str_t ssl_strerror(pj_status_t status,
*/
static const struct ssl_ciphers_t ADDITIONAL_CIPHERS[] = {
{0xFF000000, "DEFAULT"},
{0xFF000001, "@SECLEVEL=0"},
{0xFF000002, "@SECLEVEL=1"},
{0xFF000003, "@SECLEVEL=2"},
{0xFF000004, "@SECLEVEL=3"},
{0xFF000005, "@SECLEVEL=4"},
{0xFF000006, "@SECLEVEL=5"}
{0xFF000001, "@SECLEVEL=1"},
{0xFF000002, "@SECLEVEL=2"},
{0xFF000003, "@SECLEVEL=3"},
{0xFF000004, "@SECLEVEL=4"},
{0xFF000005, "@SECLEVEL=5"}
};
static const unsigned int ADDITIONAL_CIPHER_COUNT =
sizeof (ADDITIONAL_CIPHERS) / sizeof (ADDITIONAL_CIPHERS[0]);

File diff suppressed because it is too large Load Diff

View File

@ -534,14 +534,11 @@ static int cancel( pj_timer_heap_t *ht,
PJ_CHECK_STACK();
// Check to see if the timer_id is out of range.
// Moved to cancel_timer() as it needs to validate _timer_id earlier
/*
// Check to see if the timer_id is out of range
if (entry->_timer_id < 1 || (pj_size_t)entry->_timer_id >= ht->max_size) {
entry->_timer_id = -1;
return 0;
}
*/
timer_node_slot = ht->timer_ids[entry->_timer_id];
@ -814,13 +811,6 @@ static int cancel_timer(pj_timer_heap_t *ht,
PJ_ASSERT_RETURN(ht && entry, PJ_EINVAL);
lock_timer_heap(ht);
// Check to see if the timer_id is out of range
if (entry->_timer_id < 1 || (pj_size_t)entry->_timer_id >= ht->max_size) {
unlock_timer_heap(ht);
return 0;
}
timer_copy = GET_TIMER(ht, entry);
grp_lock = timer_copy->_grp_lock;

View File

@ -540,39 +540,6 @@ static pj_status_t load_cert_to_buf(pj_pool_t *pool, const pj_str_t *file_name,
}
#endif
static pj_status_t load_cert_from_store(pj_pool_t *pool,
pj_ssl_cert_t **p_cert)
{
#if 0
/* To test loading certificate from the store, follow these steps:
* 1. Install the certificate & the private-key pair to the store,
* and optionally set the friendly-name for it.
* 2. Update the lookup criteria below (field & keyword).
*/
pj_ssl_cert_lookup_criteria crit = {0};
/* Lookup by subject */
crit.type = PJ_SSL_CERT_LOOKUP_SUBJECT;
pj_cstr(&crit.keyword, "test.pjsip.org");
/* Lookup by friendly-name */
//crit.type = PJ_SSL_CERT_LOOKUP_FRIENDLY_NAME;
//pj_cstr(&crit.keyword, "schannel-test");
/* Lookup by fingerprint */
//crit.type = PJ_SSL_CERT_LOOKUP_FINGERPRINT;
//pj_cstr(&crit.keyword, "\x08\x3a\x6c\xdc\xd0\x19\x59\xec\x28\xc3"
// "\x81\xb8\xc0\x21\x09\xe9\xd5\xf6\x57\x7d");
return pj_ssl_cert_load_from_store(pool, &crit, p_cert);
#else
/* Set no certificate, Schannel will use self-signed cert */
PJ_UNUSED_ARG(pool);
PJ_UNUSED_ARG(p_cert);
return PJ_ENOTFOUND;
#endif
}
static int echo_test(pj_ssl_sock_proto srv_proto, pj_ssl_sock_proto cli_proto,
pj_ssl_cipher srv_cipher, pj_ssl_cipher cli_cipher,
pj_bool_t req_client_cert, pj_bool_t client_provide_cert)
@ -635,19 +602,6 @@ static int echo_test(pj_ssl_sock_proto srv_proto, pj_ssl_sock_proto cli_proto,
}
/* Set server cert */
#if (PJ_SSL_SOCK_IMP == PJ_SSL_SOCK_IMP_SCHANNEL)
/* Schannel backend currently can only load certificates from
* OS cert store. If the certificate loading fails, we'll skip setting
* certificate, so the SSL socket will create & use a self-signed cert.
*/
status = load_cert_from_store(pool, &cert);
if (status == PJ_SUCCESS) {
status = pj_ssl_sock_set_certificate(ssock_serv, pool, cert);
if (status != PJ_SUCCESS) {
goto on_return;
}
}
#else
{
pj_str_t ca_file = pj_str(CERT_CA_FILE);
pj_str_t cert_file = pj_str(CERT_FILE);
@ -689,7 +643,6 @@ static int echo_test(pj_ssl_sock_proto srv_proto, pj_ssl_sock_proto cli_proto,
goto on_return;
}
}
#endif
status = pj_ssl_sock_start_accept(ssock_serv, pool, &addr, pj_sockaddr_get_len(&addr));
if (status != PJ_SUCCESS) {
@ -733,22 +686,9 @@ static int echo_test(pj_ssl_sock_proto srv_proto, pj_ssl_sock_proto cli_proto,
goto on_return;
}
/* Set cert for client.
* Reusing certificate for server above, but if client_provide_cert
* is not set, override the certificate with CA certificate.
*/
#if (PJ_SSL_SOCK_IMP == PJ_SSL_SOCK_IMP_SCHANNEL)
if (client_provide_cert) {
status = load_cert_from_store(pool, &cert);
if (status == PJ_SUCCESS)
status = pj_ssl_sock_set_certificate(ssock_cli, pool, cert);
if (status != PJ_SUCCESS) {
goto on_return;
}
}
#else
/* Set cert for client */
{
if (!client_provide_cert) {
pj_str_t ca_file = pj_str(CERT_CA_FILE);
pj_str_t null_str = pj_str("");
@ -780,7 +720,6 @@ static int echo_test(pj_ssl_sock_proto srv_proto, pj_ssl_sock_proto cli_proto,
goto on_return;
}
}
#endif
status = pj_ssl_sock_start_connect(ssock_cli, pool, &addr, &listen_addr, pj_sockaddr_get_len(&addr));
if (status == PJ_SUCCESS) {
@ -987,41 +926,7 @@ static int client_non_ssl(unsigned ms_timeout)
goto on_return;
}
pj_ssl_sock_param_default(&param);
param.cb.on_accept_complete2 = &ssl_on_accept_complete;
param.cb.on_data_read = &ssl_on_data_read;
param.cb.on_data_sent = &ssl_on_data_sent;
param.ioqueue = ioqueue;
param.timer_heap = timer;
param.timeout.sec = 0;
param.timeout.msec = ms_timeout;
pj_time_val_normalize(&param.timeout);
/* SERVER */
param.user_data = &state_serv;
state_serv.pool = pool;
state_serv.is_server = PJ_TRUE;
state_serv.is_verbose = PJ_TRUE;
status = pj_ssl_sock_create(pool, &param, &ssock_serv);
if (status != PJ_SUCCESS) {
goto on_return;
}
/* Set cert */
#if (PJ_SSL_SOCK_IMP == PJ_SSL_SOCK_IMP_SCHANNEL)
/* Schannel backend currently can only load certificates from
* OS cert store. If the certificate loading fails, we'll skip setting
* certificate, so the SSL socket will create & use a self-signed cert.
*/
status = load_cert_from_store(pool, &cert);
if (status == PJ_SUCCESS) {
status = pj_ssl_sock_set_certificate(ssock_serv, pool, cert);
if (status != PJ_SUCCESS) {
goto on_return;
}
}
#else
{
pj_str_t ca_file = pj_str(CERT_CA_FILE);
pj_str_t cert_file = pj_str(CERT_FILE);
@ -1059,11 +964,31 @@ static int client_non_ssl(unsigned ms_timeout)
}
}
pj_ssl_sock_param_default(&param);
param.cb.on_accept_complete2 = &ssl_on_accept_complete;
param.cb.on_data_read = &ssl_on_data_read;
param.cb.on_data_sent = &ssl_on_data_sent;
param.ioqueue = ioqueue;
param.timer_heap = timer;
param.timeout.sec = 0;
param.timeout.msec = ms_timeout;
pj_time_val_normalize(&param.timeout);
/* SERVER */
param.user_data = &state_serv;
state_serv.pool = pool;
state_serv.is_server = PJ_TRUE;
state_serv.is_verbose = PJ_TRUE;
status = pj_ssl_sock_create(pool, &param, &ssock_serv);
if (status != PJ_SUCCESS) {
goto on_return;
}
status = pj_ssl_sock_set_certificate(ssock_serv, pool, cert);
if (status != PJ_SUCCESS) {
goto on_return;
}
#endif
/* Init bind address */
{
@ -1336,49 +1261,7 @@ static int perf_test(unsigned clients, unsigned ms_handshake_timeout)
goto on_return;
}
pj_ssl_sock_param_default(&param);
param.cb.on_accept_complete2 = &ssl_on_accept_complete;
param.cb.on_connect_complete = &ssl_on_connect_complete;
param.cb.on_data_read = &ssl_on_data_read;
param.cb.on_data_sent = &ssl_on_data_sent;
param.ioqueue = ioqueue;
param.timer_heap = timer;
param.timeout.sec = 0;
param.timeout.msec = ms_handshake_timeout;
pj_time_val_normalize(&param.timeout);
/* Init default bind address */
{
pj_str_t tmp_st;
pj_sockaddr_init(PJ_AF_INET, &addr, pj_strset2(&tmp_st, "127.0.0.1"), 0);
}
/* SERVER */
param.user_data = &state_serv;
state_serv.pool = pool;
state_serv.echo = PJ_TRUE;
state_serv.is_server = PJ_TRUE;
status = pj_ssl_sock_create(pool, &param, &ssock_serv);
if (status != PJ_SUCCESS) {
goto on_return;
}
/* Set cert */
#if (PJ_SSL_SOCK_IMP == PJ_SSL_SOCK_IMP_SCHANNEL)
/* Schannel backend currently can only load certificates from
* OS cert store. If the certificate loading fails, we'll skip setting
* certificate, so the SSL socket will create & use a self-signed cert.
*/
status = load_cert_from_store(pool, &cert);
if (status == PJ_SUCCESS) {
status = pj_ssl_sock_set_certificate(ssock_serv, pool, cert);
if (status != PJ_SUCCESS) {
goto on_return;
}
}
#else
{
pj_str_t ca_file = pj_str(CERT_CA_FILE);
pj_str_t cert_file = pj_str(CERT_FILE);
@ -1416,11 +1299,39 @@ static int perf_test(unsigned clients, unsigned ms_handshake_timeout)
}
}
pj_ssl_sock_param_default(&param);
param.cb.on_accept_complete2 = &ssl_on_accept_complete;
param.cb.on_connect_complete = &ssl_on_connect_complete;
param.cb.on_data_read = &ssl_on_data_read;
param.cb.on_data_sent = &ssl_on_data_sent;
param.ioqueue = ioqueue;
param.timer_heap = timer;
param.timeout.sec = 0;
param.timeout.msec = ms_handshake_timeout;
pj_time_val_normalize(&param.timeout);
/* Init default bind address */
{
pj_str_t tmp_st;
pj_sockaddr_init(PJ_AF_INET, &addr, pj_strset2(&tmp_st, "127.0.0.1"), 0);
}
/* SERVER */
param.user_data = &state_serv;
state_serv.pool = pool;
state_serv.echo = PJ_TRUE;
state_serv.is_server = PJ_TRUE;
status = pj_ssl_sock_create(pool, &param, &ssock_serv);
if (status != PJ_SUCCESS) {
goto on_return;
}
status = pj_ssl_sock_set_certificate(ssock_serv, pool, cert);
if (status != PJ_SUCCESS) {
goto on_return;
}
#endif
status = pj_ssl_sock_start_accept(ssock_serv, pool, &addr, pj_sockaddr_get_len(&addr));
if (status != PJ_SUCCESS) {
@ -1624,15 +1535,6 @@ int ssl_sock_test(void)
* which require SSL server, for now.
*/
/* Schannel backend notes:
* - currently it does not support ciphers settings, so we exclude tests
* whose ciphers setting is specified.
* - TLS protocol older than 1.0 is not supported, TLS 1.0 & 1.1 will be
* disabled soon, TLS 1.3 is supported since Windows 11, so for now
* we only include tests with TLS 1.2.
*/
#if (PJ_SSL_SOCK_IMP != PJ_SSL_SOCK_IMP_SCHANNEL)
PJ_LOG(3,("", "..echo test w/ TLSv1 and PJ_TLS_RSA_WITH_AES_256_CBC_SHA cipher"));
ret = echo_test(PJ_SSL_SOCK_PROTO_TLS1, PJ_SSL_SOCK_PROTO_TLS1,
PJ_TLS_RSA_WITH_AES_256_CBC_SHA, PJ_TLS_RSA_WITH_AES_256_CBC_SHA,
@ -1646,7 +1548,6 @@ int ssl_sock_test(void)
PJ_FALSE, PJ_FALSE);
if (ret != 0)
return ret;
#endif
PJ_LOG(3,("", "..echo test w/ compatible proto: server TLSv1.2 vs client TLSv1.2"));
ret = echo_test(PJ_SSL_SOCK_PROTO_TLS1_2, PJ_SSL_SOCK_PROTO_TLS1_2,
@ -1655,7 +1556,6 @@ int ssl_sock_test(void)
if (ret != 0)
return ret;
#if (PJ_SSL_SOCK_IMP != PJ_SSL_SOCK_IMP_SCHANNEL)
PJ_LOG(3,("", "..echo test w/ compatible proto: server TLSv1.2+1.3 vs client TLSv1.3"));
ret = echo_test(PJ_SSL_SOCK_PROTO_TLS1_2 | PJ_SSL_SOCK_PROTO_TLS1_3, PJ_SSL_SOCK_PROTO_TLS1_3,
-1, -1,
@ -1669,10 +1569,9 @@ int ssl_sock_test(void)
PJ_FALSE, PJ_FALSE);
if (ret == 0)
return PJ_EBUG;
#endif
/* We can't set min/max proto for TLS protocol higher than 1.0. */
#if (PJ_SSL_SOCK_IMP != PJ_SSL_SOCK_IMP_DARWIN && PJ_SSL_SOCK_IMP != PJ_SSL_SOCK_IMP_SCHANNEL)
#if (PJ_SSL_SOCK_IMP != PJ_SSL_SOCK_IMP_DARWIN)
PJ_LOG(3,("", "..echo test w/ incompatible proto: server TLSv1.2 vs client TLSv1.3"));
ret = echo_test(PJ_SSL_SOCK_PROTO_TLS1_2, PJ_SSL_SOCK_PROTO_TLS1_3,
-1, -1,
@ -1685,7 +1584,7 @@ int ssl_sock_test(void)
* deprecated and we only have sec_protocol_options_append_tls_ciphersuite(),
* but there's no API to remove certain or all ciphers.
*/
#if (PJ_SSL_SOCK_IMP != PJ_SSL_SOCK_IMP_APPLE && PJ_SSL_SOCK_IMP != PJ_SSL_SOCK_IMP_SCHANNEL)
#if (PJ_SSL_SOCK_IMP != PJ_SSL_SOCK_IMP_APPLE)
PJ_LOG(3,("", "..echo test w/ incompatible ciphers"));
ret = echo_test(PJ_SSL_SOCK_PROTO_DEFAULT, PJ_SSL_SOCK_PROTO_DEFAULT,
PJ_TLS_RSA_WITH_DES_CBC_SHA, PJ_TLS_RSA_WITH_AES_256_CBC_SHA,
@ -1694,7 +1593,6 @@ int ssl_sock_test(void)
return PJ_EBUG;
#endif
#if (PJ_SSL_SOCK_IMP != PJ_SSL_SOCK_IMP_SCHANNEL)
PJ_LOG(3,("", "..echo test w/ client cert required but not provided"));
ret = echo_test(PJ_SSL_SOCK_PROTO_DEFAULT, PJ_SSL_SOCK_PROTO_DEFAULT,
PJ_TLS_RSA_WITH_AES_256_CBC_SHA, PJ_TLS_RSA_WITH_AES_256_CBC_SHA,
@ -1708,7 +1606,6 @@ int ssl_sock_test(void)
PJ_TRUE, PJ_TRUE);
if (ret != 0)
return ret;
#endif
#if WITH_BENCHMARK
PJ_LOG(3,("", "..performance test"));

View File

@ -300,13 +300,6 @@ ifeq ($(AC_PJMEDIA_VIDEO_HAS_DARWIN),yes)
export PJMEDIA_VIDEODEV_OBJS += darwin_dev.o
endif
#
# Metal video device
#
ifeq ($(AC_PJMEDIA_VIDEO_HAS_METAL),yes)
export PJMEDIA_VIDEODEV_OBJS += metal_dev.o
endif
#
# VideoToolbox codec
#

View File

@ -58,11 +58,6 @@ typedef enum pjmedia_vid_dev_hwnd_type
*/
PJMEDIA_VID_DEV_HWND_TYPE_WINDOWS,
/**
* Native view on Cocoa Mac.
*/
PJMEDIA_VID_DEV_HWND_TYPE_COCOA,
/**
* Native view on iOS.
*/

View File

@ -150,9 +150,9 @@ static int AndroidRecorderCallback(void *userData)
{
struct android_aud_stream *stream = (struct android_aud_stream *)userData;
jmethodID read_method=0, record_method=0, stop_method=0;
int size = stream->rec_buf_size / 2;
jshortArray inputBuffer;
jshort *buf;
int size = stream->rec_buf_size;
jbyteArray inputBuffer;
jbyte *buf;
JNIEnv *jni_env = 0;
pj_bool_t attached = attach_jvm(&jni_env);
@ -166,7 +166,7 @@ static int AndroidRecorderCallback(void *userData)
/* Get methods ids */
read_method = (*jni_env)->GetMethodID(jni_env, stream->record_class,
"read", "([SII)I");
"read", "([BII)I");
record_method = (*jni_env)->GetMethodID(jni_env, stream->record_class,
"startRecording", "()V");
stop_method = (*jni_env)->GetMethodID(jni_env, stream->record_class,
@ -177,7 +177,7 @@ static int AndroidRecorderCallback(void *userData)
}
/* Create a buffer for frames read */
inputBuffer = (*jni_env)->NewShortArray(jni_env, size);
inputBuffer = (*jni_env)->NewByteArray(jni_env, size);
if (inputBuffer == 0) {
PJ_LOG(3, (THIS_FILE, "Unable to allocate input buffer"));
goto on_return;
@ -190,7 +190,7 @@ static int AndroidRecorderCallback(void *userData)
while (!stream->quit_flag) {
pjmedia_frame frame;
pj_status_t status;
int shortRead;
int bytesRead;
if (!stream->running) {
(*jni_env)->CallVoidMethod(jni_env, stream->record, stop_method);
@ -200,25 +200,25 @@ static int AndroidRecorderCallback(void *userData)
(*jni_env)->CallVoidMethod(jni_env, stream->record, record_method);
}
shortRead = (*jni_env)->CallIntMethod(jni_env, stream->record,
bytesRead = (*jni_env)->CallIntMethod(jni_env, stream->record,
read_method, inputBuffer,
0, size);
if (shortRead <= 0 || shortRead != size) {
if (bytesRead <= 0 || bytesRead != size) {
PJ_LOG (4, (THIS_FILE, "Record thread : error %d reading data",
shortRead));
bytesRead));
continue;
}
buf = (*jni_env)->GetShortArrayElements(jni_env, inputBuffer, 0);
buf = (*jni_env)->GetByteArrayElements(jni_env, inputBuffer, 0);
frame.type = PJMEDIA_FRAME_TYPE_AUDIO;
frame.size = stream->rec_buf_size;
frame.size = size;
frame.bit_info = 0;
frame.buf = (void *)buf;
frame.timestamp.u64 = stream->rec_timestamp.u64;
status = (*stream->rec_cb)(stream->user_data, &frame);
(*jni_env)->ReleaseShortArrayElements(jni_env, inputBuffer, buf,
JNI_ABORT);
(*jni_env)->ReleaseByteArrayElements(jni_env, inputBuffer, buf,
JNI_ABORT);
if (status != PJ_SUCCESS || stream->quit_flag)
break;
@ -241,9 +241,9 @@ static int AndroidTrackCallback(void *userData)
{
struct android_aud_stream *stream = (struct android_aud_stream*) userData;
jmethodID write_method=0, play_method=0, stop_method=0, flush_method=0;
int size = stream->play_buf_size / 2;
jshortArray outputBuffer;
jshort *buf;
int size = stream->play_buf_size;
jbyteArray outputBuffer;
jbyte *buf;
JNIEnv *jni_env = 0;
pj_bool_t attached = attach_jvm(&jni_env);
@ -255,7 +255,7 @@ static int AndroidTrackCallback(void *userData)
/* Get methods ids */
write_method = (*jni_env)->GetMethodID(jni_env, stream->track_class,
"write", "([SII)I");
"write", "([BII)I");
play_method = (*jni_env)->GetMethodID(jni_env, stream->track_class,
"play", "()V");
stop_method = (*jni_env)->GetMethodID(jni_env, stream->track_class,
@ -269,12 +269,12 @@ static int AndroidTrackCallback(void *userData)
goto on_return;
}
outputBuffer = (*jni_env)->NewShortArray(jni_env, size);
outputBuffer = (*jni_env)->NewByteArray(jni_env, size);
if (outputBuffer == 0) {
PJ_LOG(3, (THIS_FILE, "Unable to allocate output buffer"));
goto on_return;
}
buf = (*jni_env)->GetShortArrayElements(jni_env, outputBuffer, 0);
buf = (*jni_env)->GetByteArrayElements(jni_env, outputBuffer, 0);
/* Start playing */
pj_thread_set_prio(NULL, THREAD_PRIORITY_URGENT_AUDIO);
@ -283,7 +283,7 @@ static int AndroidTrackCallback(void *userData)
while (!stream->quit_flag) {
pjmedia_frame frame;
pj_status_t status;
int shortWritten;
int bytesWritten;
if (!stream->running) {
(*jni_env)->CallVoidMethod(jni_env, stream->track, stop_method);
@ -295,7 +295,7 @@ static int AndroidTrackCallback(void *userData)
}
frame.type = PJMEDIA_FRAME_TYPE_AUDIO;
frame.size = stream->play_buf_size;
frame.size = size;
frame.buf = (void *)buf;
frame.timestamp.u64 = stream->play_timestamp.u64;
frame.bit_info = 0;
@ -307,16 +307,16 @@ static int AndroidTrackCallback(void *userData)
if (frame.type != PJMEDIA_FRAME_TYPE_AUDIO)
pj_bzero(frame.buf, frame.size);
(*jni_env)->ReleaseShortArrayElements(jni_env, outputBuffer, buf,
(*jni_env)->ReleaseByteArrayElements(jni_env, outputBuffer, buf,
JNI_COMMIT);
/* Write to the device output. */
shortWritten = (*jni_env)->CallIntMethod(jni_env, stream->track,
bytesWritten = (*jni_env)->CallIntMethod(jni_env, stream->track,
write_method, outputBuffer,
0, size);
if (shortWritten <= 0 || shortWritten != size) {
if (bytesWritten <= 0 || bytesWritten != size) {
PJ_LOG(4, (THIS_FILE, "Player thread: Error %d writing data",
shortWritten));
bytesWritten));
continue;
}
@ -324,7 +324,7 @@ static int AndroidTrackCallback(void *userData)
stream->param.channel_count;
};
(*jni_env)->ReleaseShortArrayElements(jni_env, outputBuffer, buf, 0);
(*jni_env)->ReleaseByteArrayElements(jni_env, outputBuffer, buf, 0);
(*jni_env)->DeleteLocalRef(jni_env, outputBuffer);
on_return:
@ -476,8 +476,7 @@ static pj_status_t android_create_stream(pjmedia_aud_dev_factory *f,
PJ_ASSERT_RETURN(param->channel_count >= 1 && param->channel_count <= 2,
PJ_EINVAL);
PJ_ASSERT_RETURN(/* param->bits_per_sample==8 || */
param->bits_per_sample==16,
PJ_ASSERT_RETURN(param->bits_per_sample==8 || param->bits_per_sample==16,
PJ_EINVAL);
PJ_ASSERT_RETURN(play_cb && rec_cb && p_aud_strm, PJ_EINVAL);
@ -501,11 +500,8 @@ static pj_status_t android_create_stream(pjmedia_aud_dev_factory *f,
12 /*CHANNEL_IN_STEREO*/;
channelOutCfg = (param->channel_count == 1)? 4 /*CHANNEL_OUT_MONO*/:
12 /*CHANNEL_OUT_STEREO*/;
// The 8bit/byte read/write methods no longer support 16bit
//sampleFormat = (param->bits_per_sample == 8)? 3 /*ENCODING_PCM_8BIT*/:
// 2 /*ENCODING_PCM_16BIT*/;
sampleFormat = 2 /*ENCODING_PCM_16BIT*/;
sampleFormat = (param->bits_per_sample == 8)? 3 /*ENCODING_PCM_8BIT*/:
2 /*ENCODING_PCM_16BIT*/;
attached = attach_jvm(&jni_env);

View File

@ -29,12 +29,6 @@
#define COREAUDIO_MAC 1
#endif
#if (TARGET_OS_OSX && defined(__MAC_12_0))
#define AUDIO_OBJECT_ELEMENT_MAIN kAudioObjectPropertyElementMain;
#else
#define AUDIO_OBJECT_ELEMENT_MAIN kAudioObjectPropertyElementMaster;
#endif
#include <AudioUnit/AudioUnit.h>
#include <AudioToolbox/AudioConverter.h>
#if COREAUDIO_MAC
@ -453,7 +447,7 @@ static pj_status_t ca_factory_refresh(pjmedia_aud_dev_factory *f)
/* Find out how many audio devices there are */
addr.mSelector = kAudioHardwarePropertyDevices;
addr.mScope = kAudioObjectPropertyScopeGlobal;
addr.mElement = AUDIO_OBJECT_ELEMENT_MAIN;
addr.mElement = kAudioObjectPropertyElementMaster;
ostatus = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &addr,
0, NULL, &dev_size);
if (ostatus != noErr) {
@ -498,7 +492,7 @@ static pj_status_t ca_factory_refresh(pjmedia_aud_dev_factory *f)
/* Find default audio input device */
addr.mSelector = kAudioHardwarePropertyDefaultInputDevice;
addr.mScope = kAudioObjectPropertyScopeGlobal;
addr.mElement = AUDIO_OBJECT_ELEMENT_MAIN;
addr.mElement = kAudioObjectPropertyElementMaster;
size = sizeof(dev_id);
ostatus = AudioObjectGetPropertyData(kAudioObjectSystemObject,
@ -550,7 +544,7 @@ static pj_status_t ca_factory_refresh(pjmedia_aud_dev_factory *f)
/* Get device name */
addr.mSelector = kAudioDevicePropertyDeviceName;
addr.mScope = kAudioObjectPropertyScopeGlobal;
addr.mElement = AUDIO_OBJECT_ELEMENT_MAIN;
addr.mElement = kAudioObjectPropertyElementMaster;
size = sizeof(cdi->info.name);
AudioObjectGetPropertyData(cdi->dev_id, &addr,
0, NULL,

View File

@ -22,6 +22,7 @@
#include <pjmedia/errno.h>
#include <pjmedia/endpoint.h>
#include <pjmedia/port.h>
#include <speex/speex.h>
#include <pj/assert.h>
#include <pj/log.h>
#include <pj/pool.h>
@ -33,7 +34,6 @@
*/
#if defined(PJMEDIA_HAS_SPEEX_CODEC) && PJMEDIA_HAS_SPEEX_CODEC!=0
#include <speex/speex.h>
#define THIS_FILE "speex_codec.c"

View File

@ -554,20 +554,17 @@ static OSStatus create_encoder(vtool_codec_data *vtool_data)
ret = VTSessionCopySupportedPropertyDictionary(vtool_data->enc,
&supported_prop);
if (ret == noErr) {
if (CFDictionaryContainsKey(supported_prop,
if (ret == noErr &&
CFDictionaryContainsKey(supported_prop,
kVTCompressionPropertyKey_MaxH264SliceBytes))
{
/* kVTCompressionPropertyKey_MaxH264SliceBytes is not yet supported
* by Apple. We leave it here for possible future enhancements.
SET_PROPERTY(vtool_data->enc,
kVTCompressionPropertyKey_MaxH264SliceBytes,
// param->enc_mtu - NAL_HEADER_ADD_0X30BYTES
(__bridge CFTypeRef)@(param->enc_mtu - 50));
*/
}
CFRelease(supported_prop);
{
/* kVTCompressionPropertyKey_MaxH264SliceBytes is not yet supported
* by Apple. We leave it here for possible future enhancements.
SET_PROPERTY(vtool_data->enc,
kVTCompressionPropertyKey_MaxH264SliceBytes,
// param->enc_mtu - NAL_HEADER_ADD_0X30BYTES
(__bridge CFTypeRef)@(param->enc_mtu - 50));
*/
}
VTCompressionSessionPrepareToEncodeFrames(vtool_data->enc);

View File

@ -313,34 +313,23 @@ static pj_status_t darwin_factory_refresh(pjmedia_vid_dev_factory *f)
if (NSClassFromString(@"AVCaptureSession")) {
NSArray *dev_list = NULL;
if (@available(macOS 10.15, iOS 10.0, *)) {
#if (TARGET_OS_IPHONE && defined(__IPHONE_10_0)) || \
(TARGET_OS_OSX && defined(__MAC_10_15))
if (__builtin_available(macOS 10.15, iOS 10.0, *)) {
/* Starting in iOS 10 and macOS 10.15, [AVCaptureDevice devices]
* is deprecated and replaced by AVCaptureDeviceDiscoverySession.
*/
AVCaptureDeviceDiscoverySession *dds;
NSMutableArray<AVCaptureDeviceType> *dev_types =
[NSMutableArray arrayWithCapacity:5];
[dev_types addObject:AVCaptureDeviceTypeBuiltInWideAngleCamera];
NSArray<AVCaptureDeviceType> *dev_types =
@[AVCaptureDeviceTypeBuiltInWideAngleCamera
#if TARGET_OS_OSX && defined(__MAC_10_15)
, AVCaptureDeviceTypeExternalUnknown
#endif
#if TARGET_OS_IPHONE && defined(__IPHONE_10_0)
// Deprecated in iOS 10.2
// AVCaptureDeviceTypeBuiltInDuoCamera
[dev_types addObject:AVCaptureDeviceTypeBuiltInTelephotoCamera];
#endif
#if (TARGET_OS_IPHONE && defined(__IPHONE_17_0)) || \
(TARGET_OS_OSX && defined(__MAC_14_0))
if (@available(macOS 14.0, iOS 17.0, *)) {
[dev_types addObject:AVCaptureDeviceTypeExternal];
} else {
# if (TARGET_OS_OSX && __MAC_OS_X_VERSION_MIN_REQUIRED < 140000)
[dev_types addObject:AVCaptureDeviceTypeExternalUnknown];
# endif
}
#elif TARGET_OS_OSX
[dev_types addObject:AVCaptureDeviceTypeExternalUnknown];
, AVCaptureDeviceTypeBuiltInDuoCamera
, AVCaptureDeviceTypeBuiltInTelephotoCamera
#endif
];
dds = [AVCaptureDeviceDiscoverySession
discoverySessionWithDeviceTypes:dev_types
@ -349,11 +338,13 @@ static pj_status_t darwin_factory_refresh(pjmedia_vid_dev_factory *f)
dev_list = [dds devices];
} else {
#if (TARGET_OS_OSX && __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_15) || \
(TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_10_0)
#if __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_15
dev_list = [AVCaptureDevice devices];
#endif
}
#else
dev_list = [AVCaptureDevice devices];
#endif
for (AVCaptureDevice *device in dev_list) {
if (![device hasMediaType:AVMediaTypeVideo] ||
@ -1049,32 +1040,6 @@ static pj_status_t darwin_stream_get_cap(pjmedia_vid_dev_stream *s,
return PJMEDIA_EVID_INVCAP;
}
static pj_bool_t set_orientation(struct darwin_stream *strm)
{
#if (TARGET_OS_OSX && __MAC_OS_X_VERSION_MIN_REQUIRED < 140000) || \
(TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED < 170000)
const AVCaptureVideoOrientation cap_ori[4] =
{
AVCaptureVideoOrientationLandscapeLeft, /* NATURAL */
AVCaptureVideoOrientationPortrait, /* 90DEG */
AVCaptureVideoOrientationLandscapeRight, /* 180DEG */
AVCaptureVideoOrientationPortraitUpsideDown, /* 270DEG */
};
AVCaptureConnection *vidcon;
vidcon = [strm->video_output
connectionWithMediaType:AVMediaTypeVideo];
if ([vidcon isVideoOrientationSupported]) {
vidcon.videoOrientation = cap_ori[strm->param.orient-1];
return PJ_TRUE;
}
#endif
return PJ_FALSE;
}
/* API: set capability */
static pj_status_t darwin_stream_set_cap(pjmedia_vid_dev_stream *s,
pjmedia_vid_dev_cap cap,
@ -1277,7 +1242,6 @@ static pj_status_t darwin_stream_set_cap(pjmedia_vid_dev_stream *s,
case PJMEDIA_VID_DEV_CAP_ORIENTATION:
{
pjmedia_orient orient = *(pjmedia_orient *)pval;
pj_bool_t support_ori = PJ_FALSE;
pj_assert(orient >= PJMEDIA_ORIENT_UNKNOWN &&
orient <= PJMEDIA_ORIENT_ROTATE_270DEG);
@ -1299,35 +1263,30 @@ static pj_status_t darwin_stream_set_cap(pjmedia_vid_dev_stream *s,
return PJ_SUCCESS;
}
const AVCaptureVideoOrientation cap_ori[4] =
{
AVCaptureVideoOrientationLandscapeLeft, /* NATURAL */
AVCaptureVideoOrientationPortrait, /* 90DEG */
AVCaptureVideoOrientationLandscapeRight, /* 180DEG */
AVCaptureVideoOrientationPortraitUpsideDown, /* 270DEG */
};
AVCaptureConnection *vidcon;
pj_bool_t support_ori = PJ_TRUE;
pj_assert(strm->param.dir == PJMEDIA_DIR_CAPTURE);
if (!strm->video_output)
return PJMEDIA_EVID_NOTREADY;
#if (TARGET_OS_IPHONE && defined(__IPHONE_17_0)) || \
(TARGET_OS_OSX && defined(__MAC_14_0))
if (@available(macOS 14.0, iOS 17.0, *)) {
const CGFloat cap_ori[4] = { 0, 90, 180, 270};
AVCaptureConnection *vidcon;
vidcon = [strm->video_output
connectionWithMediaType:AVMediaTypeVideo];
if ([vidcon isVideoRotationAngleSupported:
cap_ori[strm->param.orient-1]])
{
vidcon.videoRotationAngle = cap_ori[strm->param.orient-1];
support_ori = PJ_TRUE;
}
vidcon = [strm->video_output
connectionWithMediaType:AVMediaTypeVideo];
if ([vidcon isVideoOrientationSupported]) {
vidcon.videoOrientation = cap_ori[strm->param.orient-1];
} else {
support_ori = set_orientation(strm);
support_ori = PJ_FALSE;
}
#else
support_ori = set_orientation(strm);
#endif
if (!strm->conv.conv) {
pj_status_t status;
pjmedia_rect_size orig_size;

View File

@ -1,971 +0,0 @@
/*
* Copyright (C) 2024 Teluu Inc. (http://www.teluu.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "util.h"
#include <pjmedia-videodev/videodev_imp.h>
#include <pj/assert.h>
#include <pj/log.h>
#include <pj/os.h>
#if defined(PJMEDIA_HAS_VIDEO) && PJMEDIA_HAS_VIDEO != 0 && \
defined(PJMEDIA_VIDEO_DEV_HAS_METAL) && PJMEDIA_VIDEO_DEV_HAS_METAL != 0
#import "MetalKit/MetalKit.h"
#include "TargetConditionals.h"
#define THIS_FILE "metal_dev.m"
#define DEFAULT_CLOCK_RATE 90000
#define DEFAULT_WIDTH 640
#define DEFAULT_HEIGHT 480
#define DEFAULT_FPS 15
#if TARGET_OS_IPHONE
# define NSView UIView
# define NSWindow UIWindow
#endif
typedef struct metal_fmt_info
{
pjmedia_format_id pjmedia_format;
MTLPixelFormat metal_format;
} metal_fmt_info;
static metal_fmt_info metal_fmts[] =
{
{ PJMEDIA_FORMAT_BGRA, MTLPixelFormatBGRA8Unorm },
{ PJMEDIA_FORMAT_RGBA, MTLPixelFormatRGBA8Unorm },
};
struct metal_dev_info
{
pjmedia_vid_dev_info info;
};
/* metal factory */
struct metal_factory
{
pjmedia_vid_dev_factory base;
pj_pool_t *pool;
pj_pool_factory *pf;
unsigned dev_count;
struct metal_dev_info dev_info[1];
};
@interface MetalRenderer : NSObject<MTKViewDelegate>
@end
/* Video stream. */
struct metal_stream
{
pjmedia_vid_dev_stream base; /**< Base stream */
pjmedia_vid_dev_param param; /**< Settings */
pj_pool_t *pool; /**< Memory pool */
struct metal_factory *factory; /**< Factory */
pjmedia_vid_dev_cb vid_cb; /**< Stream callback */
void *user_data; /**< Application data */
pjmedia_rect_size size;
unsigned bytes_per_row;
unsigned frame_size; /**< Frame size (bytes)*/
pj_bool_t is_planar;
pjmedia_vid_dev_conv conv;
pjmedia_rect_size vid_size;
MetalRenderer *renderer;
MTKView *view;
MTLPixelFormat format;
NSWindow *window;
pj_bool_t is_running;
pj_bool_t is_rendering;
void *render_buf;
pj_size_t render_buf_size;
pj_timestamp frame_ts;
unsigned ts_inc;
};
/* Prototypes */
static pj_status_t metal_factory_init(pjmedia_vid_dev_factory *f);
static pj_status_t metal_factory_destroy(pjmedia_vid_dev_factory *f);
static pj_status_t metal_factory_refresh(pjmedia_vid_dev_factory *f);
static unsigned metal_factory_get_dev_count(pjmedia_vid_dev_factory *f);
static pj_status_t metal_factory_get_dev_info(pjmedia_vid_dev_factory *f,
unsigned index,
pjmedia_vid_dev_info *info);
static pj_status_t metal_factory_default_param(pj_pool_t *pool,
pjmedia_vid_dev_factory *f,
unsigned index,
pjmedia_vid_dev_param *param);
static pj_status_t metal_factory_create_stream(
pjmedia_vid_dev_factory *f,
pjmedia_vid_dev_param *param,
const pjmedia_vid_dev_cb *cb,
void *user_data,
pjmedia_vid_dev_stream **p_vid_strm);
static pj_status_t metal_stream_get_param(pjmedia_vid_dev_stream *strm,
pjmedia_vid_dev_param *param);
static pj_status_t metal_stream_get_cap(pjmedia_vid_dev_stream *strm,
pjmedia_vid_dev_cap cap,
void *value);
static pj_status_t metal_stream_set_cap(pjmedia_vid_dev_stream *strm,
pjmedia_vid_dev_cap cap,
const void *value);
static pj_status_t metal_stream_start(pjmedia_vid_dev_stream *strm);
static pj_status_t metal_stream_put_frame(pjmedia_vid_dev_stream *strm,
const pjmedia_frame *frame);
static pj_status_t metal_stream_stop(pjmedia_vid_dev_stream *strm);
static pj_status_t metal_stream_destroy(pjmedia_vid_dev_stream *strm);
/* Operations */
static pjmedia_vid_dev_factory_op factory_op =
{
&metal_factory_init,
&metal_factory_destroy,
&metal_factory_get_dev_count,
&metal_factory_get_dev_info,
&metal_factory_default_param,
&metal_factory_create_stream,
&metal_factory_refresh
};
static pjmedia_vid_dev_stream_op stream_op =
{
&metal_stream_get_param,
&metal_stream_get_cap,
&metal_stream_set_cap,
&metal_stream_start,
NULL,
&metal_stream_put_frame,
&metal_stream_stop,
&metal_stream_destroy
};
static void dispatch_sync_on_main_queue(void (^block)(void))
{
if ([NSThread isMainThread]) {
block();
} else {
dispatch_sync(dispatch_get_main_queue(), block);
}
}
/****************************************************************************
* Factory operations
*/
/*
* Init metal_ video driver.
*/
pjmedia_vid_dev_factory* pjmedia_metal_factory(pj_pool_factory *pf)
{
struct metal_factory *f;
pj_pool_t *pool;
pool = pj_pool_create(pf, "metal video", 8000, 4000, NULL);
f = PJ_POOL_ZALLOC_T(pool, struct metal_factory);
f->pf = pf;
f->pool = pool;
f->base.op = &factory_op;
return &f->base;
}
/* API: init factory */
static pj_status_t metal_factory_init(pjmedia_vid_dev_factory *f)
{
return metal_factory_refresh(f);
}
/* API: destroy factory */
static pj_status_t metal_factory_destroy(pjmedia_vid_dev_factory *f)
{
struct metal_factory *qf = (struct metal_factory*)f;
pj_pool_t *pool = qf->pool;
qf->pool = NULL;
pj_pool_release(pool);
return PJ_SUCCESS;
}
/* API: refresh the list of devices */
static pj_status_t metal_factory_refresh(pjmedia_vid_dev_factory *f)
{
struct metal_factory *qf = (struct metal_factory*)f;
if (@available(macOS 10.14, iOS 12.0, *)) {
struct metal_dev_info *qdi;
unsigned l;
id<MTLDevice> device;
device = MTLCreateSystemDefaultDevice();
if (!device) {
PJ_LOG(3, (THIS_FILE, "No Metal device found"));
return PJ_SUCCESS;
} else {
[device release];
}
/* Init output device */
qdi = &qf->dev_info[qf->dev_count++];
pj_bzero(qdi, sizeof(*qdi));
pj_ansi_strxcpy(qdi->info.name, "Metal", sizeof(qdi->info.name));
pj_ansi_strxcpy(qdi->info.driver, "Apple", sizeof(qdi->info.driver));
qdi->info.dir = PJMEDIA_DIR_RENDER;
qdi->info.has_callback = PJ_FALSE;
/* Set supported formats */
qdi->info.caps |= PJMEDIA_VID_DEV_CAP_FORMAT |
PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW |
PJMEDIA_VID_DEV_CAP_OUTPUT_RESIZE |
PJMEDIA_VID_DEV_CAP_OUTPUT_POSITION |
PJMEDIA_VID_DEV_CAP_OUTPUT_HIDE |
PJMEDIA_VID_DEV_CAP_ORIENTATION;
for (l = 0; l < PJ_ARRAY_SIZE(metal_fmts); l++) {
pjmedia_format *fmt = &qdi->info.fmt[qdi->info.fmt_cnt++];
pjmedia_format_init_video(fmt, metal_fmts[l].pjmedia_format,
DEFAULT_WIDTH, DEFAULT_HEIGHT,
DEFAULT_FPS, 1);
}
}
PJ_LOG(4, (THIS_FILE, "Metal video initialized with %d devices",
qf->dev_count));
return PJ_SUCCESS;
}
/* API: get number of devices */
static unsigned metal_factory_get_dev_count(pjmedia_vid_dev_factory *f)
{
struct metal_factory *qf = (struct metal_factory*)f;
return qf->dev_count;
}
/* API: get device info */
static pj_status_t metal_factory_get_dev_info(pjmedia_vid_dev_factory *f,
unsigned index,
pjmedia_vid_dev_info *info)
{
struct metal_factory *qf = (struct metal_factory*)f;
PJ_ASSERT_RETURN(index < qf->dev_count, PJMEDIA_EVID_INVDEV);
pj_memcpy(info, &qf->dev_info[index].info, sizeof(*info));
return PJ_SUCCESS;
}
/* API: create default device parameter */
static pj_status_t metal_factory_default_param(pj_pool_t *pool,
pjmedia_vid_dev_factory *f,
unsigned index,
pjmedia_vid_dev_param *param)
{
struct metal_factory *qf = (struct metal_factory*)f;
struct metal_dev_info *di;
PJ_ASSERT_RETURN(index < qf->dev_count, PJMEDIA_EVID_INVDEV);
PJ_UNUSED_ARG(pool);
di = &qf->dev_info[index];
pj_bzero(param, sizeof(*param));
if (di->info.dir & PJMEDIA_DIR_RENDER) {
param->dir = PJMEDIA_DIR_RENDER;
param->rend_id = index;
param->cap_id = PJMEDIA_VID_INVALID_DEV;
} else {
return PJMEDIA_EVID_INVDEV;
}
param->flags = PJMEDIA_VID_DEV_CAP_FORMAT;
param->clock_rate = DEFAULT_CLOCK_RATE;
pj_memcpy(&param->fmt, &di->info.fmt[0], sizeof(param->fmt));
return PJ_SUCCESS;
}
@implementation MetalRenderer
{
MTKView *_view;
id<MTLDevice> device;
id<MTLCommandQueue> commandQueue;
id<MTLRenderPipelineState> pipelineState;
id<MTLBuffer> vertexBuffer;
id<MTLBuffer> textureCoordBuffer;
@public
struct metal_stream *stream;
}
#define _STRINGIFY( _x ) # _x
- (nonnull instancetype)initWithMetalKitView:(nonnull MTKView *)mtkView
{
self = [super init];
if (self) {
NSString *code;
NSError *error = nil;
id<MTLLibrary> shaderLibrary;
id <MTLFunction> fragmentProgram;
id <MTLFunction> vertexProgram;
MTLRenderPipelineDescriptor *pQuadPipelineStateDescriptor;
/* Create a buffer for a full-screen quad */
static const float vertexData[] = {
-1.0, -1.0, 0.0, 1.0,
1.0, -1.0, 0.0, 1.0,
-1.0, 1.0, 0.0, 1.0,
1.0, 1.0, 0.0, 1.0,
};
/* Create texture coordinates for a full-screen quad */
static const float textureCoordinates[] = {
0.0, 1.0,
1.0, 1.0,
0.0, 0.0,
1.0, 0.0,
};
_view = mtkView;
device = mtkView.device;
/* Create the command queue */
commandQueue = [device newCommandQueue];
/* Metal shader code */
code = [NSString stringWithFormat:@"#include <metal_stdlib>\n%s",
_STRINGIFY(
using namespace metal;
struct VertexInOut
{
float4 m_Position [[position]];
float2 m_TexCoord [[user(texturecoord)]];
};
vertex VertexInOut
texturedVertex(constant float4 *pPosition [[ buffer(0) ]],
constant packed_float2 *pTexCoords [[ buffer(1) ]],
constant float4x4 *pMVP [[ buffer(2) ]],
uint vid [[ vertex_id ]])
{
VertexInOut outVertices;
outVertices.m_Position = pPosition[vid];
outVertices.m_TexCoord = pTexCoords[vid];
return outVertices;
}
fragment half4
texturedFrag(VertexInOut inFrag [[ stage_in ]],
texture2d<half> tex2D [[ texture(0) ]])
{
constexpr sampler quad_sampler;
half4 color = tex2D.sample(quad_sampler, inFrag.m_TexCoord);
return color;
}
)];
/* Create a Metal library instance by compiling the code */
shaderLibrary = [device newLibraryWithSource:code options:nil
error:&error];
if (error) {
NSLog(@"Unable to create Metal library err: %@", error);
return self;
}
fragmentProgram = [shaderLibrary newFunctionWithName:@"texturedFrag"];
vertexProgram = [shaderLibrary newFunctionWithName:@"texturedVertex"];
if (!fragmentProgram || !vertexProgram) {
NSLog(@"Unable to load Metal functions");
return self;
}
/* Create a pipeline state */
pQuadPipelineStateDescriptor = [MTLRenderPipelineDescriptor new];
pQuadPipelineStateDescriptor.colorAttachments[0].pixelFormat =
stream->format;
pQuadPipelineStateDescriptor.vertexFunction = vertexProgram;
pQuadPipelineStateDescriptor.fragmentFunction = fragmentProgram;
pipelineState = [device
newRenderPipelineStateWithDescriptor:pQuadPipelineStateDescriptor
error:&error];
if (error) {
NSLog(@"newRenderPipelineStateWithDescriptor err: %@", error);
return self;
}
vertexBuffer = [device newBufferWithBytes:vertexData
length:sizeof(vertexData)
options:MTLResourceStorageModeShared];
textureCoordBuffer = [device newBufferWithBytes:textureCoordinates
length:sizeof(textureCoordinates)
options:MTLResourceStorageModeShared];
[pQuadPipelineStateDescriptor release];
[fragmentProgram release];
[vertexProgram release];
[shaderLibrary release];
}
return self;
}
- (void)dealloc {
if (vertexBuffer) {
[vertexBuffer release];
vertexBuffer = nil;
}
if (textureCoordBuffer) {
[textureCoordBuffer release];
textureCoordBuffer = nil;
}
if (device) {
[device release];
device = nil;
}
if (commandQueue) {
[commandQueue release];
commandQueue = nil;
}
if (pipelineState) {
[pipelineState release];
pipelineState = nil;
}
[super dealloc];
}
- (void)update_image
{
MTLRenderPassDescriptor *renderPassDescriptor;
id<MTLCommandBuffer> commandBuffer;
id<MTLRenderCommandEncoder> renderEncoder;
id<MTLDrawable> drawable;
id<MTLTexture> texture;
MTLTextureDescriptor *textureDescriptor;
MTLRegion region;
unsigned width = stream->size.w, height = stream->size.h;
/* Place the buffer into a texture */
textureDescriptor = [MTLTextureDescriptor
texture2DDescriptorWithPixelFormat:stream->format
width:width height:height mipmapped:NO];
texture = [device newTextureWithDescriptor:textureDescriptor];
region = MTLRegionMake2D(0, 0, width, height);
[texture replaceRegion:region mipmapLevel:0 withBytes:stream->render_buf
bytesPerRow:stream->bytes_per_row];
/* The render pass descriptor references the texture into which Metal
* should draw.
*/
renderPassDescriptor = _view.currentRenderPassDescriptor;
if (renderPassDescriptor == nil)
return;
commandBuffer = [commandQueue commandBuffer];
renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:
renderPassDescriptor];
[renderEncoder setRenderPipelineState:pipelineState];
[renderEncoder setVertexBuffer:vertexBuffer offset:0 atIndex:0];
[renderEncoder setVertexBuffer:textureCoordBuffer offset:0 atIndex:1];
[renderEncoder setFragmentTexture:texture atIndex:0];
[renderEncoder drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0
vertexCount:4];
[renderEncoder endEncoding];
/* Get the drawable that will be presented at the end of the frame */
drawable = _view.currentDrawable;
/* Request that the drawable texture be presented by the windowing system
* once drawing is done.
*/
[commandBuffer presentDrawable:drawable];
[commandBuffer commit];
[texture release];
stream->is_rendering = PJ_FALSE;
}
/* Called whenever the view needs to render a frame. */
- (void)drawInMTKView:(nonnull MTKView *)view
{
}
/* Called whenever view changes orientation or is resized */
- (void)mtkView:(nonnull MTKView *)view drawableSizeWillChange:(CGSize)size
{
}
@end
static pj_status_t metal_init_view(struct metal_stream *strm)
{
pjmedia_vid_dev_param *param = &strm->param;
CGRect view_rect = CGRectMake(0, 0, param->fmt.det.vid.size.w,
param->fmt.det.vid.size.h);
if (param->flags & PJMEDIA_VID_DEV_CAP_OUTPUT_RESIZE) {
view_rect.size.width = param->disp_size.w;
view_rect.size.height = param->disp_size.h;
}
if (param->flags & PJMEDIA_VID_DEV_CAP_OUTPUT_POSITION) {
view_rect.origin.x = param->window_pos.x;
view_rect.origin.y = param->window_pos.y;
}
strm->view = [[MTKView alloc] initWithFrame:view_rect];
if (!strm->view)
return PJMEDIA_EVID_SYSERR;
strm->view.enableSetNeedsDisplay = NO;
strm->view.paused = NO;
strm->view.device = MTLCreateSystemDefaultDevice();
strm->view.clearColor = MTLClearColorMake(0.0, 0.0, 0.0, 1.0);
strm->param.window.info.window = strm->view;
strm->renderer = [MetalRenderer alloc];
if (!strm->renderer)
return PJ_ENOMEM;
strm->renderer->stream = strm;
strm->view.delegate = strm->renderer;
[strm->renderer initWithMetalKitView:strm->view];
if (param->flags & PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW) {
PJ_ASSERT_RETURN(param->window.info.ios.window, PJ_EINVAL);
metal_stream_set_cap(&strm->base, PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW,
param->window.info.ios.window);
} else {
#if !TARGET_OS_IPHONE
/* Create the main window */
strm->window = [[NSWindow alloc] initWithContentRect:view_rect
styleMask:(NSWindowStyleMaskTitled |
NSWindowStyleMaskClosable |
NSWindowStyleMaskResizable)
backing:NSBackingStoreBuffered
defer:NO];
if (!strm->window)
return PJMEDIA_EVID_SYSERR;
/* Make the window visible */
[strm->window.contentView addSubview:strm->view];
[strm->window makeKeyAndOrderFront:strm->window];
strm->param.window.info.window = strm->window;
#endif
}
if (param->flags & PJMEDIA_VID_DEV_CAP_OUTPUT_HIDE) {
metal_stream_set_cap(&strm->base, PJMEDIA_VID_DEV_CAP_OUTPUT_HIDE,
&param->window_hide);
}
if (param->flags & PJMEDIA_VID_DEV_CAP_ORIENTATION) {
metal_stream_set_cap(&strm->base, PJMEDIA_VID_DEV_CAP_ORIENTATION,
&param->orient);
}
return PJ_SUCCESS;
}
static metal_fmt_info* get_metal_format_info(pjmedia_format_id id)
{
unsigned i;
for (i = 0; i < PJ_ARRAY_SIZE(metal_fmts); i++) {
if (metal_fmts[i].pjmedia_format == id)
return &metal_fmts[i];
}
return NULL;
}
/* API: create stream */
static pj_status_t metal_factory_create_stream(
pjmedia_vid_dev_factory *f,
pjmedia_vid_dev_param *param,
const pjmedia_vid_dev_cb *cb,
void *user_data,
pjmedia_vid_dev_stream **p_vid_strm)
{
struct metal_factory *qf = (struct metal_factory*)f;
pj_pool_t *pool;
struct metal_stream *strm;
pjmedia_video_format_detail *vfd;
const pjmedia_video_format_info *vfi;
metal_fmt_info *mfi;
pj_status_t status = PJ_SUCCESS;
PJ_ASSERT_RETURN(f && param && p_vid_strm, PJ_EINVAL);
PJ_ASSERT_RETURN(param->fmt.type == PJMEDIA_TYPE_VIDEO &&
param->fmt.detail_type == PJMEDIA_FORMAT_DETAIL_VIDEO &&
param->dir == PJMEDIA_DIR_RENDER,
PJ_EINVAL);
if (!(mfi = get_metal_format_info(param->fmt.id)))
return PJMEDIA_EVID_BADFORMAT;
vfi = pjmedia_get_video_format_info(NULL, param->fmt.id);
if (!vfi)
return PJMEDIA_EVID_BADFORMAT;
/* Create and Initialize stream descriptor */
pool = pj_pool_create(qf->pf, "metal-dev", 4000, 4000, NULL);
PJ_ASSERT_RETURN(pool != NULL, PJ_ENOMEM);
strm = PJ_POOL_ZALLOC_T(pool, struct metal_stream);
pj_memcpy(&strm->param, param, sizeof(*param));
strm->pool = pool;
pj_memcpy(&strm->vid_cb, cb, sizeof(*cb));
strm->user_data = user_data;
strm->factory = qf;
vfd = pjmedia_format_get_video_format_detail(&strm->param.fmt, PJ_TRUE);
pj_memcpy(&strm->size, &vfd->size, sizeof(vfd->size));
strm->bytes_per_row = strm->size.w * vfi->bpp / 8;
strm->frame_size = strm->bytes_per_row * strm->size.h;
strm->ts_inc = PJMEDIA_SPF2(param->clock_rate, &vfd->fps, 1);
strm->is_planar = vfi->plane_cnt > 1;
strm->format = mfi->metal_format;
if (param->dir & PJMEDIA_DIR_RENDER) {
/* Create renderer stream here */
dispatch_sync_on_main_queue(^{
metal_init_view(strm);
});
strm->render_buf = pj_pool_alloc(pool, strm->frame_size);
strm->render_buf_size = strm->frame_size;
PJ_LOG(4, (THIS_FILE, "Metal renderer initialized"));
}
/* Done */
strm->base.op = &stream_op;
*p_vid_strm = &strm->base;
return PJ_SUCCESS;
on_error:
metal_stream_destroy((pjmedia_vid_dev_stream *)strm);
return status;
}
/* API: Get stream info. */
static pj_status_t metal_stream_get_param(pjmedia_vid_dev_stream *s,
pjmedia_vid_dev_param *pi)
{
struct metal_stream *strm = (struct metal_stream*)s;
PJ_ASSERT_RETURN(strm && pi, PJ_EINVAL);
pj_memcpy(pi, &strm->param, sizeof(*pi));
return PJ_SUCCESS;
}
/* API: get capability */
static pj_status_t metal_stream_get_cap(pjmedia_vid_dev_stream *s,
pjmedia_vid_dev_cap cap,
void *pval)
{
struct metal_stream *strm = (struct metal_stream*)s;
PJ_ASSERT_RETURN(s && pval, PJ_EINVAL);
PJ_UNUSED_ARG(strm);
switch (cap) {
case PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW:
{
pjmedia_vid_dev_hwnd *hwnd = (pjmedia_vid_dev_hwnd *) pval;
hwnd->type = TARGET_OS_IPHONE? PJMEDIA_VID_DEV_HWND_TYPE_IOS:
PJMEDIA_VID_DEV_HWND_TYPE_COCOA;
hwnd->info.window = (void *)strm->view;
return PJ_SUCCESS;
}
default:
break;
}
return PJMEDIA_EVID_INVCAP;
}
/* API: set capability */
static pj_status_t metal_stream_set_cap(pjmedia_vid_dev_stream *s,
pjmedia_vid_dev_cap cap,
const void *pval)
{
struct metal_stream *strm = (struct metal_stream*)s;
PJ_ASSERT_RETURN(s && pval, PJ_EINVAL);
switch (cap) {
case PJMEDIA_VID_DEV_CAP_FORMAT:
{
const pjmedia_video_format_info *vfi;
pjmedia_video_format_detail *vfd;
pjmedia_format *fmt = (pjmedia_format *)pval;
metal_fmt_info *ifi;
if (!(ifi = get_metal_format_info(fmt->id)))
return PJMEDIA_EVID_BADFORMAT;
vfi = pjmedia_get_video_format_info(
pjmedia_video_format_mgr_instance(),
fmt->id);
if (!vfi)
return PJMEDIA_EVID_BADFORMAT;
pjmedia_format_copy(&strm->param.fmt, fmt);
vfd = pjmedia_format_get_video_format_detail(fmt, PJ_TRUE);
pj_memcpy(&strm->size, &vfd->size, sizeof(vfd->size));
strm->bytes_per_row = strm->size.w * vfi->bpp / 8;
strm->frame_size = strm->bytes_per_row * strm->size.h;
if (strm->render_buf_size < strm->frame_size) {
/* Realloc only when needed */
strm->render_buf = pj_pool_alloc(strm->pool, strm->frame_size);
strm->render_buf_size = strm->frame_size;
}
return PJ_SUCCESS;
}
case PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW:
{
strm->param.window.info.window = (void *)pval;
dispatch_sync_on_main_queue(^{
[(NSView *)pval addSubview:strm->view];
});
return PJ_SUCCESS;
}
case PJMEDIA_VID_DEV_CAP_OUTPUT_RESIZE:
{
pj_memcpy(&strm->param.disp_size, pval,
sizeof(strm->param.disp_size));
dispatch_sync_on_main_queue(^{
CGRect r = (strm->window)? strm->window.frame:
strm->view.bounds;
r.size = CGSizeMake(strm->param.disp_size.w,
strm->param.disp_size.h);
if (!strm->window)
strm->view.bounds = r;
#if !TARGET_OS_IPHONE
else
[strm->window setFrame:r display:YES];
#endif
});
return PJ_SUCCESS;
}
case PJMEDIA_VID_DEV_CAP_OUTPUT_POSITION:
{
pj_memcpy(&strm->param.window_pos, pval,
sizeof(strm->param.window_pos));
dispatch_sync_on_main_queue(^{
#if TARGET_OS_IPHONE
strm->view.center =
CGPointMake(strm->param.window_pos.x +
strm->param.disp_size.w/2.0,
strm->param.window_pos.y +
strm->param.disp_size.h/2.0);
#else
if (strm->window) {
[strm->window setFrameOrigin:
NSMakePoint(strm->param.window_pos.x,
strm->param.window_pos.y)];
} else {
[strm->view setFrameOrigin:
NSMakePoint(strm->param.window_pos.x,
strm->param.window_pos.y)];
}
#endif
});
return PJ_SUCCESS;
}
case PJMEDIA_VID_DEV_CAP_OUTPUT_HIDE:
{
dispatch_sync_on_main_queue(^{
pj_bool_t hide = *((pj_bool_t *)pval);
if (strm->window) {
#if !TARGET_OS_IPHONE
if (hide)
[strm->window orderOut: nil];
else
[strm->window orderFront: nil];
#endif
} else {
strm->view.hidden = (BOOL)hide;
}
});
return PJ_SUCCESS;
}
case PJMEDIA_VID_DEV_CAP_ORIENTATION:
{
pjmedia_orient orient = *(pjmedia_orient *)pval;
pj_assert(orient >= PJMEDIA_ORIENT_UNKNOWN &&
orient <= PJMEDIA_ORIENT_ROTATE_270DEG);
if (orient == PJMEDIA_ORIENT_UNKNOWN)
return PJ_EINVAL;
pj_memcpy(&strm->param.orient, pval,
sizeof(strm->param.orient));
dispatch_sync_on_main_queue(^{
CGFloat angle = -M_PI_2 * ((int)strm->param.orient-1);
#if TARGET_OS_IPHONE
strm->view.transform =
CGAffineTransformMakeRotation(angle);
#else
strm->view.layer.affineTransform =
CGAffineTransformMakeRotation(angle);
#endif
});
return PJ_SUCCESS;
}
default:
break;
}
return PJMEDIA_EVID_INVCAP;
}
/* API: Start stream. */
static pj_status_t metal_stream_start(pjmedia_vid_dev_stream *strm)
{
struct metal_stream *stream = (struct metal_stream*)strm;
PJ_LOG(4, (THIS_FILE, "Starting Metal video stream"));
stream->is_running = PJ_TRUE;
return PJ_SUCCESS;
}
/* API: Put frame from stream */
static pj_status_t metal_stream_put_frame(pjmedia_vid_dev_stream *strm,
const pjmedia_frame *frame)
{
struct metal_stream *stream = (struct metal_stream*)strm;
/* Video conference just trying to send heart beat for updating timestamp
* or keep-alive, this port doesn't need any, just ignore.
*/
if (frame->size==0 || frame->buf==NULL)
return PJ_SUCCESS;
if (!stream->is_running)
return PJ_EINVALIDOP;
/* Prevent more than one async rendering task. */
if (stream->is_rendering)
return PJ_EIGNORED;
if (stream->frame_size >= frame->size)
pj_memcpy(stream->render_buf, frame->buf, frame->size);
else
pj_memcpy(stream->render_buf, frame->buf, stream->frame_size);
/* Perform video display in the main thread */
stream->is_rendering = PJ_TRUE;
[stream->renderer performSelectorOnMainThread:@selector(update_image)
withObject:nil waitUntilDone:NO];
return PJ_SUCCESS;
}
/* API: Stop stream. */
static pj_status_t metal_stream_stop(pjmedia_vid_dev_stream *strm)
{
struct metal_stream *stream = (struct metal_stream*)strm;
unsigned i;
PJ_LOG(4, (THIS_FILE, "Stopping Metal video stream"));
stream->is_running = PJ_FALSE;
/* Wait until the rendering finishes */
for (i = 0; i < 15; i++) pj_thread_sleep(10);
while (stream->is_rendering);
return PJ_SUCCESS;
}
/* API: Destroy stream. */
static pj_status_t metal_stream_destroy(pjmedia_vid_dev_stream *strm)
{
struct metal_stream *stream = (struct metal_stream*)strm;
PJ_ASSERT_RETURN(stream != NULL, PJ_EINVAL);
metal_stream_stop(strm);
if (stream->renderer) {
[stream->renderer release];
stream->renderer = nil;
}
if (stream->view) {
[stream->view
performSelectorOnMainThread:@selector(removeFromSuperview)
withObject:nil waitUntilDone:YES];
[stream->view release];
stream->view = nil;
}
if (stream->window) {
[stream->window performSelectorOnMainThread:@selector(close)
withObject:nil waitUntilDone:YES];
stream->window = nil;
}
pjmedia_vid_dev_conv_destroy_converter(&stream->conv);
pj_pool_release(stream->pool);
return PJ_SUCCESS;
}
#endif /* PJMEDIA_VIDEO_DEV_HAS_METAL */

View File

@ -34,10 +34,6 @@ pjmedia_vid_dev_factory* pjmedia_dshow_factory(pj_pool_factory *pf);
pjmedia_vid_dev_factory* pjmedia_cbar_factory(pj_pool_factory *pf);
#endif
#if PJMEDIA_VIDEO_DEV_HAS_METAL
pjmedia_vid_dev_factory* pjmedia_metal_factory(pj_pool_factory *pf);
#endif
#if PJMEDIA_VIDEO_DEV_HAS_SDL
pjmedia_vid_dev_factory* pjmedia_sdl_factory(pj_pool_factory *pf);
#endif
@ -101,9 +97,6 @@ PJ_DEF(pj_status_t) pjmedia_vid_dev_subsys_init(pj_pool_factory *pf)
#if PJMEDIA_VIDEO_DEV_HAS_QT
vid_subsys->drv[vid_subsys->drv_cnt++].create = &pjmedia_qt_factory;
#endif
#if PJMEDIA_VIDEO_DEV_HAS_METAL
vid_subsys->drv[vid_subsys->drv_cnt++].create = &pjmedia_metal_factory;
#endif
#if PJMEDIA_VIDEO_DEV_HAS_OPENGL
vid_subsys->drv[vid_subsys->drv_cnt++].create = &pjmedia_opengl_factory;
#endif

View File

@ -79,8 +79,7 @@ pjmedia_clock_src_get_time_msec( const pjmedia_clock_src *clocksrc )
{
pj_timestamp ts;
if (pjmedia_clock_src_get_current_timestamp(clocksrc, &ts) != PJ_SUCCESS)
return 0;
pjmedia_clock_src_get_current_timestamp(clocksrc, &ts);
#if PJ_HAS_INT64
if (ts.u64 > PJ_UINT64(0x3FFFFFFFFFFFFF))

View File

@ -24,12 +24,14 @@
#include <pj/log.h>
#include <pj/pool.h>
#define THIS_FILE "resample.c"
#if PJMEDIA_RESAMPLE_IMP==PJMEDIA_RESAMPLE_LIBRESAMPLE
#include <third_party/resample/include/resamplesubs.h>
#define THIS_FILE "resample.c"
struct pjmedia_resample
{
@ -156,7 +158,7 @@ PJ_DEF(void) pjmedia_resample_run( pjmedia_resample *resample,
* So here comes the trick.
*
* First of all, because of the history and lookahead requirement,
* resample->buffer need to accommodate framesize+2*xoff samples in its
* resample->buffer need to accomodate framesize+2*xoff samples in its
* buffer. This is done when the buffer is created.
*
* On the first run, the input frame (supplied by application) is
@ -174,8 +176,8 @@ PJ_DEF(void) pjmedia_resample_run( pjmedia_resample *resample,
* | 0000 | 0000 | frame0... |
* +------+------+--------------+
* ^ ^ ^ ^
* 0 xoff 2*xoff size+2*xoff
*
* 0 xoff 2*xoff size+2*xoff
*
* (Note again: resample algorithm is called at resample->buffer+xoff)
*
* At the end of the run, 2*xoff samples from the end of
@ -202,7 +204,7 @@ PJ_DEF(void) pjmedia_resample_run( pjmedia_resample *resample,
* | frm0 | frm0 | frame1... |
* +------+------+--------------+
* ^ ^ ^ ^
* 0 xoff 2*xoff size+2*xoff
* 0 xoff 2*xoff size+2*xoff
*
* As you can see from above diagram, the resampling algorithm is
* actually called from the last xoff part of previous frame (frm0).
@ -318,8 +320,6 @@ PJ_DEF(pj_status_t) pjmedia_resample_create( pj_pool_t *pool,
PJ_UNUSED_ARG(samples_per_frame);
PJ_UNUSED_ARG(p_resample);
PJ_LOG(3, (THIS_FILE, "No resampler created (sample rate conversion is "
"disabled or no resample implementation selected)"));
return PJ_EINVALIDOP;
}

View File

@ -895,11 +895,9 @@ static int print_session(const pjmedia_sdp_session *ses,
int printed;
/* Check length for v= and o= lines. */
if (len < 5 + 2 + ses->origin.user.slen +
20 + 20 + 3 + /* max digits of origin.id and version +
* whitespaces */
ses->origin.net_type.slen + ses->origin.addr_type.slen +
ses->origin.addr.slen + 2 + 2)
if (len < 5+
2+ses->origin.user.slen+18+
ses->origin.net_type.slen+ses->origin.addr.slen + 2)
{
return -1;
}
@ -961,7 +959,7 @@ static int print_session(const pjmedia_sdp_session *ses,
}
/* Time */
if ((end-p) < 2+20+1+20+2) {
if ((end-p) < 24) {
return -1;
}
*p++ = 't';

View File

@ -464,7 +464,7 @@ static pj_status_t ssl_generate_cert(X509 **p_cert, EVP_PKEY **p_priv_key)
if (!X509_set_pubkey(cert, priv_key)) goto on_error;
/* Sign with the private key */
if (!X509_sign(cert, priv_key, EVP_sha256())) goto on_error;
if (!X509_sign(cert, priv_key, EVP_sha1())) goto on_error;
/* Free big number */
BN_free(bne);
@ -829,6 +829,8 @@ static pj_status_t ssl_flush_wbio(dtls_srtp *ds, unsigned idx)
PJ_LOG(2,(ds->base.name, "DTLS-SRTP negotiation for %s completed!",
CHANNEL_TO_STRING(idx)));
DTLS_UNLOCK(ds);
/* Stop the retransmission clock. Note that the clock may not be stopped
* if this function is called from clock thread context. We'll try again
* later in socket context.
@ -836,8 +838,6 @@ static pj_status_t ssl_flush_wbio(dtls_srtp *ds, unsigned idx)
if (ds->clock[idx])
pjmedia_clock_stop(ds->clock[idx]);
DTLS_UNLOCK(ds);
/* Get SRTP key material */
status = ssl_get_srtp_material(ds, idx);
if (status != PJ_SUCCESS) {
@ -1890,10 +1890,8 @@ static pj_status_t dtls_media_stop(pjmedia_transport *tp)
PJ_LOG(2,(ds->base.name, "dtls_media_stop()"));
#endif
DTLS_LOCK(ds);
dtls_media_stop_channel(ds, RTP_CHANNEL);
dtls_media_stop_channel(ds, RTCP_CHANNEL);
DTLS_UNLOCK(ds);
ds->setup = DTLS_SETUP_UNKNOWN;
ds->use_ice = PJ_FALSE;

View File

@ -34,9 +34,6 @@
# endif
#endif
#if (PJ_SSL_SOCK_IMP == PJ_SSL_SOCK_IMP_APPLE)
#include <Security/SecRandom.h>
#endif
#include <pj/rand.h>
@ -137,16 +134,6 @@ static pj_status_t generate_crypto_attr_value(pj_pool_t *pool,
"(native err=%d)", err));
return PJMEDIA_ERRNO_FROM_LIBSRTP(1);
}
#elif defined(PJ_HAS_SSL_SOCK) && (PJ_HAS_SSL_SOCK != 0) && \
(PJ_SSL_SOCK_IMP == PJ_SSL_SOCK_IMP_APPLE)
int err = SecRandomCopyBytes(kSecRandomDefault,
crypto_suites[cs_idx].cipher_key_len,
&key);
if (err != errSecSuccess) {
PJ_LOG(4,(THIS_FILE, "Failed generating random key "
"(native err=%d)", err));
return PJMEDIA_ERRNO_FROM_LIBSRTP(1);
}
#else
PJ_LOG(3,(THIS_FILE, "Warning: simple random generator is used "
"for generating SRTP key"));

View File

@ -240,7 +240,7 @@ static int loopback_test(void)
if ((cdi.dir & PJMEDIA_DIR_CAPTURE) == 0)
continue;
for (j=0; j<count; ++j) {
for (j=i+1; j<count; ++j) {
pjmedia_vid_dev_info rdi;
unsigned k;

View File

@ -223,14 +223,6 @@ typedef struct pj_turn_sock_tls_cfg
*/
pj_str_t password;
/**
* Lookup certificate from OS certificate store with specified criteria.
*
* Currently only used by TLS backend Windows Schannel, please check
* pj_ssl_cert_load_from_store() for more info.
*/
pj_ssl_cert_lookup_criteria cert_lookup;
/**
* The ssl socket parameter.
* These fields are used by TURN TLS:
@ -363,8 +355,8 @@ typedef struct pj_turn_sock_cfg
unsigned so_sndbuf_size;
/**
* This specifies TLS settings for TLS transport. It's only applicable when
* TLS is used to connect to the TURN server.
* This specifies TLS settings for TLS transport. It is only be used
* when this TLS is used to connect to the TURN server.
*/
pj_turn_sock_tls_cfg tls_cfg;

View File

@ -1677,8 +1677,8 @@ static pj_bool_t on_check_complete(pj_ice_sess *ice,
}
}
LOG5((ice->obj_name, "Check %d is successful%s",
(int)GET_CHECK_ID(&ice->clist, check),
LOG5((ice->obj_name, "Check %ld is successful%s",
GET_CHECK_ID(&ice->clist, check),
(check->nominated ? " and nominated" : "")));
/* On the first valid pair, we call the callback, if present */

View File

@ -664,9 +664,7 @@ PJ_DEF(pj_status_t) pj_turn_session_set_server( pj_turn_session *sess,
unsigned i, cnt;
/* Default port must be specified */
PJ_ASSERT_ON_FAIL(default_port>0 && default_port<65536,
{status=PJ_EINVAL; goto on_return;});
PJ_ASSERT_RETURN(default_port>0 && default_port<65536, PJ_EINVAL);
sess->default_port = (pj_uint16_t)default_port;
cnt = PJ_TURN_MAX_DNS_SRV_CNT;
@ -1201,7 +1199,7 @@ PJ_DEF(pj_status_t) pj_turn_session_connection_bind(
PJ_STUN_ATTR_CONNECTION_ID,
conn_id);
conn_bind = PJ_POOL_ZALLOC_T(tdata->pool, struct conn_bind_t);
conn_bind = PJ_POOL_ZALLOC_T(pool, struct conn_bind_t);
conn_bind->id = conn_id;
pj_sockaddr_cp(&conn_bind->peer_addr, peer_addr);
conn_bind->peer_addr_len = addr_len;

View File

@ -1389,21 +1389,12 @@ static void turn_on_state(pj_turn_session *sess,
&turn_sock->setting.tls_cfg.privkey_buf,
&turn_sock->setting.tls_cfg.password,
&turn_sock->cert);
} else if (turn_sock->setting.tls_cfg.cert_lookup.type !=
PJ_SSL_CERT_LOOKUP_NONE &&
turn_sock->setting.tls_cfg.cert_lookup.keyword.slen)
{
status = pj_ssl_cert_load_from_store(
turn_sock->pool,
&turn_sock->setting.tls_cfg.cert_lookup,
&turn_sock->cert);
}
if (status != PJ_SUCCESS) {
turn_sock_destroy(turn_sock, status);
pj_grp_lock_release(turn_sock->grp_lock);
return;
}
if (turn_sock->cert) {
pj_turn_sock_tls_cfg_wipe_keys(&turn_sock->setting.tls_cfg);
}

View File

@ -387,8 +387,6 @@ static void set_device_offline(const char *dev_id)
{
int i;
pj_mutex_lock(upnp_mgr.mutex);
for (i = 0; i < (int)upnp_mgr.igd_cnt; i++) {
struct igd *igd = &upnp_mgr.igd_devs[i];
@ -396,6 +394,7 @@ static void set_device_offline(const char *dev_id)
if (!pj_strcmp2(&igd->dev_id, dev_id) && igd->valid) {
igd->alive = PJ_FALSE;
pj_mutex_lock(upnp_mgr.mutex);
if (i == upnp_mgr.primary_igd_idx) {
unsigned j;
@ -414,10 +413,9 @@ static void set_device_offline(const char *dev_id)
(upnp_mgr.primary_igd_idx < 0? "(none)":
igd->dev_id.ptr)));
}
pj_mutex_unlock(upnp_mgr.mutex);
}
}
pj_mutex_unlock(upnp_mgr.mutex);
}
/* UPnP client callback. */
@ -855,6 +853,7 @@ PJ_DEF(pj_status_t)pj_upnp_del_port_mapping(const pj_sockaddr *mapped_addr)
}
igd = &upnp_mgr.igd_devs[upnp_mgr.primary_igd_idx];
pj_mutex_unlock(upnp_mgr.mutex);
/* Compare IGD's public IP to the mapped public address. */
pj_sockaddr_cp(&host_addr, mapped_addr);
@ -875,8 +874,7 @@ PJ_DEF(pj_status_t)pj_upnp_del_port_mapping(const pj_sockaddr *mapped_addr)
}
}
}
pj_mutex_unlock(upnp_mgr.mutex);
if (!igd) {
/* Either the IGD we previously requested to add port mapping has become
* offline, or the address is actually not a valid.

View File

@ -49,9 +49,8 @@ static void dump_status(pj_turn_srv *srv)
}
printf("Worker threads : %d\n", srv->core.thread_cnt);
/* Field used_size is deprecated by #3897 */
//printf("Total mem usage: %u.%03uMB\n", (unsigned)(g_cp.used_size / 1000000),
// (unsigned)((g_cp.used_size % 1000000)/1000));
printf("Total mem usage: %u.%03uMB\n", (unsigned)(g_cp.used_size / 1000000),
(unsigned)((g_cp.used_size % 1000000)/1000));
printf("UDP port range : %u %u %u (next/min/max)\n", srv->ports.next_udp,
srv->ports.min_udp, srv->ports.max_udp);
printf("TCP port range : %u %u %u (next/min/max)\n", srv->ports.next_tcp,

View File

@ -7,9 +7,6 @@
objects = {
/* Begin PBXBuildFile section */
3A4E3B582B62025C0016735C /* MetalKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A4E3B562B62025B0016735C /* MetalKit.framework */; };
3A4E3B592B62025C0016735C /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A4E3B572B62025B0016735C /* Metal.framework */; };
3A4E3BA52B734E9A0016735C /* Network.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A4E3BA42B734E9A0016735C /* Network.framework */; };
3A6FC61C25CBD4540065F472 /* ipjsua_swiftApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A6FC61B25CBD4540065F472 /* ipjsua_swiftApp.swift */; };
3A6FC61E25CBD4540065F472 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A6FC61D25CBD4540065F472 /* ContentView.swift */; };
3A6FC62025CBD4550065F472 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3A6FC61F25CBD4550065F472 /* Assets.xcassets */; };
@ -52,24 +49,9 @@
3A6FC7F225CD1A3E0065F472 /* libwebrtc.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A6FC7DE25CD1A3D0065F472 /* libwebrtc.a */; };
3A6FC7F325CD1A3E0065F472 /* libpjmedia-codec.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A6FC7DF25CD1A3D0065F472 /* libpjmedia-codec.a */; };
3A6FC7F425CD1A3E0065F472 /* libpjmedia-audiodev.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A6FC7E025CD1A3D0065F472 /* libpjmedia-audiodev.a */; };
3AF9B5372B7B454D0043987D /* ipjsua_swiftVidTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AF9B5362B7B454D0043987D /* ipjsua_swiftVidTest.swift */; };
3AF9B5392B7B454D0043987D /* ipjsua_swiftVidTestLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AF9B5382B7B454D0043987D /* ipjsua_swiftVidTestLaunchTests.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
3AF9B53A2B7B454D0043987D /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 3A6FC61025CBD4540065F472 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 3A6FC61725CBD4540065F472;
remoteInfo = "ipjsua-swift";
};
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
3A4E3B562B62025B0016735C /* MetalKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MetalKit.framework; path = System/Library/Frameworks/MetalKit.framework; sourceTree = SDKROOT; };
3A4E3B572B62025B0016735C /* Metal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Metal.framework; path = System/Library/Frameworks/Metal.framework; sourceTree = SDKROOT; };
3A4E3BA42B734E9A0016735C /* Network.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Network.framework; path = System/Library/Frameworks/Network.framework; sourceTree = SDKROOT; };
3A6FC61825CBD4540065F472 /* ipjsua-swift.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "ipjsua-swift.app"; sourceTree = BUILT_PRODUCTS_DIR; };
3A6FC61B25CBD4540065F472 /* ipjsua_swiftApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ipjsua_swiftApp.swift; sourceTree = "<group>"; };
3A6FC61D25CBD4540065F472 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
@ -115,10 +97,6 @@
3A6FC7DE25CD1A3D0065F472 /* libwebrtc.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libwebrtc.a; sourceTree = "<group>"; };
3A6FC7DF25CD1A3D0065F472 /* libpjmedia-codec.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libpjmedia-codec.a"; sourceTree = "<group>"; };
3A6FC7E025CD1A3D0065F472 /* libpjmedia-audiodev.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libpjmedia-audiodev.a"; sourceTree = "<group>"; };
3AF9B5342B7B454D0043987D /* ipjsua-swiftVidTest.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "ipjsua-swiftVidTest.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
3AF9B5362B7B454D0043987D /* ipjsua_swiftVidTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ipjsua_swiftVidTest.swift; sourceTree = "<group>"; };
3AF9B5382B7B454D0043987D /* ipjsua_swiftVidTestLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ipjsua_swiftVidTestLaunchTests.swift; sourceTree = "<group>"; };
3AF9B53F2B7B583C0043987D /* ipjsua-swift.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = "ipjsua-swift.xctestplan"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -157,22 +135,12 @@
3A6FC7E725CD1A3E0065F472 /* libyuv.a in Frameworks */,
3A6FC78325CBE3700065F472 /* Security.framework in Frameworks */,
3A6FC7F425CD1A3E0065F472 /* libpjmedia-audiodev.a in Frameworks */,
3A4E3B592B62025C0016735C /* Metal.framework in Frameworks */,
3A4E3B582B62025C0016735C /* MetalKit.framework in Frameworks */,
3A6FC7EA25CD1A3E0065F472 /* libpjnath.a in Frameworks */,
3A6FC7E125CD1A3D0065F472 /* libpjsip-simple.a in Frameworks */,
3A6FC78425CBE3700065F472 /* SystemConfiguration.framework in Frameworks */,
3A6FC7F325CD1A3E0065F472 /* libpjmedia-codec.a in Frameworks */,
3A6FC78525CBE3700065F472 /* UIKit.framework in Frameworks */,
3A6FC78625CBE3700065F472 /* VideoToolbox.framework in Frameworks */,
3A4E3BA52B734E9A0016735C /* Network.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
3AF9B5312B7B454D0043987D /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -182,8 +150,6 @@
3A6FC60F25CBD4540065F472 = {
isa = PBXGroup;
children = (
3AF9B53F2B7B583C0043987D /* ipjsua-swift.xctestplan */,
3AF9B5352B7B454D0043987D /* ipjsua-swiftVidTest */,
3A6FC75A25CBD6CF0065F472 /* Frameworks */,
3A6FC6AF25CBD5790065F472 /* Libraries */,
3A6FC61A25CBD4540065F472 /* ipjsua-swift */,
@ -195,7 +161,6 @@
isa = PBXGroup;
children = (
3A6FC61825CBD4540065F472 /* ipjsua-swift.app */,
3AF9B5342B7B454D0043987D /* ipjsua-swiftVidTest.xctest */,
);
name = Products;
sourceTree = "<group>";
@ -252,9 +217,6 @@
3A6FC75A25CBD6CF0065F472 /* Frameworks */ = {
isa = PBXGroup;
children = (
3A4E3BA42B734E9A0016735C /* Network.framework */,
3A4E3B572B62025B0016735C /* Metal.framework */,
3A4E3B562B62025B0016735C /* MetalKit.framework */,
3A6FC75B25CBD6E10065F472 /* AudioToolbox.framework */,
3A6FC76B25CBD6E10065F472 /* AVFoundation.framework */,
3A6FC76925CBD6E10065F472 /* CFNetwork.framework */,
@ -276,15 +238,6 @@
name = Frameworks;
sourceTree = "<group>";
};
3AF9B5352B7B454D0043987D /* ipjsua-swiftVidTest */ = {
isa = PBXGroup;
children = (
3AF9B5362B7B454D0043987D /* ipjsua_swiftVidTest.swift */,
3AF9B5382B7B454D0043987D /* ipjsua_swiftVidTestLaunchTests.swift */,
);
path = "ipjsua-swiftVidTest";
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@ -305,41 +258,19 @@
productReference = 3A6FC61825CBD4540065F472 /* ipjsua-swift.app */;
productType = "com.apple.product-type.application";
};
3AF9B5332B7B454D0043987D /* ipjsua-swiftVidTest */ = {
isa = PBXNativeTarget;
buildConfigurationList = 3AF9B53E2B7B454D0043987D /* Build configuration list for PBXNativeTarget "ipjsua-swiftVidTest" */;
buildPhases = (
3AF9B5302B7B454D0043987D /* Sources */,
3AF9B5312B7B454D0043987D /* Frameworks */,
3AF9B5322B7B454D0043987D /* Resources */,
);
buildRules = (
);
dependencies = (
3AF9B53B2B7B454D0043987D /* PBXTargetDependency */,
);
name = "ipjsua-swiftVidTest";
productName = "ipjsua-swiftVidTest";
productReference = 3AF9B5342B7B454D0043987D /* ipjsua-swiftVidTest.xctest */;
productType = "com.apple.product-type.bundle.ui-testing";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
3A6FC61025CBD4540065F472 /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 1520;
LastSwiftUpdateCheck = 1240;
LastUpgradeCheck = 1240;
TargetAttributes = {
3A6FC61725CBD4540065F472 = {
CreatedOnToolsVersion = 12.4;
LastSwiftMigration = 1240;
};
3AF9B5332B7B454D0043987D = {
CreatedOnToolsVersion = 15.2;
TestTargetID = 3A6FC61725CBD4540065F472;
};
};
};
buildConfigurationList = 3A6FC61325CBD4540065F472 /* Build configuration list for PBXProject "ipjsua-swift" */;
@ -356,7 +287,6 @@
projectRoot = "";
targets = (
3A6FC61725CBD4540065F472 /* ipjsua-swift */,
3AF9B5332B7B454D0043987D /* ipjsua-swiftVidTest */,
);
};
/* End PBXProject section */
@ -371,13 +301,6 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
3AF9B5322B7B454D0043987D /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
@ -391,25 +314,8 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
3AF9B5302B7B454D0043987D /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
3AF9B5392B7B454D0043987D /* ipjsua_swiftVidTestLaunchTests.swift in Sources */,
3AF9B5372B7B454D0043987D /* ipjsua_swiftVidTest.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
3AF9B53B2B7B454D0043987D /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 3A6FC61725CBD4540065F472 /* ipjsua-swift */;
targetProxy = 3AF9B53A2B7B454D0043987D /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
3A6FC62525CBD4550065F472 /* Debug */ = {
isa = XCBuildConfiguration;
@ -549,11 +455,9 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CLANG_ENABLE_MODULES = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Manual;
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_ASSET_PATHS = "\"ipjsua-swift/Preview Content\"";
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 93NHJQ455P;
DEVELOPMENT_TEAM = 93NHJQ455P;
ENABLE_PREVIEWS = YES;
INFOPLIST_FILE = "ipjsua-swift/Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
@ -576,8 +480,6 @@
);
PRODUCT_BUNDLE_IDENTIFIER = "com.teluu.ipjsua-swift";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "Teluu Profile";
SWIFT_OBJC_BRIDGING_HEADER = "ipjsua-swift/ipjsua-swift-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
@ -591,11 +493,9 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CLANG_ENABLE_MODULES = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Manual;
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_ASSET_PATHS = "\"ipjsua-swift/Preview Content\"";
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 93NHJQ455P;
DEVELOPMENT_TEAM = 93NHJQ455P;
ENABLE_PREVIEWS = YES;
INFOPLIST_FILE = "ipjsua-swift/Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
@ -618,69 +518,12 @@
);
PRODUCT_BUNDLE_IDENTIFIER = "com.teluu.ipjsua-swift";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "Teluu Profile";
SWIFT_OBJC_BRIDGING_HEADER = "ipjsua-swift/ipjsua-swift-Bridging-Header.h";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
3AF9B53C2B7B454D0043987D /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 93NHJQ455P;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = "com.teluu.ipjsua-swiftVidTest";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "Teluu Profile";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
SWIFT_EMIT_LOC_STRINGS = NO;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_TARGET_NAME = "ipjsua-swift";
};
name = Debug;
};
3AF9B53D2B7B454D0043987D /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 93NHJQ455P;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = "com.teluu.ipjsua-swiftVidTest";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "Teluu Profile";
SWIFT_EMIT_LOC_STRINGS = NO;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_TARGET_NAME = "ipjsua-swift";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
@ -702,15 +545,6 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
3AF9B53E2B7B454D0043987D /* Build configuration list for PBXNativeTarget "ipjsua-swiftVidTest" */ = {
isa = XCConfigurationList;
buildConfigurations = (
3AF9B53C2B7B454D0043987D /* Debug */,
3AF9B53D2B7B454D0043987D /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 3A6FC61025CBD4540065F472 /* Project object */;

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1420"
version = "1.7">
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
@ -27,24 +27,7 @@
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<TestPlans>
<TestPlanReference
reference = "container:ipjsua-swift.xctestplan"
default = "YES">
</TestPlanReference>
</TestPlans>
<Testables>
<TestableReference
skipped = "NO"
parallelizable = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "3AF9B5332B7B454D0043987D"
BuildableName = "ipjsua-swiftVidTest.xctest"
BlueprintName = "ipjsua-swiftVidTest"
ReferencedContainer = "container:ipjsua-swift.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction

View File

@ -1,30 +0,0 @@
{
"configurations" : [
{
"id" : "A0480BD1-665B-4D82-9F04-A4890A775321",
"name" : "Configuration 1",
"options" : {
}
}
],
"defaultOptions" : {
"codeCoverage" : false,
"targetForVariableExpansion" : {
"containerPath" : "container:ipjsua-swift.xcodeproj",
"identifier" : "3A6FC61725CBD4540065F472",
"name" : "ipjsua-swift"
}
},
"testTargets" : [
{
"parallelizable" : true,
"target" : {
"containerPath" : "container:ipjsua-swift.xcodeproj",
"identifier" : "3AF9B5332B7B454D0043987D",
"name" : "ipjsua-swiftVidTest"
}
}
],
"version" : 1
}

View File

@ -75,9 +75,8 @@ struct ContentView: View {
var body: some View {
VStack(alignment: .center) {
HStack(alignment: .center) {
Text(pjsip_vars.calling != true ? "Destination:" :
pjsip_vars.vid_win != nil ? "Video" : "")
if (!pjsip_vars.calling) {
Text("Destination:")
TextField(pjsip_vars.dest, text: $pjsip_vars.dest)
.frame(minWidth:0, maxWidth:200)
}

View File

@ -6,8 +6,6 @@
<string>Audio call permission</string>
<key>NSCameraUsageDescription</key>
<string>Video call permission</string>
<key>NSLocalNetworkUsageDescription</key>
<string>Local network permission</string>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>

View File

@ -54,7 +54,6 @@ struct ipjsua_swiftApp: App {
pjsua_media_config_default(&media_cfg);
/* Initialize application callbacks */
cfg.cb.on_incoming_call = on_incoming_call;
cfg.cb.on_call_state = on_call_state;
cfg.cb.on_call_media_state = on_call_media_state;
@ -65,37 +64,10 @@ struct ipjsua_swiftApp: App {
var transport_id = pjsua_transport_id();
var tcp_cfg = pjsua_transport_config();
pjsua_transport_config_default(&tcp_cfg);
tcp_cfg.port = 5080;
tcp_cfg.port = 5060;
status = pjsua_transport_create(PJSIP_TRANSPORT_TCP,
&tcp_cfg, &transport_id);
/* Add local account */
var aid = pjsua_acc_id();
status = pjsua_acc_add_local(transport_id, pj_bool_t(PJ_TRUE.rawValue), &aid);
/* Use colorbar for local account and enable incoming video */
var acc_cfg = pjsua_acc_config();
var tmp_pool:UnsafeMutablePointer<pj_pool_t>? = nil;
var info : [pjmedia_vid_dev_info] =
Array(repeating: pjmedia_vid_dev_info(), count: 16);
var count:UInt32 = UInt32(info.capacity);
tmp_pool = pjsua_pool_create("tmp-ipjsua", 1000, 1000);
pjsua_acc_get_config(aid, tmp_pool, &acc_cfg);
acc_cfg.vid_in_auto_show = pj_bool_t(PJ_TRUE.rawValue);
pjsua_vid_enum_devs(&info, &count);
for i in 0..<count {
let name: [CChar] = tupleToArray(tuple: info[Int(i)].name);
if let dev_name = String(validatingUTF8: name) {
if (dev_name == "Colorbar generator") {
acc_cfg.vid_cap_dev = pjmedia_vid_dev_index(i);
break;
}
}
}
pjsua_acc_modify(aid, &acc_cfg);
/* Init account config */
let id = strdup("Test<sip:test@sip.pjsip.org>");
let username = strdup("test");
@ -104,6 +76,7 @@ struct ipjsua_swiftApp: App {
let registrar = strdup("sip:sip.pjsip.org");
let proxy = strdup("sip:sip.pjsip.org;transport=tcp");
var acc_cfg = pjsua_acc_config();
pjsua_acc_config_default(&acc_cfg);
acc_cfg.id = pj_str(id);
acc_cfg.cred_count = 1;
@ -122,9 +95,7 @@ struct ipjsua_swiftApp: App {
/* Free strings */
free(id); free(username); free(passwd); free(realm);
free(registrar); free(proxy);
pj_pool_release(tmp_pool);
/* Start pjsua */
status = pjsua_start();
}
@ -138,19 +109,6 @@ struct ipjsua_swiftApp: App {
}
}
private func on_incoming_call(acc_id: pjsua_acc_id, call_id: pjsua_call_id,
rdata: UnsafeMutablePointer<pjsip_rx_data>?)
{
var opt = pjsua_call_setting();
pjsua_call_setting_default(&opt);
opt.aud_cnt = 1;
opt.vid_cnt = 1;
/* Automatically answer call with 200 */
pjsua_call_answer2(call_id, &opt, 200, nil, nil);
}
private func on_call_state(call_id: pjsua_call_id,
e: UnsafeMutablePointer<pjsip_event>?)
{
@ -199,25 +157,9 @@ private func on_call_media_state(call_id: pjsua_call_id)
let vid_win:UIView =
Unmanaged<UIView>.fromOpaque(wi.hwnd.info.ios.window).takeUnretainedValue();
/* For local loopback test, one acts as a transmitter,
the other as a receiver.
*/
if (AppDelegate.Shared.pjsip_vars.vid_win == nil) {
/* UIView update must be done in the main thread */
DispatchQueue.main.sync {
AppDelegate.Shared.pjsip_vars.vid_win = vid_win;
}
} else {
if (AppDelegate.Shared.pjsip_vars.vid_win != vid_win) {
/* Transmitter */
var param = pjsua_call_vid_strm_op_param ();
pjsua_call_vid_strm_op_param_default(&param);
param.med_idx = 1;
pjsua_call_set_vid_strm(call_id,
PJSUA_CALL_VID_STRM_START_TRANSMIT,
&param);
}
/* UIView update must be done in the main thread */
DispatchQueue.main.sync {
AppDelegate.Shared.pjsip_vars.vid_win = vid_win;
}
}
break;

View File

@ -1,112 +0,0 @@
//
// ipjsua_swiftVidTest.swift
// ipjsua-swiftVidTest
//
import XCTest
final class ipjsua_swiftVidTest: XCTestCase {
override func setUpWithError() throws {
// Put setup code here. This method is called before the invocation of each test method in the class.
// Add an interruption monitor to handle system alerts
addUIInterruptionMonitor(withDescription: "Allow network permission") { (alert) -> Bool in
print("UI alert: ", alert.description)
if alert.buttons["Allow"].exists {
alert.buttons["Allow"].tap()
return true
}
if alert.buttons["OK"].exists {
alert.buttons["OK"].tap()
return true
}
return false
}
// In UI tests it is usually best to stop immediately when a failure occurs.
continueAfterFailure = false
// In UI tests its important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
}
override func tearDownWithError() throws {
// Put teardown code here. This method is called after the invocation of each test method in the class.
}
func testVideo() throws {
// UI tests must launch the application that they test.
let app = XCUIApplication()
app.launch()
// Access the Destination text field
let textField = app.textFields["sip:test@sip.pjsip.org"]
// Type localhost into the text field
textField.tap()
textField.tap(withNumberOfTaps: 3, numberOfTouches: 1)
let dest = "sip:localhost:5080"
textField.typeText(dest)
// Use XCTAssert to verify the text is correct
XCTAssertEqual(textField.value as? String, dest)
// Click "Make call" button
print("Making video call")
app.buttons["Make call"].tap()
// Wait for video to appear
let expectation = XCTestExpectation(description: "Wait for video")
let label = app.staticTexts["Video"]
waitForElement(label, timeout: 6)
expectation.fulfill()
// This is necessary to invoke UI interruption monitor above
app.staticTexts["Video"].tap()
sleep(1)
// Capture a screenshot of the entire screen
let fullScreenshot = app.windows.firstMatch.screenshot()
// Save the screenshot to a file
saveScreenshot(image: fullScreenshot)
}
// Helper method to wait for an element to appear/exist
func waitForElement(_ element: XCUIElement, timeout: TimeInterval)
{
let predicate = NSPredicate(format: "exists == 1")
let expectation = XCTNSPredicateExpectation(predicate: predicate,
object: element)
let result = XCTWaiter().wait(for: [expectation], timeout: timeout)
XCTAssertEqual(result, .completed, "Element not found within " +
"\(timeout) seconds")
}
func saveScreenshot(image: XCUIScreenshot) {
let pngData = image.pngRepresentation
let documentsDirectory = FileManager.default.urls(
for: .documentDirectory,
in: .userDomainMask).first!
let fileURL = documentsDirectory.appendingPathComponent("screenshot.png")
do {
try pngData.write(to: fileURL)
print("Screenshot saved to:", fileURL)
} catch {
XCTFail("Failed to save screenshot: \(error)")
}
}
/*
func testLaunchPerformance() throws {
if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *) {
// This measures how long it takes to launch your application.
measure(metrics: [XCTApplicationLaunchMetric()]) {
XCUIApplication().launch()
}
}
}
*/
}

View File

@ -1,31 +0,0 @@
//
// ipjsua_swiftVidTestLaunchTests.swift
// ipjsua-swiftVidTest
//
import XCTest
final class ipjsua_swiftVidTestLaunchTests: XCTestCase {
override class var runsForEachTargetApplicationUIConfiguration: Bool {
true
}
override func setUpWithError() throws {
continueAfterFailure = false
}
/*
func testLaunch() throws {
let app = XCUIApplication()
app.launch()
// Insert steps here to perform after app launch but before taking a screenshot,
// such as logging into a test account or navigating somewhere in the app
let attachment = XCTAttachment(screenshot: app.screenshot())
attachment.name = "Launch Screen"
attachment.lifetime = .keepAlways
add(attachment)
}
*/
}

View File

@ -8,9 +8,6 @@
/* Begin PBXBuildFile section */
3A31F1B21DA4F568007C23A3 /* libwebrtc.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A31F1B11DA4F568007C23A3 /* libwebrtc.a */; };
3A4E3B542B61FEAB0016735C /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A4E3B522B61FEAB0016735C /* Metal.framework */; };
3A4E3B552B61FEAB0016735C /* MetalKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A4E3B532B61FEAB0016735C /* MetalKit.framework */; };
3A4E3B5B2B6205BA0016735C /* Network.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A4E3B5A2B6205B90016735C /* Network.framework */; };
3A6FDEF0223B3BEC001726FD /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A6FDEEF223B3BEC001726FD /* Security.framework */; };
3AA31FF618F3FB4C00112C3D /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AA31FE918F3FB4C00112C3D /* AudioToolbox.framework */; };
3AA31FF718F3FB4C00112C3D /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AA31FEA18F3FB4C00112C3D /* AVFoundation.framework */; };
@ -42,9 +39,6 @@
3AF0582816F050780046B835 /* ipjsuaViewController_iPad.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3AF0582616F050780046B835 /* ipjsuaViewController_iPad.xib */; };
3AF253001EFBD15E00213893 /* libyuv.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AF252FF1EFBD15E00213893 /* libyuv.a */; };
3AF253021EFBD36E00213893 /* VideoToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AF253011EFBD36E00213893 /* VideoToolbox.framework */; };
3AF9B5422B8890880043987D /* PushKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AF9B5412B8890880043987D /* PushKit.framework */; };
3AF9B5462B8890F40043987D /* UserNotifications.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AF9B5442B8890F40043987D /* UserNotifications.framework */; };
3AF9B5482BA407AD0043987D /* CallKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AF9B5472BA407AD0043987D /* CallKit.framework */; };
7485A6AF1F09AAE500122F1A /* Reachability.m in Sources */ = {isa = PBXBuildFile; fileRef = 7485A6AE1F09AAE500122F1A /* Reachability.m */; };
7485A6B11F09B2D500122F1A /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7485A6B01F09B2D500122F1A /* SystemConfiguration.framework */; };
E5E991E61B67A45500017E67 /* libg7221codec.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E5E991D41B67A45500017E67 /* libg7221codec.a */; };
@ -69,9 +63,6 @@
/* Begin PBXFileReference section */
3A31F1B11DA4F568007C23A3 /* libwebrtc.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libwebrtc.a; sourceTree = "<group>"; };
3A4E3B522B61FEAB0016735C /* Metal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Metal.framework; path = System/Library/Frameworks/Metal.framework; sourceTree = SDKROOT; };
3A4E3B532B61FEAB0016735C /* MetalKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MetalKit.framework; path = System/Library/Frameworks/MetalKit.framework; sourceTree = SDKROOT; };
3A4E3B5A2B6205B90016735C /* Network.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Network.framework; path = System/Library/Frameworks/Network.framework; sourceTree = SDKROOT; };
3A6FDEEF223B3BEC001726FD /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
3AA31FE918F3FB4C00112C3D /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; };
3AA31FEA18F3FB4C00112C3D /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; };
@ -108,11 +99,6 @@
3AF0582716F050780046B835 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/ipjsuaViewController_iPad.xib; sourceTree = "<group>"; };
3AF252FF1EFBD15E00213893 /* libyuv.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libyuv.a; sourceTree = "<group>"; };
3AF253011EFBD36E00213893 /* VideoToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = VideoToolbox.framework; path = System/Library/Frameworks/VideoToolbox.framework; sourceTree = SDKROOT; };
3AF9B5402B88896D0043987D /* ipjsua.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = ipjsua.entitlements; sourceTree = "<group>"; };
3AF9B5412B8890880043987D /* PushKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PushKit.framework; path = System/Library/Frameworks/PushKit.framework; sourceTree = SDKROOT; };
3AF9B5432B8890F40043987D /* UserNotificationsUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UserNotificationsUI.framework; path = System/Library/Frameworks/UserNotificationsUI.framework; sourceTree = SDKROOT; };
3AF9B5442B8890F40043987D /* UserNotifications.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UserNotifications.framework; path = System/Library/Frameworks/UserNotifications.framework; sourceTree = SDKROOT; };
3AF9B5472BA407AD0043987D /* CallKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CallKit.framework; path = System/Library/Frameworks/CallKit.framework; sourceTree = SDKROOT; };
7485A6AD1F09AAE500122F1A /* Reachability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Reachability.h; sourceTree = "<group>"; };
7485A6AE1F09AAE500122F1A /* Reachability.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Reachability.m; sourceTree = "<group>"; };
7485A6B01F09B2D500122F1A /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
@ -146,7 +132,6 @@
3AF253021EFBD36E00213893 /* VideoToolbox.framework in Frameworks */,
E5E991EC1B67A45500017E67 /* libpjmedia-codec.a in Frameworks */,
3AA31FF818F3FB4C00112C3D /* CFNetwork.framework in Frameworks */,
3AF9B5422B8890880043987D /* PushKit.framework in Frameworks */,
E5E991E61B67A45500017E67 /* libg7221codec.a in Frameworks */,
E5E991EB1B67A45500017E67 /* libpjmedia-audiodev.a in Frameworks */,
3AA31FFB18F3FB4C00112C3D /* CoreImage.framework in Frameworks */,
@ -161,22 +146,17 @@
E5E991EE1B67A45500017E67 /* libpjmedia.a in Frameworks */,
E5E991EA1B67A45500017E67 /* libpjlib-util.a in Frameworks */,
E5E991ED1B67A45500017E67 /* libpjmedia-videodev.a in Frameworks */,
3AF9B5462B8890F40043987D /* UserNotifications.framework in Frameworks */,
E5E991E81B67A45500017E67 /* libilbccodec.a in Frameworks */,
3A4E3B5B2B6205BA0016735C /* Network.framework in Frameworks */,
3AF9B5482BA407AD0043987D /* CallKit.framework in Frameworks */,
3AA3200118F3FB4C00112C3D /* CoreGraphics.framework in Frameworks */,
3AA31FF918F3FB4C00112C3D /* CoreAudio.framework in Frameworks */,
3AA31FFD18F3FB4C00112C3D /* CoreVideo.framework in Frameworks */,
3AA3200218F3FB4C00112C3D /* UIKit.framework in Frameworks */,
3AA31FFA18F3FB4C00112C3D /* CoreFoundation.framework in Frameworks */,
E5E991F01B67A45500017E67 /* libpjsip-simple.a in Frameworks */,
3A4E3B542B61FEAB0016735C /* Metal.framework in Frameworks */,
E5E991E91B67A45500017E67 /* libpj.a in Frameworks */,
E5E991F71B67A45500017E67 /* libsrtp.a in Frameworks */,
3AA31FFC18F3FB4C00112C3D /* CoreMedia.framework in Frameworks */,
E5E991F21B67A45500017E67 /* libpjsip.a in Frameworks */,
3A4E3B552B61FEAB0016735C /* MetalKit.framework in Frameworks */,
3A31F1B21DA4F568007C23A3 /* libwebrtc.a in Frameworks */,
E5E991F51B67A45500017E67 /* libresample.a in Frameworks */,
E5E991F61B67A45500017E67 /* libspeex.a in Frameworks */,
@ -222,13 +202,6 @@
3AF0580716F050770046B835 /* Frameworks */ = {
isa = PBXGroup;
children = (
3AF9B5472BA407AD0043987D /* CallKit.framework */,
3AF9B5442B8890F40043987D /* UserNotifications.framework */,
3AF9B5432B8890F40043987D /* UserNotificationsUI.framework */,
3AF9B5412B8890880043987D /* PushKit.framework */,
3A4E3B5A2B6205B90016735C /* Network.framework */,
3A4E3B522B61FEAB0016735C /* Metal.framework */,
3A4E3B532B61FEAB0016735C /* MetalKit.framework */,
3A6FDEEF223B3BEC001726FD /* Security.framework */,
7485A6B01F09B2D500122F1A /* SystemConfiguration.framework */,
3AF253011EFBD36E00213893 /* VideoToolbox.framework */,
@ -252,7 +225,6 @@
3AF0580E16F050770046B835 /* ipjsua */ = {
isa = PBXGroup;
children = (
3AF9B5402B88896D0043987D /* ipjsua.entitlements */,
3A92068D16F1D1A100D49F96 /* pjsua */,
3AF0581716F050780046B835 /* ipjsuaAppDelegate.h */,
3AF0581816F050780046B835 /* ipjsuaAppDelegate.m */,
@ -341,7 +313,6 @@
TargetAttributes = {
3AF0580316F050770046B835 = {
DevelopmentTeam = 93NHJQ455P;
ProvisioningStyle = Manual;
};
};
};
@ -529,12 +500,7 @@
3AF0582C16F050780046B835 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_ENTITLEMENTS = ipjsua/ipjsua.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Manual;
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 93NHJQ455P;
CODE_SIGN_IDENTITY = "iPhone Developer";
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "ipjsua/ipjsua-Prefix.pch";
GCC_PREPROCESSOR_DEFINITIONS = (
@ -563,11 +529,8 @@
"$(PROJECT_DIR)",
);
ONLY_ACTIVE_ARCH = YES;
PRODUCT_BUNDLE_IDENTIFIER = "com.teluupush.--PRODUCT-NAME-rfc1034identifier-";
"PRODUCT_BUNDLE_IDENTIFIER[sdk=iphoneos*]" = com.teluupush.ipjsua;
PRODUCT_BUNDLE_IDENTIFIER = "com.teluu.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "ipjsua Push";
VALID_ARCHS = arm64;
WRAPPER_EXTENSION = app;
};
@ -576,12 +539,7 @@
3AF0582D16F050780046B835 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_ENTITLEMENTS = ipjsua/ipjsua.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Manual;
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 93NHJQ455P;
CODE_SIGN_IDENTITY = "iPhone Developer";
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "ipjsua/ipjsua-Prefix.pch";
GCC_PREPROCESSOR_DEFINITIONS = (
@ -609,11 +567,8 @@
"$(PROJECT_DIR)",
);
ONLY_ACTIVE_ARCH = YES;
PRODUCT_BUNDLE_IDENTIFIER = "com.teluupush.--PRODUCT-NAME-rfc1034identifier-";
"PRODUCT_BUNDLE_IDENTIFIER[sdk=iphoneos*]" = com.teluupush.ipjsua;
PRODUCT_BUNDLE_IDENTIFIER = "com.teluu.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "ipjsua Push";
VALID_ARCHS = arm64;
WRAPPER_EXTENSION = app;
};

View File

@ -4,8 +4,6 @@
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>AppIdentifierPrefix</key>
<string>$(AppIdentifierPrefix)</string>
<key>CFBundleDisplayName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundleExecutable</key>

View File

@ -1,16 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>aps-environment</key>
<string>development</string>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.device.audio-input</key>
<true/>
<key>com.apple.security.device.camera</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>
</dict>
</plist>

View File

@ -18,23 +18,14 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#import <CallKit/CallKit.h>
#import <PushKit/PushKit.h>
#import <UIKit/UIKit.h>
#import <UserNotifications/UserNotifications.h>
@class ipjsuaViewController;
@interface ipjsuaAppDelegate : UIResponder
<UIApplicationDelegate, PKPushRegistryDelegate,
UNUserNotificationCenterDelegate, CXProviderDelegate>
@interface ipjsuaAppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) PKPushRegistry *voipRegistry;
@property (strong, nonatomic) NSMutableString *token;
@property (strong, nonatomic) CXProvider *provider;
@property (strong, nonatomic) ipjsuaViewController *viewController;
@end

View File

@ -22,8 +22,6 @@
#import <pjlib.h>
#import <pjsua.h>
#import <pj/log.h>
#import <AVFoundation/AVFoundation.h>
#import <CallKit/CallKit.h>
#include "../../pjsua_app.h"
#include "../../pjsua_app_config.h"
@ -35,172 +33,14 @@
#define THIS_FILE "ipjsuaAppDelegate.m"
/* Specify if we use push notification. */
#define USE_PUSH_NOTIFICATION 1
/* Specify the timeout (in sec) to wait for the incoming INVITE
* to come after we receive push notification.
*/
#define MAX_INV_TIMEOUT 10
/* Account details. */
#define SIP_DOMAIN "sip.pjsip.org"
#define SIP_USER "test"
#define SIP_PASSWD "test"
#define KEEP_ALIVE_INTERVAL 600
ipjsuaAppDelegate *app;
static pjsua_app_cfg_t app_cfg;
static bool isShuttingDown;
static char **restartArgv;
static int restartArgc;
Reachability *internetReach;
/* Mapping between CallKit UUID and pjsua_call_id. */
NSMutableDictionary<NSUUID *, NSNumber *> *call_map;
enum {
REREGISTER = 1,
ANSWER_CALL,
END_CALL,
ACTIVATE_AUDIO,
DEACTIVATE_AUDIO,
HANDLE_IP_CHANGE,
HANDLE_ORI_CHANGE
};
#define REGISTER_THREAD \
static pj_thread_desc a_thread_desc; \
static pj_thread_t *a_thread; \
if (!pj_thread_is_registered()) { \
pj_thread_register("ipjsua", a_thread_desc, &a_thread); \
}
#define SCHEDULE_TIMER(action) \
{ \
REGISTER_THREAD \
pjsua_schedule_timer2(pjsip_funcs, (void *)action, 0); \
}
static void pjsip_funcs(void *user_data)
{
/* IMPORTANT:
* We need to call PJSIP API from a separate thread since
* PJSIP API can potentially block the main/GUI thread.
* And make sure we don't use Apple's Dispatch / gcd since
* it's incompatible with POSIX threads.
* In this example, we take advantage of PJSUA's timer thread
* to invoke PJSIP APIs. For a more complex application,
* it is recommended to create your own separate thread
* instead for this purpose.
*/
long code = (long)user_data & 0xF;
if (code == REREGISTER) {
for (unsigned i = 0; i < pjsua_acc_get_count(); ++i) {
if (pjsua_acc_is_valid(i)) {
pjsua_acc_set_registration(i, PJ_TRUE);
}
}
} else if (code == ANSWER_CALL) {
pj_status_t status;
pjsua_call_id call_id = (pjsua_call_id)((long)user_data & 0xFF0) >> 4;
status = pjsua_call_answer(call_id, PJSIP_SC_OK, NULL, NULL);
if (status != PJ_SUCCESS) {
NSUUID *uuid =(__bridge NSUUID *)pjsua_call_get_user_data(call_id);
if (uuid) {
[app.provider reportCallWithUUID:uuid
endedAtDate:[NSDate date]
reason:CXCallEndedReasonFailed];
}
}
} else if (code == END_CALL) {
pj_status_t status;
pjsua_call_id call_id = (pjsua_call_id)((long)user_data & 0xFF0) >> 4;
status = pjsua_call_hangup(call_id, PJSIP_SC_OK, NULL, NULL);
if (status != PJ_SUCCESS) {
NSUUID *uuid =(__bridge NSUUID *)pjsua_call_get_user_data(call_id);
if (uuid) {
[app.provider reportCallWithUUID:uuid
endedAtDate:[NSDate date]
reason:CXCallEndedReasonFailed];
}
}
} else if (code == ACTIVATE_AUDIO) {
pjsua_call_info call_info;
pjsua_call_id ids[PJSUA_MAX_CALLS];
unsigned count = PJSUA_MAX_CALLS;
/* If we use CallKit, sound device may not work until audio session
* becomes active, so we need to force reopen sound device here.
*/
pjsua_set_no_snd_dev();
pjsua_set_snd_dev(PJSUA_SND_DEFAULT_CAPTURE_DEV,
PJSUA_SND_DEFAULT_PLAYBACK_DEV);
pjsua_enum_calls(ids, &count);
for (unsigned i = 0; i < count; i++) {
pjsua_call_get_info(i, &call_info);
for (unsigned mi = 0; mi < call_info.media_cnt; ++mi) {
if (call_info.media[mi].type == PJMEDIA_TYPE_AUDIO &&
(call_info.media[mi].status == PJSUA_CALL_MEDIA_ACTIVE ||
call_info.media[mi].status == PJSUA_CALL_MEDIA_REMOTE_HOLD))
{
pjsua_conf_port_id call_conf_slot;
call_conf_slot = call_info.media[mi].stream.aud.conf_slot;
pjsua_conf_connect(0, call_conf_slot);
pjsua_conf_connect(call_conf_slot, 0);
}
}
}
} else if (code == DEACTIVATE_AUDIO) {
NSLog(@"Deactivating audio session, is sound active: %d",
pjsua_snd_is_active());
if (!pjsua_snd_is_active()) {
[[AVAudioSession sharedInstance] setActive:NO
withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation
error:nil];
}
} else if (code == HANDLE_IP_CHANGE) {
pjsua_ip_change_param param;
pjsua_ip_change_param_default(&param);
pjsua_handle_ip_change(&param);
} else if (code == HANDLE_ORI_CHANGE) {
#if PJSUA_HAS_VIDEO
const pjmedia_orient pj_ori[4] =
{
PJMEDIA_ORIENT_ROTATE_90DEG, /* UIDeviceOrientationPortrait */
PJMEDIA_ORIENT_ROTATE_270DEG, /* UIDeviceOrientationPortraitUpsideDown */
PJMEDIA_ORIENT_ROTATE_180DEG, /* UIDeviceOrientationLandscapeLeft,
home button on the right side */
PJMEDIA_ORIENT_NATURAL /* UIDeviceOrientationLandscapeRight,
home button on the left side */
};
static UIDeviceOrientation prev_ori = 0;
UIDeviceOrientation dev_ori = [[UIDevice currentDevice] orientation];
int i;
if (dev_ori == prev_ori) return;
NSLog(@"Device orientation changed: %d", (int)(prev_ori = dev_ori));
if (dev_ori >= UIDeviceOrientationPortrait &&
dev_ori <= UIDeviceOrientationLandscapeRight)
{
/* Here we set the orientation for all video devices.
* This may return failure for renderer devices or for
* capture devices which do not support orientation setting,
* we can simply ignore them.
*/
for (i = pjsua_vid_dev_count()-1; i >= 0; i--) {
pjsua_vid_dev_set_setting(i, PJMEDIA_VID_DEV_CAP_ORIENTATION,
&pj_ori[dev_ori-1], PJ_TRUE);
}
}
#endif
}
}
Reachability *internetReach;
- (void) updateWithReachability: (Reachability *)curReach
{
@ -208,18 +48,18 @@ static void pjsip_funcs(void *user_data)
BOOL connectionRequired = [curReach connectionRequired];
switch (netStatus) {
case NotReachable:
NSLog(@"Access Not Available..");
PJ_LOG(3,("", "Access Not Available.."));
connectionRequired= NO;
break;
case ReachableViaWiFi:
NSLog(@"Reachable WiFi..");
PJ_LOG(3,("", "Reachable WiFi.."));
break;
case ReachableViaWWAN:
NSLog(@"Reachable WWAN..");
PJ_LOG(3,("", "Reachable WWAN.."));
break;
}
if (connectionRequired) {
NSLog(@"Connection Required");
PJ_LOG(3,("", "Connection Required"));
}
}
@ -228,34 +68,18 @@ static void pjsip_funcs(void *user_data)
{
Reachability* curReach = [note object];
NSParameterAssert([curReach isKindOfClass: [Reachability class]]);
NSLog(@"reachability changed..");
PJ_LOG(3,("", "reachability changed.."));
[self updateWithReachability: curReach];
if ([curReach currentReachabilityStatus] != NotReachable &&
![curReach connectionRequired])
{
SCHEDULE_TIMER(HANDLE_IP_CHANGE);
pjsua_ip_change_param param;
pjsua_ip_change_param_default(&param);
pjsua_handle_ip_change(&param);
}
}
- (void)pushRegistry:(PKPushRegistry *)registry didUpdatePushCredentials:(PKPushCredentials *)credentials forType:(NSString *)type
{
if ([credentials.token length] == 0) {
NSLog(@"voip token NULL");
return;
}
/* Get device token */
const char *data = [credentials.token bytes];
self.token = [NSMutableString string];
for (NSUInteger i = 0; i < [credentials.token length]; i++) {
[self.token appendFormat:@"%02.2hhx", data[i]];
}
NSLog(@"VOIP Push Notification Token: %@", self.token);
/* Now start pjsua */
[NSThread detachNewThreadSelector:@selector(pjsuaStart) toTarget:self withObject:nil];
}
void displayLog(const char *msg, int len)
{
@ -347,57 +171,6 @@ static void pjsuaOnAppConfigCb(pjsua_app_config *cfg)
object:[UIDevice currentDevice]];
});
static char contact_uri_buf[1024];
pjsua_acc_config cfg;
pjsua_acc_config_default(&cfg);
cfg.id = pj_str("sip:" SIP_USER "@" SIP_DOMAIN);
cfg.reg_uri = pj_str("sip:" SIP_DOMAIN ";transport=tcp");
cfg.cred_count = 1;
cfg.cred_info[0].realm = pj_str(SIP_DOMAIN);
cfg.cred_info[0].scheme = pj_str("digest");
cfg.cred_info[0].username = pj_str(SIP_USER);
cfg.cred_info[0].data = pj_str(SIP_PASSWD);
/* Uncomment this to enable video. Note that video can only
* work in the foreground.
*/
// app_config_init_video(&cfg);
/* If we have Push Notification token, put it in the registration
* Contact URI params.
*/
if ([self.token length]) {
/* According to RFC 8599:
* - pn-provider is the Push Notification Service provider. Here
* we use APNS (Apple Push Notification Service).
* - pn-param is composed of Team ID and Topic separated by
* a period (.).
* The Topic consists of the Bundle ID, the app's unique ID,
* and the app's service value ("voip" for VoIP apps), separated
* by a period (.).
* - pn-prid is the PN token.
*/
NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];
NSString *bundleID = infoDictionary[@"CFBundleIdentifier"];
NSString *teamID = infoDictionary[@"AppIdentifierPrefix"];
NSLog(@"Team ID from settings: %@", teamID);
pj_ansi_snprintf(contact_uri_buf, sizeof(contact_uri_buf),
";pn-provider=apns"
";pn-param=%s%s.voip"
";pn-prid=%s",
(teamID? [teamID UTF8String]: "93NHJQ455P."),
[bundleID UTF8String],
[self.token UTF8String]);
cfg.reg_contact_uri_params = pj_str(contact_uri_buf);
}
status = pjsua_acc_add(&cfg, PJ_TRUE, NULL);
if (status != PJ_SUCCESS) {
char errmsg[PJ_ERR_MSG_SIZE];
pj_strerror(status, errmsg, sizeof(errmsg));
displayMsg(errmsg);
}
status = pjsua_app_run(PJ_TRUE);
if (status != PJ_SUCCESS) {
char errmsg[PJ_ERR_MSG_SIZE];
@ -414,116 +187,6 @@ static void pjsuaOnAppConfigCb(pjsua_app_config *cfg)
restartArgc = 0;
}
- (void) provider:(CXProvider *) provider
didActivateAudioSession:(AVAudioSession *) audioSession
{
NSLog(@"Did activate Audio Session");
pjsua_schedule_timer2(pjsip_funcs, (void *)ACTIVATE_AUDIO, 0);
}
- (void) provider:(CXProvider *) provider
didDectivateAudioSession:(AVAudioSession *) audioSession
{
NSLog(@"Did deactivate Audio Session");
}
- (void)provider:(CXProvider *)provider
performAnswerCallAction:(CXAnswerCallAction *)action
{
NSLog(@"Perform answer call %@", action.callUUID.UUIDString);
/* User has answered the call, but we may need to wait for
* the incoming INVITE to come.
*/
for (int i = MAX_INV_TIMEOUT * 1000 / 100; i >= 0; i--) {
if (call_map[action.callUUID].intValue != PJSUA_INVALID_ID) break;
[NSThread sleepForTimeInterval:0.1];
}
[action fulfill];
pjsua_call_id call_id = call_map[action.callUUID].intValue;
if (call_id == PJSUA_INVALID_ID) {
[app.provider reportCallWithUUID:action.callUUID
endedAtDate:[NSDate date]
reason:CXCallEndedReasonFailed];
return;
}
long code = (long)ANSWER_CALL | (call_id << 4);
pjsua_schedule_timer2(pjsip_funcs, (void *)code, 0);
}
- (void)provider:(CXProvider *)provider
performEndCallAction:(CXEndCallAction *)action
{
NSLog(@"Perform end call %@", action.callUUID.UUIDString);
/* User has answered the call, but we may need to wait for
* the incoming INVITE to come.
*/
for (int i = MAX_INV_TIMEOUT * 1000 / 100; i >= 0; i--) {
if (call_map[action.callUUID].intValue != PJSUA_INVALID_ID) break;
[NSThread sleepForTimeInterval:0.1];
}
[action fulfill];
pjsua_call_id call_id = call_map[action.callUUID].intValue;
if (call_id == PJSUA_INVALID_ID) {
[app.provider reportCallWithUUID:action.callUUID
endedAtDate:[NSDate date]
reason:CXCallEndedReasonFailed];
return;
}
long code = (long)END_CALL | (call_id << 4);
pjsua_schedule_timer2(pjsip_funcs, (void *)code, 0);
}
- (void)pushRegistry:(PKPushRegistry *)registry
didReceiveIncomingPushWithPayload:(PKPushPayload *)payload
forType:(PKPushType)type withCompletionHandler:(void (^)(void))completion
{
/* Handle incoming VoIP push notification. */
NSUUID *uuid = [NSUUID UUID];
call_map[uuid] = @(PJSUA_INVALID_ID);
NSLog(@"Receiving push notification %@", uuid.UUIDString);
/* Re-register, so the server will send us the suspended INVITE. */
SCHEDULE_TIMER(REREGISTER);
/* Activate audio session. */
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
NSError *error = nil;
if (![audioSession setCategory:AVAudioSessionCategoryPlayAndRecord
mode:AVAudioSessionModeVoiceChat
options:0 error:&error])
{
NSLog(@"Error setting up audio session: %@", error.localizedDescription);
}
if (![audioSession setActive:YES error:&error]) {
NSLog(@"Error activating audio session: %@", error.localizedDescription);
}
/* Report the incoming call to the system using CallKit. */
CXCallUpdate *callUpdate = [[CXCallUpdate alloc] init];
[self.provider reportNewIncomingCallWithUUID:uuid
update:callUpdate
completion:^(NSError * _Nullable error)
{
if (error) {
NSLog(@"Error reporting incoming call: %@",
error.localizedDescription);
[call_map removeObjectForKey:uuid];
}
}];
/* Call the completion handler when you have finished processing the incoming call. */
completion();
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
@ -535,62 +198,7 @@ didDectivateAudioSession:(AVAudioSession *) audioSession
}
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
#if USE_PUSH_NOTIFICATION
call_map = [NSMutableDictionary dictionary];
/* Set up a push notification registry for Voice over IP (VoIP). */
self.voipRegistry = [[PKPushRegistry alloc] initWithQueue:dispatch_get_main_queue()];
self.voipRegistry.delegate = self;
self.voipRegistry.desiredPushTypes = [NSSet setWithObject:PKPushTypeVoIP];
/* Request permission for push notifications. */
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
center.delegate = self;
[center requestAuthorizationWithOptions:(UNAuthorizationOptionAlert |
UNAuthorizationOptionBadge |
UNAuthorizationOptionSound)
completionHandler:^(BOOL granted, NSError * _Nullable error)
{
NSLog(@"Notification request %sgranted", (granted ? "" : "not"));
if (granted) {
dispatch_async(dispatch_get_main_queue(), ^{
[application registerForRemoteNotifications];
});
}
}];
/* Note that opening audio device when in the background will not trigger
* permission request, so we won't be able to use audio device.
* Thus, we need to request permission now.
*/
[[AVAudioSession sharedInstance] requestRecordPermission:^(BOOL granted)
{
NSLog(@"Microphone access %sgranted", (granted ? "" : "not"));
}];
/* We need to request local network access permission as well to
* immediately send media traffic when in the background.
* Due to its complexity, the code is not included here in the sample app.
* Please refer to the Apple "Local Network Privacy" FAQ for more details.
*/
/* Create CallKit provider. */
CXProviderConfiguration *configuration = [[CXProviderConfiguration alloc]
initWithLocalizedName:@"ipjsua"];
configuration.maximumCallGroups = 1;
configuration.maximumCallsPerCallGroup = 1;
self.provider = [[CXProvider alloc] initWithConfiguration:configuration];
[self.provider setDelegate:self queue:nil];
#else
/* Start pjsua app thread immediately, otherwise we do it after push
* notification setup completes.
*/
[NSThread detachNewThreadSelector:@selector(pjsuaStart) toTarget:self
withObject:nil];
#endif
/* Observe the kNetworkReachabilityChangedNotification. When that
* notification is posted, the method "reachabilityChanged" will be called.
*/
@ -603,6 +211,9 @@ didDectivateAudioSession:(AVAudioSession *) audioSession
[self updateWithReachability: internetReach];
app = self;
/* Start pjsua app thread */
[NSThread detachNewThreadSelector:@selector(pjsuaStart) toTarget:self withObject:nil];
return YES;
}
@ -615,14 +226,78 @@ didDectivateAudioSession:(AVAudioSession *) audioSession
- (void)orientationChanged:(NSNotification *)note
{
SCHEDULE_TIMER(HANDLE_ORI_CHANGE);
#if PJSUA_HAS_VIDEO
const pjmedia_orient pj_ori[4] =
{
PJMEDIA_ORIENT_ROTATE_90DEG, /* UIDeviceOrientationPortrait */
PJMEDIA_ORIENT_ROTATE_270DEG, /* UIDeviceOrientationPortraitUpsideDown */
PJMEDIA_ORIENT_ROTATE_180DEG, /* UIDeviceOrientationLandscapeLeft,
home button on the right side */
PJMEDIA_ORIENT_NATURAL /* UIDeviceOrientationLandscapeRight,
home button on the left side */
};
static pj_thread_desc a_thread_desc;
static pj_thread_t *a_thread;
static UIDeviceOrientation prev_ori = 0;
UIDeviceOrientation dev_ori = [[UIDevice currentDevice] orientation];
int i;
if (dev_ori == prev_ori) return;
NSLog(@"Device orientation changed: %d", (int)(prev_ori = dev_ori));
if (dev_ori >= UIDeviceOrientationPortrait &&
dev_ori <= UIDeviceOrientationLandscapeRight)
{
if (!pj_thread_is_registered()) {
pj_thread_register("ipjsua", a_thread_desc, &a_thread);
}
/* Here we set the orientation for all video devices.
* This may return failure for renderer devices or for
* capture devices which do not support orientation setting,
* we can simply ignore them.
*/
for (i = pjsua_vid_dev_count()-1; i >= 0; i--) {
pjsua_vid_dev_set_setting(i, PJMEDIA_VID_DEV_CAP_ORIENTATION,
&pj_ori[dev_ori-1], PJ_TRUE);
}
}
#endif
}
- (void)keepAlive {
static pj_thread_desc a_thread_desc;
static pj_thread_t *a_thread;
int i;
if (!pj_thread_is_registered()) {
pj_thread_register("ipjsua", a_thread_desc, &a_thread);
}
/* Since iOS requires that the minimum keep alive interval is 600s,
* application needs to make sure that the account's registration
* timeout is long enough.
*/
for (i = 0; i < (int)pjsua_acc_get_count(); ++i) {
if (pjsua_acc_is_valid(i)) {
pjsua_acc_set_registration(i, PJ_TRUE);
}
}
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
SCHEDULE_TIMER(REREGISTER);
/* Allow the re-registration to complete. */
[NSThread sleepForTimeInterval:0.3];
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
[self performSelectorOnMainThread:@selector(keepAlive) withObject:nil waitUntilDone:YES];
#if 0
/* setKeepAliveTimeout is deprecated. Use PushKit instead. */
[application setKeepAliveTimeout:KEEP_ALIVE_INTERVAL handler: ^{
[self performSelectorOnMainThread:@selector(keepAlive) withObject:nil waitUntilDone:YES];
}];
#endif
}
- (void)applicationWillEnterForeground:(UIApplication *)application
@ -641,44 +316,27 @@ didDectivateAudioSession:(AVAudioSession *) audioSession
}
pj_bool_t reportCallState(pjsua_call_id call_id)
{
pjsua_call_info info;
pjsua_call_get_info(call_id, &info);
if (info.state == PJSIP_INV_STATE_DISCONNECTED) {
NSUUID *uuid = (__bridge NSUUID *)pjsua_call_get_user_data(call_id);
if (uuid && call_map[uuid].intValue == call_id) {
[app.provider reportCallWithUUID:uuid
endedAtDate:[NSDate date]
reason:CXCallEndedReasonRemoteEnded];
[call_map removeObjectForKey:uuid];
}
/* Check if we need to deactivate audio session. Note that sound device
* will only be closed after pjsua_media_config.snd_auto_close_time.
*/
pjsua_schedule_timer2(pjsip_funcs, (void *)DEACTIVATE_AUDIO, 1500);
}
return PJ_FALSE;
}
pj_bool_t showNotification(pjsua_call_id call_id)
{
#if USE_PUSH_NOTIFICATION
NSLog(@"Receiving incoming call %d", call_id);
for (NSUUID *uuid in call_map) {
if (call_map[uuid].intValue == PJSUA_INVALID_ID) {
NSLog(@"Associating incoming call %d with UUID %@",
call_id, uuid.UUIDString);
call_map[uuid] = @(call_id);
pjsua_call_set_user_data(call_id, (__bridge void *)uuid);
break;
}
/* This is deprecated. Use VoIP Push Notifications with PushKit
* framework instead.
*/
#if 0
// Create a new notification
UILocalNotification* alert = [[UILocalNotification alloc] init];
if (alert)
{
alert.repeatInterval = 0;
alert.alertBody = @"Incoming call received...";
/* This action just brings the app to the FG, it doesn't
* automatically answer the call (unless you specify the
* --auto-answer option).
*/
alert.alertAction = @"Activate app";
dispatch_async(dispatch_get_main_queue(),
^{[[UIApplication sharedApplication]
presentLocalNotificationNow:alert];});
}
#endif

View File

@ -47,7 +47,6 @@ static void stereo_demo();
#ifdef USE_GUI
pj_bool_t showNotification(pjsua_call_id call_id);
pj_bool_t reportCallState(pjsua_call_id call_id);
#endif
static void ringback_start(pjsua_call_id call_id);
@ -172,10 +171,6 @@ static void on_call_state(pjsua_call_id call_id, pjsip_event *e)
PJ_UNUSED_ARG(e);
#ifdef USE_GUI
reportCallState(call_id);
#endif
pjsua_call_get_info(call_id, &call_info);
if (call_info.state == PJSIP_INV_STATE_DISCONNECTED) {
@ -671,40 +666,6 @@ static void on_buddy_state(pjsua_buddy_id buddy_id)
}
/*
* Handler on buddy dialog event state changed.
*/
static void on_buddy_dlg_event_state(pjsua_buddy_id buddy_id)
{
pjsua_buddy_dlg_event_info info;
pjsua_buddy_get_dlg_event_info(buddy_id, &info);
PJ_LOG(3,(THIS_FILE, "%.*s dialog-info-state: %.*s, "
"dialog-info-entity: %.*s, dialog-id: %.*s, "
"dialog-call-id: %.*s, dialog-direction: %.*s, "
"dialog-state: %.*s, dialog-duration: %.*s, "
"local-identity: %.*s, local-target-uri: %.*s, "
"remote-identity: %.*s, remote-target-uri: %.*s, "
"dialog-local-tag: %.*s, dialog-remote-tag: %.*s, "
"subscription state: %s (last termination reason code=%d %.*s)",
(int)info.uri.slen, info.uri.ptr,
(int)info.dialog_info_state.slen, info.dialog_info_state.ptr,
(int)info.dialog_info_entity.slen, info.dialog_info_entity.ptr,
(int)info.dialog_id.slen, info.dialog_id.ptr,
(int)info.dialog_call_id.slen, info.dialog_call_id.ptr,
(int)info.dialog_direction.slen, info.dialog_direction.ptr,
(int)info.dialog_state.slen, info.dialog_state.ptr,
(int)info.dialog_duration.slen, info.dialog_duration.ptr,
(int)info.local_identity.slen, info.local_identity.ptr,
(int)info.local_target_uri.slen, info.local_target_uri.ptr,
(int)info.remote_identity.slen, info.remote_identity.ptr,
(int)info.remote_target_uri.slen, info.remote_target_uri.ptr,
(int)info.dialog_local_tag.slen, info.dialog_local_tag.ptr,
(int)info.dialog_remote_tag.slen, info.dialog_remote_tag.ptr,
info.sub_state_name, info.sub_term_code,
(int)info.sub_term_reason.slen, info.sub_term_reason.ptr));
}
/*
* Subscription state has changed.
*/
@ -735,36 +696,11 @@ static void on_buddy_evsub_state(pjsua_buddy_id buddy_id,
}
static void on_buddy_evsub_dlg_event_state(pjsua_buddy_id buddy_id,
pjsip_evsub *sub,
pjsip_event *event)
{
char event_info[80];
PJ_UNUSED_ARG(sub);
event_info[0] = '\0';
if (event->type == PJSIP_EVENT_TSX_STATE &&
event->body.tsx_state.type == PJSIP_EVENT_RX_MSG)
{
pjsip_rx_data *rdata = event->body.tsx_state.src.rdata;
snprintf(event_info, sizeof(event_info),
" (RX %s)",
pjsip_rx_data_get_info(rdata));
}
PJ_LOG(4,(THIS_FILE,
"Buddy %d: dialog event subscription state: %s (event: %s%s)",
buddy_id, pjsip_evsub_get_state_name(sub),
pjsip_event_str(event->type), event_info));
}
/**
* Incoming IM message (i.e. MESSAGE request)!
*/
static void on_pager(pjsua_call_id call_id, const pj_str_t *from,
static void on_pager(pjsua_call_id call_id, const pj_str_t *from,
const pj_str_t *to, const pj_str_t *contact,
const pj_str_t *mime_type, const pj_str_t *text)
{
@ -1457,10 +1393,7 @@ static pj_status_t app_init(void)
app_config.cfg.cb.on_reg_state = &on_reg_state;
app_config.cfg.cb.on_incoming_subscribe = &on_incoming_subscribe;
app_config.cfg.cb.on_buddy_state = &on_buddy_state;
app_config.cfg.cb.on_buddy_dlg_event_state = &on_buddy_dlg_event_state;
app_config.cfg.cb.on_buddy_evsub_state = &on_buddy_evsub_state;
app_config.cfg.cb.on_buddy_evsub_dlg_event_state =
&on_buddy_evsub_dlg_event_state;
app_config.cfg.cb.on_pager = &on_pager;
app_config.cfg.cb.on_typing = &on_typing;
app_config.cfg.cb.on_call_transfer_status = &on_call_transfer_status;
@ -2003,9 +1936,6 @@ static pj_status_t app_init(void)
pjsua_call_setting_default(&call_opt);
call_opt.aud_cnt = app_config.aud_cnt;
call_opt.vid_cnt = app_config.vid.vid_cnt;
if (app_config.enable_loam) {
call_opt.flag |= PJSUA_CALL_NO_SDP_OFFER;
}
#if defined(PJSIP_HAS_TLS_TRANSPORT) && PJSIP_HAS_TLS_TRANSPORT!=0
/* Wipe out TLS key settings in transport configs */

View File

@ -38,7 +38,6 @@
#define CMD_QUIT 110
#define CMD_RESTART 120
#define CMD_HANDLE_IP_CHANGE 130
#define CMD_TOGGLE_SDP_OFFER 140
/* call level 2 command */
#define CMD_CALL_NEW ((CMD_CALL*10)+1)
@ -2087,19 +2086,6 @@ static pj_status_t cmd_show_current_call(pj_cli_cmd_val *cval)
return PJ_SUCCESS;
}
static pj_status_t cmd_toggle_call_sdp_offer(pj_cli_cmd_val* cval)
{
char out_str[64];
app_config.enable_loam = !app_config.enable_loam;
pj_ansi_snprintf(out_str, sizeof(out_str),
"Subsequent calls and UPDATEs will contain SDP offer: %s\n",
app_config.enable_loam ? "No" : "Yes");
pj_cli_sess_write_msg(cval->sess, out_str, pj_ansi_strlen(out_str));
return PJ_SUCCESS;
}
/* Call handler */
pj_status_t cmd_call_handler(pj_cli_cmd_val *cval)
{
@ -2108,14 +2094,6 @@ pj_status_t cmd_call_handler(pj_cli_cmd_val *cval)
CHECK_PJSUA_RUNNING();
/* Update call setting */
pjsua_call_setting_default(&call_opt);
call_opt.aud_cnt = app_config.aud_cnt;
call_opt.vid_cnt = app_config.vid.vid_cnt;
if (app_config.enable_loam) {
call_opt.flag |= PJSUA_CALL_NO_SDP_OFFER;
}
switch(cmd_id) {
case CMD_CALL_NEW:
status = cmd_make_single_call(cval);
@ -3243,17 +3221,12 @@ static pj_status_t add_other_command(pj_cli_t *c)
char* ip_change_command =
"<CMD name='ip_change' id='130' desc='Handle IP change'/>";
char* toggle_sdp_offer_command =
"<CMD name='toggle_sdp_offer' sc='o' id='140' "
"desc='Toggle SDP offer use on subsequent calls and UPDATEs' />";
pj_status_t status;
pj_str_t sleep_xml = pj_str(sleep_command);
pj_str_t network_xml = pj_str(network_command);
pj_str_t shutdown_xml = pj_str(shutdown_command);
pj_str_t restart_xml = pj_str(restart_command);
pj_str_t ip_change_xml = pj_str(ip_change_command);
pj_str_t toggle_sdp_offer_xml = pj_str(toggle_sdp_offer_command);
status = pj_cli_add_cmd_from_xml(c, NULL,
&sleep_xml, cmd_sleep_handler,
@ -3284,13 +3257,6 @@ static pj_status_t add_other_command(pj_cli_t *c)
status = pj_cli_add_cmd_from_xml(c, NULL,
&ip_change_xml, cmd_ip_change_handler,
NULL, NULL);
if (status != PJ_SUCCESS)
return status;
status = pj_cli_add_cmd_from_xml(c, NULL,
&toggle_sdp_offer_xml,
cmd_toggle_call_sdp_offer,
NULL, NULL);
return status;
}

View File

@ -77,8 +77,6 @@ typedef struct pjsua_app_config
pj_bool_t no_refersub;
pj_bool_t ipv6;
pj_bool_t enable_qos;
pj_bool_t no_mci;
pj_bool_t enable_loam;
pj_bool_t no_tcp;
pj_bool_t no_udp;
pj_bool_t use_tls;

View File

@ -94,7 +94,6 @@ static void usage(void)
puts (" --ipv6 Create SIP IPv6 transports.");
#endif
puts (" --set-qos Enable QoS tagging for SIP and media.");
puts (" --no-mci Disable message composition indication (RFC 3994)");
puts (" --local-port=port Set TCP/UDP port. This implicitly enables both ");
puts (" TCP and UDP transports on the specified port, unless");
puts (" if TCP or UDP is disabled.");
@ -393,7 +392,7 @@ static pj_status_t parse_args(int argc, char *argv[],
OPT_TLS_NEG_TIMEOUT, OPT_TLS_CIPHER,
OPT_CAPTURE_DEV, OPT_PLAYBACK_DEV,
OPT_CAPTURE_LAT, OPT_PLAYBACK_LAT, OPT_NO_TONES, OPT_JB_MAX_SIZE,
OPT_STDOUT_REFRESH, OPT_STDOUT_REFRESH_TEXT, OPT_IPV6, OPT_QOS, OPT_MCI,
OPT_STDOUT_REFRESH, OPT_STDOUT_REFRESH_TEXT, OPT_IPV6, OPT_QOS,
#ifdef _IONBF
OPT_STDOUT_NO_BUF,
#endif
@ -534,7 +533,6 @@ static pj_status_t parse_args(int argc, char *argv[],
{ "ipv6", 0, 0, OPT_IPV6},
#endif
{ "set-qos", 0, 0, OPT_QOS},
{ "no-mci", 0, 0, OPT_MCI},
{ "use-timer", 1, 0, OPT_TIMER},
{ "timer-se", 1, 0, OPT_TIMER_SE},
{ "timer-min-se", 1, 0, OPT_TIMER_MIN_SE},
@ -1468,9 +1466,6 @@ static pj_status_t parse_args(int argc, char *argv[],
cfg->udp_cfg.qos_params.flags = PJ_QOS_PARAM_HAS_DSCP;
cfg->udp_cfg.qos_params.dscp_val = 0x18;
break;
case OPT_MCI:
cfg->no_mci = PJ_TRUE;
break;
case OPT_VIDEO:
cfg->vid.vid_cnt = 1;
cfg->vid.in_auto_show = PJ_TRUE;
@ -1984,11 +1979,6 @@ int write_settings(pjsua_app_config *config, char *buf, pj_size_t max)
pj_strcat2(&cfg, "--set-qos\n");
}
/* Message Composition Indication */
if (config->no_mci) {
pj_strcat2(&cfg, "--no-mci\n");
}
/* UDP Transport. */
pj_ansi_snprintf(line, sizeof(line), "--local-port %d\n",
config->udp_cfg.port);

View File

@ -236,8 +236,6 @@ static void keystroke_help()
puts("| a Answer call | i Send IM | !a Modify accnt. |");
puts("| h Hangup call (ha=all) | s Subscribe presence | rr (Re-)register |");
puts("| H Hold call | u Unsubscribe presence | ru Unregister |");
puts("| o Toggle call SDP offer | D Subscribe dlg event | |");
puts("| | Du Unsub dlg event | |");
puts("| v re-inVite (release hold) | t Toggle online status | > Cycle next ac.|");
puts("| U send UPDATE | T Set online status | < Cycle prev ac.|");
puts("| ],[ Select next/prev call +--------------------------+-------------------+");
@ -734,9 +732,6 @@ static void ui_make_new_call()
pjsua_msg_data_init(&msg_data_);
TEST_MULTIPART(&msg_data_);
if (app_config.enable_loam) {
call_opt.flag |= PJSUA_CALL_NO_SDP_OFFER;
}
pjsua_call_make_call(current_acc, &tmp, &call_opt, NULL,
&msg_data_, &current_call);
@ -776,10 +771,6 @@ static void ui_make_multi_call()
tmp = pj_str(result.uri_result);
}
if (app_config.enable_loam) {
call_opt.flag |= PJSUA_CALL_NO_SDP_OFFER;
}
for (i=0; i<my_atoi(menuin); ++i) {
pj_status_t status;
@ -831,30 +822,26 @@ static void ui_send_instant_message()
/* Send typing indication. */
if (!app_config.no_mci) {
if (i != -1)
pjsua_call_send_typing_ind(i, PJ_TRUE, NULL);
else {
pj_str_t tmp_uri = pj_str(uri);
pjsua_im_typing(current_acc, &tmp_uri, PJ_TRUE, NULL);
}
if (i != -1)
pjsua_call_send_typing_ind(i, PJ_TRUE, NULL);
else {
pj_str_t tmp_uri = pj_str(uri);
pjsua_im_typing(current_acc, &tmp_uri, PJ_TRUE, NULL);
}
/* Input the IM . */
if (!simple_input("Message", text, sizeof(text))) {
if (!app_config.no_mci) {
/*
* Cancelled.
* Send typing notification too, saying we're not typing.
*/
if (i != -1)
pjsua_call_send_typing_ind(i, PJ_FALSE, NULL);
else {
pj_str_t tmp_uri = pj_str(uri);
pjsua_im_typing(current_acc, &tmp_uri, PJ_FALSE, NULL);
}
return;
/*
* Cancelled.
* Send typing notification too, saying we're not typing.
*/
if (i != -1)
pjsua_call_send_typing_ind(i, PJ_FALSE, NULL);
else {
pj_str_t tmp_uri = pj_str(uri);
pjsua_im_typing(current_acc, &tmp_uri, PJ_FALSE, NULL);
}
return;
}
tmp = pj_str(text);
@ -1004,10 +991,7 @@ static void ui_add_buddy()
pj_bzero(&buddy_cfg, sizeof(pjsua_buddy_config));
buddy_cfg.uri = pj_str(buf);
/* Only one subscription can be active, so we need to disable this
* to allow user to choose between presence or dialog event.
*/
// buddy_cfg.subscribe = PJ_TRUE;
buddy_cfg.subscribe = PJ_TRUE;
status = pjsua_buddy_add(&buddy_cfg, &buddy_id);
if (status == PJ_SUCCESS) {
@ -1088,11 +1072,6 @@ static void ui_delete_account()
}
}
static void ui_unset_loam_mode()
{
app_config.enable_loam = PJ_FALSE;
}
static void ui_call_hold()
{
if (current_call != -1) {
@ -1111,9 +1090,6 @@ static void ui_call_reinvite()
static void ui_send_update()
{
if (current_call != -1) {
if (app_config.enable_loam) {
call_opt.flag |= PJSUA_CALL_NO_SDP_OFFER;
}
pjsua_call_update2(current_call, &call_opt, NULL);
} else {
PJ_LOG(3,(THIS_FILE, "No current call"));
@ -1458,18 +1434,6 @@ static void ui_send_arbitrary_request()
}
}
static void ui_toggle_call_sdp_offer()
{
app_config.enable_loam = !app_config.enable_loam;
printf("Subsequent calls and UPDATEs will contain SDP offer: ");
if (app_config.enable_loam) {
printf("NO.\n");
} else {
printf("YES.\n");
}
}
static void ui_echo(char menuin[])
{
if (pj_ansi_strnicmp(menuin, "echo", 4)==0) {
@ -1532,32 +1496,6 @@ static void ui_subscribe(char menuin[])
}
}
static void ui_subscribe_dlg_event(pj_bool_t sub)
{
char buf[128];
input_result result;
ui_input_url("(un)Subscribe dialog event of", buf, sizeof(buf), &result,
PJ_TRUE);
if (result.nb_result != PJSUA_APP_NO_NB) {
if (result.nb_result == -1) {
int i, count;
count = pjsua_get_buddy_count();
for (i=0; i<count; ++i)
pjsua_buddy_subscribe_dlg_event(i, sub);
} else if (result.nb_result == 0) {
puts("Sorry, can only subscribe to buddy's dialog event, "
"not from existing call");
} else {
pjsua_buddy_subscribe_dlg_event(result.nb_result-1, sub);
}
} else if (result.uri_result) {
puts("Sorry, can only subscribe to buddy's dialog event, "
"not arbitrary URL (for now)");
}
}
static void ui_register(char menuin[])
{
switch (menuin[1]) {
@ -1848,6 +1786,8 @@ static void ui_handle_ip_change()
status = pjsua_handle_ip_change(&param);
if (status != PJ_SUCCESS) {
pjsua_perror(THIS_FILE, "IP change failed", status);
} else {
PJ_LOG(3,(THIS_FILE, "IP change succeeded"));
}
}
@ -1967,13 +1907,6 @@ void legacy_main(void)
ui_call_hold();
break;
case 'o':
/*
* Toggle call SDP offer
*/
ui_toggle_call_sdp_offer();
break;
case 'v':
#if PJSUA_HAS_VIDEO
if (menuin[1]=='i' && menuin[2]=='d' && menuin[3]==' ') {
@ -2054,11 +1987,6 @@ void legacy_main(void)
ui_subscribe(menuin);
break;
case 'D':
/* Subscribe/unsubscribe dialog event */
ui_subscribe_dlg_event(menuin[1] != 'u');
break;
case 'r':
ui_register(menuin);
break;

View File

@ -7,8 +7,6 @@
objects = {
/* Begin PBXBuildFile section */
3A4E3B5E2B6206E50016735C /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A4E3B5C2B6206E50016735C /* Metal.framework */; };
3A4E3B5F2B6206E50016735C /* MetalKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A4E3B5D2B6206E50016735C /* MetalKit.framework */; };
3AEC29312995BF1400F59EA0 /* VideoToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AEC29302995BF1400F59EA0 /* VideoToolbox.framework */; };
3AEC29332995BF4C00F59EA0 /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AEC29322995BF4C00F59EA0 /* CoreMedia.framework */; };
C337417325BADEEE007785D7 /* Model.swift in Sources */ = {isa = PBXBuildFile; fileRef = C337417225BADEEE007785D7 /* Model.swift */; };
@ -48,8 +46,6 @@
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
3A4E3B5C2B6206E50016735C /* Metal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Metal.framework; path = System/Library/Frameworks/Metal.framework; sourceTree = SDKROOT; };
3A4E3B5D2B6206E50016735C /* MetalKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MetalKit.framework; path = System/Library/Frameworks/MetalKit.framework; sourceTree = SDKROOT; };
3AEC29302995BF1400F59EA0 /* VideoToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = VideoToolbox.framework; path = System/Library/Frameworks/VideoToolbox.framework; sourceTree = SDKROOT; };
3AEC29322995BF4C00F59EA0 /* CoreMedia.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMedia.framework; path = System/Library/Frameworks/CoreMedia.framework; sourceTree = SDKROOT; };
C337417225BADEEE007785D7 /* Model.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Model.swift; sourceTree = "<group>"; };
@ -98,7 +94,6 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
3A4E3B5F2B6206E50016735C /* MetalKit.framework in Frameworks */,
C351398125A5F70D00A090AA /* libg7221codec.a in Frameworks */,
C351398225A5F70D00A090AA /* libgsmcodec.a in Frameworks */,
C351398325A5F70D00A090AA /* libilbccodec.a in Frameworks */,
@ -117,7 +112,6 @@
C351398E25A5F70D00A090AA /* libpjsua.a in Frameworks */,
C351398F25A5F70D00A090AA /* libpjsua2.a in Frameworks */,
C351399025A5F70D00A090AA /* libresample.a in Frameworks */,
3A4E3B5E2B6206E50016735C /* Metal.framework in Frameworks */,
C351399125A5F70D00A090AA /* libspeex.a in Frameworks */,
C351399225A5F70D00A090AA /* libsrtp.a in Frameworks */,
C351399325A5F70D00A090AA /* libwebrtc.a in Frameworks */,
@ -194,8 +188,6 @@
C3B8521725A5EC380037A8AB /* Frameworks */ = {
isa = PBXGroup;
children = (
3A4E3B5C2B6206E50016735C /* Metal.framework */,
3A4E3B5D2B6206E50016735C /* MetalKit.framework */,
3AEC29322995BF4C00F59EA0 /* CoreMedia.framework */,
3AEC29302995BF1400F59EA0 /* VideoToolbox.framework */,
C3B8524625A5ED6D0037A8AB /* AudioToolbox.framework */,

View File

@ -212,9 +212,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "shlex"
version = "1.3.0"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3"
[[package]]
name = "syn"

View File

@ -900,9 +900,8 @@ static void destroy_app()
if (app.pool) {
pj_pool_release(app.pool);
app.pool = NULL;
/* Field peak_used_size is deprecated by #3897 */
//PJ_LOG(3,(THIS_FILE, "Peak memory size: %luMB",
// app.cp.peak_used_size / 1000000));
PJ_LOG(3,(THIS_FILE, "Peak memory size: %luMB",
app.cp.peak_used_size / 1000000));
pj_caching_pool_destroy(&app.cp);
}

View File

@ -205,7 +205,11 @@ void MyCall::onCallMediaState(OnCallMediaStateParam &prm)
med_port = new MyAudioMediaPort();
MediaFormatAudio fmt;
fmt.init(PJMEDIA_FORMAT_PCM, 16000, 1, 20000, 16);
fmt.type = PJMEDIA_TYPE_AUDIO;
fmt.clockRate = 16000;
fmt.channelCount = 1;
fmt.bitsPerSample = 16;
fmt.frameTimeUsec = 20000;
med_port->createPort("med_port", fmt);

View File

@ -1420,11 +1420,6 @@ static void call_on_media_update( pjsip_inv_session *inv,
pjmedia_sdp_neg_get_active_local(inv->neg, &local_sdp);
pjmedia_sdp_neg_get_active_remote(inv->neg, &remote_sdp);
if (local_sdp->media[0]->desc.port == 0) {
PJ_LOG(3, (THIS_FILE, "Audio media inactive"));
return;
}
status = pjmedia_stream_info_from_sdp(&audio->si, inv->pool, app.med_endpt,
local_sdp, remote_sdp, 0);
if (status != PJ_SUCCESS) {

View File

@ -121,13 +121,6 @@ using namespace pj;
%feature("director") FindBuddyMatch;
%feature("director") AudioMediaPlayer;
%feature("director") AudioMediaPort;
// PendingJob is only used on Python
#ifdef SWIGPYTHON
%feature("director") PendingJob;
#else
%ignore pj::PendingJob;
%ignore pj::Endpoint::utilAddPendingJob;
#endif
//
// STL stuff.
@ -244,11 +237,4 @@ using namespace pj;
%}
#endif
#ifdef SWIGPYTHON
%pythonprepend pj::Endpoint::utilAddPendingJob(PendingJob *job) %{
# print('disowning job')
job.__disown__()
%}
#endif
%include "pjsua2/endpoint.hpp"

View File

@ -26,9 +26,7 @@ SWIG_FLAGS=-I../../../../pjlib/include \
SRC_DIR=../../../../pjsip/include
SRCS=$(SRC_DIR)/pjsua2/endpoint.hpp $(SRC_DIR)/pjsua2/types.hpp
USE_THREADS = -threads
# In SWIG 4.2 the build will fail if we use this flag
#-DSWIG_NO_EXPORT_ITERATOR_METHODS
USE_THREADS = -threads -DSWIG_NO_EXPORT_ITERATOR_METHODS
SWIG_FLAGS += -w312 $(USE_THREADS)
.PHONY: all install uninstall

View File

@ -3,9 +3,6 @@ import sys
import time
from collections import deque
import struct
import gc
from random import randint
import threading
write=sys.stdout.write
@ -213,69 +210,6 @@ def ua_tonegen_test():
ep.libDestroy()
class RandomIntVal():
def __init__(self):
self.value = randint(0, 100000)
class TestJob(pj.PendingJob):
def __init__(self):
super().__init__()
self.val = RandomIntVal()
print("Job created id:", id(self), "value:", self.val.value)
def execute(self, is_pending):
print("Executing job value:", self.val.value, is_pending)
def __del__(self):
print("Job deleted id:", id(self), "value:", self.val.value)
def add_new_job1(ep):
print("Creating job 1")
job = TestJob()
print("Adding job 1")
ep.utilAddPendingJob(job)
# Function to be executed in a separate thread
def add_new_job2(ep):
ep.libRegisterThread("thread")
print("Creating job 2")
job = TestJob()
print("Adding job 2")
ep.utilAddPendingJob(job)
def ua_pending_job_test():
write("PendingJob test.." + "\r\n")
ep_cfg = pj.EpConfig()
ep_cfg.uaConfig.threadCnt = 0
ep_cfg.uaConfig.mainThreadOnly = True
ep = pj.Endpoint()
ep.libCreate()
ep.libInit(ep_cfg)
ep.libStart()
# test 1
# adding job from a separate function
add_new_job1(ep)
# test 2
# adding job from a different thread
my_thread = threading.Thread(target=add_new_job2, args=(ep,))
my_thread.start()
time.sleep(1)
print("Collecting gc 1")
gc.collect()
print("Handling events")
for _ in range(100):
ep.libHandleEvents(10)
print("Collecting gc 2")
gc.collect()
ep.libDestroy()
#
# main()
#
@ -285,7 +219,6 @@ if __name__ == "__main__":
ua_run_log_test()
ua_run_ua_test()
ua_tonegen_test()
ua_pending_job_test()
sys.exit(0)

View File

@ -184,14 +184,6 @@ typedef enum pj_ssl_cert_verify_flag_t
PJ_SSL_CERT_EUNKNOWN = 1 << 31
} pj_ssl_cert_verify_flag_t;
typedef enum pj_ssl_cert_lookup_type
{
PJ_SSL_CERT_LOOKUP_NONE,
PJ_SSL_CERT_LOOKUP_SUBJECT,
PJ_SSL_CERT_LOOKUP_FINGERPRINT,
PJ_SSL_CERT_LOOKUP_FRIENDLY_NAME
} pj_ssl_cert_lookup_type;
typedef enum pj_ice_sess_trickle
{
PJ_ICE_SESS_TRICKLE_DISABLED,

View File

@ -2,7 +2,7 @@ pj/types.h pj_status_t pj_constants_ pj_uint8_t pj_int32_t pj_uint32_t pj_uint
pj/file_io.h pj_file_access
pj/log.h pj_log_decoration
pj/sock_qos.h pj_qos_type pj_qos_flag pj_qos_wmm_prio pj_qos_params
pj/ssl_sock.h pj_ssl_cipher pj_ssl_sock_proto pj_ssl_cert_name_type pj_ssl_cert_verify_flag_t pj_ssl_cert_lookup_type
pj/ssl_sock.h pj_ssl_cipher pj_ssl_sock_proto pj_ssl_cert_name_type pj_ssl_cert_verify_flag_t
pjnath/ice_session.h pj_ice_sess_trickle
pjnath/nat_detect.h pj_stun_nat_type

View File

@ -97,8 +97,8 @@ export PJSIP_UA_LDFLAGS += $(PJSIP_SIMPLE_LDLIB) \
export PJSIP_SIMPLE_SRCDIR = ../src/pjsip-simple
export PJSIP_SIMPLE_OBJS += $(OS_OBJS) $(M_OBJS) $(CC_OBJS) $(HOST_OBJS) \
errno.o evsub.o evsub_msg.o iscomposing.o \
mwi.o pidf.o dialog_info.o presence.o dlg_event.o presence_body.o \
publishc.o rpid.o xpidf.o
mwi.o pidf.o presence.o presence_body.o publishc.o \
rpid.o xpidf.o
export PJSIP_SIMPLE_CFLAGS += $(_CFLAGS)
export PJSIP_SIMPLE_CXXFLAGS += $(_CXXFLAGS)
export PJSIP_SIMPLE_LDFLAGS += $(PJSIP_LDLIB) \

View File

@ -674,8 +674,6 @@
</Lib>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\src\pjsip-simple\dlg_event.c" />
<ClCompile Include="..\src\pjsip-simple\dialog_info.c" />
<ClCompile Include="..\src\pjsip-simple\errno.c" />
<ClCompile Include="..\src\pjsip-simple\evsub.c" />
<ClCompile Include="..\src\pjsip-simple\evsub_msg.c" />
@ -689,8 +687,6 @@
<ClCompile Include="..\src\pjsip-simple\xpidf.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\include\pjsip-simple\dlg_event.h" />
<ClInclude Include="..\include\pjsip-simple\dialog_info.h" />
<ClInclude Include="..\include\pjsip-simple\errno.h" />
<ClInclude Include="..\include\pjsip-simple\evsub.h" />
<ClInclude Include="..\include\pjsip-simple\evsub_msg.h" />

View File

@ -44,12 +44,6 @@
<ClCompile Include="..\src\pjsip-simple\xpidf.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\pjsip-simple\dlg_event.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\pjsip-simple\dialog_info.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\include\pjsip-simple\errno.h">
@ -88,11 +82,5 @@
<ClInclude Include="..\include\pjsip-simple\xpidf.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\pjsip-simple\dlg_event.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\pjsip-simple\dialog_info.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -1,345 +0,0 @@
/*
* Copyright (C) 2024 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2013 Maxim Kondratenko <max.kondr@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJSIP_SIMPLE_DIALOG_INFO_H__
#define __PJSIP_SIMPLE_DIALOG_INFO_H__
/**
* @file dialog_info.h
* @brief Dialog-Info Information Data Format (RFC 4235)
*/
#include <pjsip-simple/types.h>
#include <pjlib-util/xml.h>
PJ_BEGIN_DECL
/**
* @defgroup PJSIP_SIMPLE_DIALOG_INFO Dialog-Info Data Format (RFC 4235)
* @ingroup PJSIP_SIMPLE
* @brief Support for Dialog-Info Information Data Format (RFC 4235)
* @{
*
* This file provides tools for manipulating Dialog-Info Information Data
* Format as described in RFC 4235.
*/
typedef struct pj_xml_node pjsip_dlg_info_dialog_info;
typedef struct pj_xml_node pjsip_dlg_info_dialog;
typedef struct pj_xml_node pjsip_dlg_info_local;
typedef struct pj_xml_node pjsip_dlg_info_remote;
typedef struct pjsip_dlg_info_local_op
{
void (*construct)(pj_pool_t *, pjsip_dlg_info_local *);
const pj_str_t * (*get_identity)(const pjsip_dlg_info_local *);
void (*set_identity)(pj_pool_t *pool, const pjsip_dlg_info_local *,
const pj_str_t *);
const pj_str_t * (*get_identity_display)(const pjsip_dlg_info_local*);
void (*set_identity_display)(pj_pool_t *pool, const pjsip_dlg_info_local *,
const pj_str_t *);
const pj_str_t * (*get_target_uri)(const pjsip_dlg_info_local*);
void (*set_target_uri)(pj_pool_t *pool, const pjsip_dlg_info_local *,
const pj_str_t *);
} pjsip_dlg_info_local_op;
typedef struct pjsip_dlg_info_remote_op
{
void (*construct)(pj_pool_t *, pjsip_dlg_info_remote *);
const pj_str_t * (*get_identity)(const pjsip_dlg_info_remote *);
void (*set_identity)(pj_pool_t *pool, const pjsip_dlg_info_remote *,
const pj_str_t *);
const pj_str_t * (*get_identity_display)(const pjsip_dlg_info_remote*);
void (*set_identity_display)(pj_pool_t *pool, const pjsip_dlg_info_remote*,
const pj_str_t *);
const pj_str_t * (*get_target_uri)(const pjsip_dlg_info_remote*);
void (*set_target_uri)(pj_pool_t *pool, const pjsip_dlg_info_remote *,
const pj_str_t *);
} pjsip_dlg_info_remote_op;
typedef struct pjsip_dlg_info_dialog_op
{
void (*construct)(pj_pool_t *, pjsip_dlg_info_dialog *, const pj_str_t *);
const pj_str_t * (*get_id)(const pjsip_dlg_info_dialog *);
void (*set_id)(pj_pool_t *pool, const pjsip_dlg_info_dialog *,
const pj_str_t *);
const pj_str_t * (*get_call_id)(const pjsip_dlg_info_dialog *);
void (*set_call_id)(pj_pool_t *pool, const pjsip_dlg_info_dialog *,
const pj_str_t *);
const pj_str_t * (*get_remote_tag)(const pjsip_dlg_info_dialog *);
void (*set_remote_tag)(pj_pool_t *pool, const pjsip_dlg_info_dialog *,
const pj_str_t *);
const pj_str_t * (*get_local_tag)(const pjsip_dlg_info_dialog *);
void (*set_local_tag)(pj_pool_t *pool, const pjsip_dlg_info_dialog *,
const pj_str_t *);
const pj_str_t * (*get_direction)(const pjsip_dlg_info_dialog *);
void (*set_direction)(pj_pool_t *pool, const pjsip_dlg_info_dialog *,
const pj_str_t *);
const pj_str_t * (*get_state)(const pjsip_dlg_info_dialog *);
void (*set_state)(pj_pool_t *pool, const pjsip_dlg_info_dialog *,
const pj_str_t *);
const pj_str_t * (*get_duration)(const pjsip_dlg_info_dialog *);
void (*set_duration)(pj_pool_t *pool, const pjsip_dlg_info_dialog *,
const pj_str_t *);
pjsip_dlg_info_local* (*get_local)(const pjsip_dlg_info_dialog *);
pjsip_dlg_info_local* (*set_local)(pj_pool_t *pool,
const pjsip_dlg_info_dialog *,
const pjsip_dlg_info_local *);
pjsip_dlg_info_remote* (*get_remote)(const pjsip_dlg_info_dialog *);
pjsip_dlg_info_remote* (*set_remote)(pj_pool_t *pool,
const pjsip_dlg_info_dialog *,
const pjsip_dlg_info_remote *);
} pjsip_dlg_info_dialog_op;
typedef struct pjsip_dlg_info_dialog_info_op
{
void (*construct)(pj_pool_t *, pjsip_dlg_info_dialog_info *,
const pj_str_t *, const pj_str_t *, const pj_str_t *);
const pj_str_t * (*get_state)(const pjsip_dlg_info_dialog_info *);
void (*set_state)(pj_pool_t *pool, const pjsip_dlg_info_dialog_info *,
const pj_str_t *);
const pj_str_t * (*get_version)(const pjsip_dlg_info_dialog_info *);
void (*set_version)(pj_pool_t *pool, const pjsip_dlg_info_dialog_info *,
const pj_str_t *);
const pj_str_t * (*get_entity)(const pjsip_dlg_info_dialog_info *);
void (*set_entity)(pj_pool_t *pool, const pjsip_dlg_info_dialog_info *,
const pj_str_t *);
pjsip_dlg_info_dialog* (*get_dialog)(const pjsip_dlg_info_dialog_info *);
void (*set_dialog)(pj_pool_t *pool, const pjsip_dlg_info_dialog_info *,
const pjsip_dlg_info_dialog * );
} pjsip_dlg_info_dialog_info_op;
/******************************************************************************
* Top level API for managing dialog-info document.
*****************************************************************************/
PJ_DECL(pjsip_dlg_info_dialog_info *)
pjsip_dlg_info_create(pj_pool_t *pool, const pj_str_t *version,
const pj_str_t *state, const pj_str_t *entity);
PJ_DECL(pjsip_dlg_info_dialog_info *)
pjsip_dlg_info_parse(pj_pool_t *pool, char *text, int len);
PJ_DECL(int)
pjsip_dlg_info_print(const pjsip_dlg_info_dialog_info *dialog_info,
char *buf, int len);
/******************************************************************************
* API for managing Dialog-info node.
*****************************************************************************/
PJ_DECL(void)
pjsip_dlg_info_dialog_info_construct(pj_pool_t *pool,
pjsip_dlg_info_dialog_info *dialog_info,
const pj_str_t *version,
const pj_str_t *state,
const pj_str_t *entity);
PJ_DECL(const pj_str_t *)
pjsip_dlg_info_dialog_info_get_state(pjsip_dlg_info_dialog_info *dialog_info);
PJ_DECL(void)
pjsip_dlg_info_dialog_info_set_state(pj_pool_t *pool,
pjsip_dlg_info_dialog_info *dialog_info,
const pj_str_t *state);
PJ_DECL(const pj_str_t *)
pjsip_dlg_info_dialog_info_get_version(pjsip_dlg_info_dialog_info *dlg_info);
PJ_DECL(void)
pjsip_dlg_info_dialog_info_set_version(pj_pool_t *pool,
pjsip_dlg_info_dialog_info *dialog_info,
const pj_str_t *version);
PJ_DECL(const pj_str_t *)
pjsip_dlg_info_dialog_info_get_entity(pjsip_dlg_info_dialog_info *dialog_info);
PJ_DECL(void)
pjsip_dlg_info_dialog_info_set_entity(pj_pool_t *pool,
pjsip_dlg_info_dialog_info *dialog_info,
const pj_str_t *entity);
PJ_DECL(pjsip_dlg_info_dialog *)
pjsip_dlg_info_dialog_info_add_dialog(pj_pool_t *pool,
pjsip_dlg_info_dialog_info *dialog_info,
const pj_str_t *id);
PJ_DECL(pjsip_dlg_info_dialog *)
pjsip_dlg_info_dialog_info_get_dialog(pjsip_dlg_info_dialog_info *dialog_info);
/******************************************************************************
* API for managing Dialog node.
*****************************************************************************/
PJ_DECL(void)
pjsip_dlg_info_dialog_construct(pj_pool_t *pool,
pjsip_dlg_info_dialog *dialog,
const pj_str_t *id);
PJ_DECL(const pj_str_t *)
pjsip_dlg_info_dialog_get_id(const pjsip_dlg_info_dialog *dialog);
PJ_DECL(void)
pjsip_dlg_info_dialog_set_id(pj_pool_t *pool,
pjsip_dlg_info_dialog *dialog,
const pj_str_t *id);
PJ_DECL(const pj_str_t *)
pjsip_dlg_info_dialog_get_call_id(const pjsip_dlg_info_dialog *dialog);
PJ_DECL(void)
pjsip_dlg_info_dialog_set_call_id(pj_pool_t *pool,
pjsip_dlg_info_dialog *dialog,
const pj_str_t *call_id);
PJ_DECL(const pj_str_t *)
pjsip_dlg_info_dialog_get_remote_tag(const pjsip_dlg_info_dialog *dialog);
PJ_DECL(void)
pjsip_dlg_info_dialog_set_remote_tag(pj_pool_t *pool,
pjsip_dlg_info_dialog *dialog,
const pj_str_t *remote_tag);
PJ_DECL(const pj_str_t *)
pjsip_dlg_info_dialog_get_local_tag(const pjsip_dlg_info_dialog *dialog);
PJ_DECL(void)
pjsip_dlg_info_dialog_set_local_tag(pj_pool_t *pool,
pjsip_dlg_info_dialog *dialog,
const pj_str_t *local_tag);
PJ_DECL(const pj_str_t *)
pjsip_dlg_info_dialog_get_direction(const pjsip_dlg_info_dialog *dialog);
PJ_DECL(void)
pjsip_dlg_info_dialog_set_direction(pj_pool_t *pool,
pjsip_dlg_info_dialog *dialog,
const pj_str_t *direction);
PJ_DECL(const pj_str_t *)
pjsip_dlg_info_dialog_get_state(pjsip_dlg_info_dialog *dialog);
PJ_DECL(void)
pjsip_dlg_info_dialog_set_state(pj_pool_t *pool,
pjsip_dlg_info_dialog *dialog,
const pj_str_t *state);
PJ_DECL(const pj_str_t *)
pjsip_dlg_info_dialog_get_duration(pjsip_dlg_info_dialog *dialog);
PJ_DECL(void)
pjsip_dlg_info_dialog_set_duration(pj_pool_t *pool,
pjsip_dlg_info_dialog *dialog,
const pj_str_t *duration);
PJ_DECL(pjsip_dlg_info_local *)
pjsip_dlg_info_dialog_get_local(pjsip_dlg_info_dialog *dialog);
PJ_DECL(pjsip_dlg_info_local *)
pjsip_dlg_info_dialog_add_local(pj_pool_t *pool,
pjsip_dlg_info_dialog *dialog);
PJ_DECL(pjsip_dlg_info_remote *)
pjsip_dlg_info_dialog_get_remote(pjsip_dlg_info_dialog *dialog);
PJ_DECL(pjsip_dlg_info_remote *)
pjsip_dlg_info_dialog_add_remote(pj_pool_t *pool,
pjsip_dlg_info_dialog *dialog);
/******************************************************************************
* API for managing Local node.
*****************************************************************************/
PJ_DECL(void)
pjsip_dlg_info_local_construct(pj_pool_t *pool,
pjsip_dlg_info_local *local);
PJ_DECL(const pj_str_t *)
pjsip_dlg_info_local_get_identity(const pjsip_dlg_info_local *local);
PJ_DECL(void)
pjsip_dlg_info_local_add_identity(pj_pool_t *pool,
pjsip_dlg_info_local *local,
const pj_str_t *identity);
PJ_DECL(const pj_str_t *)
pjsip_dlg_info_local_get_identity_display(const pjsip_dlg_info_local *local);
PJ_DECL(void)
pjsip_dlg_info_local_set_identity_display(pj_pool_t *pool,
pjsip_dlg_info_local *local,
const pj_str_t *identity_display);
PJ_DECL(const pj_str_t *)
pjsip_dlg_info_local_get_target_uri(const pjsip_dlg_info_local *local);
PJ_DECL(void)
pjsip_dlg_info_local_set_target_uri(pj_pool_t *pool,
pjsip_dlg_info_local *local,
const pj_str_t *target_uri);
/******************************************************************************
* API for managing Remote node.
*****************************************************************************/
PJ_DECL(void)
pjsip_dlg_info_remote_construct(pj_pool_t *pool,
pjsip_dlg_info_remote *remote);
PJ_DECL(const pj_str_t *)
pjsip_dlg_info_remote_get_identity(const pjsip_dlg_info_remote *remote);
PJ_DECL(void)
pjsip_dlg_info_remote_add_identity(pj_pool_t *pool,
pjsip_dlg_info_remote *remote,
const pj_str_t *identity);
PJ_DECL(const pj_str_t *)
pjsip_dlg_info_remote_get_identity_display(const pjsip_dlg_info_remote *remote);
PJ_DECL(void)
pjsip_dlg_info_remote_set_identity_display(pj_pool_t *pool,
pjsip_dlg_info_remote *remote,
const pj_str_t *identity_display);
PJ_DECL(const pj_str_t *)
pjsip_dlg_info_remote_get_target_uri(const pjsip_dlg_info_remote *remote);
PJ_DECL(void)
pjsip_dlg_info_remote_set_target_uri(pj_pool_t *pool,
pjsip_dlg_info_remote *remote,
const pj_str_t *target_uri);
PJ_END_DECL
#endif /* __PJSIP_SIMPLE_DIALOG_INFO_H__ */

View File

@ -1,273 +0,0 @@
/*
* Copyright (C) 2024 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2013 Maxim Kondratenko <max.kondr@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __PJSIP_SIMPLE_DLG_EVENT_H__
#define __PJSIP_SIMPLE_DLG_EVENT_H__
/**
* @file dlg_event.h
* @brief SIP Extension for INVITE-Initiated Dialog Event (RFC 4235)
*/
#include <pjsip-simple/evsub.h>
#include <pjsip-simple/dialog_info.h>
PJ_BEGIN_DECL
/**
* @defgroup PJSIP_SIMPLE_DLG_EVENT SIP Extension for Dialog Event (RFC 4235)
* @ingroup PJSIP_SIMPLE
* @brief Support for SIP Extension for Dialog Event (RFC 4235)
* @{
*
* This module contains the implementation of INVITE-Initiated Dialog Event
* Package as described in RFC 4235. It uses the SIP Event Notification
* framework (evsub.h) and extends the framework by implementing
* "dialog-info+xml" event package. This could be useful for features such as
* Busy Lamp Field (BLF).
*/
/**
* Initialize the dialog event module and register it as endpoint module and
* package to the event subscription module.
*
* @param endpt The endpoint instance.
* @param mod_evsub The event subscription module instance.
*
* @return PJ_SUCCESS if the module is successfully
* initialized and registered to both endpoint
* and the event subscription module.
*/
PJ_DECL(pj_status_t) pjsip_dlg_event_init_module(pjsip_endpoint *endpt,
pjsip_module *mod_evsub);
/**
* Get the dialog event module instance.
*
* @return The dialog event module instance.
*/
PJ_DECL(pjsip_module*) pjsip_bdlg_event_instance(void);
/**
* Maximum dialog event status info items which can handled by application.
*
*/
#define PJSIP_DLG_EVENT_STATUS_MAX_INFO 8
/**
* This structure describes dialog event status of an entity.
*/
struct pjsip_dlg_event_status
{
unsigned info_cnt; /**< Number of info in the status */
struct {
pj_str_t dialog_info_state; /**< Dialog-Info state */
pj_str_t dialog_info_entity; /**< Dialog-Info entity */
pj_str_t dialog_call_id; /**< Dialog's call_id */
pj_str_t dialog_remote_tag; /**< Dialog's remote-tag */
pj_str_t dialog_local_tag; /**< Dialog's local-tag */
pj_str_t dialog_direction; /**< Dialog's direction */
pj_str_t dialog_id; /**< Dialog's id */
pj_str_t dialog_state; /**< Dialog state */
pj_str_t dialog_duration; /**< Dialog duration */
pj_xml_node *dialog_node; /**< Pointer to tuple XML node of
parsed dialog-info body received
from remote agent. Only valid
for client subscription. If the
last received NOTIFY request
does not contain any dialog-info
body, this will be set to NULL*/
pj_str_t local_identity;
pj_str_t local_identity_display;
pj_str_t local_target_uri;
pj_str_t remote_identity;
pj_str_t remote_identity_display;
pj_str_t remote_target_uri;
} info[PJSIP_DLG_EVENT_STATUS_MAX_INFO]; /**< Array of info. */
};
/**
* @see pjsip_dlg_event_status
*/
typedef struct pjsip_dlg_event_status pjsip_dlg_event_status;
/**
* Create dialog event client subscription session.
*
* @param dlg The underlying dialog to use.
* @param user_cb Pointer to callbacks to receive dialog events.
* @param options Option flags. Currently only PJSIP_EVSUB_NO_EVENT_ID
* is recognized.
* @param p_evsub Pointer to receive the dialog event subscription
* session.
*
* @return PJ_SUCCESS on success.
*/
PJ_DECL(pj_status_t)
pjsip_dlg_event_create_uac(pjsip_dialog *dlg,
const pjsip_evsub_user *user_cb,
unsigned options,
pjsip_evsub **p_evsub );
/**
* Forcefully destroy the dialog event subscription. This function should only
* be called on special condition, such as when the subscription
* initialization has failed. For other conditions, application MUST terminate
* the subscription by sending the appropriate un(SUBSCRIBE) or NOTIFY.
*
* @param sub The dialog event subscription.
* @param notify Specify whether the state notification callback
* should be called.
*
* @return PJ_SUCCESS if subscription session has been destroyed.
*/
PJ_DECL(pj_status_t) pjsip_dlg_event_terminate(pjsip_evsub *sub,
pj_bool_t notify );
/**
* Call this function to create request to initiate dialog event subscription,
* to refresh subcription, or to request subscription termination.
*
* @param sub Client subscription instance.
* @param expires Subscription expiration. If the value is set to zero,
* this will request unsubscription.
* @param p_tdata Pointer to receive the request.
*
* @return PJ_SUCCESS on success.
*/
PJ_DECL(pj_status_t) pjsip_dlg_event_initiate(pjsip_evsub *sub,
pj_int32_t expires,
pjsip_tx_data **p_tdata);
/**
* Add a list of headers to the subscription instance. The list of headers
* will be added to outgoing dialog event subscription requests.
*
* @param sub Subscription instance.
* @param hdr_list List of headers to be added.
*
* @return PJ_SUCCESS on success.
*/
PJ_DECL(pj_status_t) pjsip_dlg_event_add_header(pjsip_evsub *sub,
const pjsip_hdr *hdr_list);
/**
* Accept the incoming subscription request by sending 2xx response to
* incoming SUBSCRIBE request.
*
* @param sub Server subscription instance.
* @param rdata The incoming subscription request message.
* @param st_code Status code, which MUST be final response.
* @param hdr_list Optional list of headers to be added in the response.
*
* @return PJ_SUCCESS on success.
*/
PJ_DECL(pj_status_t) pjsip_dlg_event_accept(pjsip_evsub *sub,
pjsip_rx_data *rdata,
int st_code,
const pjsip_hdr *hdr_list );
/**
* Send request message. Application may also send request created with other
* functions, e.g. authentication. But the request MUST be either request
* that creates/refresh subscription or NOTIFY request.
*
* @param sub The subscription object.
* @param tdata Request message to be sent.
*
* @return PJ_SUCCESS on success.
*/
PJ_DECL(pj_status_t) pjsip_dlg_event_send_request(pjsip_evsub *sub,
pjsip_tx_data *tdata);
/**
* Get the dialog event status. Client normally would call this function
* after receiving NOTIFY request from server.
*
* @param sub The client or server subscription.
* @param status The structure to receive dialog event status.
*
* @return PJ_SUCCESS on success.
*/
PJ_DECL(pj_status_t)
pjsip_dlg_event_get_status(pjsip_evsub *sub, pjsip_dlg_event_status *status);
/**
* This is a utility function to parse XML body into PJSIP dialog event status.
*
* @param rdata The incoming SIP message containing the XML body.
* @param pool Pool to allocate memory to copy the strings into
* the dialog event status structure.
* @param status The dialog event status to be initialized.
*
* @return PJ_SUCCESS on success.
*
* @see pjsip_dlg_event_parse_dialog_info()
*/
PJ_DECL(pj_status_t)
pjsip_dlg_event_parse_dialog_info(pjsip_rx_data *rdata,
pj_pool_t *pool,
pjsip_dlg_event_status *dlg_status);
/**
* This is a utility function to parse XML body into PJSIP dialog event status.
*
* @param body Text body, with one extra space at the end to place
* NULL character temporarily during parsing.
* @param body_len Length of the body, not including the NULL termination
* character.
* @param pool Pool to allocate memory to copy the strings into
* the dialog event status structure.
* @param status The dialog event status to be initialized.
*
* @return PJ_SUCCESS on success.
*
* @see pjsip_dlg_event_parse_dialog_info2()
*/
PJ_DECL(pj_status_t)
pjsip_dlg_event_parse_dialog_info2(char *body, unsigned body_len,
pj_pool_t *pool,
pjsip_dlg_event_status *dlg_status);
/**
* @}
*/
PJ_END_DECL
#endif /* __PJSIP_SIMPLE_DLG_EVENT_H__ */

View File

@ -98,6 +98,8 @@ struct pjsip_pres_status
this valud will be set to NULL */
} info[PJSIP_PRES_STATUS_MAX_INFO]; /**< Array of info. */
pj_bool_t _is_valid; /**< Internal flag. */
};

View File

@ -932,14 +932,6 @@ PJ_INLINE(pjsip_cfg_t*) pjsip_cfg(void)
# endif
#endif
/**
* Specify the default expiration time for dialog event subscription.
*
* Default: 600 seconds (10 minutes)
*/
#ifndef PJSIP_DLG_EVENT_DEFAULT_EXPIRES
# define PJSIP_DLG_EVENT_DEFAULT_EXPIRES 600
#endif
/**
* Specify the maximum number of timer entries initially allocated by
@ -1426,17 +1418,6 @@ PJ_INLINE(pjsip_cfg_t*) pjsip_cfg(void)
#endif
/**
* Specify the status code value to respond to bad message body in NOTIFY
* request for dialog event.
*
* Default: 488 (Not Acceptable Here)
*/
#ifndef PJSIP_DLG_EVENT_BAD_CONTENT_RESPONSE
# define PJSIP_DLG_EVENT_BAD_CONTENT_RESPONSE 488
#endif
/**
* Add "timestamp" information in generated PIDF document for both server
* subscription and presence publication.

View File

@ -188,14 +188,6 @@ typedef struct pjsip_tls_setting
*/
pj_ssl_cert_buffer privkey_buf;
/**
* Lookup certificate from OS certificate store with specified criteria.
*
* Currently only used by TLS backend Windows Schannel, please check
* pj_ssl_cert_load_from_store() for more info.
*/
pj_ssl_cert_lookup_criteria cert_lookup;
/**
* Password to open private key.
*/
@ -482,9 +474,6 @@ PJ_INLINE(void) pjsip_tls_setting_copy(pj_pool_t *pool,
pj_strdup(pool, &dst->cert_buf, &src->cert_buf);
pj_strdup(pool, &dst->privkey_buf, &src->privkey_buf);
pj_strdup_with_null(pool, &dst->cert_lookup.keyword,
&src->cert_lookup.keyword);
if (src->ciphers_num) {
unsigned i;
dst->ciphers = (pj_ssl_cipher*) pj_pool_calloc(pool, src->ciphers_num,

View File

@ -33,7 +33,6 @@
#ifndef __PJSIP_SIMPLE_H__
#define __PJSIP_SIMPLE_H__
#include <pjsip-simple/dlg_event.h>
#include <pjsip-simple/evsub.h>
#include <pjsip-simple/evsub_msg.h>
#include <pjsip-simple/iscomposing.h>

View File

@ -1649,13 +1649,6 @@ typedef struct pjsua_callback
*/
void (*on_buddy_state)(pjsua_buddy_id buddy_id);
/**
* Notify application when the buddy dialog state has changed.
* Application may then query the buddy into to get the details.
*
* @param buddy_id The buddy id.
*/
void (*on_buddy_dlg_event_state)(pjsua_buddy_id buddy_id);
/**
* Notify application when the state of client subscription session
@ -1671,20 +1664,6 @@ typedef struct pjsua_callback
pjsip_evsub *sub,
pjsip_event *event);
/**
* Notify application when the state of client subscription session
* associated with a buddy dialog state has changed. Application
* may use this callback to retrieve more detailed information about the
* state changed event.
*
* @param buddy_id The buddy id.
* @param sub Event subscription session.
* @param event The event which triggers state change event.
*/
void (*on_buddy_evsub_dlg_event_state)(pjsua_buddy_id buddy_id,
pjsip_evsub *sub,
pjsip_event *event);
/**
* Notify application on incoming pager (i.e. MESSAGE request).
* Argument call_id will be -1 if MESSAGE request is not related to an
@ -2787,9 +2766,6 @@ typedef struct pjsua_ip_change_param
{
/**
* If set to PJ_TRUE, this will restart the transport listener.
* Note that if restarting listener is enabled and the listener is
* configured with a bound address, the address will be reset
* so it will bind to any address (e.g: IPv4 "0.0.0.0" or IPv6 "::").
*
* Default : PJ_TRUE
*/
@ -3208,8 +3184,9 @@ typedef struct pjsua_transport_config
pj_str_t bound_addr;
/**
* This specifies TLS settings for TLS transport.
* Its only used when creating a SIP TLS transport.
* This specifies TLS settings for TLS transport. It is only be used
* when this transport config is being used to create a SIP TLS
* transport.
*/
pjsip_tls_setting tls_setting;
@ -3798,8 +3775,8 @@ typedef struct pjsua_turn_config
pj_stun_auth_cred turn_auth_cred;
/**
* This specifies TLS settings for TURN TLS. Its only applicable when
* TLS is used to connect to the TURN server.
* This specifies TLS settings for TURN TLS. It is only be used
* when this TLS is used to connect to the TURN server.
*/
pj_turn_sock_tls_cfg turn_tls_setting;
@ -4552,18 +4529,6 @@ typedef struct pjsua_acc_config
*/
pj_bool_t register_on_acc_add;
/**
* Specify whether account modification with pjsua_acc_modify() should
* automatically update registration if necessary, for example if
* account credentials change.
*
* Disable this when immediate registration is not desirable, such as
* during IP address change.
*
* Default: PJ_FALSE.
*/
pj_bool_t disable_reg_on_modify;
/**
* Specify account configuration specific to IP address change used when
* calling #pjsua_handle_ip_change().
@ -6443,14 +6408,7 @@ pjsua_call_get_med_transport_info(pjsua_call_id call_id,
# define PJSUA_PRES_TIMER 300
#endif
/**
* This specifies the buffer size of pjsua_buddy_dlg_event_info.
*
* Default: 1024 bytes
*/
#ifndef PJSUA_BUDDY_DLG_EVENT_INFO_BUF_SIZE
# define PJSUA_BUDDY_DLG_EVENT_INFO_BUF_SIZE 1024
#endif
/**
* This structure describes buddy configuration when adding a buddy to
* the buddy list with #pjsua_buddy_add(). Application MUST initialize
@ -6466,19 +6424,9 @@ typedef struct pjsua_buddy_config
/**
* Specify whether presence subscription should start immediately.
* Note that only one subscription (presence or dialog event)
* can be active at any time.
*/
pj_bool_t subscribe;
/**
* Specify whether we should immediately subscribe to the buddy's
* dialog event, such as for Busy Lamp Field (BLF) feature.
* Note that only one subscription (presence or dialog event)
* can be active at any time.
*/
pj_bool_t subscribe_dlg_event;
/**
* Specify arbitrary application data to be associated with with
* the buddy object.
@ -6599,91 +6547,6 @@ typedef struct pjsua_buddy_info
} pjsua_buddy_info;
typedef struct pjsua_buddy_dlg_event_info
{
/**
* The buddy ID.
*/
pjsua_buddy_id id;
/**
* The full URI of the buddy, as specified in the configuration.
*/
pj_str_t uri;
/* Dialog event Dialog-Info id */
pj_str_t dialog_id;
/* Dialog event Dialog-Info state */
pj_str_t dialog_info_state;
/* Dialog event Dialog-Info entity */
pj_str_t dialog_info_entity;
/* Dialog event Dialog call_id */
pj_str_t dialog_call_id;
/* Dialog event Dialog remote_tag */
pj_str_t dialog_remote_tag;
/* Dialog event Dialog local_tag */
pj_str_t dialog_local_tag;
/* Dialog event Dialog direction */
pj_str_t dialog_direction;
/* Dialog event dialog state */
pj_str_t dialog_state;
/* Dialog event dialog duration */
pj_str_t dialog_duration;
/* Dialog event local identity */
pj_str_t local_identity;
/* Dialog event local identity_display */
pj_str_t local_identity_display;
/* Dialog event local target uri */
pj_str_t local_target_uri;
/* Dialog event remote identity */
pj_str_t remote_identity;
/* Dialog event remote identity_display */
pj_str_t remote_identity_display;
/* Dialog event remote target uri */
pj_str_t remote_target_uri;
/**
* This specifies the last state of the dialog event subscription.
*/
pjsip_evsub_state sub_state;
/**
* String representation of subscription state.
*/
const char *sub_state_name;
/**
* Specifies the last dialog event subscription termination code.
*/
unsigned sub_term_code;
/**
* Specifies the last dialog event subscription termination reason. If
* presence subscription is currently active, the value will be empty.
*/
pj_str_t sub_term_reason;
/**
* Internal buffer.
*/
char buf_[PJSUA_BUDDY_DLG_EVENT_INFO_BUF_SIZE];
} pjsua_buddy_dlg_event_info;
/**
* Set default values to the buddy config.
*/
@ -6744,18 +6607,6 @@ PJ_DECL(pjsua_buddy_id) pjsua_buddy_find(const pj_str_t *uri);
PJ_DECL(pj_status_t) pjsua_buddy_get_info(pjsua_buddy_id buddy_id,
pjsua_buddy_info *info);
/**
* Get detailed buddy dialog event info.
*
* @param buddy_id The buddy identification.
* @param info Pointer to receive information about buddy.
*
* @return PJ_SUCCESS on success, or the appropriate error code.
*/
PJ_DECL(pj_status_t)
pjsua_buddy_get_dlg_event_info(pjsua_buddy_id buddy_id,
pjsua_buddy_dlg_event_info *info);
/**
* Set the user data associated with the buddy object.
*
@ -6809,9 +6660,6 @@ PJ_DECL(pj_status_t) pjsua_buddy_del(pjsua_buddy_id buddy_id);
* subscribed, application will be informed about buddy's presence status
* changed via \a on_buddy_state() callback.
*
* Note that only one subscription (presence or dialog event) can be active
* at any time.
*
* @param buddy_id Buddy identification.
* @param subscribe Specify non-zero to activate presence subscription to
* the specified buddy.
@ -6822,24 +6670,6 @@ PJ_DECL(pj_status_t) pjsua_buddy_subscribe_pres(pjsua_buddy_id buddy_id,
pj_bool_t subscribe);
/**
* Enable/disable buddy's dialog event monitoring. Once buddy's dialog event
* is subscribed, application will be informed about buddy's dialog info
* status change via \a on_buddy_dlg_event_state() callback.
*
* Note that only one subscription (presence or dialog event) can be active
* at any time.
*
* @param buddy_id Buddy identification.
* @param subscribe Specify non-zero to activate dialog event subscription
* to the specified buddy.
*
* @return PJ_SUCCESS on success, or the appropriate error code.
*/
PJ_DECL(pj_status_t) pjsua_buddy_subscribe_dlg_event(pjsua_buddy_id buddy_id,
pj_bool_t subscribe);
/**
* Update the presence information for the buddy. Although the library
* periodically refreshes the presence subscription for all buddies, some
@ -6863,30 +6693,6 @@ PJ_DECL(pj_status_t) pjsua_buddy_subscribe_dlg_event(pjsua_buddy_id buddy_id,
PJ_DECL(pj_status_t) pjsua_buddy_update_pres(pjsua_buddy_id buddy_id);
/**
* Update the dialog event information for the buddy. Although the library
* periodically refreshes the dialog event subscription for all buddies, some
* application may want to refresh the buddy's dialog event subscription
* immediately, and in this case it can use this function to accomplish
* this.
*
* Note that the buddy's dialog event subscription will only be initiated
* if dialog event monitoring is enabled for the buddy. See
* #pjsua_buddy_subscribe_dlg_event() for more info. Also if dialog event
* subscription for the buddy is already active, this function will not do
* anything.
*
* Once the dialog event subscription is activated successfully for the buddy,
* application will be notified about the buddy's dialog info status in the
* on_buddy_dlg_event_state() callback.
*
* @param buddy_id Buddy identification.
*
* @return PJ_SUCCESS on success, or the appropriate error code.
*/
PJ_DECL(pj_status_t) pjsua_buddy_update_dlg_event(pjsua_buddy_id buddy_id);
/**
* Send NOTIFY to inform account presence status or to terminate server
* side presence subscription. If application wants to reject the incoming
@ -7408,8 +7214,8 @@ struct pjsua_media_config
pj_stun_auth_cred turn_auth_cred;
/**
* This specifies TLS settings for TLS transport. Its only applicable
* when TLS is used to connect to the TURN server.
* This specifies TLS settings for TLS transport. It is only be used
* when this TLS is used to connect to the TURN server.
*/
pj_turn_sock_tls_cfg turn_tls_setting;

View File

@ -377,12 +377,10 @@ typedef struct pjsua_buddy
unsigned port; /**< Buddy port. */
pj_bool_t monitor; /**< Should we monitor? */
pjsip_dialog *dlg; /**< The underlying dialog. */
pjsip_evsub *sub; /**< Buddy subscription */
pj_bool_t presence; /**< Presence subscription? */
pjsip_evsub *sub; /**< Buddy presence subscription */
unsigned term_code; /**< Subscription termination code */
pj_str_t term_reason;/**< Subscription termination reason */
pjsip_pres_status status; /**< Buddy presence status. */
pjsip_dlg_event_status dlg_ev_status;/**< Buddy dialog event status */
pj_timer_entry timer; /**< Resubscription timer */
} pjsua_buddy;
@ -774,7 +772,6 @@ void pjsua_ice_check_start_trickling(pjsua_call *call,
pj_bool_t pjsua_call_media_is_changing(pjsua_call *call);
pj_status_t pjsua_call_media_init(pjsua_call_media *call_med,
pjmedia_type type,
const pjmedia_sdp_session *rem_sdp,
const pjsua_transport_config *tcfg,
int security_level,
int *sip_err_code,

View File

@ -62,18 +62,6 @@ struct AccountRegConfig : public PersistentObject
*/
bool registerOnAdd;
/**
* Specify whether account modification with Account::modify() should
* automatically update registration if necessary, for example if
* account credentials change.
*
* Disable this when immediate registration is not desirable, such as
* during IP address change.
*
* Default: false.
*/
bool disableRegOnModify;
/**
* The optional custom SIP headers to be put in the registration
* request.

View File

@ -1779,6 +1779,7 @@ public:
*/
void resetVideoCodecParam(const string &codec_id) PJSUA2_THROW(Error);
#if defined(PJMEDIA_HAS_OPUS_CODEC) && (PJMEDIA_HAS_OPUS_CODEC!=0)
/**
* Get codec Opus config.
*
@ -1793,6 +1794,7 @@ public:
*/
void setCodecOpusConfig(const CodecOpusConfig &opus_cfg)
PJSUA2_THROW(Error);
#endif
/**
* Enumerate all SRTP crypto-suite names.

View File

@ -96,13 +96,6 @@ public:
MediaFormatAudio() : clockRate(0), channelCount(0), frameTimeUsec(0),
bitsPerSample(0), avgBps(0), maxBps(0)
{}
/**
* Initialization
*/
void init(pj_uint32_t formatId, unsigned clockRate, unsigned channelCount,
int frameTimeUsec, int bitsPerSample,
pj_uint32_t avgBps=0, pj_uint32_t maxBps=0);
};
/**
@ -126,21 +119,6 @@ struct MediaFormatVideo : public MediaFormat
* Export to pjmedia_format.
*/
pjmedia_format toPj() const;
public:
/**
* Default constructor
*/
MediaFormatVideo() : width(0), height(0), fpsNum(0),
fpsDenum(1), avgBps(0), maxBps(0)
{}
/**
* Initialization
*/
void init(pj_uint32_t formatId, unsigned width, unsigned height,
int fpsNum, int fpsDenum=1,
pj_uint32_t avgBps=0, pj_uint32_t maxBps=0);
};
/** Array of MediaFormatAudio */
@ -2048,16 +2026,12 @@ struct VideoPreviewOpParam {
unsigned windowFlags;
/**
* Media format video. By default, this parameter is uninitialized
* and will not be used.
*
* To initialize it, use MediaFormatVideo::init().
* If left uninitialized, the capture device will be opened using
* PJMEDIA wrapper default format, e.g:
* Media format video. If left uninitialized, this parameter will not be used and
* the capture device will be opened using PJMEDIA wrapper default format,
* e.g:
* - Android : PJMEDIA_FORMAT_I420 using the first supported size and 15fps
* - iOS : PJMEDIA_FORMAT_BGRA using size 352x288 and 15fps
* Note that when the preview is already opened, this setting will be
* ignored.
* Note that when the preview is already opened, this setting will be ignored.
*/
MediaFormatVideo format;

View File

@ -174,25 +174,6 @@ struct TlsConfig : public PersistentObject
*/
string privKeyBuf;
/**
* Lookup certificate from OS certificate store, this setting will
* specify the field type to lookup.
*
* Currently only used by Windows Schannel backend, see also
* \a pj_ssl_cert_load_from_store() for more info.
*/
pj_ssl_cert_lookup_type certLookupType;
/**
* Lookup certificate from OS certificate store, this setting will
* specify the keyword to match on the field specified in
* \a certLookupType above.
*
* Currently only used by Windows Schannel backend, see also
* \a pj_ssl_cert_load_from_store() for more info.
*/
string certLookupKeyword;
/**
* TLS protocol method from #pjsip_ssl_method. In the future, this field
* might be deprecated in favor of <b>proto</b> field. For now, this field
@ -395,8 +376,9 @@ struct TransportConfig : public PersistentObject
string boundAddress;
/**
* This specifies TLS settings for TLS transport.
* Its only used when creating a SIP TLS transport.
* This specifies TLS settings for TLS transport. It is only be used
* when this transport config is being used to create a SIP TLS
* transport.
*/
TlsConfig tlsConfig;

View File

@ -1,646 +0,0 @@
/*
* Copyright (C) 2024 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2013 Maxim Kondratenko <max.kondr@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <pjsip-simple/dialog_info.h>
#include <pj/string.h>
#include <pj/pool.h>
#include <pj/assert.h>
static pj_str_t DIALOG_INFO = { "dialog-info", 11 };
static pj_str_t VERSION = { "version", 7 };
static pj_str_t DIALOG = { "dialog", 6};
static pj_str_t STATE = { "state", 5 };
static pj_str_t DURATION = { "duration", 8 };
static pj_str_t ID = { "id", 2 };
static pj_str_t LOCAL = { "local", 5 };
static pj_str_t IDENTITY = { "identity", 8 };
static pj_str_t DISPLAY = { "display", 7 };
static pj_str_t TARGET = { "target", 6 };
static pj_str_t URI = { "uri", 3 };
static pj_str_t REMOTE = { "remote", 6 };
static pj_str_t CALL_ID = { "call-id", 7 };
static pj_str_t ENTITY = { "entity", 6 };
static pj_str_t DIRECTION = { "direction", 9 };
static pj_str_t REMOTE_TAG = { "remote-tag", 10 };
static pj_str_t LOCAL_TAG = { "local-tag", 9 };
static pj_str_t EMPTY_STRING = { NULL, 0 };
/*
static pj_str_t XMLNS = { "xmlns", 5 };
static pj_str_t DIALOG_INFO_XMLNS = {"urn:ietf:params:xml:ns:dialog-info", 34};
*/
static void xml_init_node(pj_pool_t *pool, pj_xml_node *node,
pj_str_t *name, const pj_str_t *value)
{
pj_list_init(&node->attr_head);
pj_list_init(&node->node_head);
node->name = *name;
if (value) pj_strdup(pool, &node->content, value);
else node->content.ptr=NULL, node->content.slen=0;
}
static pj_xml_attr* xml_create_attr(pj_pool_t *pool, pj_str_t *name,
const pj_str_t *value)
{
pj_xml_attr *attr = PJ_POOL_ALLOC_T(pool, pj_xml_attr);
attr->name = *name;
pj_strdup(pool, &attr->value, value);
return attr;
}
/* Remote */
PJ_DEF(void) pjsip_dlg_info_remote_construct(pj_pool_t *pool,
pjsip_dlg_info_remote *remote)
{
pj_xml_node *node;
xml_init_node(pool, remote, &REMOTE, NULL);
node = PJ_POOL_ALLOC_T(pool, pj_xml_node);
xml_init_node(pool, node, NULL, NULL);
pj_xml_add_node(remote, node);
}
PJ_DEF(const pj_str_t *)
pjsip_dlg_info_remote_get_identity(const pjsip_dlg_info_remote *remote)
{
pj_xml_node *node = pj_xml_find_node((pj_xml_node*)remote, &IDENTITY);
if (!node)
return &EMPTY_STRING;
return &node->content;
}
PJ_DEF(void) pjsip_dlg_info_remote_add_identity(pj_pool_t *pool,
pjsip_dlg_info_remote *remote,
const pj_str_t *identity)
{
pj_xml_node *node = pj_xml_find_node((pj_xml_node*)remote, &IDENTITY);
if (!node) {
node = PJ_POOL_ALLOC_T(pool, pj_xml_node);
xml_init_node(pool, node, &IDENTITY, identity);
pj_xml_add_node(remote, node);
} else {
pj_strdup(pool, &node->content, identity);
}
}
PJ_DEF(const pj_str_t *)
pjsip_dlg_info_remote_get_identity_display(const pjsip_dlg_info_remote *remote)
{
pj_xml_node *node = pj_xml_find_node((pj_xml_node*)remote, &IDENTITY);
pj_xml_attr *attr;
if (!node)
return &EMPTY_STRING;
attr = pj_xml_find_attr(node, &DISPLAY, NULL);
if (!attr)
return &EMPTY_STRING;
return &attr->value;
}
PJ_DEF(void)
pjsip_dlg_info_remote_set_identity_display(pj_pool_t *pool,
pjsip_dlg_info_remote *remote,
const pj_str_t *identity_display)
{
pj_xml_node *node = pj_xml_find_node((pj_xml_node*)remote, &IDENTITY);
pj_xml_attr *attr;
if (!node) {
node = PJ_POOL_ALLOC_T(pool, pj_xml_node);
xml_init_node(pool, node, &IDENTITY, NULL);
pj_xml_add_node(remote, node);
}
attr = pj_xml_find_attr(node, &DISPLAY, NULL);
if (!attr) {
attr = xml_create_attr(pool, &DISPLAY, identity_display);
pj_xml_add_attr(node, attr);
} else {
pj_strdup(pool, &attr->value, identity_display);
}
}
PJ_DEF(const pj_str_t *)
pjsip_dlg_info_remote_get_target_uri(const pjsip_dlg_info_remote *remote)
{
pj_xml_node *node = pj_xml_find_node((pj_xml_node*)remote, &TARGET);
pj_xml_attr *attr;
if (!node)
return &EMPTY_STRING;
attr = pj_xml_find_attr(node, &URI, NULL);
if (!attr)
return &EMPTY_STRING;
return &attr->value;
}
PJ_DEF(void)
pjsip_dlg_info_remote_set_target_uri(pj_pool_t *pool,
pjsip_dlg_info_remote *remote,
const pj_str_t * target_uri)
{
pj_xml_node *node = pj_xml_find_node((pj_xml_node*)remote, &TARGET);
pj_xml_attr *attr;
if (!node) {
node = PJ_POOL_ALLOC_T(pool, pj_xml_node);
xml_init_node(pool, node, &TARGET, NULL);
pj_xml_add_node(remote, node);
}
attr = pj_xml_find_attr(node, &URI, NULL);
if (!attr) {
attr = xml_create_attr(pool, &URI, target_uri);
pj_xml_add_attr(node, attr);
} else {
pj_strdup(pool, &attr->value, target_uri);
}
}
/* Local */
PJ_DEF(void) pjsip_dlg_info_local_construct(pj_pool_t *pool,
pjsip_dlg_info_local *local)
{
pj_xml_node *node;
xml_init_node(pool, local, &LOCAL, NULL);
node = PJ_POOL_ALLOC_T(pool, pj_xml_node);
xml_init_node(pool, node, NULL, NULL);
pj_xml_add_node(local, node);
}
PJ_DEF(const pj_str_t *)
pjsip_dlg_info_local_get_identity(const pjsip_dlg_info_local *local)
{
pj_xml_node *node = pj_xml_find_node((pj_xml_node*)local, &IDENTITY);
if (!node)
return &EMPTY_STRING;
return &node->content;
}
PJ_DEF(void) pjsip_dlg_info_local_add_identity(pj_pool_t *pool,
pjsip_dlg_info_local *local,
const pj_str_t *identity)
{
pj_xml_node *node = pj_xml_find_node((pj_xml_node*)local, &IDENTITY);
if (!node) {
node = PJ_POOL_ALLOC_T(pool, pj_xml_node);
xml_init_node(pool, node, &IDENTITY, identity);
pj_xml_add_node(local, node);
} else {
pj_strdup(pool, &node->content, identity);
}
}
PJ_DEF(const pj_str_t *)
pjsip_dlg_info_local_get_identity_display(const pjsip_dlg_info_local *local)
{
pj_xml_node *node = pj_xml_find_node((pj_xml_node*)local, &IDENTITY);
pj_xml_attr *attr;
if (!node)
return &EMPTY_STRING;
attr = pj_xml_find_attr(node, &DISPLAY, NULL);
if (!attr)
return &EMPTY_STRING;
return &attr->value;
}
PJ_DEF(void)
pjsip_dlg_info_local_set_identity_display(pj_pool_t *pool,
pjsip_dlg_info_local *local,
const pj_str_t *identity_display)
{
pj_xml_node *node = pj_xml_find_node((pj_xml_node*)local, &IDENTITY);
pj_xml_attr *attr;
if (!node) {
node = PJ_POOL_ALLOC_T(pool, pj_xml_node);
xml_init_node(pool, node, &IDENTITY, NULL);
pj_xml_add_node(local, node);
}
attr = pj_xml_find_attr(node, &DISPLAY, NULL);
if (!attr) {
attr = xml_create_attr(pool, &DISPLAY, identity_display);
pj_xml_add_attr(node, attr);
} else {
pj_strdup(pool, &attr->value, identity_display);
}
}
PJ_DEF(const pj_str_t *)
pjsip_dlg_info_local_get_target_uri(const pjsip_dlg_info_local *local)
{
pj_xml_node *node = pj_xml_find_node((pj_xml_node*)local, &TARGET);
pj_xml_attr *attr;
if (!node)
return &EMPTY_STRING;
attr = pj_xml_find_attr(node, &URI, NULL);
if (!attr)
return &EMPTY_STRING;
return &attr->value;
}
PJ_DEF(void)
pjsip_dlg_info_local_set_target_uri(pj_pool_t *pool,
pjsip_dlg_info_local *local,
const pj_str_t * target_uri)
{
pj_xml_node *node = pj_xml_find_node((pj_xml_node*)local, &TARGET);
pj_xml_attr *attr;
if (!node) {
node = PJ_POOL_ALLOC_T(pool, pj_xml_node);
xml_init_node(pool, node, &TARGET, NULL);
pj_xml_add_node(local, node);
}
attr = pj_xml_find_attr(node, &URI, NULL);
if (!attr) {
attr = xml_create_attr(pool, &URI, target_uri);
pj_xml_add_attr(node, attr);
} else {
pj_strdup(pool, &attr->value, target_uri);
}
}
/* Dialog */
PJ_DEF(void)
pjsip_dlg_info_dialog_construct(pj_pool_t *pool,
pjsip_dlg_info_dialog *dialog,
const pj_str_t *id)
{
pj_xml_attr *attr;
pjsip_dlg_info_local *local;
pjsip_dlg_info_remote *remote;
xml_init_node(pool, dialog, &DIALOG, NULL);
attr = xml_create_attr(pool, &ID, id);
pj_xml_add_attr(dialog, attr);
local = PJ_POOL_ALLOC_T(pool, pjsip_dlg_info_local);
pjsip_dlg_info_local_construct(pool, local);
pj_xml_add_node(dialog, local);
remote = PJ_POOL_ALLOC_T(pool, pjsip_dlg_info_remote);
pjsip_dlg_info_remote_construct(pool, remote);
pj_xml_add_node(dialog, remote);
}
PJ_DEF(const pj_str_t *)
pjsip_dlg_info_dialog_get_id(const pjsip_dlg_info_dialog *dialog)
{
const pj_xml_attr *attr = pj_xml_find_attr((pj_xml_node*)dialog,
&ID, NULL);
if (!attr)
return &EMPTY_STRING;
return &attr->value;
}
PJ_DEF(void)
pjsip_dlg_info_dialog_set_id(pj_pool_t *pool,
pjsip_dlg_info_dialog *dialog,
const pj_str_t *id)
{
pj_xml_attr *attr = pj_xml_find_attr(dialog, &ID, NULL);
pj_assert(attr);
pj_strdup(pool, &attr->value, id);
}
PJ_DEF(const pj_str_t*)
pjsip_dlg_info_dialog_get_call_id(const pjsip_dlg_info_dialog *dialog)
{
const pj_xml_attr *attr = pj_xml_find_attr((pj_xml_node*)dialog, &CALL_ID,
NULL);
if (attr)
return &attr->value;
return &EMPTY_STRING;
}
PJ_DEF(void)
pjsip_dlg_info_dialog_set_call_id(pj_pool_t *pool,
pjsip_dlg_info_dialog *dialog,
const pj_str_t *call_id)
{
pj_xml_attr *attr = pj_xml_find_attr(dialog, &CALL_ID, NULL);
if (!attr) {
attr = xml_create_attr(pool, &CALL_ID, call_id);
pj_xml_add_attr(dialog, attr);
} else {
pj_strdup(pool, &attr->value, call_id);
}
}
PJ_DEF(const pj_str_t *)
pjsip_dlg_info_dialog_get_remote_tag(const pjsip_dlg_info_dialog *dialog)
{
const pj_xml_attr *attr = pj_xml_find_attr((pj_xml_node*)dialog,
&REMOTE_TAG, NULL);
if (attr)
return &attr->value;
return &EMPTY_STRING;
}
PJ_DEF(void)
pjsip_dlg_info_dialog_set_remote_tag(pj_pool_t *pool,
pjsip_dlg_info_dialog *dialog,
const pj_str_t *remote_tag)
{
pj_xml_attr *attr = pj_xml_find_attr(dialog, &REMOTE_TAG, NULL);
if (!attr) {
attr = xml_create_attr(pool, &REMOTE_TAG, remote_tag);
pj_xml_add_attr(dialog, attr);
} else {
pj_strdup(pool, &attr->value, remote_tag);
}
}
PJ_DEF(const pj_str_t *)
pjsip_dlg_info_dialog_get_local_tag(const pjsip_dlg_info_dialog *dialog)
{
const pj_xml_attr *attr = pj_xml_find_attr((pj_xml_node*)dialog,
&LOCAL_TAG, NULL);
if (attr)
return &attr->value;
return &EMPTY_STRING;
}
PJ_DEF(void) pjsip_dlg_info_dialog_set_local_tag(pj_pool_t *pool,
pjsip_dlg_info_dialog *dialog,
const pj_str_t *local_tag)
{
pj_xml_attr *attr = pj_xml_find_attr(dialog, &LOCAL_TAG, NULL);
if (!attr) {
attr = xml_create_attr(pool, &LOCAL_TAG, local_tag);
pj_xml_add_attr(dialog, attr);
} else {
pj_strdup(pool, &attr->value, local_tag);
}
}
PJ_DEF(const pj_str_t *)
pjsip_dlg_info_dialog_get_direction(const pjsip_dlg_info_dialog *dialog)
{
const pj_xml_attr *attr = pj_xml_find_attr((pj_xml_node*)dialog,
&DIRECTION, NULL);
if (attr)
return &attr->value;
return &EMPTY_STRING;
}
PJ_DEF(void)
pjsip_dlg_info_dialog_set_direction(pj_pool_t *pool,
pjsip_dlg_info_dialog *dialog,
const pj_str_t *direction)
{
pj_xml_attr *attr = pj_xml_find_attr(dialog, &DIRECTION, NULL);
if (!attr) {
attr = xml_create_attr(pool, &DIRECTION, direction);
pj_xml_add_attr(dialog, attr);
} else {
pj_strdup(pool, &attr->value, direction);
}
}
PJ_DEF(const pj_str_t *)
pjsip_dlg_info_dialog_get_state(pjsip_dlg_info_dialog *dialog)
{
pj_xml_node *node = pj_xml_find_node((pj_xml_node*)dialog, &STATE);
if (!node)
return &EMPTY_STRING;
return &node->content;
}
PJ_DEF(void)
pjsip_dlg_info_dialog_set_state(pj_pool_t *pool,
pjsip_dlg_info_dialog *dialog,
const pj_str_t *state)
{
pj_xml_node *node = pj_xml_find_node((pj_xml_node*)dialog, &STATE);
if (!node) {
node = PJ_POOL_ALLOC_T(pool, pj_xml_node);
xml_init_node(pool, node, &STATE, state);
pj_xml_add_node(dialog, node);
} else {
pj_strdup(pool, &node->content, state);
}
}
PJ_DEF(const pj_str_t *)
pjsip_dlg_info_dialog_get_duration(pjsip_dlg_info_dialog *dialog)
{
pj_xml_node *node = pj_xml_find_node((pj_xml_node*)dialog, &DURATION);
if (!node)
return &EMPTY_STRING;
return &node->content;
}
PJ_DEF(void)
pjsip_dlg_info_dialog_set_duration(pj_pool_t *pool,
pjsip_dlg_info_dialog *dialog,
const pj_str_t *duration)
{
pj_xml_node *node = pj_xml_find_node((pj_xml_node*)dialog, &DURATION);
if (!node) {
node = PJ_POOL_ALLOC_T(pool, pj_xml_node);
xml_init_node(pool, node, &DURATION, duration);
pj_xml_add_node(dialog, node);
} else {
pj_strdup(pool, &node->content, duration);
}
}
PJ_DEF(pjsip_dlg_info_local *)
pjsip_dlg_info_dialog_get_local(pjsip_dlg_info_dialog *dialog)
{
pjsip_dlg_info_local *local = (pjsip_dlg_info_local*)
pj_xml_find_node(dialog, &LOCAL);
if (local)
return local;
return NULL;
}
PJ_DEF(pjsip_dlg_info_local *)
pjsip_dlg_info_dialog_add_local(pj_pool_t *pool,
pjsip_dlg_info_dialog *dialog)
{
pjsip_dlg_info_local *local = PJ_POOL_ALLOC_T(pool, pjsip_dlg_info_local);
xml_init_node(pool, local, &LOCAL, NULL);
pj_xml_add_node(dialog, local);
return local;
}
PJ_DEF(pjsip_dlg_info_remote *)
pjsip_dlg_info_dialog_get_remote(pjsip_dlg_info_dialog *dialog)
{
pjsip_dlg_info_remote *remote = (pjsip_dlg_info_remote*)
pj_xml_find_node(dialog, &REMOTE);
if (remote)
return remote;
return NULL;
}
PJ_DEF(pjsip_dlg_info_remote *)
pjsip_dlg_info_dialog_add_remote(pj_pool_t *pool,
pjsip_dlg_info_dialog *dialog)
{
pjsip_dlg_info_remote *remote = PJ_POOL_ALLOC_T(pool,
pjsip_dlg_info_remote);
xml_init_node(pool, remote, &REMOTE, NULL);
pj_xml_add_node(dialog, remote);
return remote;
}
/* Dialog-Info */
PJ_DEF(void)
pjsip_dlg_info_dialog_info_construct(pj_pool_t *pool,
pjsip_dlg_info_dialog_info *dialog_info,
const pj_str_t *version,
const pj_str_t *state,
const pj_str_t* entity)
{
pj_xml_attr *attr;
pjsip_dlg_info_dialog *dialog;
xml_init_node(pool, dialog_info, &DIALOG_INFO, NULL);
attr = xml_create_attr(pool, &VERSION, version);
pj_xml_add_attr(dialog_info, attr);
attr = xml_create_attr(pool, &STATE, state);
pj_xml_add_attr(dialog_info, attr);
attr = xml_create_attr(pool, &ENTITY, entity);
pj_xml_add_attr(dialog_info, attr);
dialog = PJ_POOL_ALLOC_T(pool, pjsip_dlg_info_dialog);
pjsip_dlg_info_local_construct(pool, dialog);
pj_xml_add_node(dialog_info, dialog);
}
PJ_DEF(const pj_str_t *)
pjsip_dlg_info_dialog_info_get_state(pjsip_dlg_info_dialog_info *dialog_info)
{
const pj_xml_attr *attr = pj_xml_find_attr((pj_xml_node*)dialog_info,
&STATE, NULL);
if (!attr)
return &EMPTY_STRING;
return &attr->value;
}
PJ_DEF(void)
pjsip_dlg_info_dialog_info_set_state(pj_pool_t *pool,
pjsip_dlg_info_dialog_info *dialog_info,
const pj_str_t *state)
{
pj_xml_attr *attr = pj_xml_find_attr(dialog_info, &STATE, NULL);
pj_assert(attr);
pj_strdup(pool, &attr->value, state);
}
PJ_DEF(const pj_str_t *)
pjsip_dlg_info_dialog_info_get_version(pjsip_dlg_info_dialog_info *dialog_info)
{
const pj_xml_attr *attr = pj_xml_find_attr((pj_xml_node*)dialog_info,
&VERSION, NULL);
if (!attr)
return &EMPTY_STRING;
return &attr->value;
}
PJ_DEF(void)
pjsip_dlg_info_dialog_info_set_version(pj_pool_t *pool,
pjsip_dlg_info_dialog_info *dialog_info,
const pj_str_t *version)
{
pj_xml_attr *attr = pj_xml_find_attr(dialog_info, &VERSION, NULL);
pj_assert(attr);
pj_strdup(pool, &attr->value, version);
}
PJ_DEF(const pj_str_t *)
pjsip_dlg_info_dialog_info_get_entity(pjsip_dlg_info_dialog_info *dialog_info)
{
const pj_xml_attr *attr = pj_xml_find_attr((pj_xml_node*)dialog_info,
&ENTITY, NULL);
if (!attr)
return &EMPTY_STRING;
return &attr->value;
}
PJ_DEF(void)
pjsip_dlg_info_dialog_info_set_entity(pj_pool_t *pool,
pjsip_dlg_info_dialog_info *dialog_info,
const pj_str_t *entity)
{
pj_xml_attr *attr = pj_xml_find_attr(dialog_info, &ENTITY, NULL);
pj_assert(attr);
pj_strdup(pool, &attr->value, entity);
}
PJ_DEF(pjsip_dlg_info_dialog *)
pjsip_dlg_info_dialog_info_get_dialog(pjsip_dlg_info_dialog_info *dialog_info)
{
pjsip_dlg_info_dialog *dialog = (pjsip_dlg_info_dialog*)
pj_xml_find_node(dialog_info, &DIALOG);
return dialog;
}
PJ_DEF(pjsip_dlg_info_dialog *)
pjsip_dlg_info_dialog_info_add_dialog(pj_pool_t *pool,
pjsip_dlg_info_dialog_info *dialog_info,
const pj_str_t *id)
{
pjsip_dlg_info_dialog *dialog = PJ_POOL_ALLOC_T(pool,
pjsip_dlg_info_dialog);
pjsip_dlg_info_dialog_construct(pool, dialog, id);
pj_xml_add_node(dialog_info, dialog);
return dialog;
}
/* Dialog-Info document */
PJ_DEF(pjsip_dlg_info_dialog *)
pjsip_dlg_info_create(pj_pool_t *pool, const pj_str_t *version,
const pj_str_t *state, const pj_str_t *entity)
{
pjsip_dlg_info_dialog *dialog_info;
dialog_info = PJ_POOL_ALLOC_T(pool, pjsip_dlg_info_dialog);
pjsip_dlg_info_dialog_info_construct(pool, dialog_info, version,
state, entity);
return dialog_info;
}
PJ_DEF(pjsip_dlg_info_dialog *) pjsip_dlg_info_parse(pj_pool_t *pool,
char *text,
int len)
{
pjsip_dlg_info_dialog *dialog_info = pj_xml_parse(pool, text, len);
if (dialog_info) {
if (pj_stricmp(&dialog_info->name, &DIALOG_INFO) == 0)
return dialog_info;
}
return NULL;
}
PJ_DEF(int) pjsip_dlg_info_print(const pjsip_dlg_info_dialog *dialog_info,
char *buf, int len)
{
return pj_xml_print(dialog_info, buf, len, PJ_TRUE);
}

View File

@ -1,630 +0,0 @@
/*
* Copyright (C) 2024 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2013 Maxim Kondratenko <max.kondr@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <pjsip-simple/dlg_event.h>
#include <pjsip-simple/errno.h>
#include <pjsip-simple/evsub_msg.h>
#include <pjsip/sip_module.h>
#include <pjsip/sip_multipart.h>
#include <pjsip/sip_endpoint.h>
#include <pjsip/sip_dialog.h>
#include <pj/assert.h>
#include <pj/guid.h>
#include <pj/log.h>
#include <pj/os.h>
#include <pj/pool.h>
#include <pj/string.h>
#define THIS_FILE "dlg_event.c"
#define DLG_EVENT_DEFAULT_EXPIRES PJSIP_DLG_EVENT_DEFAULT_EXPIRES
#if PJSIP_DLG_EVENT_BAD_CONTENT_RESPONSE < 200 || \
PJSIP_DLG_EVENT_BAD_CONTENT_RESPONSE > 699 || \
PJSIP_DLG_EVENT_BAD_CONTENT_RESPONSE/100 == 3
# error Invalid PJSIP_DLG_EVENT_BAD_CONTENT_RESPONSE value
#endif
/*
* Dialog event module (mod-dlg_event)
*/
static struct pjsip_module mod_dlg_event =
{
NULL, NULL, /* prev, next. */
{ "mod-dlg_event", 12 }, /* Name. */
-1, /* Id */
PJSIP_MOD_PRIORITY_DIALOG_USAGE,/* Priority */
NULL, /* load() */
NULL, /* start() */
NULL, /* stop() */
NULL, /* unload() */
NULL, /* on_rx_request() */
NULL, /* on_rx_response() */
NULL, /* on_tx_request. */
NULL, /* on_tx_response() */
NULL, /* on_tsx_state() */
};
/*
* Dialog event message body type.
*/
typedef enum content_type_e
{
CONTENT_TYPE_NONE,
CONTENT_TYPE_DIALOG_INFO,
} content_type_e;
/*
* This structure describe an entity, for both subscriber and notifier.
*/
struct pjsip_dlg_event
{
pjsip_evsub *sub; /**< Event subscription record. */
pjsip_dialog *dlg; /**< The dialog. */
content_type_e content_type; /**< Content-Type. */
pj_pool_t *status_pool; /**< Pool for dlgev_status */
pjsip_dlg_event_status status; /**< Dialog event status. */
pj_pool_t *tmp_pool; /**< Pool for tmp_status */
pjsip_dlg_event_status tmp_status; /**< Temp, before NOTIFY is answered */
pj_bool_t is_ts_valid; /**< Is tmp_status valid? */
pjsip_evsub_user user_cb; /**< The user callback. */
pj_mutex_t *mutex; /**< Mutex */
};
typedef struct pjsip_dlg_event pjsip_dlg_event;
/*
* Forward decl for evsub callback.
*/
static void dlg_event_on_evsub_state(pjsip_evsub *sub, pjsip_event *event);
static void dlg_event_on_evsub_tsx_state(pjsip_evsub *sub, pjsip_transaction *tsx,
pjsip_event *event);
static void dlg_event_on_evsub_rx_notify(pjsip_evsub *sub,
pjsip_rx_data *rdata,
int *p_st_code,
pj_str_t **p_st_text,
pjsip_hdr *res_hdr,
pjsip_msg_body **p_body);
static void dlg_event_on_evsub_client_refresh(pjsip_evsub *sub);
/*
* Event subscription callback for dialog event.
*/
static pjsip_evsub_user dlg_event_user =
{
&dlg_event_on_evsub_state,
&dlg_event_on_evsub_tsx_state,
NULL,
&dlg_event_on_evsub_rx_notify,
&dlg_event_on_evsub_client_refresh,
NULL,
};
/*
* Some static constants.
*/
const pj_str_t STR_DIALOG_EVENT = { "Event", 5 };
const pj_str_t STR_DIALOG = { "dialog", 6 };
const pj_str_t STR_DIALOG_APPLICATION = { "application", 11 };
const pj_str_t STR_DIALOG_INFO_XML = { "dialog-info+xml", 15 };
const pj_str_t STR_APP_DIALOG_INFO_XML = { "application/dialog-info+xml", 27 };
/*
* Init dialog event module.
*/
PJ_DEF(pj_status_t) pjsip_dlg_event_init_module(pjsip_endpoint *endpt,
pjsip_module *mod_evsub)
{
pj_status_t status;
pj_str_t accept[1];
/* Check arguments. */
PJ_ASSERT_RETURN(endpt && mod_evsub, PJ_EINVAL);
/* Must have not been registered */
PJ_ASSERT_RETURN(mod_dlg_event.id == -1, PJ_EINVALIDOP);
/* Register to endpoint */
status = pjsip_endpt_register_module(endpt, &mod_dlg_event);
if (status != PJ_SUCCESS)
return status;
accept[0] = STR_APP_DIALOG_INFO_XML;
/* Register event package to event module. */
status = pjsip_evsub_register_pkg(&mod_dlg_event, &STR_DIALOG,
DLG_EVENT_DEFAULT_EXPIRES,
PJ_ARRAY_SIZE(accept), accept);
if (status != PJ_SUCCESS) {
pjsip_endpt_unregister_module(endpt, &mod_dlg_event);
return status;
}
return PJ_SUCCESS;
}
/*
* Get dialog event module instance.
*/
PJ_DEF(pjsip_module*) pjsip_dlg_event_instance(void)
{
return &mod_dlg_event;
}
/*
* Create client subscription.
*/
PJ_DEF(pj_status_t)
pjsip_dlg_event_create_uac(pjsip_dialog *dlg,
const pjsip_evsub_user *user_cb,
unsigned options,
pjsip_evsub **p_evsub)
{
pj_status_t status;
pjsip_dlg_event *dlgev;
char obj_name[PJ_MAX_OBJ_NAME];
pjsip_evsub *sub;
PJ_ASSERT_RETURN(dlg && p_evsub, PJ_EINVAL);
pjsip_dlg_inc_lock(dlg);
/* Create event subscription */
status = pjsip_evsub_create_uac(dlg, &dlg_event_user, &STR_DIALOG,
options, &sub);
if (status != PJ_SUCCESS)
goto on_return;
/* Create dialog event */
dlgev = PJ_POOL_ZALLOC_T(dlg->pool, pjsip_dlg_event);
dlgev->dlg = dlg;
dlgev->sub = sub;
if (user_cb)
pj_memcpy(&dlgev->user_cb, user_cb, sizeof(pjsip_evsub_user));
status = pj_mutex_create_recursive(dlg->pool, "dlgev_mutex",
&dlgev->mutex);
if (status != PJ_SUCCESS)
goto on_return;
pj_ansi_snprintf(obj_name, PJ_MAX_OBJ_NAME, "dlgev%p", dlg->pool);
dlgev->status_pool = pj_pool_create(dlg->pool->factory, obj_name,
512, 512, NULL);
pj_ansi_snprintf(obj_name, PJ_MAX_OBJ_NAME, "tmdlgev%p", dlg->pool);
dlgev->tmp_pool = pj_pool_create(dlg->pool->factory, obj_name,
512, 512, NULL);
/* Attach to evsub */
pjsip_evsub_set_mod_data(sub, mod_dlg_event.id, dlgev);
*p_evsub = sub;
on_return:
pjsip_dlg_dec_lock(dlg);
return status;
}
/*
* Forcefully terminate dialog event.
*/
PJ_DEF(pj_status_t) pjsip_dlg_event_terminate(pjsip_evsub *sub,
pj_bool_t notify)
{
return pjsip_evsub_terminate(sub, notify);
}
/*
* Create SUBSCRIBE
*/
PJ_DEF(pj_status_t) pjsip_dlg_event_initiate(pjsip_evsub *sub,
pj_int32_t expires,
pjsip_tx_data **p_tdata)
{
return pjsip_evsub_initiate(sub, &pjsip_subscribe_method, expires,
p_tdata);
}
/*
* Add custom headers.
*/
PJ_DEF(pj_status_t) pjsip_dlg_event_add_header(pjsip_evsub *sub,
const pjsip_hdr *hdr_list )
{
return pjsip_evsub_add_header( sub, hdr_list );
}
/*
* Accept incoming subscription.
*/
PJ_DEF(pj_status_t) pjsip_dlg_event_accept(pjsip_evsub *sub,
pjsip_rx_data *rdata,
int st_code,
const pjsip_hdr *hdr_list)
{
return pjsip_evsub_accept( sub, rdata, st_code, hdr_list );
}
/*
* Get dialog event status.
*/
PJ_DEF(pj_status_t) pjsip_dlg_event_get_status(pjsip_evsub *sub,
pjsip_dlg_event_status *status)
{
pjsip_dlg_event *dlgev;
PJ_ASSERT_RETURN(sub && status, PJ_EINVAL);
dlgev = (pjsip_dlg_event*) pjsip_evsub_get_mod_data(sub, mod_dlg_event.id);
PJ_ASSERT_RETURN(dlgev!=NULL, PJSIP_SIMPLE_ENOPRESENCE);
pj_mutex_lock(dlgev->mutex);
if (dlgev->is_ts_valid) {
PJ_ASSERT_ON_FAIL(dlgev->tmp_pool!=NULL,
{pj_mutex_unlock(dlgev->mutex);
return PJSIP_SIMPLE_ENOPRESENCE;});
pj_memcpy(status, &dlgev->tmp_status, sizeof(pjsip_dlg_event_status));
} else {
PJ_ASSERT_ON_FAIL(dlgev->status_pool!=NULL,
{pj_mutex_unlock(dlgev->mutex);
return PJSIP_SIMPLE_ENOPRESENCE;});
pj_memcpy(status, &dlgev->status, sizeof(pjsip_dlg_event_status));
}
pj_mutex_unlock(dlgev->mutex);
return PJ_SUCCESS;
}
/*
* Send request.
*/
PJ_DEF(pj_status_t) pjsip_dlg_event_send_request(pjsip_evsub *sub,
pjsip_tx_data *tdata )
{
return pjsip_evsub_send_request(sub, tdata);
}
PJ_DEF(pj_status_t)
pjsip_dlg_event_parse_dialog_info(pjsip_rx_data *rdata,
pj_pool_t *pool,
pjsip_dlg_event_status *dlgev_st)
{
return pjsip_dlg_event_parse_dialog_info2(
(char*)rdata->msg_info.msg->body->data,
rdata->msg_info.msg->body->len,
pool, dlgev_st);
}
PJ_DEF(pj_status_t)
pjsip_dlg_event_parse_dialog_info2(char *body, unsigned body_len,
pj_pool_t *pool,
pjsip_dlg_event_status *dlgev_st)
{
pjsip_dlg_info_dialog_info *dialog_info;
pjsip_dlg_info_dialog *dialog;
dialog_info = pjsip_dlg_info_parse(pool, body, body_len);
if (dialog_info == NULL)
return PJSIP_SIMPLE_EBADPIDF;
dlgev_st->info_cnt = 0;
dialog = pjsip_dlg_info_dialog_info_get_dialog(dialog_info);
pj_strdup(pool, &dlgev_st->info[dlgev_st->info_cnt].dialog_info_entity,
pjsip_dlg_info_dialog_info_get_entity(dialog_info));
pj_strdup(pool, &dlgev_st->info[dlgev_st->info_cnt].dialog_info_state,
pjsip_dlg_info_dialog_info_get_state(dialog_info));
if (dialog) {
pjsip_dlg_info_local * local;
pjsip_dlg_info_remote * remote;
dlgev_st->info[dlgev_st->info_cnt].dialog_node =
pj_xml_clone(pool, dialog);
pj_strdup(pool, &dlgev_st->info[dlgev_st->info_cnt].dialog_id,
pjsip_dlg_info_dialog_get_id(dialog));
pj_strdup(pool, &dlgev_st->info[dlgev_st->info_cnt].dialog_call_id,
pjsip_dlg_info_dialog_get_call_id(dialog));
pj_strdup(pool, &dlgev_st->info[dlgev_st->info_cnt].dialog_remote_tag,
pjsip_dlg_info_dialog_get_remote_tag(dialog));
pj_strdup(pool, &dlgev_st->info[dlgev_st->info_cnt].dialog_local_tag,
pjsip_dlg_info_dialog_get_local_tag(dialog));
pj_strdup(pool, &dlgev_st->info[dlgev_st->info_cnt].dialog_direction,
pjsip_dlg_info_dialog_get_direction(dialog));
pj_strdup(pool, &dlgev_st->info[dlgev_st->info_cnt].dialog_state,
pjsip_dlg_info_dialog_get_state(dialog));
pj_strdup(pool, &dlgev_st->info[dlgev_st->info_cnt].dialog_duration,
pjsip_dlg_info_dialog_get_duration(dialog));
local =pjsip_dlg_info_dialog_get_local(dialog);
if (local) {
pj_strdup(pool, &dlgev_st->info[dlgev_st->info_cnt].local_identity,
pjsip_dlg_info_local_get_identity(local));
pj_strdup(pool,
&dlgev_st->info[dlgev_st->info_cnt].local_identity_display,
pjsip_dlg_info_local_get_identity_display(local));
pj_strdup(pool,
&dlgev_st->info[dlgev_st->info_cnt].local_target_uri,
pjsip_dlg_info_local_get_target_uri(local));
} else {
dlgev_st->info[dlgev_st->info_cnt].local_identity.ptr = NULL;
dlgev_st->info[dlgev_st->info_cnt].local_identity_display.ptr =
NULL;
dlgev_st->info[dlgev_st->info_cnt].local_target_uri.ptr = NULL;
}
remote = pjsip_dlg_info_dialog_get_remote(dialog);
if (remote) {
pj_strdup(pool, &dlgev_st->info[dlgev_st->info_cnt].remote_identity,
pjsip_dlg_info_remote_get_identity(remote));
pj_strdup(pool,
&dlgev_st->info[dlgev_st->info_cnt].remote_identity_display,
pjsip_dlg_info_remote_get_identity_display(remote));
pj_strdup(pool,
&dlgev_st->info[dlgev_st->info_cnt].remote_target_uri,
pjsip_dlg_info_remote_get_target_uri(remote));
} else {
dlgev_st->info[dlgev_st->info_cnt].remote_identity.ptr = NULL;
dlgev_st->info[dlgev_st->info_cnt].remote_identity_display.ptr =
NULL;
dlgev_st->info[dlgev_st->info_cnt].remote_target_uri.ptr = NULL;
}
} else {
dlgev_st->info[dlgev_st->info_cnt].dialog_node = NULL;
}
return PJ_SUCCESS;
}
/*
* This callback is called by event subscription when subscription
* state has changed.
*/
static void dlg_event_on_evsub_state( pjsip_evsub *sub, pjsip_event *event)
{
pjsip_dlg_event *dlgev;
dlgev = (pjsip_dlg_event*) pjsip_evsub_get_mod_data(sub, mod_dlg_event.id);
PJ_ASSERT_ON_FAIL(dlgev!=NULL, {return;});
if (dlgev->user_cb.on_evsub_state)
(*dlgev->user_cb.on_evsub_state)(sub, event);
if (pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_TERMINATED) {
if (dlgev->status_pool) {
pj_pool_release(dlgev->status_pool);
dlgev->status_pool = NULL;
}
if (dlgev->tmp_pool) {
pj_pool_release(dlgev->tmp_pool);
dlgev->tmp_pool = NULL;
}
if (dlgev->mutex) {
pj_mutex_destroy(dlgev->mutex);
dlgev->mutex = NULL;
}
}
}
/*
* Called when transaction state has changed.
*/
static void dlg_event_on_evsub_tsx_state(pjsip_evsub *sub,
pjsip_transaction *tsx,
pjsip_event *event)
{
pjsip_dlg_event *dlgev;
dlgev = (pjsip_dlg_event*) pjsip_evsub_get_mod_data(sub, mod_dlg_event.id);
PJ_ASSERT_ON_FAIL(dlgev!=NULL, {return;});
if (dlgev->user_cb.on_tsx_state)
(*dlgev->user_cb.on_tsx_state)(sub, tsx, event);
}
/*
* Process the content of incoming NOTIFY request and update temporary
* status.
*
* return PJ_SUCCESS if incoming request is acceptable. If return value
* is not PJ_SUCCESS, res_hdr may be added with Warning header.
*/
static pj_status_t
dlg_event_process_rx_notify(pjsip_dlg_event *dlgev,
pjsip_rx_data *rdata,
int *p_st_code,
pj_str_t **p_st_text,
pjsip_hdr *res_hdr)
{
pjsip_ctype_hdr *ctype_hdr;
pj_status_t status = PJ_SUCCESS;
*p_st_text = NULL;
/* Check Content-Type and msg body are dlgevent. */
ctype_hdr = rdata->msg_info.ctype;
if (ctype_hdr==NULL || rdata->msg_info.msg->body==NULL)
{
pjsip_warning_hdr *warn_hdr;
pj_str_t warn_text;
*p_st_code = PJSIP_SC_BAD_REQUEST;
warn_text = pj_str("Message body is not dlgevent");
warn_hdr = pjsip_warning_hdr_create(rdata->tp_info.pool, 399,
pjsip_endpt_name(dlgev->dlg->endpt),
&warn_text);
pj_list_push_back(res_hdr, warn_hdr);
return PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_BAD_REQUEST);
}
/* Parse content. */
if (pj_stricmp(&ctype_hdr->media.type, &STR_DIALOG_APPLICATION)==0 &&
pj_stricmp(&ctype_hdr->media.subtype, &STR_DIALOG_INFO_XML)==0)
{
status = pjsip_dlg_event_parse_dialog_info(rdata, dlgev->tmp_pool,
&dlgev->tmp_status);
}
else {
status = PJSIP_SIMPLE_EBADCONTENT;
}
/* If application calls dlgev_get_status(), redirect the call to
* retrieve the temporary status.
*/
dlgev->is_ts_valid = (status == PJ_SUCCESS? PJ_TRUE: PJ_FALSE);
if (status != PJ_SUCCESS) {
/* Unsupported or bad Content-Type */
if (PJSIP_DLG_EVENT_BAD_CONTENT_RESPONSE >= 300) {
pjsip_accept_hdr *accept_hdr;
pjsip_warning_hdr *warn_hdr;
*p_st_code = PJSIP_DLG_EVENT_BAD_CONTENT_RESPONSE;
/* Add Accept header */
accept_hdr = pjsip_accept_hdr_create(rdata->tp_info.pool);
accept_hdr->values[accept_hdr->count++] = STR_APP_DIALOG_INFO_XML;
pj_list_push_back(res_hdr, accept_hdr);
/* Add Warning header */
warn_hdr = pjsip_warning_hdr_create_from_status(
rdata->tp_info.pool,
pjsip_endpt_name(dlgev->dlg->endpt),
status);
pj_list_push_back(res_hdr, warn_hdr);
return status;
} else {
pj_assert(PJSIP_DLG_EVENT_BAD_CONTENT_RESPONSE/100 == 2);
PJ_PERROR(4,(THIS_FILE, status,
"Ignoring dlgev error due to "
"PJSIP_DLG_EVENT_BAD_CONTENT_RESPONSE setting [%d]",
PJSIP_DLG_EVENT_BAD_CONTENT_RESPONSE));
*p_st_code = PJSIP_DLG_EVENT_BAD_CONTENT_RESPONSE;
status = PJ_SUCCESS;
}
}
return PJ_SUCCESS;
}
/*
* Called when NOTIFY is received.
*/
static void dlg_event_on_evsub_rx_notify(pjsip_evsub *sub,
pjsip_rx_data *rdata,
int *p_st_code,
pj_str_t **p_st_text,
pjsip_hdr *res_hdr,
pjsip_msg_body **p_body)
{
pjsip_dlg_event *dlgev;
pj_status_t status;
dlgev = (pjsip_dlg_event*) pjsip_evsub_get_mod_data(sub, mod_dlg_event.id);
PJ_ASSERT_ON_FAIL(dlgev!=NULL, {return;});
if (rdata->msg_info.msg->body) {
status = dlg_event_process_rx_notify( dlgev, rdata, p_st_code, p_st_text,
res_hdr );
if (status != PJ_SUCCESS)
return;
} else {
unsigned i;
pj_mutex_lock(dlgev->mutex);
for (i=0; i<dlgev->status.info_cnt; ++i) {
dlgev->status.info[i].dialog_node = NULL;
}
pj_mutex_unlock(dlgev->mutex);
}
/* Notify application. */
if (dlgev->user_cb.on_rx_notify) {
(*dlgev->user_cb.on_rx_notify)(sub, rdata, p_st_code, p_st_text,
res_hdr, p_body);
}
/* If application responded NOTIFY with 2xx, copy temporary status
* to main status, and mark the temporary status as invalid.
*/
pj_mutex_lock(dlgev->mutex);
if ((*p_st_code)/100 == 2) {
pj_pool_t *tmp;
pj_memcpy(&dlgev->status, &dlgev->tmp_status,
sizeof(pjsip_dlg_event_status));
/* Swap the pool */
tmp = dlgev->tmp_pool;
dlgev->tmp_pool = dlgev->status_pool;
dlgev->status_pool = tmp;
}
dlgev->is_ts_valid = PJ_FALSE;
pj_pool_reset(dlgev->tmp_pool);
pj_mutex_unlock(dlgev->mutex);
/* Done */
}
/*
* Called when it's time to send SUBSCRIBE.
*/
static void dlg_event_on_evsub_client_refresh(pjsip_evsub *sub)
{
pjsip_dlg_event *dlgev;
dlgev = (pjsip_dlg_event*) pjsip_evsub_get_mod_data(sub, mod_dlg_event.id);
PJ_ASSERT_ON_FAIL(dlgev!=NULL, {return;});
if (dlgev->user_cb.on_client_refresh) {
(*dlgev->user_cb.on_client_refresh)(sub);
} else {
pj_status_t status;
pjsip_tx_data *tdata;
status = pjsip_dlg_event_initiate(sub, -1, &tdata);
if (status == PJ_SUCCESS)
pjsip_dlg_event_send_request(sub, tdata);
}
}

View File

@ -83,9 +83,7 @@ struct pjsip_pres
pjsip_pres_status status; /**< Presence status. */
pj_pool_t *tmp_pool; /**< Pool for tmp_status */
pjsip_pres_status tmp_status; /**< Temp, before NOTIFY is answred.*/
pj_bool_t is_ts_valid; /**< Is tmp_status valid? */
pjsip_evsub_user user_cb; /**< The user callback. */
pj_mutex_t *mutex; /**< Mutex. */
};
@ -215,11 +213,6 @@ PJ_DEF(pj_status_t) pjsip_pres_create_uac( pjsip_dialog *dlg,
if (user_cb)
pj_memcpy(&pres->user_cb, user_cb, sizeof(pjsip_evsub_user));
status = pj_mutex_create_recursive(dlg->pool, "pres_mutex",
&pres->mutex);
if (status != PJ_SUCCESS)
goto on_return;
pj_ansi_snprintf(obj_name, PJ_MAX_OBJ_NAME, "pres%p", dlg->pool);
pres->status_pool = pj_pool_create(dlg->pool->factory, obj_name,
512, 512, NULL);
@ -396,24 +389,14 @@ PJ_DEF(pj_status_t) pjsip_pres_get_status( pjsip_evsub *sub,
pres = (pjsip_pres*) pjsip_evsub_get_mod_data(sub, mod_presence.id);
PJ_ASSERT_RETURN(pres!=NULL, PJSIP_SIMPLE_ENOPRESENCE);
if (pres->mutex)
pj_mutex_lock(pres->mutex);
if (pres->is_ts_valid) {
PJ_ASSERT_ON_FAIL(pres->tmp_pool!=NULL,
{if (pres->mutex) pj_mutex_unlock(pres->mutex);
return PJSIP_SIMPLE_ENOPRESENCE;});
if (pres->tmp_status._is_valid) {
PJ_ASSERT_RETURN(pres->tmp_pool!=NULL, PJSIP_SIMPLE_ENOPRESENCE);
pj_memcpy(status, &pres->tmp_status, sizeof(pjsip_pres_status));
} else {
PJ_ASSERT_ON_FAIL(pres->status_pool!=NULL,
{if (pres->mutex) pj_mutex_unlock(pres->mutex);
return PJSIP_SIMPLE_ENOPRESENCE;});
PJ_ASSERT_RETURN(pres->status_pool!=NULL, PJSIP_SIMPLE_ENOPRESENCE);
pj_memcpy(status, &pres->status, sizeof(pjsip_pres_status));
}
if (pres->mutex)
pj_mutex_unlock(pres->mutex);
return PJ_SUCCESS;
}
@ -645,10 +628,6 @@ static void pres_on_evsub_state( pjsip_evsub *sub, pjsip_event *event)
pj_pool_release(pres->tmp_pool);
pres->tmp_pool = NULL;
}
if (pres->mutex) {
pj_mutex_destroy(pres->mutex);
pres->mutex = NULL;
}
}
}
@ -793,11 +772,6 @@ static pj_status_t pres_process_rx_notify( pjsip_pres *pres,
status = PJSIP_SIMPLE_EBADCONTENT;
}
/* If application calls pres_get_status(), redirect the call to
* retrieve the temporary status.
*/
pres->is_ts_valid = (status == PJ_SUCCESS? PJ_TRUE: PJ_FALSE);
if (status != PJ_SUCCESS) {
/* Unsupported or bad Content-Type */
if (PJSIP_PRES_BAD_CONTENT_RESPONSE >= 300) {
@ -831,6 +805,11 @@ static pj_status_t pres_process_rx_notify( pjsip_pres *pres,
}
}
/* If application calls pres_get_status(), redirect the call to
* retrieve the temporary status.
*/
pres->tmp_status._is_valid = PJ_TRUE;
return PJ_SUCCESS;
}
@ -866,11 +845,10 @@ static void pres_on_evsub_rx_notify( pjsip_evsub *sub,
* "tuple_node" in pjsip_pres_status to NULL.
*/
unsigned i;
pj_mutex_lock(pres->mutex);
for (i=0; i<pres->status.info_cnt; ++i) {
pres->status.info[i].tuple_node = NULL;
}
pj_mutex_unlock(pres->mutex);
#elif 0
/* This has just been changed. Previously, we treat incoming NOTIFY
* with no message body as having the presence subscription closed.
@ -881,7 +859,7 @@ static void pres_on_evsub_rx_notify( pjsip_evsub *sub,
#else
unsigned i;
/* Subscription is terminated. Consider contact is offline */
pres->is_ts_valid = PJ_TRUE;
pres->tmp_status._is_valid = PJ_TRUE;
for (i=0; i<pres->tmp_status.info_cnt; ++i)
pres->tmp_status.info[i].basic_open = PJ_FALSE;
#endif
@ -897,8 +875,6 @@ static void pres_on_evsub_rx_notify( pjsip_evsub *sub,
/* If application responded NOTIFY with 2xx, copy temporary status
* to main status, and mark the temporary status as invalid.
*/
pj_mutex_lock(pres->mutex);
if ((*p_st_code)/100 == 2) {
pj_pool_t *tmp;
@ -910,11 +886,9 @@ static void pres_on_evsub_rx_notify( pjsip_evsub *sub,
pres->status_pool = tmp;
}
pres->is_ts_valid = PJ_FALSE;
pres->tmp_status._is_valid = PJ_FALSE;
pj_pool_reset(pres->tmp_pool);
pj_mutex_unlock(pres->mutex);
/* Done */
}

View File

@ -474,8 +474,6 @@ pj_status_t create_uas_dialog( pjsip_user_agent *ua,
if (rdata->tp_info.transport->dir == PJSIP_TP_DIR_OUTGOING) {
pj_strdup(dlg->pool, &dlg->initial_dest,
&rdata->tp_info.transport->remote_name.host);
PJ_LOG(5, (THIS_FILE, "Saving initial dest %.*s",
(int)dlg->initial_dest.slen, dlg->initial_dest.ptr));
}
/* Init remote's contact from Contact header.
@ -1224,11 +1222,8 @@ static pj_status_t dlg_create_request_throw( pjsip_dialog *dlg,
/* Copy the initial destination host to tdata. This information can be
* used later by transport for transport selection.
*/
if (dlg->initial_dest.slen) {
if (dlg->initial_dest.slen)
pj_strdup(tdata->pool, &tdata->dest_info.name, &dlg->initial_dest);
PJ_LOG(5, (THIS_FILE, "Setting initial dest %.*s",
(int)dlg->initial_dest.slen, dlg->initial_dest.ptr));
}
/* Done. */
*p_tdata = tdata;
@ -1883,8 +1878,6 @@ static void dlg_update_routeset(pjsip_dialog *dlg, const pjsip_rx_data *rdata)
{
pj_strdup(dlg->pool, &dlg->initial_dest,
&rdata->tp_info.transport->remote_name.host);
PJ_LOG(5, (THIS_FILE, "Saving initial dest %.*s",
(int)dlg->initial_dest.slen, dlg->initial_dest.ptr));
} else {
/* Reset the stored remote name if the transport is a server
* transport.

View File

@ -2221,13 +2221,6 @@ static void send_msg_callback( pjsip_send_state *send_state,
tsx_set_state( tsx, PJSIP_TSX_STATE_DESTROYED,
PJSIP_EVENT_TRANSPORT_ERROR,
send_state->tdata, 0);
} else if (tsx->role == PJSIP_ROLE_UAS &&
tsx->transport_flag & TSX_HAS_PENDING_RESCHED &&
tsx->state != PJSIP_TSX_STATE_TERMINATED &&
tsx->state != PJSIP_TSX_STATE_DESTROYED)
{
tsx->transport_flag &= ~(TSX_HAS_PENDING_RESCHED);
tsx_resched_retransmission(tsx);
}
} else {

View File

@ -877,12 +877,6 @@ static void transport_send_callback(pjsip_transport *transport,
PJ_UNUSED_ARG(transport);
/* Print log on successful sending */
if (size > 0) {
PJ_LOG(5,(transport->obj_name,
"%s sent successfully", pjsip_tx_data_get_info(tdata)));
}
/* Mark pending off so that app can resend/reuse txdata from inside
* the callback.
*/
@ -971,13 +965,6 @@ PJ_DEF(pj_status_t) pjsip_transport_send( pjsip_transport *tr,
if (status != PJ_EPENDING) {
tdata->is_pending = 0;
/* Print log on successful sending */
if (status == PJ_SUCCESS) {
PJ_LOG(5,(tr->obj_name,
"%s sent successfully", pjsip_tx_data_get_info(tdata)));
}
pjsip_tx_data_dec_ref(tdata);
}
@ -1296,10 +1283,8 @@ PJ_DEF(pj_status_t) pjsip_transport_register( pjsip_tpmgr *mgr,
/* Allocate new entry for the freelist. */
for (; i < PJSIP_TRANSPORT_ENTRY_ALLOC_CNT; ++i) {
tp_add = PJ_POOL_ZALLOC_T(mgr->pool, transport);
if (!tp_add){
pj_lock_release(mgr->lock);
if (!tp_add)
return PJ_ENOMEM;
}
pj_list_init(tp_add);
pj_list_push_back(&mgr->tp_entry_freelist, tp_add);
}
@ -2486,7 +2471,6 @@ PJ_DEF(pj_status_t) pjsip_tpmgr_acquire_transport2(pjsip_tpmgr *mgr,
(sel->u.ip_ver == PJSIP_TPSELECTOR_USE_IPV6_ONLY &&
pjsip_transport_type_get_af(type) != pj_AF_INET6()))
{
pj_lock_release(mgr->lock);
TRACE_((THIS_FILE, "Address type in tpsel not matched"));
return PJSIP_ETPNOTSUITABLE;
}

View File

@ -1744,22 +1744,6 @@ PJ_DEF(pj_status_t) pjsip_tcp_transport_restart(pjsip_tpfactory *factory,
pj_status_t status = PJ_SUCCESS;
struct tcp_listener *listener = (struct tcp_listener *)factory;
/* Just update the published address if currently no listener */
if (!listener->asock) {
PJ_LOG(3,(factory->obj_name,
"TCP restart requested while no listener created, "
"update the published address only"));
status = update_factory_addr(listener, a_name);
if (status != PJ_SUCCESS)
return status;
/* Set transport info. */
update_transport_info(listener);
return PJ_SUCCESS;
}
lis_close(listener);
status = pjsip_tcp_transport_lis_start(factory, local, a_name);
@ -1769,15 +1753,15 @@ PJ_DEF(pj_status_t) pjsip_tcp_transport_restart(pjsip_tpfactory *factory,
return status;
}
status = pjsip_tpmgr_register_tpfactory(listener->tpmgr,
&listener->factory);
if (status != PJ_SUCCESS) {
tcp_perror(listener->factory.obj_name,
"Unable to register the transport listener", status);
} else {
listener->is_registered = PJ_TRUE;
}
listener->is_registered = PJ_TRUE;
}
return status;
}

View File

@ -647,16 +647,6 @@ PJ_DEF(pj_status_t) pjsip_tls_transport_start2( pjsip_endpoint *endpt,
&listener->cert);
if (status != PJ_SUCCESS)
goto on_error;
} else if (listener->tls_setting.cert_lookup.type !=
PJ_SSL_CERT_LOOKUP_NONE &&
listener->tls_setting.cert_lookup.keyword.slen)
{
status = pj_ssl_cert_load_from_store(
pool,
&listener->tls_setting.cert_lookup,
&listener->cert);
if (status != PJ_SUCCESS)
goto on_error;
}
/* Register to transport manager */
@ -766,22 +756,6 @@ PJ_DEF(pj_status_t) pjsip_tls_transport_restart(pjsip_tpfactory *factory,
pj_status_t status = PJ_SUCCESS;
struct tls_listener *listener = (struct tls_listener *)factory;
/* Just update the published address if currently no listener */
if (!listener->ssock) {
PJ_LOG(3,(factory->obj_name,
"TLS restart requested while no listener created, "
"update the published address only"));
status = update_factory_addr(listener, a_name);
if (status != PJ_SUCCESS)
return status;
/* Set transport info. */
update_transport_info(listener);
return PJ_SUCCESS;
}
lis_close(listener);
status = pjsip_tls_transport_lis_start(factory, local, a_name);

View File

@ -1409,7 +1409,7 @@ stateless_send_resolver_callback( pj_status_t status,
if (tdata->tp_sel.type == PJSIP_TPSELECTOR_IP_VER) {
PJ_LOG(5, (THIS_FILE, "Resorting target addresses based on "
"%s preference",
tdata->tp_sel.u.ip_ver <= PJSIP_TPSELECTOR_PREFER_IPV4?
tdata->tp_sel.u.ip_ver == PJSIP_TPSELECTOR_PREFER_IPV4?
"IPv4": "IPv6"));
if (tdata->tp_sel.u.ip_ver == PJSIP_TPSELECTOR_PREFER_IPV4)
resort_address(&tdata->dest_info.addr, pj_AF_INET());
@ -1463,28 +1463,6 @@ PJ_DEF(pj_status_t) pjsip_endpt_send_request_stateless(pjsip_endpoint *endpt,
if (!tdata->dest_info.name.slen) {
pj_strdup(tdata->pool, &tdata->dest_info.name,
&dest_info.addr.host);
} else {
/* Check if:
* - User configures transport to use a specific IP version
* - The IP version doesn't match with destination info
*/
if (tdata->tp_sel.type == PJSIP_TPSELECTOR_IP_VER &&
((tdata->tp_sel.u.ip_ver == PJSIP_TPSELECTOR_USE_IPV4_ONLY &&
(dest_info.type & PJSIP_TRANSPORT_IPV6) != 0) ||
(tdata->tp_sel.u.ip_ver == PJSIP_TPSELECTOR_USE_IPV6_ONLY &&
(dest_info.type & PJSIP_TRANSPORT_IPV6) == 0)))
{
PJ_LOG(5, (THIS_FILE, "Using initial dest %.*s",
(int)tdata->dest_info.name.slen,
tdata->dest_info.name.ptr));
pj_strdup(tdata->pool, &dest_info.addr.host,
&tdata->dest_info.name);
if (tdata->tp_sel.u.ip_ver == PJSIP_TPSELECTOR_USE_IPV4_ONLY) {
dest_info.type &= ~PJSIP_TRANSPORT_IPV6;
} else {
dest_info.type |= PJSIP_TRANSPORT_IPV6;
}
}
}
pjsip_endpt_resolve( endpt, tdata->pool, &dest_info, stateless_data,

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