sip-lab 1.14.0 → 1.16.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.
@@ -0,0 +1,344 @@
1
+ const sip = require ('../index.js')
2
+ const Zeq = require('@mayama/zeq')
3
+ const m = require('data-matching')
4
+ const sip_msg = require('sip-matching')
5
+ const sdp = require('sdp-matching')
6
+
7
+ // here we create our Zeq instance
8
+ var z = new Zeq()
9
+
10
+ async function test() {
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
+ // Let's ignore '100 Trying'
19
+ z.add_event_filter({
20
+ event: 'response',
21
+ msg: sip_msg({
22
+ $rs: '100',
23
+ }),
24
+ })
25
+
26
+ console.log(sip.start((data) => { console.log(data)} ))
27
+
28
+ const t1 = sip.transport.create({address: "127.0.0.1"})
29
+ const t2 = sip.transport.create({address: "127.0.0.1"})
30
+
31
+ console.log("t1", t1)
32
+ console.log("t2", t2)
33
+
34
+ const oc = sip.call.create(t1.id, {from_uri: 'sip:alice@test.com', to_uri: `sip:bob@${t2.address}:${t2.port}`,
35
+ media: [
36
+ {
37
+ type: 'audio',
38
+ secure: true,
39
+ },
40
+ ]})
41
+
42
+ await z.wait([
43
+ {
44
+ event: "incoming_call",
45
+ call_id: m.collect("call_id"),
46
+ transport_id: t2.id,
47
+ },
48
+ ], 1000)
49
+
50
+ const 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: [
56
+ {
57
+ type: 'audio',
58
+ secure: true,
59
+ },
60
+ ]})
61
+
62
+ await z.wait([
63
+ {
64
+ event: 'response',
65
+ call_id: oc.id,
66
+ method: 'INVITE',
67
+ msg: sip_msg({
68
+ $rs: '200',
69
+ $rr: 'OK',
70
+ '$(hdrcnt(VIA))': 1,
71
+ $fU: 'alice',
72
+ $fd: 'test.com',
73
+ $tU: 'bob',
74
+ '$hdr(content-type)': 'application/sdp',
75
+ $rb: '!{_}a=sendrecv',
76
+ }),
77
+ },
78
+ {
79
+ event: 'media_update',
80
+ call_id: oc.id,
81
+ status: 'ok',
82
+ },
83
+ {
84
+ event: 'media_update',
85
+ call_id: ic.id,
86
+ status: 'ok',
87
+ },
88
+ ], 1000)
89
+
90
+ sip.call.send_dtmf(oc.id, {digits: '1234', mode: 1})
91
+ sip.call.send_dtmf(ic.id, {digits: '1234', mode: 1})
92
+
93
+ await z.wait([
94
+ {
95
+ event: 'dtmf',
96
+ call_id: ic.id,
97
+ digits: '1234',
98
+ mode: 1,
99
+ media_id: 0,
100
+ },
101
+ {
102
+ event: 'dtmf',
103
+ call_id: oc.id,
104
+ digits: '1234',
105
+ mode: 1,
106
+ media_id: 0,
107
+ },
108
+ ], 2000)
109
+
110
+ sip.call.reinvite(oc.id, {media: [
111
+ {
112
+ type: 'audio',
113
+ secure: true,
114
+ },
115
+ ]})
116
+
117
+ await z.wait([
118
+ {
119
+ event: 'reinvite',
120
+ call_id: ic.id,
121
+ },
122
+ ], 500)
123
+
124
+ sip.call.respond(ic.id, {code: 200, reason: 'OK', media: [
125
+ {
126
+ type: 'audio',
127
+ secure: true,
128
+ },
129
+ ]})
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
+ $rb: sdp.jsonpath_matcher({
139
+ '$.media.length': [1],
140
+ '$.media[*].desc.type': ['audio'],
141
+ '$.media[*].desc.port': [m.nonzero],
142
+ '$.media[*].desc.protocol': ['RTP/SAVP'],
143
+ }),
144
+ }),
145
+ },
146
+ {
147
+ event: 'media_update',
148
+ call_id: ic.id,
149
+ status: 'ok',
150
+ media: m.fm([
151
+ m.pm({
152
+ type: 'audio',
153
+ protocol: 'RTP/SAVP',
154
+ local: {
155
+ mode: 'sendrecv'
156
+ },
157
+ remote: {
158
+ mode: 'sendrecv'
159
+ },
160
+ fmt: [
161
+ '0 PCMU/8000',
162
+ '120 telephone-event/8000'
163
+ ]
164
+ }),
165
+ ]),
166
+ },
167
+ {
168
+ event: 'media_update',
169
+ call_id: oc.id,
170
+ status: 'ok',
171
+ media: m.fm([
172
+ m.pm({
173
+ type: 'audio',
174
+ protocol: 'RTP/SAVP',
175
+ local: {
176
+ mode: 'sendrecv'
177
+ },
178
+ remote: {
179
+ mode: 'sendrecv'
180
+ },
181
+ fmt: [
182
+ '0 PCMU/8000',
183
+ '120 telephone-event/8000'
184
+ ]
185
+ }),
186
+ ]),
187
+ },
188
+ ], 1000)
189
+
190
+ sip.call.send_dtmf(oc.id, {digits: '1234', mode: 1})
191
+ sip.call.send_dtmf(ic.id, {digits: '1234', mode: 1})
192
+
193
+ await z.wait([
194
+ {
195
+ event: 'dtmf',
196
+ call_id: ic.id,
197
+ digits: '1234',
198
+ mode: 1,
199
+ media_id: 0,
200
+ },
201
+ {
202
+ event: 'dtmf',
203
+ call_id: oc.id,
204
+ digits: '1234',
205
+ mode: 1,
206
+ media_id: 0,
207
+ },
208
+ ], 2000)
209
+
210
+
211
+ sip.call.reinvite(ic.id, {media: [
212
+ {
213
+ type: 'audio',
214
+ secure: true,
215
+ },
216
+ ]})
217
+
218
+ await z.wait([
219
+ {
220
+ event: 'reinvite',
221
+ call_id: oc.id,
222
+ },
223
+ ], 500)
224
+
225
+ sip.call.respond(oc.id, {code: 200, reason: 'OK', media: [
226
+ {
227
+ type: 'audio',
228
+ secure: true,
229
+ },
230
+ ]})
231
+
232
+ await z.wait([
233
+ {
234
+ event: 'response',
235
+ call_id: ic.id,
236
+ method: 'INVITE',
237
+ msg: sip_msg({
238
+ $rs: '200',
239
+ $rb: sdp.jsonpath_matcher({
240
+ '$.media.length': [1],
241
+ '$.media[*].desc.type': ['audio'],
242
+ '$.media[*].desc.port': [m.nonzero],
243
+ '$.media[*].desc.protocol': ['RTP/SAVP'],
244
+ }),
245
+ }),
246
+ },
247
+ {
248
+ event: 'media_update',
249
+ call_id: oc.id,
250
+ status: 'ok',
251
+ media: m.fm([
252
+ m.pm({
253
+ type: 'audio',
254
+ protocol: 'RTP/SAVP',
255
+ local: {
256
+ mode: 'sendrecv'
257
+ },
258
+ remote: {
259
+ mode: 'sendrecv'
260
+ },
261
+ fmt: [
262
+ '0 PCMU/8000',
263
+ '120 telephone-event/8000'
264
+ ]
265
+ }),
266
+ ]),
267
+ },
268
+ {
269
+ event: 'media_update',
270
+ call_id: ic.id,
271
+ status: 'ok',
272
+ media: m.fm([
273
+ m.pm({
274
+ type: 'audio',
275
+ protocol: 'RTP/SAVP',
276
+ local: {
277
+ mode: 'sendrecv'
278
+ },
279
+ remote: {
280
+ mode: 'sendrecv'
281
+ },
282
+ fmt: [
283
+ '0 PCMU/8000',
284
+ '120 telephone-event/8000'
285
+ ]
286
+ }),
287
+ ]),
288
+ },
289
+ ], 1000)
290
+
291
+ sip.call.send_dtmf(oc.id, {digits: '1234', mode: 1})
292
+ sip.call.send_dtmf(ic.id, {digits: '1234', mode: 1})
293
+
294
+ await z.wait([
295
+ {
296
+ event: 'dtmf',
297
+ call_id: ic.id,
298
+ digits: '1234',
299
+ mode: 1,
300
+ media_id: 0,
301
+ },
302
+ {
303
+ event: 'dtmf',
304
+ call_id: oc.id,
305
+ digits: '1234',
306
+ mode: 1,
307
+ media_id: 0,
308
+ },
309
+ ], 2000)
310
+
311
+ sip.call.terminate(oc.id)
312
+
313
+ await z.wait([
314
+ {
315
+ event: 'response',
316
+ call_id: oc.id,
317
+ method: 'BYE',
318
+ msg: sip_msg({
319
+ $rs: '200',
320
+ $rr: 'OK',
321
+ }),
322
+ },
323
+ {
324
+ event: 'call_ended',
325
+ call_id: oc.id,
326
+ },
327
+ {
328
+ event: 'call_ended',
329
+ call_id: ic.id,
330
+ },
331
+ ], 1000)
332
+
333
+ console.log("Success")
334
+
335
+ sip.stop()
336
+ }
337
+
338
+
339
+ test()
340
+ .catch(e => {
341
+ console.error(e)
342
+ process.exit(1)
343
+ })
344
+
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 {
@@ -423,6 +424,8 @@ struct Call {
423
424
 
424
425
  pjmedia_sdp_session *active_local_sdp;
425
426
  pjmedia_sdp_session *active_remote_sdp;
427
+
428
+ bool local_sdp_answer_already_set;
426
429
  };
427
430
 
428
431
  #define MAX_TCP_DATA 4096
@@ -630,7 +633,7 @@ void close_media_endpoint(MediaEndpoint *me);
630
633
 
631
634
  void close_media(Call *c);
632
635
 
633
- bool process_media(Call *c, pjsip_dialog *dlg, Document &document);
636
+ bool process_media(Call *c, pjsip_dialog *dlg, Document &document, bool answer);
634
637
 
635
638
  typedef pj_status_t (*audio_endpoint_stop_op_t)(Call *call, AudioEndpoint *ae);
636
639
 
@@ -685,6 +688,13 @@ const char *translate_pjsip_inv_state(int state) {
685
688
  }
686
689
  }
