sip-lab 1.40.0 → 1.41.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DEV.md +5 -11
- package/binding.gyp +2 -1
- package/build_deps.sh +52 -59
- package/package.json +8 -3
- package/prebuilds/linux-x64/node.napi.node +0 -0
- package/runtests +25 -9
- package/samples/call_with_authentication.js +278 -0
- package/samples/{t → speex.js} +5 -14
- package/prebuilds/linux-x64/node.abi102.node +0 -0
- package/prebuilds/linux-x64/node.abi108.node +0 -0
- package/prebuilds/linux-x64/node.abi111.node +0 -0
- package/prebuilds/linux-x64/node.abi115.node +0 -0
- package/prebuilds/linux-x64/node.abi120.node +0 -0
- package/prebuilds/linux-x64/node.abi88.node +0 -0
- package/prebuilds/linux-x64/node.abi93.node +0 -0
- package/src/sip.cpp.old +0 -9236
package/DEV.md
CHANGED
|
@@ -8,10 +8,11 @@ Basic tasks for development:
|
|
|
8
8
|
```
|
|
9
9
|
sudo apt install build-essential automake autoconf libtool libspeex-dev libopus-dev libsdl2-dev libavdevice-dev libswscale-dev libv4l-dev libopencore-amrnb-dev libopencore-amrwb-dev libvo-amrwbenc-dev libvo-amrwbenc-dev libboost-dev libtiff-dev libpcap-dev libssl-dev uuid-dev cmake flite-dev
|
|
10
10
|
|
|
11
|
+
nvm use v16.13.1 # other versions might work.
|
|
11
12
|
npm install
|
|
12
13
|
```
|
|
13
14
|
|
|
14
|
-
|
|
15
|
+
Then confirm it is working:
|
|
15
16
|
```
|
|
16
17
|
node samples/simple.js
|
|
17
18
|
```
|
|
@@ -44,15 +45,8 @@ npm install
|
|
|
44
45
|
Then perform code changes and tests. When you are satisfied with them, update build_deps.sh with the new commit IDs.
|
|
45
46
|
|
|
46
47
|
#### prebuild binaries
|
|
47
|
-
Previously we would do:
|
|
48
48
|
|
|
49
|
-
|
|
50
|
-
nvm use v16.13.1 # if we try with v17 it will fail to build for -t 15.0.0
|
|
51
|
-
npx prebuildify --strip -t 15.0.0 -t 16.0.0 -t 17.0.0 -t 18.0.0 19.0.0 20.0.0 21.0.0
|
|
52
|
-
```
|
|
53
|
-
However the above will build the addon to run on the current OS.
|
|
54
|
-
|
|
55
|
-
Instead we will force the build on debian11 (using docker) using prebuildify-cross. So do this instead:
|
|
49
|
+
We will use prebuildify-cross to generate the images for different architectures.
|
|
56
50
|
|
|
57
51
|
Make sure you have the docker image built (the image must be rebuilt whenever we update build_deps.sh)
|
|
58
52
|
|
|
@@ -73,10 +67,10 @@ If it fails due to proxy problems, check if you have proxy configured in ~/.dock
|
|
|
73
67
|
|
|
74
68
|
```
|
|
75
69
|
|
|
76
|
-
|
|
70
|
+
The to prebuild the addon versions:
|
|
77
71
|
```
|
|
78
72
|
nvm use v16.13.1
|
|
79
|
-
|
|
73
|
+
./gen_prebuilds.sh
|
|
80
74
|
```
|
|
81
75
|
Obs: however the above will fail if you are behind proxy (solution pending).
|
|
82
76
|
|
package/binding.gyp
CHANGED
|
@@ -25,13 +25,14 @@
|
|
|
25
25
|
],
|
|
26
26
|
'conditions': [
|
|
27
27
|
[ 'OS!="win"', {
|
|
28
|
-
'cflags': ['-g', '-DPJ_HAS_SSL_SOCK=1'],
|
|
28
|
+
'cflags': ['-g', '-DPJ_HAS_SSL_SOCK=1', '-DNAPI_VERSION=6'],
|
|
29
29
|
'cflags_cc': [
|
|
30
30
|
'-g',
|
|
31
31
|
'-DPJ_HAS_SSL_SOCK=1',
|
|
32
32
|
'-fexceptions',
|
|
33
33
|
'-Wno-maybe-uninitialized',
|
|
34
34
|
'-fPIC',
|
|
35
|
+
'-DNAPI_VERSION=6',
|
|
35
36
|
],
|
|
36
37
|
'ldflags_cc': [
|
|
37
38
|
'-all-static',
|
package/build_deps.sh
CHANGED
|
@@ -5,77 +5,72 @@ set -o nounset
|
|
|
5
5
|
set -o pipefail
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
START_DIR
|
|
8
|
+
START_DIR=$(pwd)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
ensure_git_repo() {
|
|
12
|
+
local dir=$1
|
|
13
|
+
local repo=$2
|
|
14
|
+
local commit=$3
|
|
15
|
+
shift 3
|
|
16
|
+
|
|
17
|
+
cd "$START_DIR/3rdParty"
|
|
18
|
+
if [[ -d "$dir" ]]; then
|
|
19
|
+
cd "$dir"
|
|
20
|
+
local current=$(git rev-parse HEAD 2>/dev/null || echo "")
|
|
21
|
+
cd "$START_DIR/3rdParty"
|
|
22
|
+
if [[ "$current" == "$commit" ]]; then
|
|
23
|
+
echo "$dir: already at desired commit $commit, skipping"
|
|
24
|
+
return 0
|
|
25
|
+
fi
|
|
26
|
+
echo "$dir: commit mismatch ($current != $commit), re-cloning"
|
|
27
|
+
rm -rf "$dir"
|
|
28
|
+
fi
|
|
29
|
+
|
|
30
|
+
git clone "$repo" "$dir"
|
|
31
|
+
cd "$dir"
|
|
32
|
+
git checkout "$commit"
|
|
33
|
+
|
|
34
|
+
if [[ $# -gt 0 ]]; then
|
|
35
|
+
eval "$*"
|
|
36
|
+
fi
|
|
37
|
+
cd "$START_DIR/3rdParty"
|
|
38
|
+
}
|
|
9
39
|
|
|
10
40
|
|
|
11
41
|
mkdir -p $START_DIR/3rdParty
|
|
12
42
|
|
|
13
|
-
|
|
14
|
-
cd $START_DIR/3rdParty
|
|
15
|
-
if [[ ! -d spandsp ]]
|
|
16
|
-
then
|
|
17
|
-
commit=e59ca8fb8b1591e626e6a12fdc60a2ebe83435ed
|
|
18
|
-
git clone https://github.com/freeswitch/spandsp
|
|
19
|
-
cd spandsp
|
|
20
|
-
git checkout $commit
|
|
43
|
+
ensure_git_repo spandsp https://github.com/freeswitch/spandsp e59ca8fb8b1591e626e6a12fdc60a2ebe83435ed '
|
|
21
44
|
./bootstrap.sh
|
|
22
|
-
CFLAGS=
|
|
45
|
+
CFLAGS="-O -fPIC" ./configure --enable-shared
|
|
23
46
|
make
|
|
24
|
-
|
|
47
|
+
'
|
|
25
48
|
|
|
49
|
+
ensure_git_repo rapidjson https://github.com/Tencent/rapidjson 27c3a8dc0e2c9218fe94986d249a12b5ed838f1d
|
|
26
50
|
|
|
27
|
-
|
|
28
|
-
if [[ ! -d rapidjson ]]
|
|
29
|
-
then
|
|
30
|
-
git clone https://github.com/Tencent/rapidjson
|
|
31
|
-
cd rapidjson
|
|
32
|
-
git checkout 27c3a8dc0e2c9218fe94986d249a12b5ed838f1d
|
|
33
|
-
fi
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
cd $START_DIR/3rdParty
|
|
37
|
-
if [[ ! -d bcg729 ]]
|
|
38
|
-
then
|
|
39
|
-
git clone https://github.com/MayamaTakeshi/bcg729
|
|
40
|
-
cd bcg729
|
|
41
|
-
git checkout faaa895862165acde6df8add722ba4f85a25007d
|
|
51
|
+
ensure_git_repo bcg729 https://github.com/MayamaTakeshi/bcg729 faaa895862165acde6df8add722ba4f85a25007d '
|
|
42
52
|
cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo .
|
|
43
53
|
make
|
|
44
54
|
mkdir -p lib
|
|
45
55
|
cp -f src/libbcg729.a lib
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
cd $START_DIR/3rdParty
|
|
50
|
-
if [[ ! -d pjproject ]]
|
|
51
|
-
then
|
|
52
|
-
git clone https://github.com/pjsip/pjproject
|
|
53
|
-
cd pjproject
|
|
54
|
-
#git checkout de3d744c2e1188b59bb907b6ee32ef83740ebc64
|
|
55
|
-
#git checkout 33a3c9e0a5eb84426edef05a9aa98af17d8011c3 # required for bcg729
|
|
56
|
-
#git checkout 797088ed133c98492519b7d042b75735f6f9388c # updated as part of #21
|
|
57
|
-
#git checkout 651df5b50129b7c5a5feec8336dda4468d53d2b0 # updated to latest to see of crash issues improve
|
|
58
|
-
#git checkout 043926a5846963a2c99378e8daa495230923eaab # updated to try to solve #49 (but issue remains)
|
|
59
|
-
#git checkout c36802585ddefb3ca477d1f6d773d179510c5412 # updated to try to solve #83 (but issue remains)
|
|
60
|
-
git checkout 9543a1bcf50be721d030be99afeeb63bd8cf2013 # updated to latest commit to permit to report https://github.com/pjsip/pjproject/issues/4082
|
|
56
|
+
'
|
|
61
57
|
|
|
58
|
+
ensure_git_repo pjproject https://github.com/pjsip/pjproject 9543a1bcf50be721d030be99afeeb63bd8cf2013 '
|
|
62
59
|
cat > user.mak <<EOF
|
|
63
60
|
export CFLAGS += -fPIC -g
|
|
64
61
|
export LDFLAGS +=
|
|
65
62
|
EOF
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
cat > pjlib/include/pj/config_site.h <<EOF
|
|
63
|
+
sed -i -r "s/BCG729_LIBS=\"-lbcg729\"/BCG729_LIBS=\"\"/" aconfigure
|
|
64
|
+
LIBS=$(pwd)/../bcg729/src/libbcg729.a ./configure --with-bcg729=$(pwd)/../bcg729
|
|
65
|
+
cat > pjlib/include/pj/config_site.h <<EOF2
|
|
70
66
|
#define PJSUA_MAX_ACC (20000)
|
|
71
67
|
#define PJ_IOQUEUE_MAX_HANDLES (1024)
|
|
72
68
|
#define PJSUA_MAX_CALLS (20000)
|
|
73
69
|
|
|
74
70
|
#define PJMEDIA_HAS_OPUS_CODEC 1
|
|
75
|
-
|
|
71
|
+
EOF2
|
|
76
72
|
make dep && make clean && make
|
|
77
|
-
|
|
78
|
-
|
|
73
|
+
'
|
|
79
74
|
|
|
80
75
|
cd $START_DIR/3rdParty
|
|
81
76
|
if [[ ! -d boost_1_66_0 ]]
|
|
@@ -84,13 +79,17 @@ then
|
|
|
84
79
|
tar xf boost_1_66_0.tar.bz2
|
|
85
80
|
fi
|
|
86
81
|
|
|
87
|
-
|
|
88
82
|
cd $START_DIR/3rdParty
|
|
83
|
+
POCKETSPHINX_VERSION=5.0.3
|
|
84
|
+
if [[ -f pocketsphinx/.version && "$(cat pocketsphinx/.version)" != "$POCKETSPHINX_VERSION" ]]
|
|
85
|
+
then
|
|
86
|
+
echo "pocketsphinx: version mismatch, re-downloading"
|
|
87
|
+
rm -rf pocketsphinx
|
|
88
|
+
fi
|
|
89
89
|
if [[ ! -d pocketsphinx ]]
|
|
90
90
|
then
|
|
91
|
-
POCKETSPHINX_VERSION=5.0.3
|
|
92
91
|
rm -f v${POCKETSPHINX_VERSION}.tar.gz
|
|
93
|
-
wget https://github.com/cmusphinx/pocketsphinx/archive/refs/tags/v${POCKETSPHINX_VERSION}.tar.gz
|
|
92
|
+
wget https://github.com/cmusphinx/pocketsphinx/archive/refs/tags/v${POCKETSPHINX_VERSION}.tar.gz
|
|
94
93
|
tar xf v${POCKETSPHINX_VERSION}.tar.gz
|
|
95
94
|
rm -f v${POCKETSPHINX_VERSION}.tar.gz
|
|
96
95
|
mv pocketsphinx-${POCKETSPHINX_VERSION} pocketsphinx
|
|
@@ -98,6 +97,7 @@ then
|
|
|
98
97
|
sed -i '/include(GNUInstallDirs)/a \\nset(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")' CMakeLists.txt
|
|
99
98
|
cmake -S . -B build
|
|
100
99
|
cmake --build build
|
|
100
|
+
echo "$POCKETSPHINX_VERSION" > .version
|
|
101
101
|
|
|
102
102
|
rm -fr ../../pocketsphinx
|
|
103
103
|
mkdir -p ../../pocketsphinx
|
|
@@ -105,14 +105,7 @@ then
|
|
|
105
105
|
fi
|
|
106
106
|
|
|
107
107
|
|
|
108
|
-
|
|
109
|
-
if [[ ! -d pjwebsock ]]
|
|
110
|
-
then
|
|
111
|
-
git clone https://github.com/jimying/pjwebsock
|
|
112
|
-
cd pjwebsock
|
|
113
|
-
#git checkout a0616ea27f01d5e3bdfd5b801fb1499473a0b0cb
|
|
114
|
-
git checkout ed8bfee79e26ef4e023bac1359301c201ee133af
|
|
115
|
-
fi
|
|
108
|
+
ensure_git_repo pjwebsock https://github.com/jimying/pjwebsock ed8bfee79e26ef4e023bac1359301c201ee133af
|
|
116
109
|
|
|
117
110
|
|
|
118
111
|
#cd $START_DIR/3rdParty
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sip-lab",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.41.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"engines": {
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"prebuildify": "^5.0.1",
|
|
37
|
-
"prebuildify-cross": "github:MayamaTakeshi/prebuildify-cross#
|
|
37
|
+
"prebuildify-cross": "github:MayamaTakeshi/prebuildify-cross#820133ce7fdbc92525b5b0d7149ed6497860a11b"
|
|
38
38
|
},
|
|
39
39
|
"files": [
|
|
40
40
|
"index.js",
|
|
@@ -49,5 +49,10 @@
|
|
|
49
49
|
"prebuilds",
|
|
50
50
|
"pocketsphinx",
|
|
51
51
|
"runtests"
|
|
52
|
-
]
|
|
52
|
+
],
|
|
53
|
+
"binary": {
|
|
54
|
+
"napi_versions": [
|
|
55
|
+
6
|
|
56
|
+
]
|
|
57
|
+
}
|
|
53
58
|
}
|
|
Binary file
|
package/runtests
CHANGED
|
@@ -45,13 +45,24 @@ while getopts "gef:a:h" o; do
|
|
|
45
45
|
done
|
|
46
46
|
shift $((OPTIND-1))
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
passed_on_first_try=()
|
|
49
|
+
passed_on_retry=()
|
|
49
50
|
failed_tests=()
|
|
50
51
|
|
|
51
|
-
function
|
|
52
|
-
if [ ${#
|
|
53
|
-
echo "
|
|
54
|
-
for t in "${
|
|
52
|
+
function output_passed_on_first_try_tests() {
|
|
53
|
+
if [ ${#passed_on_first_try[@]} -ne 0 ]; then
|
|
54
|
+
echo "Passed on first try:"
|
|
55
|
+
for t in "${passed_on_first_try[@]}"
|
|
56
|
+
do
|
|
57
|
+
echo " - $t"
|
|
58
|
+
done
|
|
59
|
+
fi
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function output_passed_on_retry_tests() {
|
|
63
|
+
if [ ${#passed_on_retry[@]} -ne 0 ]; then
|
|
64
|
+
echo "Passed on retry (flaky tests):"
|
|
65
|
+
for t in "${passed_on_retry[@]}"
|
|
55
66
|
do
|
|
56
67
|
echo " - $t"
|
|
57
68
|
done
|
|
@@ -127,11 +138,12 @@ do
|
|
|
127
138
|
formatted_duration=$(printf "%.2f seconds" $duration)
|
|
128
139
|
|
|
129
140
|
success_message="$i: duration=$formatted_duration"
|
|
130
|
-
# The variable c comes from the retry loop
|
|
131
141
|
if [[ $c -gt 1 ]]; then
|
|
132
142
|
success_message+=" (succeeded after $c attempts)"
|
|
143
|
+
passed_on_retry+=("$success_message")
|
|
144
|
+
else
|
|
145
|
+
passed_on_first_try+=("$success_message")
|
|
133
146
|
fi
|
|
134
|
-
successful_tests+=("$success_message")
|
|
135
147
|
fi
|
|
136
148
|
echo
|
|
137
149
|
done
|
|
@@ -139,7 +151,9 @@ done
|
|
|
139
151
|
echo
|
|
140
152
|
|
|
141
153
|
if [ ${#failed_tests[@]} -ne 0 ]; then
|
|
142
|
-
|
|
154
|
+
output_passed_on_first_try_tests
|
|
155
|
+
echo
|
|
156
|
+
output_passed_on_retry_tests
|
|
143
157
|
echo
|
|
144
158
|
output_failed_tests
|
|
145
159
|
echo
|
|
@@ -149,7 +163,9 @@ if [ ${#failed_tests[@]} -ne 0 ]; then
|
|
|
149
163
|
else
|
|
150
164
|
echo "Success. All tests passed"
|
|
151
165
|
echo
|
|
152
|
-
|
|
166
|
+
output_passed_on_first_try_tests
|
|
167
|
+
echo
|
|
168
|
+
output_passed_on_retry_tests
|
|
153
169
|
echo
|
|
154
170
|
echo "Everything OK"
|
|
155
171
|
echo
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
// This test creates 2 UDP SIP endpoints, makes a call between them and disconeects.
|
|
2
|
+
|
|
3
|
+
const sip = require ('../index.js')
|
|
4
|
+
const Zeq = require('@mayama/zeq')
|
|
5
|
+
const m = require('data-matching')
|
|
6
|
+
const sip_msg = require('sip-matching')
|
|
7
|
+
|
|
8
|
+
const crypto = require('crypto');
|
|
9
|
+
|
|
10
|
+
function generateDigestResponse({
|
|
11
|
+
username, password, realm, nonce, uri,
|
|
12
|
+
method = 'INVITE', qop = 'auth', nc = '00000001',
|
|
13
|
+
cnonce
|
|
14
|
+
}) {
|
|
15
|
+
const md5 = (str) => crypto.createHash('md5').update(str).digest('hex');
|
|
16
|
+
|
|
17
|
+
// Fallback to random ONLY if one isn't provided (for tests)
|
|
18
|
+
const finalCnonce = cnonce || crypto.randomBytes(8).toString('hex');
|
|
19
|
+
|
|
20
|
+
const ha1 = md5(`${username}:${realm}:${password}`);
|
|
21
|
+
const ha2 = md5(`${method}:${uri}`);
|
|
22
|
+
const response = md5(`${ha1}:${nonce}:${nc}:${finalCnonce}:${qop}:${ha2}`);
|
|
23
|
+
|
|
24
|
+
return { response, cnonce: finalCnonce };
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// here we create our Zeq instance
|
|
28
|
+
var z = new Zeq()
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
async function test() {
|
|
32
|
+
// here we set DTMF aggregation mode to 500 ms
|
|
33
|
+
sip.dtmf_aggregation_on(500)
|
|
34
|
+
|
|
35
|
+
// here we set our Zeq instance to trap events generated by sip-lab event_source
|
|
36
|
+
z.trap_events(sip.event_source, 'event', (evt) => {
|
|
37
|
+
var e = evt.args[0]
|
|
38
|
+
return e
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
sip.set_codecs("pcmu/8000/1:128,pcma/8000/1:128,gsm/8000/1:128")
|
|
42
|
+
|
|
43
|
+
// here we start sip-lab
|
|
44
|
+
console.log(sip.start((data) => { console.log(data)} ))
|
|
45
|
+
|
|
46
|
+
// Here we create the SIP endpoints (transports).
|
|
47
|
+
// Since we don't specify the port, an available port will be allocated.
|
|
48
|
+
// Since we don't specify the type ('udp' or 'tcp' or 'tls'), 'udp' will be used by default.
|
|
49
|
+
const t1 = sip.transport.create({address: "127.0.0.1"})
|
|
50
|
+
const t2 = sip.transport.create({address: "127.0.0.1"})
|
|
51
|
+
|
|
52
|
+
// here we just print the transports
|
|
53
|
+
console.log("t1", t1)
|
|
54
|
+
console.log("t2", t2)
|
|
55
|
+
|
|
56
|
+
max_forwards = '18'
|
|
57
|
+
|
|
58
|
+
var username = 'alice'
|
|
59
|
+
var password = 'secret'
|
|
60
|
+
var realm = 'test.com'
|
|
61
|
+
|
|
62
|
+
// make the call from t1 to t2 with some custom heaaders
|
|
63
|
+
const oc = sip.call.create(t1.id, {
|
|
64
|
+
from_uri: 'sip:alice@test.com',
|
|
65
|
+
to_uri: `sip:bob@${t2.address}:${t2.port}`,
|
|
66
|
+
auth: {
|
|
67
|
+
username,
|
|
68
|
+
password,
|
|
69
|
+
realm,
|
|
70
|
+
},
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
// Here we will wait for the call to arrive at t2
|
|
74
|
+
// We will also get a '100 Trying' that is sent by sip-lab automatically
|
|
75
|
+
// We will wait for at most 1000ms. If all events don't arrive within 1000ms, an exception will be thrown and the test will fail due to timeout.
|
|
76
|
+
await z.wait([
|
|
77
|
+
{
|
|
78
|
+
event: "incoming_call",
|
|
79
|
+
call_id: m.collect("call_id"),
|
|
80
|
+
transport_id: t2.id,
|
|
81
|
+
msg: sip_msg({
|
|
82
|
+
$rU: 'bob',
|
|
83
|
+
$fU: 'alice',
|
|
84
|
+
$tU: 'bob',
|
|
85
|
+
$fd: 'test.com',
|
|
86
|
+
$ru: m.collect('ruri'),
|
|
87
|
+
hds_call_id: m.collect('sip_call_id'),
|
|
88
|
+
})
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
event: 'response',
|
|
92
|
+
call_id: oc.id,
|
|
93
|
+
method: 'INVITE',
|
|
94
|
+
msg: sip_msg({
|
|
95
|
+
$rs: '100',
|
|
96
|
+
$rr: 'Trying',
|
|
97
|
+
}),
|
|
98
|
+
},
|
|
99
|
+
], 1000)
|
|
100
|
+
|
|
101
|
+
// Here we store data for the incoming call
|
|
102
|
+
// just to organize our code (not really needed)
|
|
103
|
+
var ic = {
|
|
104
|
+
id: z.$call_id,
|
|
105
|
+
sip_call_id: z.$sip_call_id,
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Now we challenge the caller.
|
|
109
|
+
var nonce = "dcd98b7102dd2f0e8b11d0f600bfb0c093"
|
|
110
|
+
var qop = 'auth'
|
|
111
|
+
var algorithm = 'MD5'
|
|
112
|
+
var uri = z.$ruri
|
|
113
|
+
sip.call.respond(ic.id, {
|
|
114
|
+
code: 407,
|
|
115
|
+
reason: 'Proxy Authentication Required',
|
|
116
|
+
headers: {
|
|
117
|
+
'Proxy-Authenticate': `Digest realm="${realm}", nonce="${nonce}", algorithm=${algorithm}, qop="${qop}"`,
|
|
118
|
+
},
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
// the caller gets the challenge and the call ends at t2.
|
|
122
|
+
await z.wait([
|
|
123
|
+
{
|
|
124
|
+
event: 'response',
|
|
125
|
+
call_id: oc.id,
|
|
126
|
+
method: 'INVITE',
|
|
127
|
+
msg: sip_msg({
|
|
128
|
+
$rs: '407',
|
|
129
|
+
$rr: 'Proxy Authentication Required',
|
|
130
|
+
hdr_proxy_authenticate: `Digest realm="${realm}",nonce="${nonce}",algorithm=${algorithm},qop="${qop}"`,
|
|
131
|
+
}),
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
event: 'call_ended',
|
|
135
|
+
call_id: ic.id,
|
|
136
|
+
}
|
|
137
|
+
], 1000)
|
|
138
|
+
|
|
139
|
+
z.store.call_id = null
|
|
140
|
+
z.store.sip_call_id = null
|
|
141
|
+
|
|
142
|
+
// Then we wait for INVITE with header Authorization
|
|
143
|
+
await z.wait([
|
|
144
|
+
{
|
|
145
|
+
event: "incoming_call",
|
|
146
|
+
call_id: m.collect("call_id"),
|
|
147
|
+
transport_id: t2.id,
|
|
148
|
+
msg: sip_msg({
|
|
149
|
+
$rU: 'bob',
|
|
150
|
+
$fU: 'alice',
|
|
151
|
+
$tU: 'bob',
|
|
152
|
+
$fd: 'test.com',
|
|
153
|
+
hdr_proxy_authorization: 'Digest username="!{username}", realm="!{realm}", nonce="!{nonce}", uri="!{uri}", response="!{response}", algorithm=!{algorithm}, cnonce="!{cnonce}", qop=!{qop}, nc=!{nc}',
|
|
154
|
+
hdr_call_id: m.collect('sip_call_id'),
|
|
155
|
+
})
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
event: 'response',
|
|
159
|
+
call_id: oc.id,
|
|
160
|
+
method: 'INVITE',
|
|
161
|
+
msg: sip_msg({
|
|
162
|
+
$rs: '100',
|
|
163
|
+
$rr: 'Trying',
|
|
164
|
+
}),
|
|
165
|
+
},
|
|
166
|
+
], 1000)
|
|
167
|
+
|
|
168
|
+
var expectedResponse = generateDigestResponse({
|
|
169
|
+
username,
|
|
170
|
+
password,
|
|
171
|
+
realm,
|
|
172
|
+
nonce,
|
|
173
|
+
uri,
|
|
174
|
+
method: 'INVITE',
|
|
175
|
+
qop,
|
|
176
|
+
nc: z.$nc,
|
|
177
|
+
cnonce: z.$cnonce,
|
|
178
|
+
})
|
|
179
|
+
|
|
180
|
+
if(z.$response != expectedResponse.response) {
|
|
181
|
+
throw new Error(`Incorrect digest response. Expected ${expectedResponse.response} but got ${z.$response}`)
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
ic = {
|
|
185
|
+
id: z.$call_id,
|
|
186
|
+
sip_call_id: z.$sip_call_id,
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// now we answer the call
|
|
190
|
+
sip.call.respond(ic.id, {
|
|
191
|
+
code: 200,
|
|
192
|
+
reason: 'OK',
|
|
193
|
+
})
|
|
194
|
+
|
|
195
|
+
// Then we wait for the '200 OK' at the t1 side
|
|
196
|
+
// We will also get event 'media_update' for both sides indicating media streams (RTP) were set up successfully
|
|
197
|
+
await z.wait([
|
|
198
|
+
{
|
|
199
|
+
event: 'response',
|
|
200
|
+
call_id: oc.id,
|
|
201
|
+
method: 'INVITE',
|
|
202
|
+
msg: sip_msg({
|
|
203
|
+
$rs: '200',
|
|
204
|
+
$rr: 'OK',
|
|
205
|
+
}),
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
event: 'media_update',
|
|
209
|
+
call_id: oc.id,
|
|
210
|
+
status: 'ok',
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
event: 'media_update',
|
|
214
|
+
call_id: ic.id,
|
|
215
|
+
status: 'ok',
|
|
216
|
+
},
|
|
217
|
+
], 1000)
|
|
218
|
+
|
|
219
|
+
sip.call.start_inband_dtmf_detection(oc.id)
|
|
220
|
+
sip.call.start_inband_dtmf_detection(ic.id)
|
|
221
|
+
|
|
222
|
+
sip.call.send_dtmf(oc.id, {digits: '1234', mode: 1})
|
|
223
|
+
sip.call.send_dtmf(ic.id, {digits: '1234', mode: 1})
|
|
224
|
+
|
|
225
|
+
await z.wait([
|
|
226
|
+
{
|
|
227
|
+
event: 'dtmf',
|
|
228
|
+
call_id: ic.id,
|
|
229
|
+
digits: '1234',
|
|
230
|
+
mode: 1,
|
|
231
|
+
media_id: 0,
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
event: 'dtmf',
|
|
235
|
+
call_id: oc.id,
|
|
236
|
+
digits: '1234',
|
|
237
|
+
mode: 1,
|
|
238
|
+
media_id: 0,
|
|
239
|
+
},
|
|
240
|
+
], 2000)
|
|
241
|
+
|
|
242
|
+
// now we terminate the call from t1 side
|
|
243
|
+
sip.call.terminate(oc.id)
|
|
244
|
+
|
|
245
|
+
// and wait for termination events
|
|
246
|
+
await z.wait([
|
|
247
|
+
{
|
|
248
|
+
event: 'response',
|
|
249
|
+
call_id: oc.id,
|
|
250
|
+
method: 'BYE',
|
|
251
|
+
msg: sip_msg({
|
|
252
|
+
$rs: '200',
|
|
253
|
+
$rr: 'OK',
|
|
254
|
+
}),
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
event: 'call_ended',
|
|
258
|
+
call_id: oc.id,
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
event: 'call_ended',
|
|
262
|
+
call_id: ic.id,
|
|
263
|
+
},
|
|
264
|
+
], 1000)
|
|
265
|
+
|
|
266
|
+
console.log("Success")
|
|
267
|
+
|
|
268
|
+
sip.stop()
|
|
269
|
+
process.exit(0)
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
test()
|
|
274
|
+
.catch(e => {
|
|
275
|
+
console.error(e)
|
|
276
|
+
process.exit(1)
|
|
277
|
+
})
|
|
278
|
+
|
package/samples/{t → speex.js}
RENAMED
|
@@ -24,8 +24,9 @@ async function test() {
|
|
|
24
24
|
console.log("t1", t1)
|
|
25
25
|
console.log("t2", t2)
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
assert(sip.get_codecs().indexOf("speex/8000/1") > 0)
|
|
28
|
+
|
|
29
|
+
sip.set_codecs("speex/8000/1:128")
|
|
29
30
|
|
|
30
31
|
flags = 0
|
|
31
32
|
|
|
@@ -188,18 +189,8 @@ async function test() {
|
|
|
188
189
|
oc_stat = JSON.parse(oc_stat)
|
|
189
190
|
ic_stat = JSON.parse(ic_stat)
|
|
190
191
|
|
|
191
|
-
assert(oc_stat.CodecInfo == '
|
|
192
|
-
assert(ic_stat.CodecInfo == '
|
|
193
|
-
|
|
194
|
-
await z.sleep(100)
|
|
195
|
-
|
|
196
|
-
sip.call.start_inband_dtmf_detection(oc.id)
|
|
197
|
-
sip.call.start_inband_dtmf_detection(ic.id)
|
|
198
|
-
|
|
199
|
-
sip.call.send_dtmf(oc.id, {digits: '12', mode: 1})
|
|
200
|
-
sip.call.send_dtmf(ic.id, {digits: '21', mode: 1})
|
|
201
|
-
|
|
202
|
-
await z.sleep(1000)
|
|
192
|
+
assert(oc_stat.CodecInfo == 'speex/8000/1')
|
|
193
|
+
assert(ic_stat.CodecInfo == 'speex/8000/1')
|
|
203
194
|
|
|
204
195
|
sip.call.stop_record_wav(oc.id)
|
|
205
196
|
sip.call.stop_record_wav(ic.id)
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|