sip-lab 1.14.0 → 1.15.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 CHANGED
@@ -48,14 +48,14 @@ Previously we would do:
48
48
 
49
49
  ```
50
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
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
52
  ```
53
53
  However the above will build the addon to run on the current OS.
54
54
 
55
55
  Instead we will force the build on debian11 (using docker). So do this instead:
56
56
  ```
57
57
  nvm use v16.13.1
58
- npx prebuildify-cross -i mayamatakeshi/sip-lab-debian11:latest -t 15.0.0 -t 16.0.0 -t 17.0.0 -t 18.0.0 --strip
58
+ npx prebuildify-cross -i mayamatakeshi/sip-lab-debian11:latest -t 15.0.0 -t 16.0.0 -t 17.0.0 -t 18.0.0 -t 19.0.0 -t 20.0.0 -t 21.0.0 --strip
59
59
  ```
60
60
 
61
61
  #### Running tests
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sip-lab",
3
- "version": "1.14.0",
3
+ "version": "1.15.0",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "engines": {
@@ -30,7 +30,7 @@
30
30
  "sip-matching": "^1.5.2"
31
31
  },
32
32
  "devDependencies": {
33
- "prebuildify": "^5.0.1",
33
+ "prebuildify": "^6.0.0",
34
34
  "prebuildify-cross": "github:MayamaTakeshi/prebuildify-cross#use_existing_images",
35
35
  "sdp-matching": "^1.3.2"
36
36
  },
