sip-lab 1.12.38 → 1.13.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.
Files changed (40) hide show
  1. package/DEV.md +27 -2
  2. package/README.md +3 -2
  3. package/binding.gyp +97 -86
  4. package/build_deps.sh +2 -1
  5. package/index.js +14 -7
  6. package/package.json +7 -2
  7. package/prebuilds/linux-x64/node.abi102.node +0 -0
  8. package/prebuilds/linux-x64/node.abi108.node +0 -0
  9. package/prebuilds/linux-x64/node.abi88.node +0 -0
  10. package/prebuilds/linux-x64/node.abi93.node +0 -0
  11. package/samples/16_audio_streams.js +179 -0
  12. package/samples/delayed_media.js +117 -81
  13. package/samples/g729.js +50 -28
  14. package/samples/mrcp_and_audio.js +445 -0
  15. package/samples/mrcp_and_audio.simplified_media.js +273 -0
  16. package/samples/mrcp_and_audio.switching_order.js +273 -0
  17. package/samples/options.js +82 -0
  18. package/samples/refer.js +247 -0
  19. package/samples/refuse_telephone_event.js +166 -0
  20. package/samples/register_no_expires.js +82 -0
  21. package/samples/register_subscribe.js +36 -4
  22. package/samples/reinvite_and_dtmf.js +236 -161
  23. package/samples/reinvite_audio_audio.js +320 -0
  24. package/samples/reinvite_with_hold_unhold.js +412 -0
  25. package/samples/send_and_receive_fax.js +4 -8
  26. package/samples/simple.js +5 -9
  27. package/samples/sip_cancel.js +4 -6
  28. package/samples/tcp_and_extra_headers.js +98 -45
  29. package/samples/two_audio_media.js +497 -0
  30. package/src/addon.cpp +488 -268
  31. package/src/event_templates.cpp +84 -35
  32. package/src/event_templates.hpp +22 -12
  33. package/src/idmanager.cpp +58 -57
  34. package/src/idmanager.hpp +10 -10
  35. package/src/log.cpp +9 -11
  36. package/src/log.hpp +4 -4
  37. package/src/sip.cpp +6838 -5041
  38. package/src/sip.hpp +26 -34
  39. package/src/packetdumper.cpp +0 -234
  40. package/src/packetdumper.hpp +0 -67
