sip-lab 1.39.0 → 1.40.1

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/binding.gyp CHANGED
@@ -14,6 +14,7 @@
14
14
  "src",
15
15
  "src/pjmedia/include",
16
16
  "src/pjmedia/include/pjmedia",
17
+ "src/pjsip/include",
17
18
  "3rdParty/rapidjson/include",
18
19
  "3rdParty/boost_1_66_0",
19
20
  "3rdParty/spandsp/src",
@@ -24,9 +25,10 @@
24
25
  ],
25
26
  'conditions': [
26
27
  [ 'OS!="win"', {
27
- 'cflags': ['-g'],
28
+ 'cflags': ['-g', '-DPJ_HAS_SSL_SOCK=1'],
28
29
  'cflags_cc': [
29
30
  '-g',
31
+ '-DPJ_HAS_SSL_SOCK=1',
30
32
  '-fexceptions',
31
33
  '-Wno-maybe-uninitialized',
32
34
  '-fPIC',
@@ -39,6 +41,7 @@
39
41
  ],
40
42
  'link_settings': {
41
43
  'libraries': [
44
+ '-Wl,--start-group',
42
45
  '-L ../3rdParty/pjproject/pjnath/lib',
43
46
  '-L ../3rdParty/pjproject/pjlib/lib',
44
47
  '-L ../3rdParty/pjproject/pjlib-util/lib',
@@ -92,6 +95,7 @@
92
95
  '-lflite_cmu_us_slt',
93
96
  '-lflite_cmu_us_kal16',
94
97
  '-l srtp-x86_64-unknown-linux-gnu',
98
+ '-Wl,--end-group',
95
99
  ],
96
100
  },
97
101
  },
@@ -118,6 +122,7 @@
118
122
  'src/idmanager.cpp',
119
123
  'src/sip.cpp',
120
124
  'src/addon.cpp',
125
+ 'src/pjsip/src/pjsip/sip_transport_ws.c',
121
126
  'src/pjmedia/src/pjmedia/dtmfdet.c',
122
127
  'src/pjmedia/src/pjmedia/bfsk_det.c',
123
128
  'src/pjmedia/src/pjmedia/bfsk_det2.c',
package/build_deps.sh CHANGED
@@ -5,77 +5,72 @@ set -o nounset
5
5
  set -o pipefail
6
6
 
7
7
 
8
- START_DIR=`pwd`
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='-O -fPIC' ./configure --enable-shared
45
+ CFLAGS="-O -fPIC" ./configure --enable-shared
23
46
  make
24
- fi
47
+ '
25
48
 
49
+ ensure_git_repo rapidjson https://github.com/Tencent/rapidjson 27c3a8dc0e2c9218fe94986d249a12b5ed838f1d
26
50
 
27
- cd $START_DIR/3rdParty
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
- fi
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
- sed -i -r 's/BCG729_LIBS="-lbcg729"/BCG729_LIBS=''/' aconfigure
68
- LIBS=`pwd`/../bcg729/src/libbcg729.a ./configure --with-bcg729=`pwd`/../bcg729
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
- EOF
71
+ EOF2
76
72
  make dep && make clean && make
77
- fi
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,13 +105,7 @@ then
105
105
  fi
106
106
 
107
107
 
108
- cd $START_DIR/3rdParty
109
- if [[ ! -d pjwebsock ]]
110
- then
111
- git clone https://github.com/jimying/pjwebsock
112
- cd pjwebsock
113
- git checkout a0616ea27f01d5e3bdfd5b801fb1499473a0b0cb
114
- fi
108
+ ensure_git_repo pjwebsock https://github.com/jimying/pjwebsock ed8bfee79e26ef4e023bac1359301c201ee133af
115
109
 
116
110
 
117
111
  #cd $START_DIR/3rdParty
package/index.js CHANGED
@@ -111,4 +111,6 @@ addon.subscription = {
111
111
  subscribe: (s_id, params) => { return addon.subscription_subscribe(s_id, JSON.stringify(params)) },
112
112
  }
113
113
 
114
+ addon.set_opus_config = (params) => { return addon._set_opus_config(JSON.stringify(params)) }
115
+
114
116
  module.exports = addon;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sip-lab",
3
- "version": "1.39.0",
3
+ "version": "1.40.1",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "engines": {
@@ -10,7 +10,7 @@
10
10
  "install": "node-gyp-build",
11
11
  "build": "node-gyp build",
12
12
  "rebuild": "node-gyp rebuild",
13
- "test": "./runtests"
13
+ "test": "./runtests -a 3"
14
14
  },
15
15
  "repository": {
16
16
  "type": "git",
Binary file
Binary file
package/runtests CHANGED
@@ -4,77 +4,153 @@ set -o nounset
4
4
 
5
5
  function usage() {
6
6
  cat <<EOF
7
- Usage: $0 [-g]
7
+ Usage: $0 [-g] [-e] [-f test_name] [-a attempts]
8
8
 
9
9
  Details:
10
10
  -g : run each test inside gdb
11
+ -e : include samples_extra
12
+ -f : start from a specific test, skipping any test before it
13
+ -a : if test fails, it can be retried up to XX times (default is 1)
11
14
  EOF
12
15
  }
13
16
 
14
17
  use_gdb=0
18
+ extra=0
19
+ from_test=""
20
+ attempts=1
15
21
 
16
- while getopts "gh" o; do
22
+ while getopts "gef:a:h" o; do
17
23
  case "${o}" in
18
24
  g)
19
25
  use_gdb=1
20
- ;;
26
+ ;;
27
+ e)
28
+ extra=1
29
+ ;;
30
+ f)
31
+ from_test=${OPTARG}
32
+ ;;
33
+ a)
34
+ attempts=${OPTARG}
35
+ ;;
21
36
  h)