Binary file
Binary file
Binary file
@@ -0,0 +1,346 @@
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
+ const sdp = require('sdp-matching')
8
+
9
+ // here we create our Zeq instance
10
+ var z = new Zeq()
11
+
12
+ async function test() {
13
+ sip.dtmf_aggregation_on(500)
14
+
15
+ z.trap_events(sip.event_source, 'event', (evt) => {
16
+ var e = evt.args[0]
17
+ return e
18
+ })
19
+
20
+ // Let's ignore '100 Trying'
21
+ z.add_event_filter({
22
+ event: 'response',
23
+ msg: sip_msg({
24
+ $rs: '100',
25
+ }),
26
+ })
27
+
28
+ console.log(sip.start((data) => { console.log(data)} ))
29
+
30
+ const t1 = sip.transport.create({address: "127.0.0.1"})
31
+ const t2 = sip.transport.create({address: "127.0.0.1"})
32
+
33
+ console.log("t1", t1)
34
+ console.log("t2", t2)
35
+
36
+ const oc = sip.call.create(t1.id, {from_uri: 'sip:alice@test.com', to_uri: `sip:bob@${t2.address}:${t2.port}`,
37
+ media: [
38
+ {
39
+ type: 'audio',
40
+ secure: true,
41
+ },
42
+ ]})
43
+
44
+ await z.wait([
45
+ {
46
+ event: "incoming_call",
47
+ call_id: m.collect("call_id"),
48
+ transport_id: t2.id,
49
+ },
50
+ ], 1000)
51
+
52
+ const ic = {
53
+ id: z.store.call_id,
54
+ sip_call_id: z.store.sip_call_id,
55
+ }
56
+
57
+ sip.call.respond(ic.id, {code: 200, reason: 'OK', media: [
58
+ {
59
+ type: 'audio',
60
+ secure: true,
61
+ },
62
+ ]})
63
+
64
+ await z.wait([
65
+ {
66
+ event: 'response',
67
+ call_id: oc.id,
68
+ method: 'INVITE',
69
+ msg: sip_msg({
70
+ $rs: '200',
71
+ $rr: 'OK',
72
+ '$(hdrcnt(VIA))': 1,
73
+ $fU: 'alice',
74
+ $fd: 'test.com',
75
+ $tU: 'bob',
76
+ '$hdr(content-type)': 'application/sdp',
77
+ $rb: '!{_}a=sendrecv',
78
+ }),
79
+ },
80
+ {
81
+ event: 'media_update',
82
+ call_id: oc.id,
83
+ status: 'ok',
84
+ },
85
+ {
86
+ event: 'media_update',
87
+ call_id: ic.id,
88
+ status: 'ok',
89
+ },
90
+ ], 1000)
91
+
92
+ sip.call.send_dtmf(oc.id, {digits: '1234', mode: 1})
93
+ sip.call.send_dtmf(ic.id, {digits: '1234', mode: 1})
94
+
95
+ await z.wait([
96
+ {
97
+ event: 'dtmf',
98
+ call_id: ic.id,
99
+ digits: '1234',
100
+ mode: 1,
101
+ media_id: 0,
102
+ },
103
+ {
104
+ event: 'dtmf',
105
+ call_id: oc.id,
106
+ digits: '1234',
107
+ mode: 1,
108
+ media_id: 0,
109
+ },
110
+ ], 2000)
111
+
112
+ sip.call.reinvite(oc.id, {media: [
113
+ {
114
+ type: 'audio',
115
+ secure: true,
116
+ },
117
+ ]})
118
+
119
+ await z.wait([
120
+ {
121
+ event: 'reinvite',
122
+ call_id: ic.id,
123
+ },
124
+ ], 500)
125
+
126
+ sip.call.respond(ic.id, {code: 200, reason: 'OK', media: [
127
+ {
128
+ type: 'audio',
129
+ secure: true,
130
+ },
131
+ ]})
132
+
133
+ await z.wait([
134
+ {
135
+ event: 'response',
136
+ call_id: oc.id,
137
+ method: 'INVITE',
138
+ msg: sip_msg({
139
+ $rs: '200',
140
+ $rb: sdp.jsonpath_matcher({
141
+ '$.media.length': [1],
142
+ '$.media[*].desc.type': ['audio'],
143
+ '$.media[*].desc.port': [m.nonzero],
144
+ '$.media[*].desc.protocol': ['RTP/SAVP'],
145
+ }),
146
+ }),
147
+ },
148
+ {
149
+ event: 'media_update',
150
+ call_id: ic.id,
151
+ status: 'ok',
152
+ media: m.fm([
153
+ m.pm({
154
+ type: 'audio',
155
+ transport: 'RTP/SAVP',
156
+ local: {
157
+ mode: 'sendrecv'
158
+ },
159
+ remote: {
160
+ mode: 'sendrecv'
161
+ },
162
+ fmt: [
163
+ '0 PCMU/8000',
164
+ '120 telephone-event/8000'
165
+ ]
166
+ }),
167
+ ]),
168
+ },
169
+ {
170
+ event: 'media_update',
171
+ call_id: oc.id,
172
+ status: 'ok',
173
+ media: m.fm([
174
+ m.pm({
175
+ type: 'audio',
176
+ transport: 'RTP/SAVP',
177
+ local: {
178
+ mode: 'sendrecv'
179
+ },
180
+ remote: {
181
+ mode: 'sendrecv'
182
+ },
183
+ fmt: [
184
+ '0 PCMU/8000',
185
+ '120 telephone-event/8000'
186
+ ]
187
+ }),
188
+ ]),
189
+ },
190
+ ], 1000)
191
+
192
+ sip.call.send_dtmf(oc.id, {digits: '1234', mode: 1})
193
+ sip.call.send_dtmf(ic.id, {digits: '1234', mode: 1})
194
+
195
+ await z.wait([
196
+ {
197
+ event: 'dtmf',
198
+ call_id: ic.id,
199
+ digits: '1234',
200
+ mode: 1,
201
+ media_id: 0,
202
+ },
203
+ {
204
+ event: 'dtmf',
205
+ call_id: oc.id,
206
+ digits: '1234',
207
+ mode: 1,
208
+ media_id: 0,
209
+ },
210
+ ], 2000)
211
+
212
+
213
+ sip.call.reinvite(ic.id, {media: [
214
+ {
215
+ type: 'audio',
216
+ secure: true,
217
+ },
218
+ ]})
219
+
220
+ await z.wait([
221
+ {
222
+ event: 'reinvite',
223
+ call_id: oc.id,
224
+ },
225
+ ], 500)
226
+
227
+ sip.call.respond(oc.id, {code: 200, reason: 'OK', media: [
228
+ {
229
+ type: 'audio',
230
+ secure: true,
231
+ },
232
+ ]})
233
+
234
+ await z.wait([
235
+ {
236
+ event: 'response',
237
+ call_id: ic.id,
238
+ method: 'INVITE',
239
+ msg: sip_msg({
240
+ $rs: '200',
241
+ $rb: sdp.jsonpath_matcher({
242
+ '$.media.length': [1],
243
+ '$.media[*].desc.type': ['audio'],
244
+ '$.media[*].desc.port': [m.nonzero],
245
+ '$.media[*].desc.protocol': ['RTP/SAVP'],
246
+ }),
247
+ }),
248
+ },
249
+ {
250
+ event: 'media_update',
251
+ call_id: oc.id,
252
+ status: 'ok',
253
+ media: m.fm([
254
+ m.pm({
255
+ type: 'audio',
256
+ transport: 'RTP/SAVP',
257
+ local: {
258
+ mode: 'sendrecv'
259
+ },
260
+ remote: {
261
+ mode: 'sendrecv'
262
+ },
263
+ fmt: [
264
+ '0 PCMU/8000',
265
+ '120 telephone-event/8000'
266
+ ]
267
+ }),
268
+ ]),
269
+ },
270
+ {
271
+ event: 'media_update',
272
+ call_id: ic.id,
273
+ status: 'ok',
274
+ media: m.fm([
275
+ m.pm({
276
+ type: 'audio',
277
+ transport: 'RTP/SAVP',
278
+ local: {
279
+ mode: 'sendrecv'
280
+ },
281
+ remote: {
282
+ mode: 'sendrecv'
283
+ },
284
+ fmt: [
285
+ '0 PCMU/8000',
286
+ '120 telephone-event/8000'
287
+ ]
288
+ }),
289
+ ]),
290
+ },
291
+ ], 1000)
292
+
293
+ sip.call.send_dtmf(oc.id, {digits: '1234', mode: 1})
294
+ sip.call.send_dtmf(ic.id, {digits: '1234', mode: 1})
295
+
296
+ await z.wait([
297
+ {
298
+ event: 'dtmf',
299
+ call_id: ic.id,
300
+ digits: '1234',
301
+ mode: 1,
302
+ media_id: 0,
303
+ },
304
+ {
305
+ event: 'dtmf',
306
+ call_id: oc.id,
307
+ digits: '1234',
308
+ mode: 1,
309
+ media_id: 0,
310
+ },
311
+ ], 2000)
312
+
313
+ sip.call.terminate(oc.id)
314
+
315
+ await z.wait([
316
+ {
317
+ event: 'response',
318
+ call_id: oc.id,
319
+ method: 'BYE',
320
+ msg: sip_msg({
321
+ $rs: '200',
322
+ $rr: 'OK',
323
+ }),
324
+ },
325
+ {
326
+ event: 'call_ended',
327
+ call_id: oc.id,
328
+ },
329
+ {
330
+ event: 'call_ended',
331
+ call_id: ic.id,
332
+ },
333
+ ], 1000)
334
+
335
+ console.log("Success")
336
+
337
+ sip.stop()
338
+ }
339
+
340
+
341
+ test()
342
+ .catch(e => {
343
+ console.error(e)
344
+ process.exit(1)
345
+ })
346
+
package/src/sip.cpp CHANGED
@@ -384,6 +384,7 @@ struct MediaEndpoint {
384
384
  pj_str_t addr;
385
385
  int port;
386
386
  int field_count;
387
+ bool secure;
387
388
  char *field[MAX_ATTRS];
388
389
 
389
390
  union {
@@ -630,7 +631,7 @@ void close_media_endpoint(MediaEndpoint *me);
630
631
 
631
632
  void close_media(Call *c);
632
633
 
633
- bool process_media(Call *c, pjsip_dialog *dlg, Document &document);
634
+ bool process_media(Call *c, pjsip_dialog *dlg, Document &document, bool answer);
634
635
 
635
636
  typedef pj_status_t (*audio_endpoint_stop_op_t)(Call *call, AudioEndpoint *ae);
636
637
 
@@ -685,6 +686,13 @@ const char *translate_pjsip_inv_state(int state) {
685
686
  }
686
687
  }
687
688
 
689
+ static pj_bool_t create_transport_srtp(pjmedia_transport *med_transport, pjmedia_transport **srtp) {
690
+ pjmedia_srtp_setting opt;
691
+ pjmedia_srtp_setting_default(&opt);
692
+ printf("calling pjmedia_transport_srtp_create\n");
693
+ return pjmedia_transport_srtp_create(g_med_endpt, med_transport, &opt, srtp);
694
+ }
695
+
688
696
  static int
689
697
  find_endpoint_by_inband_dtmf_media_stream(Call *call,
690
698
  pjmedia_stream *med_stream) {
@@ -2072,17 +2080,21 @@ int pjw_call_respond(long call_id, const char *json) {
2072
2080
  }
2073
2081
 
2074
2082
  if (183 == code || (code >= 200 && code < 300)) {
2075
- if (!process_media(call, call->inv->dlg, document)) {
2076
- goto out;
2077
- }
2078
-
2079
2083
  // process_media above set call->local_sdp based on document.
2080
2084
 
2081
2085
  if (call->pending_rdata && call->pending_rdata->msg_info.msg->body &&
2082
2086
  call->pending_rdata->msg_info.msg->body->len) {
2087
+ if (!process_media(call, call->inv->dlg, document, true)) {
2088
+ goto out;
2089
+ }
2090
+
2083
2091
  status = pjsip_inv_set_sdp_answer(call->inv, call->local_sdp);
2084
2092
  } else {
2085
2093
  // delayed media. we need to sned the offer
2094
+ if (!process_media(call, call->inv->dlg, document, false)) {
2095
+ goto out;
2096
+ }
2097
+
2086
2098
  status = pjmedia_sdp_neg_create_w_local_offer(
2087
2099
  call->inv->dlg->pool, call->local_sdp, &call->inv->neg);
2088
2100
  if (status != PJ_SUCCESS) {
@@ -2824,7 +2836,7 @@ int call_create(Transport *t, unsigned flags, pjsip_dialog *dlg,
2824
2836
 
2825
2837
  pjmedia_sdp_session *sdp = 0;
2826
2838
 
2827
- if (!process_media(call, dlg, document)) {
2839
+ if (!process_media(call, dlg, document, false)) {
2828
2840
  close_media(call);
2829
2841
  return -1;
2830
2842
  }
@@ -3117,7 +3129,7 @@ int pjw_call_reinvite(long call_id, const char *json) {
3117
3129
  }
3118
3130
  }
3119
3131
 
3120
- if (!process_media(call, inv->dlg, document)) {
3132
+ if (!process_media(call, inv->dlg, document, false)) {
3121
3133
  goto out;
3122
3134
  }
3123
3135
 
@@ -4064,7 +4076,7 @@ int find_sdp_media_by_media_endpt(const pjmedia_sdp_session *sdp,
4064
4076
  printf("find_sdp_media_by_media_endpt %x\n", me);
4065
4077
  for (int i = 0; i < sdp->media_count; i++) {
4066
4078
  pjmedia_sdp_media *media = sdp->media[i];
4067
- printf("i=%d media=%x\n", i, media);
4079
+ printf("i=%d me->port=%i media->desc.port=%i me->media=%.*s media->desc.media=%.*s\n", i, me->port, media->desc.port, me->media.slen, me->media.ptr, media->desc.media.slen, media->desc.media.ptr);
4068
4080
 
4069
4081
  if ((me->port == media->desc.port) &&
4070
4082
  (pj_strcmp(&me->media, &media->desc.media) == 0)) {
@@ -4116,10 +4128,10 @@ void gen_media_json(char *dest, int len, Call *call,
4116
4128
  if(!me->port) {
4117
4129
  switch (me->type) {
4118
4130
  case ENDPOINT_TYPE_AUDIO:
4119
- p += sprintf(p, "{\"type\": \"audio\", \"port\": 0}");
4131
+ p += sprintf(p, "{\"type\": \"audio\", \"transport\": \"%.*s\", \"port\": 0}", me->transport.slen, me->transport.ptr);
4120
4132
  break;
4121
4133
  case ENDPOINT_TYPE_MRCP:
4122
- p += sprintf(p, "{\"type\": \"mrcp\", \"port\": 0}");
4134
+ p += sprintf(p, "{\"type\": \"mrcp\", \"transport\": \"%.*s\", \"port\": 0}", me->transport.slen, me->transport.ptr);
4123
4135
  break;
4124
4136
  default:
4125
4137
  p += sprintf(p, "{\"type\": \"unknown\", \"port\": 0}");
@@ -4151,9 +4163,10 @@ void gen_media_json(char *dest, int len, Call *call,
4151
4163
  pj_str_t *remote_addr = &remote_conn->addr;
4152
4164
 
4153
4165
  p += sprintf(p,
4154
- "{\"type\": \"audio\", \"local\": {\"addr\": \"%.*s\", "
4166
+ "{\"type\": \"audio\", \"transport\": \"%.*s\", \"local\": {\"addr\": \"%.*s\", "
4155
4167
  "\"port\": %d, \"mode\": \"%s\"}, \"remote\": {\"addr\": "
4156
4168
  "\"%.*s\", \"port\": %d, \"mode\": \"%s\"}, \"fmt\": [",
4169
+ me->transport.slen, me->transport.ptr,
4157
4170
  local_addr->slen, local_addr->ptr, local_media->desc.port,
4158
4171
  local_mode, remote_addr->slen, remote_addr->ptr,
4159
4172
  remote_media->desc.port, remote_mode);
@@ -4175,8 +4188,9 @@ void gen_media_json(char *dest, int len, Call *call,
4175
4188
  }
4176
4189
  case ENDPOINT_TYPE_MRCP: {
4177
4190
  p += sprintf(p,
4178
- "{\"type\": \"mrcp\", \"local\": {\"port\": %d}, "
4191
+ "{\"type\": \"mrcp\", \"transport\": \"%.*s\", \"local\": {\"port\": %d}, "
4179
4192
  "\"remote\": {\"port\": %d}}",
4193
+ me->transport.slen, me->transport.ptr,
4180
4194
  local_sdp->media[idx]->desc.port,
4181
4195
  remote_sdp->media[idx]->desc.port);
4182
4196
  break;
@@ -4342,13 +4356,24 @@ bool restart_media_stream(Call *call, MediaEndpoint *me,
4342
4356
  status = pjmedia_stream_set_dtmf_callback(ae->med_stream, &on_dtmf, call);
4343
4357
  if (status != PJ_SUCCESS) {
4344
4358
  make_evt_media_update(evt, sizeof(evt), call->id,
4345
- "setup_failed (pjmedi_stream_set_dtmf_callback)", "");
4359
+ "setup_failed (pjmedia_stream_set_dtmf_callback)", "");
4346
4360
  dispatch_event(evt);
4347
4361
  return false;
4348
4362
  }
4349
4363
 
4350
4364
  /* Start the UDP media transport */
4351
- pjmedia_transport_media_start(ae->med_transport, 0, 0, 0, 0);
4365
+ status = pjmedia_transport_media_start(ae->med_transport, call->inv->pool, local_sdp, remote_sdp, idx);
4366
+ if (status != PJ_SUCCESS) {
4367
+ printf("status=%i\n", status);
4368
+ char err[1024];
4369
+ pj_strerror(status, err, sizeof(err));
4370
+ printf("pjmedia_transport_media_start status: %s\n", err);
4371
+
4372
+ make_evt_media_update(evt, sizeof(evt), call->id,
4373
+ "setup_failed (pjmedia_transport_media_start failed)", "");
4374
+ dispatch_event(evt);
4375
+ return false;
4376
+ }
4352
4377
 
4353
4378
  pjmedia_port *stream_port;
4354
4379
  status = pjmedia_stream_get_port(ae->med_stream, &stream_port);
@@ -5827,8 +5852,36 @@ bool create_media_endpoint(Call *call, Document &document, Value &descr,
5827
5852
  med_endpt->type = ENDPOINT_TYPE_AUDIO;
5828
5853
  pj_strdup2(dlg->pool, &med_endpt->media, "audio");
5829
5854
  pj_strdup(dlg->pool, &med_endpt->addr, &str_addr);
5830
- pj_strdup2(dlg->pool, &med_endpt->transport, "RTP/AVP");
5855
+
5856
+ if (descr.HasMember("secure")) {
5857
+ if (!descr["secure"].IsBool()) {
5858
+ set_error("Parameter secure must be a boolean");
5859
+ return false;
5860
+ }
5861
+ med_endpt->secure = descr["secure"].GetBool();
5862
+ }
5863
+
5864
+ if(med_endpt->secure){
5865
+ pjmedia_transport *srtp;
5866
+ pj_status_t status = create_transport_srtp(audio_endpt->med_transport, &srtp);
5867
+ if(status != PJ_SUCCESS) {
5868
+ set_error("create_transport_srtp failed");
5869
+ return false;
5870
+ }
5871
+ audio_endpt->med_transport = srtp;
5872
+
5873
+ status = pjmedia_transport_media_create(audio_endpt->med_transport, dlg->pool, NULL, NULL, 0);
5874
+ if(status != PJ_SUCCESS) {
5875
+ set_error("pjmedia_transport_media_create failed");
5876
+ return false;
5877
+ }
5878
+ pj_strdup2(dlg->pool, &med_endpt->transport, "RTP/SAVP");
5879
+ } else {
5880
+ pj_strdup2(dlg->pool, &med_endpt->transport, "RTP/AVP");
5881
+ }
5882
+
5831
5883
  med_endpt->port = allocated_port;
5884
+ printf("med_endtp->port=%i\n", med_endpt->port);
5832
5885
  med_endpt->endpoint.audio = audio_endpt;
5833
5886
  } else if (strcmp("mrcp", type) == 0) {
5834
5887
  MrcpEndpoint *mrcp_endpt = (MrcpEndpoint *)pj_pool_zalloc(dlg->pool, sizeof(MrcpEndpoint));
@@ -6019,7 +6072,7 @@ pjmedia_sdp_media *create_sdp_media(MediaEndpoint *me, pjsip_dialog *dlg) {
6019
6072
  return media;
6020
6073
  }
6021
6074
 
6022
- bool process_media(Call *call, pjsip_dialog *dlg, Document &document) {
6075
+ bool process_media(Call *call, pjsip_dialog *dlg, Document &document, bool answer) {
6023
6076
  printf("process_media call_id=%d\n", call->id);
6024
6077
 
6025
6078
  bool in_use_chart[PJMEDIA_MAX_SDP_MEDIA] = {false};
@@ -6099,6 +6152,17 @@ bool process_media(Call *call, pjsip_dialog *dlg, Document &document) {
6099
6152
  Value media = document["media"].GetArray();
6100
6153
  assert(media.Size() <= PJMEDIA_MAX_SDP_MEDIA);
6101
6154
 
6155
+ const pjmedia_sdp_session *rem_sdp = NULL;
6156
+ if(answer) {
6157
+ if(call->inv && call->inv->neg) {
6158
+ status = pjmedia_sdp_neg_get_neg_remote(call->inv->neg, &rem_sdp);
6159
+ if(status != PJ_SUCCESS) {
6160
+ addon_log(L_DBG, "Internal Server Error (pjmedia_sdp_neg_get_neg_remote failed)");
6161
+ return false;
6162
+ }
6163
+ }
6164
+ }
6165
+
6102
6166
  for (SizeType i = 0; i < media.Size(); i++) {
6103
6167
  Value descr = media[i].GetObject();
6104
6168
 
@@ -6166,6 +6230,18 @@ bool process_media(Call *call, pjsip_dialog *dlg, Document &document) {
6166
6230
 
6167
6231
  sdp->media[sdp->media_count++] = media;
6168
6232
  }
6233
+
6234
+ if(me->secure && me->endpoint.audio) {
6235
+ pj_status_t status = pjmedia_transport_encode_sdp(me->endpoint.audio->med_transport, dlg->pool, sdp, rem_sdp, i);
6236
+ if(status != PJ_SUCCESS) {
6237
+ addon_log(L_DBG, "pjmedia_transport_encode_sdp failed");
6238
+ return false;
6239
+ }
6240
+
6241
+ // The below must be done after pjmedia_transport_encode_sdp() because although at this point med_transport is a transport_srtp, it calls the transport_encode_sdp of the underlying transpor_udp and it will fail when it sees "RTP/SAVP" instead of "RTP/AVP"
6242
+ // So we change from RTP/AVP to RTP/SAVP after we add the crypto lines.
6243
+ pj_strdup2(dlg->pool, &sdp->media[i]->desc.transport, "RTP/SAVP");
6244
+ }
6169
6245
  }
6170
6246
 
6171
6247
  call->local_sdp = sdp;
package/samples/t DELETED
@@ -1,457 +0,0 @@
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(9)
10
-
11
- //sip.set_log_level(6)
12
- sip.dtmf_aggregation_on(500)
13
-
14
- // Let's ignore '100 Trying'
15
- z.add_event_filter({
16
- event: 'response',
17
- msg: sip_msg({
18
- $rs: '100',
19
- }),
20
- })
21
-
22
- z.trap_events(sip.event_source, 'event', (evt) => {
23
- var e = evt.args[0]
24
- return e
25
- })
26
-
27
- console.log(sip.start((data) => { console.log(data)} ))
28
-
29
- t1 = sip.transport.create({address: "127.0.0.1", port: 5090, type: 'udp'})
30
- t2 = sip.transport.create({address: "127.0.0.1", port: 5092, type: 'udp'})
31
-
32
- console.log("t1", t1)
33
- console.log("t2", t2)
34
-
35
- oc = sip.call.create(t1.id, {from_uri: 'sip:alice@test.com', to_uri: `sip:bob@${t2.address}:${t2.port}`, media: "audio,audio"})
36
-
37
- await z.wait([
38
- {
39
- event: "incoming_call",
40
- call_id: m.collect("call_id"),
41
- },
42
- ], 1000)
43
-
44
- ic = {
45
- id: z.store.call_id,
46
- sip_call_id: z.store.sip_call_id,
47
- }
48
-
49
- sip.call.respond(ic.id, {code: 200, reason: 'OK', media: "audio"})
50
-
51
- await z.wait([
52
- {
53
- event: 'response',
54
- call_id: oc.id,
55
- method: 'INVITE',
56
- msg: sip_msg({
57
- $rs: '200',
58
- $rr: 'OK',
59
- '$(hdrcnt(VIA))': 1,
60
- $fU: 'alice',
61
- $fd: 'test.com',
62
- $tU: 'bob',
63
- '$hdr(content-type)': 'application/sdp',
64
- $rb: '!{_}a=sendrecv',
65
- }),
66
- },
67
- {
68
- event: 'media_update',
69
- call_id: oc.id,
70
- status: 'ok',
71
- media: [
72
- {
73
- type: 'audio',
74
- local: {},
75
- },
76
- {
77
- type: 'audio',
78
- port: 0,
79
- }
80
- ],
81
- },
82
- {
83
- event: 'media_update',
84
- call_id: ic.id,
85
- status: 'ok',
86
- media: [
87
- {
88
- type: 'audio',
89
- local: {},
90
- },
91
- {
92
- type: 'audio',
93
- port: 0,
94
- }
95
- ],
96
- },
97
- ], 1000)
98
-
99
- sip.call.send_dtmf(oc.id, {digits: '1234', mode: 0})
100
- sip.call.send_dtmf(ic.id, {digits: '4321', mode: 1})
101
-
102
- await z.wait([
103
- {
104
- event: 'dtmf',
105
- call_id: ic.id,
106
- digits: '1234',
107
- mode: 0,
108
- media_id: 0
109
- },
110
- {
111
- event: 'dtmf',
112
- call_id: oc.id,
113
- digits: '4321',
114
- mode: 1,
115
- media_id: 0
116
- },
117
- ], 2000)
118
-
119
- // now reinvite with two media
120
- sip.call.reinvite(oc.id, {media: "audio,audio"})
121
-
122
- await z.wait([
123
- {
124
- event: 'reinvite',
125
- call_id: ic.id,
126
- },
127
- ], 1000)
128
-
129
- sip.call.respond(ic.id, {code: 200, reason: 'OK', media: "audio,audio"})
130
-
131
- await z.wait([
132
- {
133
- event: 'response',
134
- call_id: oc.id,
135
- method: 'INVITE',
136
- msg: sip_msg({
137
- $rs: '200',
138
- }),
139
- },
140
- {
141
- event: 'media_update',
142
- call_id: ic.id,
143
- status: 'ok',
144
- media: [
145
- {
146
- type: 'audio',
147
- local: {
148
- mode: 'sendrecv'
149
- },
150
- remote: {
151
- mode: 'sendrecv'
152
- },
153
- fmt: [
154
- '0 PCMU/8000',
155
- '120 telephone-event/8000'
156
- ]
157
- },
158
- {
159
- type: 'audio',
160
- local: {
161
- mode: 'sendrecv'
162
- },
163
- remote: {
164
- mode: 'sendrecv'
165
- },
166
- fmt: [
167
- '0 PCMU/8000',
168
- '120 telephone-event/8000'
169
- ]
170
- }
171
- ]
172
- },
173
- {
174
- event: 'media_update',
175
- call_id: oc.id,
176
- status: 'ok',
177
- media: [
178
- {
179
- type: 'audio',
180
- local: {
181
- mode: 'sendrecv'
182
- },
183
- remote: {
184
- mode: 'sendrecv'
185
- },
186
- fmt: [
187
- '0 PCMU/8000',
188
- '120 telephone-event/8000'
189
- ]
190
- },
191
- {
192
- type: 'audio',
193
- local: {
194
- mode: 'sendrecv'
195
- },
196
- remote: {
197
- mode: 'sendrecv'
198
- },
199
- fmt: [
200
- '0 PCMU/8000',
201
- '120 telephone-event/8000'
202
- ]
203
- }
204
- ]
205
- },
206
- ], 1000)
207
-
208
- await z.sleep(100)
209
-
210
- // Now change to single media
211
- sip.call.reinvite(oc.id, {media: "audio"})
212
-
213
- await z.wait([
214
- {
215
- event: 'reinvite',
216
- call_id: ic.id,
217
- },
218
- ], 1000)
219
-
220
- sip.call.respond(ic.id, {code: 200, reason: 'OK', media: "audio,audio"})
221
-
222
- await z.wait([
223
- {
224
- event: 'response',
225
- call_id: oc.id,
226
- method: 'INVITE',
227
- msg: sip_msg({
228
- $rs: '200',
229
- }),
230
- },
231
- {
232
- event: 'media_update',
233
- call_id: ic.id,
234
- status: 'ok',
235
- media: [
236
- {
237
- type: 'audio',
238
- local: {
239
- mode: 'sendrecv'
240
- },
241
- remote: {
242
- mode: 'sendrecv'
243
- },
244
- fmt: [
245
- '0 PCMU/8000',
246
- '120 telephone-event/8000'
247
- ]
248
- },
249
- {
250
- type: 'audio',
251
- port: 0,
252
- },
253
- ]
254
- },
255
- {
256
- event: 'media_update',
257
- call_id: oc.id,
258
- status: 'ok',
259
- media: [
260
- {
261
- type: 'audio',
262
- local: {
263
- mode: 'sendrecv'
264
- },
265
- remote: {
266
- mode: 'sendrecv'
267
- },
268
- fmt: [
269
- '0 PCMU/8000',
270
- '120 telephone-event/8000'
271
- ]
272
- },
273
- {
274
- type: 'audio',
275
- port: 0,
276
- },
277
- ]
278
- },
279
- ], 1000)
280
-
281
- sip.call.send_dtmf(oc.id, {digits: '1234', mode: 0})
282
- sip.call.send_dtmf(ic.id, {digits: '4321', mode: 1})
283
-
284
- await z.wait([
285
- {
286
- event: 'dtmf',
287
- call_id: ic.id,
288
- digits: '1234',
289
- mode: 0,
290
- media_id: 0
291
- },
292
- {
293
- event: 'dtmf',
294
- call_id: oc.id,
295
- digits: '4321',
296
- mode: 1,
297
- media_id: 0
298
- },
299
- ], 1500)
300
-
301
- // now switch back to two media
302
- sip.call.reinvite(oc.id, {media: "audio,audio"})
303
-
304
- await z.wait([
305
- {
306
- event: 'reinvite',
307
- call_id: ic.id,
308
- },
309
- ], 1000)
310
-
311
- sip.call.respond(ic.id, {code: 200, reason: 'OK', media: "audio,audio"})
312
-
313
- await z.wait([
314
- {
315
- event: 'response',
316
- call_id: oc.id,
317
- method: 'INVITE',
318
- msg: sip_msg({
319
- $rs: '200',
320
- }),
321
- },
322
- {
323
- event: 'media_update',
324
- call_id: ic.id,
325
- status: 'ok',
326
- media: [
327
- {
328
- type: 'audio',
329
- local: {
330
- mode: 'sendrecv'
331
- },
332
- remote: {
333
- mode: 'sendrecv'
334
- },
335
- fmt: [
336
- '0 PCMU/8000',
337
- '120 telephone-event/8000'
338
- ]
339
- },
340
- {
341
- type: 'audio',
342
- local: {
343
- mode: 'sendrecv'
344
- },
345
- remote: {
346
- mode: 'sendrecv'
347
- },
348
- fmt: [
349
- '0 PCMU/8000',
350
- '120 telephone-event/8000'
351
- ]
352
- }
353
- ]
354
- },
355
- {
356
- event: 'media_update',
357
- call_id: oc.id,
358
- status: 'ok',
359
- media: [
360
- {
361
- type: 'audio',
362
- local: {
363
- mode: 'sendrecv'
364
- },
365
- remote: {
366
- mode: 'sendrecv'
367
- },
368
- fmt: [
369
- '0 PCMU/8000',
370
- '120 telephone-event/8000'
371
- ]
372
- },
373
- {
374
- type: 'audio',
375
- local: {
376
- mode: 'sendrecv'
377
- },
378
- remote: {
379
- mode: 'sendrecv'
380
- },
381
- fmt: [
382
- '0 PCMU/8000',
383
- '120 telephone-event/8000'
384
- ]
385
- }
386
- ]
387
- },
388
- ], 1000)
389
-
390
- sip.call.send_dtmf(oc.id, {digits: '1234', mode: 0})
391
- sip.call.send_dtmf(ic.id, {digits: '4321', mode: 1})
392
-
393
- await z.wait([
394
- {
395
- event: 'dtmf',
396
- call_id: ic.id,
397
- digits: '1234',
398
- mode: 0,
399
- media_id: 0
400
- },
401
- {
402
- event: 'dtmf',
403
- call_id: oc.id,
404
- digits: '4321',
405
- mode: 1,
406
- media_id: 0
407
- },
408
- {
409
- event: 'dtmf',
410
- call_id: ic.id,
411
- digits: '1234',
412
- mode: 0,
413
- media_id: 1
414
- },
415
- {
416
- event: 'dtmf',
417
- call_id: oc.id,
418
- digits: '4321',
419
- mode: 1,
420
- media_id: 1
421
- },
422
- ], 2000)
423
-
424
- sip.call.terminate(oc.id)
425
-
426
- await z.wait([
427
- {
428
- event: 'call_ended',
429
- call_id: oc.id,
430
- },
431
- {
432
- event: 'call_ended',
433
- call_id: ic.id,
434
- },
435
- {
436
- event: 'response',
437
- call_id: oc.id,
438
- method: 'BYE',
439
- msg: sip_msg({
440
- $rs: '200',
441
- $rr: 'OK',
442
- }),
443
- },
444
- ], 1000)
445
-
446
- console.log("Success")
447
-
448
- sip.stop()
449
- }
450
-
451
-
452
- test()
453
- .catch(e => {
454
- console.error(e)
455
- process.exit(1)
456
- })
457
-