@@ -0,0 +1,273 @@
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
+
7
+ async function test() {
8
+ sip.set_log_level(9)
9
+
10
+ //sip.set_log_level(6)
11
+ sip.dtmf_aggregation_on(500)
12
+
13
+ z.trap_events(sip.event_source, 'event', (evt) => {
14
+ var e = evt.args[0]
15
+ return e
16
+ })
17
+
18
+ console.log(sip.start((data) => { console.log(data)} ))
19
+
20
+ t1 = sip.transport.create({address: "127.0.0.1", port: 5090, type: 'udp'})
21
+ t2 = sip.transport.create({address: "127.0.0.1", port: 5092, type: 'udp'})
22
+
23
+ console.log("t1", t1)
24
+ console.log("t2", t2)
25
+
26
+ oc = sip.call.create(t1.id, {from_uri: 'sip:alice@test.com', to_uri: `sip:bob@${t2.address}:${t2.port}`, media: [{type: 'mrcp'}, {type: 'audio'}]})
27
+
28
+ await z.wait([
29
+ {
30
+ event: "incoming_call",
31
+ call_id: m.collect("call_id"),
32
+ },
33
+ {
34
+ event: 'response',
35
+ call_id: oc.id,
36
+ method: 'INVITE',
37
+ msg: sip_msg({
38
+ $rs: '100',
39
+ $rr: 'Trying',
40
+ '$(hdrcnt(via))': 1,
41
+ '$hdr(call-id)': m.collect('sip_call_id'),
42
+ $fU: 'alice',
43
+ $fd: 'test.com',
44
+ $tU: 'bob',
45
+ '$hdr(l)': '0',
46
+ }),
47
+ },
48
+ ], 1000)
49
+
50
+ ic = {
51
+ id: z.store.call_id,
52
+ sip_call_id: z.store.sip_call_id,
53
+ }
54
+
55
+ sip.call.respond(ic.id, {code: 200, reason: 'OK', media: [{type: 'audio'}, {type: 'mrcp'}]})
56
+
57
+ await z.wait([
58
+ {
59
+ event: 'response',
60
+ call_id: oc.id,
61
+ method: 'INVITE',
62
+ msg: sip_msg({
63
+ $rs: '200',
64
+ $rr: 'OK',
65
+ '$(hdrcnt(VIA))': 1,
66
+ $fU: 'alice',
67
+ $fd: 'test.com',
68
+ $tU: 'bob',
69
+ '$hdr(content-type)': 'application/sdp',
70
+ $rb: '!{_}a=sendrecv',
71
+ }),
72
+ },
73
+ {
74
+ event: 'media_update',
75
+ call_id: oc.id,
76
+ status: 'ok',
77
+ media: [
78
+ {
79
+ type: 'mrcp',
80
+ local: {
81
+ port: 9
82
+ },
83
+ remote: {
84
+ port: m.collect('mrcp_server_port')
85
+ }
86
+ },
87
+ {
88
+ type: 'audio',
89
+ local: {
90
+ port: 10000,
91
+ mode: 'sendrecv'
92
+ },
93
+ remote: {
94
+ port: 10002,
95
+ mode: 'sendrecv'
96
+ }
97
+ },
98
+ ],
99
+ },
100
+ {
101
+ event: 'media_update',
102
+ call_id: ic.id,
103
+ status: 'ok',
104
+ media: [
105
+ {
106
+ type: 'mrcp',
107
+ local: {
108
+ port: m.collect('mrcp_server_port')
109
+ },
110
+ remote: {
111
+ port: 9
112
+ }
113
+ },
114
+ {
115
+ type: 'audio',
116
+ local: {
117
+ port: 10002,
118
+ mode: 'sendrecv'
119
+ },
120
+ remote: {
121
+ port: 10000,
122
+ mode: 'sendrecv'
123
+ }
124
+ },
125
+ ],
126
+ },
127
+ ], 1000)
128
+
129
+ sip.call.send_dtmf(oc.id, {digits: '1234', mode: 0})
130
+ sip.call.send_dtmf(ic.id, {digits: '4321', mode: 1})
131
+
132
+ await z.wait([
133
+ {
134
+ event: 'dtmf',
135
+ call_id: ic.id,
136
+ digits: '1234',
137
+ mode: 0,
138
+ media_id: 1
139
+ },
140
+ {
141
+ event: 'dtmf',
142
+ call_id: oc.id,
143
+ digits: '4321',
144
+ mode: 1,
145
+ media_id: 1
146
+ },
147
+ ], 1500)
148
+
149
+ for(i=0 ;i< 1; i++) {
150
+ //await z.sleep(100)
151
+ sip.call.reinvite(oc.id, {media: [{type: 'mrcp'}, {type: 'audio'}]})
152
+
153
+ await z.wait([
154
+ {
155
+ event: 'reinvite',
156
+ call_id: ic.id,
157
+ },
158
+ ], 500)
159
+
160
+ sip.call.respond(ic.id, {code: 200, reason: 'OK', media: [{type: 'audio'}, {type: 'mrcp'}]})
161
+
162
+ await z.wait([
163
+ {
164
+ event: 'response',
165
+ call_id: oc.id,
166
+ method: 'INVITE',
167
+ msg: sip_msg({
168
+ $rs: '100',
169
+ }),
170
+ },
171
+ {
172
+ event: 'response',
173
+ call_id: oc.id,
174
+ method: 'INVITE',
175
+ msg: sip_msg({
176
+ $rs: '200',
177
+ $rr: 'OK',
178
+ $rb: '!{_}a=sendrecv',
179
+ }),
180
+ },
181
+ {
182
+ event: 'media_update',
183
+ call_id: oc.id,
184
+ status: 'ok',
185
+ },
186
+ {
187
+ event: 'media_update',
188
+ call_id: ic.id,
189
+ status: 'ok',
190
+ },
191
+ ], 500)
192
+
193
+ //await z.sleep(100)
194
+ sip.call.reinvite(ic.id, {media: [{type: 'mrcp'}, {type: 'audio'}]})
195
+
196
+ await z.wait([
197
+ {
198
+ event: 'reinvite',
199
+ call_id: oc.id,
200
+ },
201
+ ], 500)
202
+
203
+ sip.call.respond(oc.id, {code: 200, reason: 'OK', media: [{type: 'audio'}, {type: 'mrcp'}]})
204
+
205
+ await z.wait([
206
+ {
207
+ event: 'response',
208
+ call_id: ic.id,
209
+ method: 'INVITE',
210
+ msg: sip_msg({
211
+ $rs: '100',
212
+ }),
213
+ },
214
+ {
215
+ event: 'response',
216
+ call_id: ic.id,
217
+ method: 'INVITE',
218
+ msg: sip_msg({
219
+ $rs: '200',
220
+ $rr: 'OK',
221
+ }),
222
+ },
223
+ {
224
+ event: 'media_update',
225
+ call_id: oc.id,
226
+ status: 'ok',
227
+ },
228
+ {
229
+ event: 'media_update',
230
+ call_id: ic.id,
231
+ status: 'ok',
232
+ },
233
+ ], 500)
234
+
235
+ //await z.sleep(100)
236
+ }
237
+
238
+ await z.sleep(1000) // we need this delay otherwise, frequently the app will crash after this point.
239
+
240
+ sip.call.terminate(oc.id)
241
+
242
+ await z.wait([
243
+ {
244
+ event: 'call_ended',
245
+ call_id: oc.id,
246
+ },
247
+ {
248
+ event: 'call_ended',
249
+ call_id: ic.id,
250
+ },
251
+ {
252
+ event: 'response',
253
+ call_id: oc.id,
254
+ method: 'BYE',
255
+ msg: sip_msg({
256
+ $rs: '200',
257
+ $rr: 'OK',
258
+ }),
259
+ },
260
+ ], 1000)
261
+
262
+ console.log("Success")
263
+
264
+ sip.stop()
265
+ }
266
+
267
+
268
+ test()
269
+ .catch(e => {
270
+ console.error(e)
271
+ process.exit(1)
272
+ })
273
+
@@ -0,0 +1,82 @@
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 assert = require('assert')
7
+
8
+ async function test() {
9
+ sip.set_log_level(9)
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", port: 5090, type: 'udp'})
20
+ t2 = sip.transport.create({address: "127.0.0.1", port: 5092, type: 'udp'})
21
+
22
+ console.log("t1", t1)
23
+ console.log("t2", t2)
24
+
25
+ var server = `${t2.address}:${t2.port}`
26
+ var domain = 'test1.com'
27
+
28
+ var uac_req = sip.request.create(t1.id, {
29
+ method: 'OPTIONS',
30
+ from_uri: `sip:alice@${domain}`,
31
+ to_uri: `sip:bob@${domain}`,
32
+ request_uri: `sip:bob@${t2.address}:${t2.port}`,
33
+ headers: {
34
+ 'X-MyHeader1': 'aaa',
35
+ 'X-MyHeader2': 'bbb',
36
+ },
37
+ })
38
+
39
+ await z.wait([
40
+ {
41
+ event: 'non_dialog_request',
42
+ request_id: m.collect('uas_req_id'),
43
+ msg: sip_msg({
44
+ $rm: 'OPTIONS',
45
+ $fU: 'alice',
46
+ $fd: domain,
47
+ $tU: 'bob',
48
+ $td: domain,
49
+ '$hdr(X-MyHeader1)': 'aaa',
50
+ 'hdr_x_myheader2': 'bbb',
51
+ }),
52
+ },
53
+ ], 1000)
54
+
55
+ sip.request.respond(z.store.uas_req_id, {code: 200, reason: 'OK', headers: {'X-SomeHeader1': 'ccc', 'X-SomeHeader2': 'ddd'}})
56
+
57
+ await z.wait([
58
+ {
59
+ event: 'response',
60
+ request_id: uac_req.id,
61
+ method: 'OPTIONS',
62
+ msg: sip_msg({
63
+ $rs: '200',
64
+ $rr: 'OK',
65
+ hdr_x_someheader1: 'ccc',
66
+ hdr_x_someheader2: 'ddd',
67
+ }),
68
+ },
69
+ ], 1000)
70
+
71
+ console.log("Success")
72
+
73
+ sip.stop()
74
+ }
75
+
76
+
77
+ test()
78
+ .catch(e => {
79
+ console.error(e)
80
+ process.exit(1)
81
+ })
82
+
@@ -0,0 +1,247 @@
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
+ // here we create our Zeq instance
9
+ var z = new Zeq()
10
+
11
+
12
+ async function test() {
13
+ // here we set our Zeq instance to trap events generated by sip-lab event_source
14
+ z.trap_events(sip.event_source, 'event', (evt) => {
15
+ var e = evt.args[0]
16
+ return e
17
+ })
18
+
19
+ // here we start sip-lab
20
+ console.log(sip.start((data) => { console.log(data)} ))
21
+
22
+ // Here we create the SIP endpoints (transports).
23
+ // Since we don't specify the port, an available port will be allocated.
24
+ // Since we don't specify the type ('udp' or 'tcp' or 'tls'), 'udp' will be used by default.
25
+ const t1 = sip.transport.create({address: "127.0.0.1"})
26
+ const t2 = sip.transport.create({address: "127.0.0.1"})
27
+
28
+ // here we just print the transports
29
+ console.log("t1", t1)
30
+ console.log("t2", t2)
31
+
32
+ // make the call from t1 to t2
33
+ const oc = sip.call.create(t1.id, {from_uri: 'sip:alice@test.com', to_uri: `sip:bob@${t2.address}:${t2.port}`})
34
+
35
+ // Here we will wait for the call to arrive at t2
36
+ // We will also get a '100 Trying' that is sent by sip-lab automatically
37
+ // 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.
38
+ await z.wait([
39
+ {
40
+ event: "incoming_call",
41
+ call_id: m.collect("call_id"),
42
+ transport_id: t2.id,
43
+ },
44
+ {
45
+ event: 'response',
46
+ call_id: oc.id,
47
+ method: 'INVITE',
48
+ msg: sip_msg({
49
+ $rs: '100',
50
+ $rr: 'Trying',
51
+ '$(hdrcnt(via))': 1,
52
+ '$hdr(call-id)': m.collect('sip_call_id'),
53
+ $fU: 'alice',
54
+ $fd: 'test.com',
55
+ $tU: 'bob',
56
+ '$hdr(l)': '0',
57
+ }),
58
+ },
59
+ ], 1000)
60
+ // Details about zeq wait(list_of_events_to_wait_for, timeout_in_ms):
61
+ // The order of events in the list is irrelevant.
62
+ // What matters is that all events arrive within the specified timeout.
63
+ // When specifying events, you can be as detailed or succinct as you need.
64
+ // For example, the above event 'response' is waiting for a SIP '100 Trying' to arrive,
65
+ // but we are specifying things to match just to show that we can be very detailed when performing a match.
66
+ // But it could have been just like this:
67
+ //
68
+ // {
69
+ // event: 'response',
70
+ // call_id: oc.id,
71
+ // method: 'INVITE',
72
+ // msg: sip_msg({
73
+ // $rs: '100',
74
+ // }),
75
+ // }
76
+ // Regarding the function sip_msg() this is a special matching function provided by https://github.com/MayamaTakeshi/sip-matching that makes it
77
+ // easy to match a SIP message using openser/kamailio/opensips pseudo-variables syntax.
78
+
79
+
80
+ // Here we store data for the incoming call
81
+ // just to organize our code (not really needed)
82
+ const ic = {
83
+ id: z.store.call_id,
84
+ sip_call_id: z.store.sip_call_id,
85
+ }
86
+
87
+ // Now we answer the call at t2 side
88
+ sip.call.respond(ic.id, {code: 200, reason: 'OK'})
89
+
90
+ // Then we wait for the '200 OK' at the t1 side
91
+ // We will also get event 'media_update' for both sides indicating media streams (RTP) were set up successfully
92
+ await z.wait([
93
+ {
94
+ event: 'response',
95
+ call_id: oc.id,
96
+ method: 'INVITE',
97
+ msg: sip_msg({
98
+ $rs: '200',
99
+ $rr: 'OK',
100
+ '$(hdrcnt(VIA))': 1,
101
+ $fU: 'alice',
102
+ $fd: 'test.com',
103
+ $tU: 'bob',
104
+ '$hdr(content-type)': 'application/sdp',
105
+ $rb: '!{_}a=sendrecv',
106
+ }),
107
+ },
108
+ {
109
+ event: 'media_update',
110
+ call_id: oc.id,
111
+ status: 'ok',
112
+ },
113
+ {
114
+ event: 'media_update',
115
+ call_id: ic.id,
116
+ status: 'ok',
117
+ },
118
+ ], 1000)
119
+
120
+ sip.call.send_request(oc.id, {method: 'REFER', headers: {'Refer-To': '0312341234'}})
121
+
122
+ await z.wait([
123
+ {
124
+ event: 'request',
125
+ call_id: ic.id,
126
+ msg: sip_msg({
127
+ $rm: 'REFER',
128
+ hdr_refer_to: '0312341234',
129
+ }),
130
+ },
131
+ ], 1000)
132
+
133
+ sip.call.respond(ic.id, {code: 202, reason: 'Accepted'})
134
+
135
+ await z.wait([
136
+ {
137
+ event: 'response',
138
+ call_id: oc.id,
139
+ msg: sip_msg({
140
+ $rm: 'REFER',
141
+ $rs: '202',
142
+ $rr: 'Accepted',
143
+ }),
144
+ },
145
+ ], 1000)
146
+
147
+ sip.call.send_request(ic.id, {method: 'NOTIFY', headers: {
148
+ 'Event': 'refer',
149
+ 'Subscription-State': 'active;expires=60',
150
+ }, body: 'SIP/2.0 100 Trying', ct_type: 'message', ct_subtype: 'sipfrag;version=2.0'})
151
+
152
+ await z.wait([
153
+ {
154
+ event: 'request',
155
+ call_id: oc.id,
156
+ msg: sip_msg({
157
+ $rm: 'NOTIFY',
158
+ hdr_subscription_state: 'active;expires=60',
159
+ hdr_content_type: 'message/sipfrag;version=2.0',
160
+ $rb: 'SIP/2.0 100 Trying',
161
+ }),
162
+ },
163
+ ], 1000)
164
+
165
+ sip.call.respond(oc.id, {code: 200, reason: 'OK'})
166
+
167
+ await z.wait([
168
+ {
169
+ event: 'response',
170
+ call_id: ic.id,
171
+ msg: sip_msg({
172
+ $rm: 'NOTIFY',
173
+ $rs: '200',
174
+ $rr: 'OK',
175
+ }),
176
+ },
177
+ ], 1000)
178
+
179
+ sip.call.send_request(ic.id, {method: 'NOTIFY', headers: {'Event': 'refer',
180
+ 'Subscription-State': 'terminated;reason=noresource',
181
+ }, body: 'SIP/2.0 200 OK', ct_type: 'message', ct_subtype: 'sipfrag;version=2.0'})
182
+
183
+ await z.wait([
184
+ {
185
+ event: 'request',
186
+ call_id: oc.id,
187
+ msg: sip_msg({
188
+ $rm: 'NOTIFY',
189
+ hdr_subscription_state: 'terminated;reason=noresource',
190
+ hdr_content_type: 'message/sipfrag;version=2.0',
191
+ $rb: 'SIP/2.0 200 OK',
192
+ }),
193
+ },
194
+ ], 1000)
195
+
196
+ sip.call.respond(oc.id, {code: 200, reason: 'OK'})
197
+
198
+ await z.wait([
199
+ {
200
+ event: 'response',
201
+ call_id: ic.id,
202
+ msg: sip_msg({
203
+ $rm: 'NOTIFY',
204
+ $rs: '200',
205
+ $rr: 'OK',
206
+ }),
207
+ },
208
+ ], 1000)
209
+
210
+ await z.sleep(100)
211
+
212
+ // now we terminate the call from t1 side
213
+ sip.call.terminate(oc.id)
214
+
215
+ // and wait for termination events
216
+ await z.wait([
217
+ {
218
+ event: 'response',
219
+ call_id: oc.id,
220
+ method: 'BYE',
221
+ msg: sip_msg({
222
+ $rs: '200',
223
+ $rr: 'OK',
224
+ }),
225
+ },
226
+ {
227
+ event: 'call_ended',
228
+ call_id: oc.id,
229
+ },
230
+ {
231
+ event: 'call_ended',
232
+ call_id: ic.id,
233
+ },
234
+ ], 1000)
235
+
236
+ console.log("Success")
237
+
238
+ sip.stop()
239
+ }
240
+
241
+
242
+ test()
243
+ .catch(e => {
244
+ console.error(e)
245
+ process.exit(1)
246
+ })
247
+