687
690
 
691
+ static pj_bool_t create_transport_srtp(pjmedia_transport *med_transport, pjmedia_transport **srtp) {
692
+ pjmedia_srtp_setting opt;
693
+ pjmedia_srtp_setting_default(&opt);
694
+ printf("calling pjmedia_transport_srtp_create\n");
695
+ return pjmedia_transport_srtp_create(g_med_endpt, med_transport, &opt, srtp);
696
+ }
697
+
688
698
  static int
689
699
  find_endpoint_by_inband_dtmf_media_stream(Call *call,
690
700
  pjmedia_stream *med_stream) {
@@ -2063,26 +2073,33 @@ int pjw_call_respond(long call_id, const char *json) {
2063
2073
  set_error("pjsip_rx_data_free_cloned failed with status=%i", status);
2064
2074
  goto out;
2065
2075
  }
2076
+ call->pending_rdata = 0;
2066
2077
 
2067
2078
  call->pending_request = -1;
2068
- call->pending_rdata = 0;
2069
2079
  }
2070
2080
 
2071
2081
  goto out;
2072
2082
  }
2073
2083
 
2074
2084
  if (183 == code || (code >= 200 && code < 300)) {
2075
- if (!process_media(call, call->inv->dlg, document)) {
2076
- goto out;
2077
- }
2078
-
2079
2085
  // process_media above set call->local_sdp based on document.
2080
2086
 
2081
2087
  if (call->pending_rdata && call->pending_rdata->msg_info.msg->body &&
2082
2088
  call->pending_rdata->msg_info.msg->body->len) {
2083
- status = pjsip_inv_set_sdp_answer(call->inv, call->local_sdp);
2089
+ if(!call->local_sdp_answer_already_set) {
2090
+ if (!process_media(call, call->inv->dlg, document, true)) {
2091
+ goto out;
2092
+ }
2093
+
2094
+ status = pjsip_inv_set_sdp_answer(call->inv, call->local_sdp);
2095
+ call->local_sdp_answer_already_set = true;
2096
+ }
2084
2097
  } else {
2085
- // delayed media. we need to sned the offer
2098
+ printf("delayed media. we need to send the offer\n");
2099
+ if (!process_media(call, call->inv->dlg, document, false)) {
2100
+ goto out;
2101
+ }
2102
+
2086
2103
  status = pjmedia_sdp_neg_create_w_local_offer(
2087
2104
  call->inv->dlg->pool, call->local_sdp, &call->inv->neg);
2088
2105
  if (status != PJ_SUCCESS) {
@@ -2102,15 +2119,17 @@ int pjw_call_respond(long call_id, const char *json) {
2102
2119
 
2103
2120
  call->inv_initial_answer_required = false;
2104
2121
 
2105
- if (code >= 200) {
2122
+ if (code >= 200 && code < 300) {
2106
2123
  status = pjsip_rx_data_free_cloned(call->pending_rdata);
2107
2124
  if (status != PJ_SUCCESS) {
2108
2125
  set_error("pjsip_rx_data_free_cloned failed with status=%i", status);
2109
2126
  goto out;
2110
2127
  }
2111
-
2112
- call->pending_request = -1;
2113
2128
  call->pending_rdata = 0;
2129
+
2130
+ if (code >= 200 && code < 300) {
2131
+ call->pending_request = -1;
2132
+ }
2114
2133
  }
2115
2134
  } else {
2116
2135
  status = pjsip_inv_answer(call->inv, code, &r,
@@ -2121,7 +2140,20 @@ int pjw_call_respond(long call_id, const char *json) {
2121
2140
  goto out;
2122
2141
  }
2123
2142
 
2124
- call->pending_request = -1;
2143
+ if (code >= 200 && code < 300) {
2144
+ if(call->pending_rdata) {
2145
+ status = pjsip_rx_data_free_cloned(call->pending_rdata);
2146
+ if (status != PJ_SUCCESS) {
2147
+ set_error("pjsip_rx_data_free_cloned failed with status=%i", status);
2148
+ goto out;
2149
+ }
2150
+ call->pending_rdata = 0;
2151
+ }
2152
+
2153
+ if (code >= 200 && code < 300) {
2154
+ call->pending_request = -1;
2155
+ }
2156
+ }
2125
2157
 
2126
2158
  if (!add_headers(call->inv->dlg->pool, tdata, document)) {
2127
2159
  goto out;
@@ -2133,6 +2165,10 @@ int pjw_call_respond(long call_id, const char *json) {
2133
2165
  set_error("pjsip_inv_send_msg failed with status=%i", status);
2134
2166
  goto out;
2135
2167
  }
2168
+
2169
+ if(code >= 200 && code < 300) {
2170
+ call->local_sdp_answer_already_set = false;
2171
+ }
2136
2172
  out:
2137
2173
  PJW_UNLOCK();
2138
2174
  if (pjw_errorstring[0]) {
@@ -2824,7 +2860,7 @@ int call_create(Transport *t, unsigned flags, pjsip_dialog *dlg,
2824
2860
 
2825
2861
  pjmedia_sdp_session *sdp = 0;
2826
2862
 
2827
- if (!process_media(call, dlg, document)) {
2863
+ if (!process_media(call, dlg, document, false)) {
2828
2864
  close_media(call);
2829
2865
  return -1;
2830
2866
  }
@@ -3117,7 +3153,7 @@ int pjw_call_reinvite(long call_id, const char *json) {
3117
3153
  }
3118
3154
  }
3119
3155
 
3120
- if (!process_media(call, inv->dlg, document)) {
3156
+ if (!process_media(call, inv->dlg, document, false)) {
3121
3157
  goto out;
3122
3158
  }
3123
3159
 
@@ -4064,10 +4100,11 @@ int find_sdp_media_by_media_endpt(const pjmedia_sdp_session *sdp,
4064
4100
  printf("find_sdp_media_by_media_endpt %x\n", me);
4065
4101
  for (int i = 0; i < sdp->media_count; i++) {
4066
4102
  pjmedia_sdp_media *media = sdp->media[i];
4067
- printf("i=%d media=%x\n", i, media);
4103
+ printf("i=%d me->port=%i media->desc.port=%i me->media=%.*s media->desc.media=%.*s me->transport=%.*s media->desc.transport=%.*s\n", i, me->port, media->desc.port, me->media.slen, me->media.ptr, media->desc.media.slen, media->desc.media.ptr, me->transport.slen, me->transport.ptr, media->desc.transport.slen, media->desc.transport.ptr);
4068
4104
 
4069
4105
  if ((me->port == media->desc.port) &&
4070
- (pj_strcmp(&me->media, &media->desc.media) == 0)) {
4106
+ (pj_strcmp(&me->media, &media->desc.media) == 0) &&
4107
+ (pj_strcmp(&me->transport, &media->desc.transport) == 0)) {
4071
4108
  *media_out = media;
4072
4109
  printf("found\n");
4073
4110
  return i;
@@ -4116,10 +4153,10 @@ void gen_media_json(char *dest, int len, Call *call,
4116
4153
  if(!me->port) {
4117
4154
  switch (me->type) {
4118
4155
  case ENDPOINT_TYPE_AUDIO:
4119
- p += sprintf(p, "{\"type\": \"audio\", \"port\": 0}");
4156
+ p += sprintf(p, "{\"type\": \"audio\", \"protocol\": \"%.*s\", \"port\": 0}", me->transport.slen, me->transport.ptr);
4120
4157
  break;
4121
4158
  case ENDPOINT_TYPE_MRCP:
4122
- p += sprintf(p, "{\"type\": \"mrcp\", \"port\": 0}");
4159
+ p += sprintf(p, "{\"type\": \"mrcp\", \"protocol\": \"%.*s\", \"port\": 0}", me->transport.slen, me->transport.ptr);
4123
4160
  break;
4124
4161
  default:
4125
4162
  p += sprintf(p, "{\"type\": \"unknown\", \"port\": 0}");
@@ -4151,9 +4188,10 @@ void gen_media_json(char *dest, int len, Call *call,
4151
4188
  pj_str_t *remote_addr = &remote_conn->addr;
4152
4189
 
4153
4190
  p += sprintf(p,
4154
- "{\"type\": \"audio\", \"local\": {\"addr\": \"%.*s\", "
4191
+ "{\"type\": \"audio\", \"protocol\": \"%.*s\", \"local\": {\"addr\": \"%.*s\", "
4155
4192
  "\"port\": %d, \"mode\": \"%s\"}, \"remote\": {\"addr\": "
4156
4193
  "\"%.*s\", \"port\": %d, \"mode\": \"%s\"}, \"fmt\": [",
4194
+ me->transport.slen, me->transport.ptr,
4157
4195
  local_addr->slen, local_addr->ptr, local_media->desc.port,
4158
4196
  local_mode, remote_addr->slen, remote_addr->ptr,
4159
4197
  remote_media->desc.port, remote_mode);
@@ -4175,8 +4213,9 @@ void gen_media_json(char *dest, int len, Call *call,
4175
4213
  }
4176
4214
  case ENDPOINT_TYPE_MRCP: {
4177
4215
  p += sprintf(p,
4178
- "{\"type\": \"mrcp\", \"local\": {\"port\": %d}, "
4216
+ "{\"type\": \"mrcp\", \"protocol\": \"%.*s\", \"local\": {\"port\": %d}, "
4179
4217
  "\"remote\": {\"port\": %d}}",
4218
+ me->transport.slen, me->transport.ptr,
4180
4219
  local_sdp->media[idx]->desc.port,
4181
4220
  remote_sdp->media[idx]->desc.port);
4182
4221
  break;
@@ -4342,13 +4381,24 @@ bool restart_media_stream(Call *call, MediaEndpoint *me,
4342
4381
  status = pjmedia_stream_set_dtmf_callback(ae->med_stream, &on_dtmf, call);
4343
4382
  if (status != PJ_SUCCESS) {
4344
4383
  make_evt_media_update(evt, sizeof(evt), call->id,
4345
- "setup_failed (pjmedi_stream_set_dtmf_callback)", "");
4384
+ "setup_failed (pjmedia_stream_set_dtmf_callback)", "");
4346
4385
  dispatch_event(evt);
4347
4386
  return false;
4348
4387
  }
4349
4388
 
4350
4389
  /* Start the UDP media transport */
4351
- pjmedia_transport_media_start(ae->med_transport, 0, 0, 0, 0);
4390
+ status = pjmedia_transport_media_start(ae->med_transport, call->inv->pool, local_sdp, remote_sdp, idx);
4391
+ if (status != PJ_SUCCESS) {
4392
+ printf("status=%i\n", status);
4393
+ char err[1024];
4394
+ pj_strerror(status, err, sizeof(err));
4395
+ printf("pjmedia_transport_media_start status: %s\n", err);
4396
+
4397
+ make_evt_media_update(evt, sizeof(evt), call->id,
4398
+ "setup_failed (pjmedia_transport_media_start failed)", "");
4399
+ dispatch_event(evt);
4400
+ return false;
4401
+ }
4352
4402
 
4353
4403
  pjmedia_port *stream_port;
4354
4404
  status = pjmedia_stream_get_port(ae->med_stream, &stream_port);
@@ -4389,18 +4439,24 @@ MediaEndpoint *find_media_endpt_by_sdp_media(Call *call,
4389
4439
 
4390
4440
  if (pj_strcmp2(&local_media->desc.media, "audio") == 0) {
4391
4441
  if (ENDPOINT_TYPE_AUDIO == me->type) {
4392
- in_use_chart[i] = true;
4393
- return me;
4442
+ if (pj_strcmp(&local_media->desc.transport, &me->transport)) {
4443
+ in_use_chart[i] = true;
4444
+ return me;
4445
+ }
4394
4446
  }
4395
4447
  } else if (pj_strcmp2(&local_media->desc.media, "video") == 0) {
4396
4448
  if (ENDPOINT_TYPE_VIDEO == me->type) {
4397
- in_use_chart[i] = true;
4398
- return me;
4449
+ if (pj_strcmp(&local_media->desc.transport, &me->transport)) {
4450
+ in_use_chart[i] = true;
4451
+ return me;
4452
+ }
4399
4453
  }
4400
4454
  } else if (pj_strcmp2(&local_media->desc.media, "application") == 0) {
4401
4455
  if (ENDPOINT_TYPE_MRCP == me->type) {
4402
- in_use_chart[i] = true;
4403
- return me;
4456
+ if (pj_strcmp(&local_media->desc.transport, &me->transport)) {
4457
+ in_use_chart[i] = true;
4458
+ return me;
4459
+ }
4404
4460
  }
4405
4461
  } else {
4406
4462
  printf("local_media->desc.media=%.*s\n", local_media->desc.media.slen,
@@ -5827,8 +5883,36 @@ bool create_media_endpoint(Call *call, Document &document, Value &descr,
5827
5883
  med_endpt->type = ENDPOINT_TYPE_AUDIO;
5828
5884
  pj_strdup2(dlg->pool, &med_endpt->media, "audio");
5829
5885
  pj_strdup(dlg->pool, &med_endpt->addr, &str_addr);
5830
- pj_strdup2(dlg->pool, &med_endpt->transport, "RTP/AVP");
5886
+
5887
+ if (descr.HasMember("secure")) {
5888
+ if (!descr["secure"].IsBool()) {
5889
+ set_error("Parameter secure must be a boolean");
5890
+ return false;
5891
+ }
5892
+ med_endpt->secure = descr["secure"].GetBool();
5893
+ }
5894
+
5895
+ if(med_endpt->secure){
5896
+ pjmedia_transport *srtp;
5897
+ pj_status_t status = create_transport_srtp(audio_endpt->med_transport, &srtp);
5898
+ if(status != PJ_SUCCESS) {
5899
+ set_error("create_transport_srtp failed");
5900
+ return false;
5901
+ }
5902
+ audio_endpt->med_transport = srtp;
5903
+
5904
+ status = pjmedia_transport_media_create(audio_endpt->med_transport, dlg->pool, NULL, NULL, 0);
5905
+ if(status != PJ_SUCCESS) {
5906
+ set_error("pjmedia_transport_media_create failed");
5907
+ return false;
5908
+ }
5909
+ pj_strdup2(dlg->pool, &med_endpt->transport, "RTP/SAVP");
5910
+ } else {
5911
+ pj_strdup2(dlg->pool, &med_endpt->transport, "RTP/AVP");
5912
+ }
5913
+
5831
5914
  med_endpt->port = allocated_port;
5915
+ printf("med_endtp->port=%i\n", med_endpt->port);
5832
5916
  med_endpt->endpoint.audio = audio_endpt;
5833
5917
  } else if (strcmp("mrcp", type) == 0) {
5834
5918
  MrcpEndpoint *mrcp_endpt = (MrcpEndpoint *)pj_pool_zalloc(dlg->pool, sizeof(MrcpEndpoint));
@@ -6019,7 +6103,7 @@ pjmedia_sdp_media *create_sdp_media(MediaEndpoint *me, pjsip_dialog *dlg) {
6019
6103
  return media;
6020
6104
  }
6021
6105
 
6022
- bool process_media(Call *call, pjsip_dialog *dlg, Document &document) {
6106
+ bool process_media(Call *call, pjsip_dialog *dlg, Document &document, bool answer) {
6023
6107
  printf("process_media call_id=%d\n", call->id);
6024
6108
 
6025
6109
  bool in_use_chart[PJMEDIA_MAX_SDP_MEDIA] = {false};
@@ -6099,6 +6183,17 @@ bool process_media(Call *call, pjsip_dialog *dlg, Document &document) {
6099
6183
  Value media = document["media"].GetArray();
6100
6184
  assert(media.Size() <= PJMEDIA_MAX_SDP_MEDIA);
6101
6185
 
6186
+ const pjmedia_sdp_session *rem_sdp = NULL;
6187
+ if(answer) {
6188
+ if(call->inv && call->inv->neg) {
6189
+ status = pjmedia_sdp_neg_get_neg_remote(call->inv->neg, &rem_sdp);
6190
+ if(status != PJ_SUCCESS) {
6191
+ addon_log(L_DBG, "Internal Server Error (pjmedia_sdp_neg_get_neg_remote failed)");
6192
+ return false;
6193
+ }
6194
+ }
6195
+ }
6196
+
6102
6197
  for (SizeType i = 0; i < media.Size(); i++) {
6103
6198
  Value descr = media[i].GetObject();
6104
6199
 
@@ -6166,6 +6261,18 @@ bool process_media(Call *call, pjsip_dialog *dlg, Document &document) {
6166
6261
 
6167
6262
  sdp->media[sdp->media_count++] = media;
6168
6263
  }
6264
+
6265
+ if(me->secure && me->endpoint.audio) {
6266
+ pj_status_t status = pjmedia_transport_encode_sdp(me->endpoint.audio->med_transport, dlg->pool, sdp, rem_sdp, i);
6267
+ if(status != PJ_SUCCESS) {
6268
+ addon_log(L_DBG, "pjmedia_transport_encode_sdp failed");
6269
+ return false;
6270
+ }
6271
+
6272
+ // 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"
6273
+ // So we change from RTP/AVP to RTP/SAVP after we add the crypto lines.
6274
+ pj_strdup2(dlg->pool, &sdp->media[i]->desc.transport, "RTP/SAVP");
6275
+ }
6169
6276
  }
6170
6277
 
6171
6278
  call->local_sdp = sdp;