sip-lab 1.21.0 → 1.23.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/README.md CHANGED
@@ -7,15 +7,19 @@ It uses pjproject for SIP and media processing.
7
7
 
8
8
  It permits to:
9
9
  - make audio calls using UDP, TCP and TLS transports
10
- - send and receive DTMF inband/RFC2833/INFO.
11
- - play/record wav file on a call
10
+ - send/receive DTMF inband/RFC2833/INFO.
11
+ - play/record audio on a call from/to a wav file
12
12
  - send/receive fax (T.30 only)
13
13
  - send/receive MRCPv2 messages (TCP only, no TLS)
14
+ - send/receive audio using SRTP
15
+ - generate speech from text into a call (using flite)
14
16
 
15
17
  TODO:
16
18
  - add support for video playing/recording from/to file
19
+ - add support for speech recognition using pocketsphinx
20
+ - add support for speech synth/recog via websocket server
17
21
  - add support for T.38 fax
18
- - add support for WebSocket
22
+ - add support for SIP over WebSocket
19
23
  - add support for WebRTC
20
24
  - add support for MSRP
21
25
 
@@ -26,7 +30,7 @@ It is distributed with prebuild binaries for node.js 15.0.0 and above (but built
26
30
 
27
31
  To install it, first install build dependencies:
28
32
  ```
29
- 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
33
+ 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 flite-dev cmake
30
34
  ```
31
35
 
32
36
  Then install sip-lab (local build of the addon might be triggered here if this is not Debian 11):
package/binding.gyp CHANGED
@@ -80,6 +80,12 @@
80
80
  '-lswscale',
81
81
  '-lavutil',
82
82
  '-lspeex',
83
+ '-lflite',
84
+ '-lflite_cmu_us_awb',
85
+ '-lflite_cmu_us_kal',
86
+ '-lflite_cmu_us_rms',
87
+ '-lflite_cmu_us_slt',
88
+ '-lflite_cmu_us_kal16',
83
89
  '-l srtp-x86_64-unknown-linux-gnu',
84
90
  ],
85
91
  },
@@ -109,6 +115,7 @@
109
115
  'src/addon.cpp',
110
116
  'src/pjmedia/src/pjmedia/dtmfdet.c',
111
117
  'src/pjmedia/src/pjmedia/fax_port.c',
118
+ 'src/pjmedia/src/pjmedia/flite_port.c',
112
119
  ],
113
120
  },
114
121
  ],
package/build_deps.sh CHANGED
@@ -55,7 +55,8 @@ then
55
55
  #git checkout 33a3c9e0a5eb84426edef05a9aa98af17d8011c3 # required for bcg729
56
56
  #git checkout 797088ed133c98492519b7d042b75735f6f9388c # updated as part of #21
57
57
  #git checkout 651df5b50129b7c5a5feec8336dda4468d53d2b0 # updated to latest to see of crash issues improve
58
- git checkout 043926a5846963a2c99378e8daa495230923eaab # update to try to solve ##49 (but issue remains)
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)
59
60
 
60
61
  cat > user.mak <<EOF
61
62
  export CFLAGS += -fPIC -g