22
37
  usage
23
- exit 0
24
- ;;
25
- *)
38
+ exit 0
39
+ ;;
40
+ *)
26
41
  usage
27
- exit 1
28
- ;;
42
+ exit 1
43
+ ;;
29
44
  esac
30
45
  done
31
46
  shift $((OPTIND-1))
32
47
 
33
48
  successful_tests=()
49
+ failed_tests=()
34
50
 
35
51
  function output_successful_tests() {
36
- echo "Successful tests:"
37
- for t in "${successful_tests[@]}"
38
- do
39
- echo " - $t"
40
- done
52
+ if [ ${#successful_tests[@]} -ne 0 ]; then
53
+ echo "Successful tests:"
54
+ for t in "${successful_tests[@]}"
55
+ do
56
+ echo " - $t"
57
+ done
58
+ fi
59
+ }
60
+
61
+ function output_failed_tests() {
62
+ if [ ${#failed_tests[@]} -ne 0 ]; then
63
+ echo "Failed tests:"
64
+ for t in "${failed_tests[@]}"
65
+ do
66
+ echo " - $t"
67
+ done
68
+ fi
41
69
  }
42
70
 
43
71
  echo
44
72
 
45
- for i in $(ls samples/*.js)
73
+ # Get list of tests and sort them
74
+ test_patterns="samples/*.js"
75
+ if [[ "$extra" == 1 ]]; then
76
+ test_patterns="$test_patterns samples_extra/*.js"
77
+ fi
78
+
79
+ mapfile -t sorted_tests < <(ls -1 $test_patterns 2>/dev/null | sort)
80
+
81
+ start_running=0
82
+ if [[ -z "$from_test" ]]; then
83
+ start_running=1
84
+ fi
85
+
86
+ for i in "${sorted_tests[@]}"
46
87
  do
47
- start_time=$(date +%s.%N)
88
+ if [[ "$start_running" -eq 0 && "$i" == "$from_test" ]]; then
89
+ start_running=1
90
+ fi
48
91
 
49
- if [[ $use_gdb -eq 0 ]]
50
- then
51
- node $i
52
- else
53
- gdb -ex "handle SIGSEGV stop" -ex "run" -ex "bt" -ex "quit" --args node $i
92
+ if [[ "$start_running" -eq 0 ]]; then
93
+ echo "Skipping $i"
94
+ continue
54
95
  fi
55
96
 
56
- if [[ $? -ne 0 ]]
97
+ echo "Running test: $i"
98
+ start_time=$(date +%s.%N)
99
+
100
+ success=0
101
+ for (( c=1; c<=$attempts; c++ ))
102
+ do
103
+ if [[ $use_gdb -eq 0 ]]
104
+ then
105
+ node $i
106
+ else
107
+ gdb -ex "handle SIGSEGV stop" -ex "run" -ex "bt" -ex "quit" --args node $i
108
+ fi
109
+
110
+ if [[ $? -eq 0 ]]; then
111
+ success=1
112
+ break
113
+ fi
114
+
115
+ if [[ $c -lt $attempts ]]; then
116
+ echo "Test $i failed. Retrying (attempt $(($c + 1)) of $attempts)..."
117
+ fi
118
+ done
119
+
120
+ if [[ $success -eq 0 ]]
57
121
  then
58
- echo "$i failed"
59
- echo
60
- output_successful_tests
61
- exit 1
122
+ echo "$i failed after $attempts attempts"
123
+ failed_tests+=("$i")
62
124
  else
63
125
  end_time=$(date +%s.%N)
64
126
  duration=$(echo "$end_time - $start_time" | bc)
65
- formatted_duration=$(printf "%.2f seconds" $duration)
66
- successful_tests+=("$i: duration=$formatted_duration")
67
-
68
- echo
69
- echo "$i failed"
127
+ formatted_duration=$(printf "%.2f seconds" $duration)
128
+
129
+ success_message="$i: duration=$formatted_duration"
130
+ # The variable c comes from the retry loop
131
+ if [[ $c -gt 1 ]]; then
132
+ success_message+=" (succeeded after $c attempts)"
133
+ fi
134
+ successful_tests+=("$success_message")
70
135
  fi
136
+ echo
71
137
  done
72
138
 
73
139
  echo
74
140
 
75
- echo "Success. All tests passed"
76
- echo
77
- output_successful_tests
78
- echo
79
- echo "Everything OK"
80
- echo
141
+ if [ ${#failed_tests[@]} -ne 0 ]; then
142
+ output_successful_tests
143
+ echo
144
+ output_failed_tests
145
+ echo
146
+ echo "Some tests failed."
147
+ echo
148
+ exit 1
149
+ else
150
+ echo "Success. All tests passed"
151
+ echo
152
+ output_successful_tests
153
+ echo
154
+ echo "Everything OK"
155
+ echo
156
+ fi
package/samples/gsm.js ADDED
@@ -0,0 +1,230 @@
1
+ var sip = require ('../index.js')
2
+ var Zeq = require('@mayama/zeq')
3
+ var z = new Zeq()
4
+ var m = require('data-matching')
5
+ var sip_msg = require('sip-matching')
6
+ var sdp = require('sdp-matching')
7
+
8
+ var assert = require('assert')
9
+
10
+ async function test() {
11
+ //sip.set_log_level(6)
12
+ sip.dtmf_aggregation_on(500)
13
+
14
+ z.trap_events(sip.event_source, 'event', (evt) => {
15
+ var e = evt.args[0]
16
+ return e
17
+ })
18
+
19
+ console.log(sip.start((data) => { console.log(data)} ))
20
+
21
+ t1 = sip.transport.create({address: "127.0.0.1", type: 'udp'})
22
+ t2 = sip.transport.create({address: "127.0.0.1", type: 'udp'})
23
+
24
+ console.log("t1", t1)
25
+ console.log("t2", t2)
26
+
27
+ assert(sip.get_codecs().indexOf("GSM/8000/1") > 0)
28
+
29
+ sip.set_codecs("GSM/8000/1:128")
30
+
31
+ flags = 0
32
+
33
+ oc = sip.call.create(t1.id, {from_uri: 'sip:alice@test.com', to_uri: `sip:bob@${t2.address}:${t2.port}`})
34
+
35
+ await z.wait([
36
+ {
37
+ event: "incoming_call",
38
+ call_id: m.collect("call_id"),
39
+ },
40
+ {
41
+ event: 'response',
42
+ call_id: oc.id,
43
+ method: 'INVITE',
44
+ msg: sip_msg({
45
+ $rs: '100',
46
+ $rr: 'Trying',
47
+ }),
48
+ },
49
+ ], 1000)
50
+
51
+ ic = {
52
+ id: z.$call_id,
53
+ sip_call_id: z.$sip_call_id,
54
+ }
55
+
56
+ sip.call.respond(ic.id, {code: 200, reason: 'OK'})
57
+
58
+ await z.wait([
59
+ {
60
+ event: 'media_update',
61
+ call_id: oc.id,
62
+ status: 'ok',
63
+ },
64
+ {
65
+ event: 'media_update',
66
+ call_id: ic.id,
67
+ status: 'ok',
68
+ },
69
+ {
70
+ event: 'response',
71
+ call_id: oc.id,
72
+ method: 'INVITE',
73
+ msg: sip_msg({
74
+ $rs: '200',
75
+ $rr: 'OK',
76
+ 'hdr_content_type': 'application/sdp',
77
+ $rb: '!{_}a=sendrecv!{_}',
78
+ }),
79
+ },
80
+ ], 1000)
81
+
82
+ sip.call.start_record_wav(oc.id, {file: './oc.wav'})
83
+ sip.call.start_record_wav(ic.id, {file: './ic.wav'})
84
+
85
+ sip.call.start_play_wav(oc.id, {file: 'samples/artifacts/hello_good_morning.wav', end_of_file_event: true, no_loop: true})
86
+ sip.call.start_play_wav(ic.id, {file: 'samples/artifacts/hello_good_morning.wav', end_of_file_event: true, no_loop: true})
87
+
88
+ await z.wait([
89
+ {
90
+ event: 'end_of_file',
91
+ call_id: oc.id,
92
+ },
93
+ {
94
+ event: 'end_of_file',
95
+ call_id: ic.id,
96
+ },
97
+ ], 5000)
98
+
99
+ sip.call.reinvite(oc.id)
100
+
101
+ await z.wait([
102
+ {
103
+ event: 'reinvite',
104
+ call_id: ic.id
105
+ },
106
+ ], 1000)
107
+
108
+ sip.call.respond(ic.id, {code: 200, reason: 'OK'})
109
+
110
+ await z.wait([
111
+ {
112
+ event: 'response',
113
+ call_id: oc.id,
114
+ method: 'INVITE',
115
+ msg: sip_msg({
116
+ $rs: '100',
117
+ }),
118
+ },
119
+ {
120
+ event: 'response',
121
+ call_id: oc.id,
122
+ method: 'INVITE',
123
+ msg: sip_msg({
124
+ $rs: '200',
125
+ $rr: 'OK',
126
+ $rb: '!{_}a=sendrecv!{_}',
127
+ }),
128
+ },
129
+ {
130
+ event: 'media_update',
131
+ call_id: oc.id,
132
+ status: 'ok',
133
+ },
134
+ {
135
+ event: 'media_update',
136
+ call_id: ic.id,
137
+ status: 'ok',
138
+ },
139
+ ], 500)
140
+
141
+ sip.call.reinvite(oc.id, false, 0)
142
+
143
+ await z.wait([
144
+ {
145
+ event: 'reinvite',
146
+ call_id: ic.id
147
+ },
148
+ ], 1000)
149
+
150
+ sip.call.respond(ic.id, {code: 200, reason: 'OK'})
151
+
152
+ await z.wait([
153
+ {
154
+ event: 'response',
155
+ call_id: oc.id,
156
+ method: 'INVITE',
157
+ msg: sip_msg({
158
+ $rs: '100',
159
+ }),
160
+ },
161
+ {
162
+ event: 'response',
163
+ call_id: oc.id,
164
+ method: 'INVITE',
165
+ msg: sip_msg({
166
+ $rs: '200',
167
+ $rr: 'OK',
168
+ $rb: '!{_}a=sendrecv!{_}',
169
+ }),
170
+ },
171
+ {
172
+ event: 'media_update',
173
+ call_id: oc.id,
174
+ status: 'ok',
175
+ },
176
+ {
177
+ event: 'media_update',
178
+ call_id: ic.id,
179
+ status: 'ok',
180
+ },
181
+ ], 500)
182
+
183
+ oc_stat = sip.call.get_stream_stat(oc.id, {media_id: 0})
184
+ ic_stat = sip.call.get_stream_stat(ic.id, {media_id: 0})
185
+
186
+ console.log(oc_stat)
187
+ console.log(ic_stat)
188
+
189
+ oc_stat = JSON.parse(oc_stat)
190
+ ic_stat = JSON.parse(ic_stat)
191
+
192
+ assert(oc_stat.CodecInfo == 'GSM/8000/1')
193
+ assert(ic_stat.CodecInfo == 'GSM/8000/1')
194
+
195
+ sip.call.stop_record_wav(oc.id)
196
+ sip.call.stop_record_wav(ic.id)
197
+
198
+ sip.call.terminate(oc.id)
199
+
200
+ await z.wait([
201
+ {
202
+ event: 'call_ended',
203
+ call_id: oc.id,
204
+ },
205
+ {
206
+ event: 'call_ended',
207
+ call_id: ic.id,
208
+ },
209
+ {
210
+ event: 'response',
211
+ call_id: oc.id,
212
+ method: 'BYE',
213
+ msg: sip_msg({
214
+ $rs: '200',
215
+ $rr: 'OK',
216
+ }),
217
+ },
218
+ ], 1000)
219
+
220
+ console.log("Success")
221
+
222
+ sip.stop()
223
+ process.exit(0)
224
+ }
225
+
226
+ test()
227
+ .catch(e => {
228
+ console.error(e)
229
+ process.exit(1)
230
+ })