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.
- package/DEV.md +2 -2
- package/package.json +4 -3
- package/prebuilds/linux-x64/node.abi102.node +0 -0
- package/prebuilds/linux-x64/node.abi108.node +0 -0
- package/prebuilds/linux-x64/node.abi88.node +0 -0
- package/prebuilds/linux-x64/node.abi93.node +0 -0
- package/prebuilds/linux-x64/sip-lab.node +0 -0
- package/samples/{t → 183_session_progress.js} +98 -160
- package/samples/rtp_and_srtp.js +466 -0
- package/samples/rtp_and_srtp.rtp_refused.js +430 -0
- package/samples/rtp_and_srtp.unbalanced_sdp_answer.js.future +189 -0
- package/samples/srtp.js +344 -0
- package/src/sip.cpp +137 -30
- package/samples/183_session_progress.js.future +0 -246
package/samples/srtp.js
ADDED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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=%
|
|
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 (
|
|
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,
|
|
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
|
-
|
|
4393
|
-
|
|
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
|
-
|
|
4398
|
-
|
|
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
|
-
|
|
4403
|
-
|
|
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
|
-
|
|
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;
|