package/index.js CHANGED
@@ -66,6 +66,8 @@ addon.call = {
66
66
  stop_play_wav: (c_id, params) => { return addon.call_stop_play_wav(c_id, JSON.stringify(params ? params : {})) },
67
67
  start_fax: (c_id, params) => { return addon.call_start_fax(c_id, JSON.stringify(params)) },
68
68
  stop_fax: (c_id, params) => { return addon.call_stop_fax(c_id, JSON.stringify(params ? params : {})) },
69
+ start_speech_synth: (c_id, params) => { return addon.call_start_speech_synth(c_id, JSON.stringify(params)) },
70
+ stop_speech_synth: (c_id, params) => { return addon.call_stop_speech_synth(c_id, JSON.stringify(params ? params : {})) },
69
71
  get_stream_stat: (c_id, params) => { return addon.call_get_stream_stat(c_id, JSON.stringify(params ? params : {})) },
70
72
  //refer: (c_id, params) => { return addon.call_refer(c_id, JSON.stringify(params)) },
71
73
  get_info: addon.call_get_info,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sip-lab",
3
- "version": "1.21.0",
3
+ "version": "1.23.0",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "engines": {
Binary file
@@ -0,0 +1,269 @@
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
+ async function test() {
9
+ //sip.set_log_level(6)
10
+ sip.dtmf_aggregation_on(500)
11
+
12
+ z.trap_events(sip.event_source, 'event', (evt) => {
13
+ var e = evt.args[0]
14
+ return e
15
+ })
16
+
17
+ console.log(sip.start((data) => { console.log(data)} ))
18
+
19
+ t1 = sip.transport.create({address: "127.0.0.1"})
20
+ t2 = sip.transport.create({address: "127.0.0.1"})
21
+
22
+ console.log("t1", t1)
23
+ console.log("t2", t2)
24
+
25
+ oc = sip.call.create(t1.id, {
26
+ from_uri: '"abc"<sip:alice@test.com>',
27
+ to_uri: `sip:bob@${t2.address}:${t2.port}`,
28
+ headers: {
29
+ 'X-MyHeader1': 'abc',
30
+ 'X-MyHeader2': 'def',
31
+ },
32
+ })
33
+
34
+ await z.wait([
35
+ {
36
+ event: "incoming_call",
37
+ call_id: m.collect("call_id"),
38
+ msg: sip_msg({
39
+ $rm: 'INVITE',
40
+ $fU: 'alice',
41
+ $fd: 'test.com',
42
+ $tU: 'bob',
43
+ '$hdr(X-MyHeader1)': 'abc',
44
+ 'hdr_x_myheader2': 'def',
45
+ }),
46
+ },
47
+ {
48
+ event: 'response',
49
+ call_id: oc.id,
50
+ method: 'INVITE',
51
+ msg: sip_msg({
52
+ $rs: '100',
53
+ $rr: 'Trying',
54
+ '$(hdrcnt(via))': 1,
55
+ 'hdr_call_id': m.collect('sip_call_id'),
56
+ $fU: 'alice',
57
+ $fd: 'test.com',
58
+ $tU: 'bob',
59
+ '$hdr(l)': '0',
60
+ }),
61
+ },
62
+ ], 1000)
63
+
64
+ ic = {
65
+ id: z.store.call_id,
66
+ sip_call_id: z.store.sip_call_id,
67
+ }
68
+
69
+ sip.call.respond(ic.id, {
70
+ code: 200,
71
+ reason:'OK',
72
+ headers: {
73
+ 'X-MyHeader3': 'ghi',
74
+ 'X-MyHeader4': 'jkl',
75
+ },
76
+ })
77
+
78
+ await z.wait([
79
+ {
80
+ event: 'media_update',
81
+ call_id: oc.id,
82
+ status: 'ok',
83
+ },
84
+ {
85
+ event: 'media_update',
86
+ call_id: ic.id,
87
+ status: 'ok',
88
+ },
89
+ {
90
+ event: 'response',
91
+ call_id: oc.id,
92
+ method: 'INVITE',
93
+ msg: sip_msg({
94
+ $rs: '200',
95
+ $rr: 'OK',
96
+ '$(hdrcnt(v))': 1,
97
+ $fU: 'alice',
98
+ $fd: 'test.com',
99
+ $tU: 'bob',
100
+ '$hdr(content-type)': 'application/sdp',
101
+ $rb: '!{_}a=sendrecv',
102
+ '$hdr(X-MyHeader3)': 'ghi',
103
+ '$hdr(X-MyHeader4)': 'jkl',
104
+ }),
105
+ },
106
+ ], 1000)
107
+
108
+ sip.call.start_record_wav(oc.id, {file: './oc.wav'})
109
+ sip.call.start_record_wav(ic.id, {file: './ic.wav'})
110
+
111
+ await z.sleep(100)
112
+
113
+ sip.call.start_play_wav(oc.id, {file: 'samples/artifacts/yosemitesam.wav', end_of_file_event: true})
114
+ sip.call.start_play_wav(ic.id, {file: 'samples/artifacts/yosemitesam.wav', end_of_file_event: true})
115
+
116
+ await z.sleep(500)
117
+
118
+ sip.call.reinvite(oc.id)
119
+
120
+ await z.wait([
121
+ {
122
+ event: 'reinvite',
123
+ call_id: ic.id
124
+ },
125
+ ], 1000)
126
+
127
+ sip.call.respond(ic.id, {code: 200, reason: 'OK'})
128
+
129
+ await z.wait([
130
+ {
131
+ event: 'response',
132
+ call_id: oc.id,
133
+ method: 'INVITE',
134
+ msg: sip_msg({
135
+ $rs: '100',
136
+ }),
137
+ },
138
+ {
139
+ event: 'response',
140
+ call_id: oc.id,
141
+ method: 'INVITE',
142
+ msg: sip_msg({
143
+ $rs: '200',
144
+ $rr: 'OK',
145
+ $rb: '!{_}a=sendrecv',
146
+ }),
147
+ },
148
+ {
149
+ event: 'media_update',
150
+ call_id: oc.id,
151
+ status: 'ok',
152
+ },
153
+ {
154
+ event: 'media_update',
155
+ call_id: ic.id,
156
+ status: 'ok',
157
+ },
158
+ ], 500)
159
+
160
+ await z.wait([
161
+ {
162
+ event: 'end_of_file',
163
+ call_id: ic.id,
164
+ },
165
+ {
166
+ event: 'end_of_file',
167
+ call_id: oc.id,
168
+ },
169
+ ], 2000)
170
+
171
+
172
+ sip.call.reinvite(ic.id)
173
+
174
+ await z.wait([
175
+ {
176
+ event: 'reinvite',
177
+ call_id: oc.id
178
+ },
179
+ ], 1000)
180
+
181
+ sip.call.respond(oc.id, {code: 200, reason: 'OK'})
182
+
183
+ await z.wait([
184
+ {
185
+ event: 'response',
186
+ call_id: ic.id,
187
+ method: 'INVITE',
188
+ msg: sip_msg({
189
+ $rs: '100',
190
+ }),
191
+ },
192
+ {
193
+ event: 'response',
194
+ call_id: ic.id,
195
+ method: 'INVITE',
196
+ msg: sip_msg({
197
+ $rs: '200',
198
+ $rr: 'OK',
199
+ $rb: '!{_}a=sendrecv',
200
+ }),
201
+ },
202
+ {
203
+ event: 'media_update',
204
+ call_id: oc.id,
205
+ status: 'ok',
206
+ },
207
+ {
208
+ event: 'media_update',
209
+ call_id: ic.id,
210
+ status: 'ok',
211
+ },
212
+ ], 500)
213
+
214
+ await z.wait([
215
+ {
216
+ event: 'end_of_file',
217
+ call_id: ic.id,
218
+ },
219
+ {
220
+ event: 'end_of_file',
221
+ call_id: oc.id,
222
+ },
223
+ ], 5000)
224
+
225
+ stat1 = sip.call.get_stream_stat(oc.id, {media_id: 0})
226
+ stat2 = sip.call.get_stream_stat(ic.id, {media_id: 0})
227
+
228
+ console.log("stat1", stat1)
229
+ console.log("stat2", stat2)
230
+
231
+ sip.call.stop_record_wav(oc.id)
232
+ sip.call.stop_record_wav(ic.id)
233
+
234
+ sip.call.terminate(oc.id)
235
+
236
+ await z.wait([
237
+ {
238
+ event: 'call_ended',
239
+ call_id: oc.id,
240
+ },
241
+ {
242
+ event: 'call_ended',
243
+ call_id: ic.id,
244
+ },
245
+ {
246
+ event: 'response',
247
+ call_id: oc.id,
248
+ method: 'BYE',
249
+ msg: sip_msg({
250
+ $rs: '200',
251
+ $rr: 'OK',
252
+ }),
253
+ },
254
+ ], 1000)
255
+
256
+ await z.sleep(1000)
257
+
258
+ console.log("Success")
259
+
260
+ sip.stop()
261
+ }
262
+
263
+
264
+ test()
265
+ .catch(e => {
266
+ console.error(e)
267
+ process.exit(1)
268
+ })
269
+
@@ -0,0 +1,257 @@
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
+ async function test() {
9
+ //sip.set_log_level(6)
10
+ sip.dtmf_aggregation_on(500)
11
+
12
+ z.trap_events(sip.event_source, 'event', (evt) => {
13
+ var e = evt.args[0]
14
+ return e
15
+ })
16
+
17
+ console.log(sip.start((data) => { console.log(data)} ))
18
+
19
+ t1 = sip.transport.create({address: "127.0.0.1"})
20
+ t2 = sip.transport.create({address: "127.0.0.1"})
21
+
22
+ console.log("t1", t1)
23
+ console.log("t2", t2)
24
+
25
+ oc = sip.call.create(t1.id, {
26
+ from_uri: '"abc"<sip:alice@test.com>',
27
+ to_uri: `sip:bob@${t2.address}:${t2.port}`,
28
+ headers: {
29
+ 'X-MyHeader1': 'abc',
30
+ 'X-MyHeader2': 'def',
31
+ },
32
+ })
33
+
34
+ await z.wait([
35
+ {
36
+ event: "incoming_call",
37
+ call_id: m.collect("call_id"),
38
+ msg: sip_msg({
39
+ $rm: 'INVITE',
40
+ $fU: 'alice',
41
+ $fd: 'test.com',
42
+ $tU: 'bob',
43
+ '$hdr(X-MyHeader1)': 'abc',
44
+ 'hdr_x_myheader2': 'def',
45
+ }),
46
+ },
47
+ {
48
+ event: 'response',
49
+ call_id: oc.id,
50
+ method: 'INVITE',
51
+ msg: sip_msg({
52
+ $rs: '100',
53
+ $rr: 'Trying',
54
+ '$(hdrcnt(via))': 1,
55
+ 'hdr_call_id': m.collect('sip_call_id'),
56
+ $fU: 'alice',
57
+ $fd: 'test.com',
58
+ $tU: 'bob',
59
+ '$hdr(l)': '0',
60
+ }),
61
+ },
62
+ ], 1000)
63
+
64
+ ic = {
65
+ id: z.store.call_id,
66
+ sip_call_id: z.store.sip_call_id,
67
+ }
68
+
69
+ sip.call.respond(ic.id, {
70
+ code: 200,
71
+ reason:'OK',
72
+ headers: {
73
+ 'X-MyHeader3': 'ghi',
74
+ 'X-MyHeader4': 'jkl',
75
+ },
76
+ })
77
+
78
+ await z.wait([
79
+ {
80
+ event: 'media_update',
81
+ call_id: oc.id,
82
+ status: 'ok',
83
+ },
84
+ {
85
+ event: 'media_update',
86
+ call_id: ic.id,
87
+ status: 'ok',
88
+ },
89
+ {
90
+ event: 'response',
91
+ call_id: oc.id,
92
+ method: 'INVITE',
93
+ msg: sip_msg({
94
+ $rs: '200',
95
+ $rr: 'OK',
96
+ '$(hdrcnt(v))': 1,
97
+ $fU: 'alice',
98
+ $fd: 'test.com',
99
+ $tU: 'bob',
100
+ '$hdr(content-type)': 'application/sdp',
101
+ $rb: '!{_}a=sendrecv',
102
+ '$hdr(X-MyHeader3)': 'ghi',
103
+ '$hdr(X-MyHeader4)': 'jkl',
104
+ }),
105
+ },
106
+ ], 1000)
107
+
108
+ sip.call.start_record_wav(oc.id, {file: './oc.wav'})
109
+ sip.call.start_record_wav(ic.id, {file: './ic.wav'})
110
+
111
+ await z.sleep(100)
112
+
113
+ sip.call.start_play_wav(oc.id, {file: 'samples/artifacts/yosemitesam.wav', end_of_file_event: true, no_loop: true})
114
+ sip.call.start_play_wav(ic.id, {file: 'samples/artifacts/yosemitesam.wav', end_of_file_event: true, no_loop: true})
115
+
116
+ sip.call.reinvite(oc.id)
117
+
118
+ await z.wait([
119
+ {
120
+ event: 'reinvite',
121
+ call_id: ic.id
122
+ },
123
+ ], 1000)
124
+
125
+ sip.call.respond(ic.id, {code: 200, reason: 'OK'})
126
+
127
+ await z.wait([
128
+ {
129
+ event: 'response',
130
+ call_id: oc.id,
131
+ method: 'INVITE',
132
+ msg: sip_msg({
133
+ $rs: '100',
134
+ }),
135
+ },
136
+ {
137
+ event: 'response',
138
+ call_id: oc.id,
139
+ method: 'INVITE',
140
+ msg: sip_msg({
141
+ $rs: '200',
142
+ $rr: 'OK',
143
+ $rb: '!{_}a=sendrecv',
144
+ }),
145
+ },
146
+ {
147
+ event: 'media_update',
148
+ call_id: oc.id,
149
+ status: 'ok',
150
+ },
151
+ {
152
+ event: 'media_update',
153
+ call_id: ic.id,
154
+ status: 'ok',
155
+ },
156
+ ], 500)
157
+
158
+ sip.call.reinvite(ic.id)
159
+
160
+ await z.wait([
161
+ {
162
+ event: 'reinvite',
163
+ call_id: oc.id
164
+ },
165
+ ], 1000)
166
+
167
+ sip.call.respond(oc.id, {code: 200, reason: 'OK'})
168
+
169
+ await z.wait([
170
+ {
171
+ event: 'response',
172
+ call_id: ic.id,
173
+ method: 'INVITE',
174
+ msg: sip_msg({
175
+ $rs: '100',
176
+ }),
177
+ },
178
+ {
179
+ event: 'response',
180
+ call_id: ic.id,
181
+ method: 'INVITE',
182
+ msg: sip_msg({
183
+ $rs: '200',
184
+ $rr: 'OK',
185
+ $rb: '!{_}a=sendrecv',
186
+ }),
187
+ },
188
+ {
189
+ event: 'media_update',
190
+ call_id: oc.id,
191
+ status: 'ok',
192
+ },
193
+ {
194
+ event: 'media_update',
195
+ call_id: ic.id,
196
+ status: 'ok',
197
+ },
198
+ ], 500)
199
+
200
+ await z.wait([
201
+ {
202
+ event: 'end_of_file',
203
+ call_id: ic.id,
204
+ },
205
+ {
206
+ event: 'end_of_file',
207
+ call_id: oc.id,
208
+ },
209
+ ], 3000)
210
+
211
+ await z.sleep(3000) // we should not receive end_of_file events again
212
+
213
+ stat1 = sip.call.get_stream_stat(oc.id, {media_id: 0})
214
+ stat2 = sip.call.get_stream_stat(ic.id, {media_id: 0})
215
+
216
+ console.log("stat1", stat1)
217
+ console.log("stat2", stat2)
218
+
219
+ sip.call.stop_record_wav(oc.id)
220
+ sip.call.stop_record_wav(ic.id)
221
+
222
+ sip.call.terminate(oc.id)
223
+
224
+ await z.wait([
225
+ {
226
+ event: 'call_ended',
227
+ call_id: oc.id,
228
+ },
229
+ {
230
+ event: 'call_ended',
231
+ call_id: ic.id,
232
+ },
233
+ {
234
+ event: 'response',
235
+ call_id: oc.id,
236
+ method: 'BYE',
237
+ msg: sip_msg({
238
+ $rs: '200',
239
+ $rr: 'OK',
240
+ }),
241
+ },
242
+ ], 1000)
243
+
244
+ await z.sleep(1000)
245
+
246
+ console.log("Success")
247
+
248
+ sip.stop()
249
+ }
250
+
251
+
252
+ test()
253
+ .catch(e => {
254
+ console.error(e)
255
+ process.exit(1)
256
+ })
257
+
@@ -345,6 +345,9 @@ async function test() {
345
345
  console.log("stat1", stat1)
346
346
  console.log("stat2", stat2)
347
347
 
348
+ sip.call.stop_play_wav(oc.id) // this is not really necessary. We are just confirming it works
349
+ sip.call.stop_play_wav(ic.id) // this is not really necessary. We are just confirming it works
350
+
348
351
  sip.call.stop_record_wav(oc.id)
349
352
  sip.call.stop_record_wav(ic.id)
350
353