sip-lab 1.12.0 → 1.12.1
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/package.json +1 -1
- package/samples/register_subscribe.js +7 -1
- package/samples/tcp_and_extra_headers.js +333 -0
- package/src/sip.cpp +168 -123
package/package.json
CHANGED
|
@@ -28,7 +28,11 @@ async function test() {
|
|
|
28
28
|
domain,
|
|
29
29
|
server,
|
|
30
30
|
username: 'user1',
|
|
31
|
-
password: 'pass1'
|
|
31
|
+
password: 'pass1',
|
|
32
|
+
headers: {
|
|
33
|
+
'X-MyHeader1': 'aaa',
|
|
34
|
+
'X-MyHeader2': 'bbb',
|
|
35
|
+
},
|
|
32
36
|
})
|
|
33
37
|
|
|
34
38
|
sip.account.register(a1, {auto_register: true})
|
|
@@ -42,6 +46,8 @@ async function test() {
|
|
|
42
46
|
$fd: domain,
|
|
43
47
|
$tU: 'user1',
|
|
44
48
|
$td: domain,
|
|
49
|
+
'$hdr(X-MyHeader1)': 'aaa',
|
|
50
|
+
'$hdr(X-MyHeader2)': 'bbb',
|
|
45
51
|
}),
|
|
46
52
|
},
|
|
47
53
|
], 1000)
|
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
var sip = require ('../index.js')
|
|
2
|
+
var Zester = require('zester')
|
|
3
|
+
var z = new Zester()
|
|
4
|
+
var m = require('data-matching')
|
|
5
|
+
var sip_msg = require('sip-matching')
|
|
6
|
+
|
|
7
|
+
async function test() {
|
|
8
|
+
//sip.set_log_level(6)
|
|
9
|
+
sip.dtmf_aggregation_on(500)
|
|
10
|
+
|
|
11
|
+
z.trap_events(sip.event_source, 'event', (evt) => {
|
|
12
|
+
var e = evt.args[0]
|
|
13
|
+
return e
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
console.log(sip.start((data) => { console.log(data)} ))
|
|
17
|
+
|
|
18
|
+
t1 = sip.transport.create({address: "127.0.0.1", port: 5090, type: 'tcp'})
|
|
19
|
+
t2 = sip.transport.create({address: "127.0.0.1", port: 5092, type: 'tcp'})
|
|
20
|
+
|
|
21
|
+
console.log("t1", t1)
|
|
22
|
+
console.log("t2", t2)
|
|
23
|
+
|
|
24
|
+
oc = sip.call.create(t1.id, {
|
|
25
|
+
from_uri: '"abc"<sip:alice@test.com>',
|
|
26
|
+
to_uri: `sip:bob@${t2.address}:${t2.port}`,
|
|
27
|
+
headers: {
|
|
28
|
+
'X-MyHeader1': 'abc',
|
|
29
|
+
'X-MyHeader2': 'def',
|
|
30
|
+
},
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
await z.wait([
|
|
34
|
+
{
|
|
35
|
+
event: "incoming_call",
|
|
36
|
+
call_id: m.collect("call_id"),
|
|
37
|
+
msg: sip_msg({
|
|
38
|
+
$rm: 'INVITE',
|
|
39
|
+
$fU: 'alice',
|
|
40
|
+
$fd: 'test.com',
|
|
41
|
+
$tU: 'bob',
|
|
42
|
+
'$hdr(X-MyHeader1)': 'abc',
|
|
43
|
+
'$hdr(X-MyHeader2)': 'def',
|
|
44
|
+
}),
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
event: 'response',
|
|
48
|
+
call_id: oc.id,
|
|
49
|
+
method: 'INVITE',
|
|
50
|
+
msg: sip_msg({
|
|
51
|
+
$rs: '100',
|
|
52
|
+
$rr: 'Trying',
|
|
53
|
+
'$(hdrcnt(via))': 1,
|
|
54
|
+
'$hdr(call-id)': m.collect('sip_call_id'),
|
|
55
|
+
$fU: 'alice',
|
|
56
|
+
$fd: 'test.com',
|
|
57
|
+
$tU: 'bob',
|
|
58
|
+
'$hdr(l)': '0',
|
|
59
|
+
}),
|
|
60
|
+
},
|
|
61
|
+
], 1000)
|
|
62
|
+
|
|
63
|
+
ic = {
|
|
64
|
+
id: z.store.call_id,
|
|
65
|
+
sip_call_id: z.store.sip_call_id,
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
sip.call.respond(ic.id, {
|
|
69
|
+
code: 200,
|
|
70
|
+
reason:'OK',
|
|
71
|
+
headers: {
|
|
72
|
+
'X-MyHeader3': 'ghi',
|
|
73
|
+
'X-MyHeader4': 'jkl',
|
|
74
|
+
},
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
await z.wait([
|
|
78
|
+
{
|
|
79
|
+
event: 'media_status',
|
|
80
|
+
call_id: oc.id,
|
|
81
|
+
status: 'setup_ok',
|
|
82
|
+
local_mode: 'sendrecv',
|
|
83
|
+
remote_mode: 'sendrecv',
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
event: 'media_status',
|
|
87
|
+
call_id: ic.id,
|
|
88
|
+
status: 'setup_ok',
|
|
89
|
+
local_mode: 'sendrecv',
|
|
90
|
+
remote_mode: 'sendrecv',
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
event: 'response',
|
|
94
|
+
call_id: oc.id,
|
|
95
|
+
method: 'INVITE',
|
|
96
|
+
msg: sip_msg({
|
|
97
|
+
$rs: '200',
|
|
98
|
+
$rr: 'OK',
|
|
99
|
+
'$(hdrcnt(VIA))': 1,
|
|
100
|
+
$fU: 'alice',
|
|
101
|
+
$fd: 'test.com',
|
|
102
|
+
$tU: 'bob',
|
|
103
|
+
'$hdr(content-type)': 'application/sdp',
|
|
104
|
+
$rb: '!{_}a=sendrecv',
|
|
105
|
+
'$hdr(X-MyHeader3)': 'ghi',
|
|
106
|
+
'$hdr(X-MyHeader4)': 'jkl',
|
|
107
|
+
}),
|
|
108
|
+
},
|
|
109
|
+
], 1000)
|
|
110
|
+
|
|
111
|
+
sip.call.start_recording(oc.id, {file: './oc.wav'})
|
|
112
|
+
sip.call.start_recording(ic.id, {file: './ic.wav'})
|
|
113
|
+
|
|
114
|
+
sip.call.send_dtmf(oc.id, {digits: '1234', mode: 0})
|
|
115
|
+
sip.call.send_dtmf(ic.id, {digits: '4321', mode: 1})
|
|
116
|
+
|
|
117
|
+
await z.wait([
|
|
118
|
+
{
|
|
119
|
+
event: 'dtmf',
|
|
120
|
+
call_id: ic.id,
|
|
121
|
+
digits: '1234',
|
|
122
|
+
mode: 0,
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
event: 'dtmf',
|
|
126
|
+
call_id: oc.id,
|
|
127
|
+
digits: '4321',
|
|
128
|
+
mode: 1,
|
|
129
|
+
},
|
|
130
|
+
], 2000)
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
sip.call.reinvite(oc.id, { hold: true })
|
|
134
|
+
|
|
135
|
+
await z.wait([
|
|
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=recvonly',
|
|
144
|
+
}),
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
event: 'media_status',
|
|
148
|
+
call_id: oc.id,
|
|
149
|
+
status: 'setup_ok',
|
|
150
|
+
local_mode: 'sendonly',
|
|
151
|
+
remote_mode: 'recvonly',
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
event: 'media_status',
|
|
155
|
+
call_id: ic.id,
|
|
156
|
+
status: 'setup_ok',
|
|
157
|
+
local_mode: 'recvonly',
|
|
158
|
+
remote_mode: 'sendonly',
|
|
159
|
+
},
|
|
160
|
+
], 500)
|
|
161
|
+
|
|
162
|
+
sip.call.send_dtmf(oc.id, {digits: '1234', mode: 0})
|
|
163
|
+
sip.call.send_dtmf(ic.id, {digits: '4321', mode: 0}) // this will not generate event 'dtmf' as the call is on hold
|
|
164
|
+
|
|
165
|
+
await z.wait([
|
|
166
|
+
{
|
|
167
|
+
event: 'dtmf',
|
|
168
|
+
call_id: ic.id,
|
|
169
|
+
digits: '1234',
|
|
170
|
+
mode: 0,
|
|
171
|
+
},
|
|
172
|
+
], 2000)
|
|
173
|
+
|
|
174
|
+
sip.call.reinvite(ic.id)
|
|
175
|
+
|
|
176
|
+
await z.wait([
|
|
177
|
+
{
|
|
178
|
+
event: 'response',
|
|
179
|
+
call_id: ic.id,
|
|
180
|
+
method: 'INVITE',
|
|
181
|
+
msg: sip_msg({
|
|
182
|
+
$rs: '200',
|
|
183
|
+
$rr: 'OK',
|
|
184
|
+
$rb: '!{_}a=sendonly',
|
|
185
|
+
}),
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
event: 'media_status',
|
|
189
|
+
call_id: oc.id,
|
|
190
|
+
status: 'setup_ok',
|
|
191
|
+
local_mode: 'sendonly',
|
|
192
|
+
remote_mode: 'recvonly',
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
event: 'media_status',
|
|
196
|
+
call_id: ic.id,
|
|
197
|
+
status: 'setup_ok',
|
|
198
|
+
local_mode: 'recvonly',
|
|
199
|
+
remote_mode: 'sendonly',
|
|
200
|
+
},
|
|
201
|
+
], 500)
|
|
202
|
+
|
|
203
|
+
sip.call.send_dtmf(oc.id, {digits: '1234', mode: 0})
|
|
204
|
+
sip.call.send_dtmf(ic.id, {digits: '4321', mode: 1}) // this will not generate event 'dtmf' as the call is on hold
|
|
205
|
+
|
|
206
|
+
await z.wait([
|
|
207
|
+
{
|
|
208
|
+
event: 'dtmf',
|
|
209
|
+
call_id: ic.id,
|
|
210
|
+
digits: '1234',
|
|
211
|
+
mode: 0,
|
|
212
|
+
},
|
|
213
|
+
], 2000)
|
|
214
|
+
|
|
215
|
+
sip.call.send_request(oc.id, {method: 'INFO'})
|
|
216
|
+
|
|
217
|
+
await z.wait([
|
|
218
|
+
{
|
|
219
|
+
event: 'request',
|
|
220
|
+
call_id: ic.id,
|
|
221
|
+
msg: sip_msg({
|
|
222
|
+
$rm: 'INFO',
|
|
223
|
+
}),
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
event: 'response',
|
|
227
|
+
call_id: oc.id,
|
|
228
|
+
method: 'INFO',
|
|
229
|
+
msg: sip_msg({
|
|
230
|
+
$rs: '200',
|
|
231
|
+
$rr: 'OK',
|
|
232
|
+
}),
|
|
233
|
+
},
|
|
234
|
+
], 500)
|
|
235
|
+
|
|
236
|
+
sip.call.reinvite(oc.id)
|
|
237
|
+
|
|
238
|
+
await z.wait([
|
|
239
|
+
{
|
|
240
|
+
event: 'response',
|
|
241
|
+
call_id: oc.id,
|
|
242
|
+
method: 'INVITE',
|
|
243
|
+
msg: sip_msg({
|
|
244
|
+
$rs: '200',
|
|
245
|
+
$rr: 'OK',
|
|
246
|
+
$rb: '!{_}a=sendrecv',
|
|
247
|
+
}),
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
event: 'media_status',
|
|
251
|
+
call_id: oc.id,
|
|
252
|
+
status: 'setup_ok',
|
|
253
|
+
local_mode: 'sendrecv',
|
|
254
|
+
remote_mode: 'sendrecv',
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
event: 'media_status',
|
|
258
|
+
call_id: ic.id,
|
|
259
|
+
status: 'setup_ok',
|
|
260
|
+
local_mode: 'sendrecv',
|
|
261
|
+
remote_mode: 'sendrecv',
|
|
262
|
+
},
|
|
263
|
+
], 500)
|
|
264
|
+
|
|
265
|
+
sip.call.send_dtmf(oc.id, {digits: '1234', mode: 0})
|
|
266
|
+
sip.call.send_dtmf(ic.id, {digits: '4321', mode: 1})
|
|
267
|
+
|
|
268
|
+
await z.wait([
|
|
269
|
+
{
|
|
270
|
+
event: 'dtmf',
|
|
271
|
+
call_id: ic.id,
|
|
272
|
+
digits: '1234',
|
|
273
|
+
mode: 0,
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
event: 'dtmf',
|
|
277
|
+
call_id: oc.id,
|
|
278
|
+
digits: '4321',
|
|
279
|
+
mode: 1,
|
|
280
|
+
},
|
|
281
|
+
], 2000)
|
|
282
|
+
|
|
283
|
+
sip.call.start_playing(oc.id, {file: '/home/takeshi/work/src/svn/brastel/SIP-Tools/trunk/sip-tester/yosemitesam.wav'})
|
|
284
|
+
sip.call.start_playing(ic.id, {file: '/home/takeshi/work/src/svn/brastel/SIP-Tools/trunk/sip-tester/yosemitesam.wav'})
|
|
285
|
+
|
|
286
|
+
await z.sleep(2000)
|
|
287
|
+
|
|
288
|
+
stat1 = sip.call.get_stream_stat(oc.id)
|
|
289
|
+
stat2 = sip.call.get_stream_stat(ic.id)
|
|
290
|
+
|
|
291
|
+
console.log("stat1", stat1)
|
|
292
|
+
console.log("stat2", stat2)
|
|
293
|
+
|
|
294
|
+
sip.call.stop_recording(oc.id)
|
|
295
|
+
sip.call.stop_recording(ic.id)
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
sip.call.terminate(oc.id)
|
|
299
|
+
|
|
300
|
+
await z.wait([
|
|
301
|
+
{
|
|
302
|
+
event: 'call_ended',
|
|
303
|
+
call_id: oc.id,
|
|
304
|
+
},
|
|
305
|
+
{
|
|
306
|
+
event: 'call_ended',
|
|
307
|
+
call_id: ic.id,
|
|
308
|
+
},
|
|
309
|
+
{
|
|
310
|
+
event: 'response',
|
|
311
|
+
call_id: oc.id,
|
|
312
|
+
method: 'BYE',
|
|
313
|
+
msg: sip_msg({
|
|
314
|
+
$rs: '200',
|
|
315
|
+
$rr: 'OK',
|
|
316
|
+
}),
|
|
317
|
+
},
|
|
318
|
+
], 1000)
|
|
319
|
+
|
|
320
|
+
await z.sleep(1000)
|
|
321
|
+
|
|
322
|
+
console.log("Success")
|
|
323
|
+
|
|
324
|
+
sip.stop()
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
test()
|
|
329
|
+
.catch(e => {
|
|
330
|
+
console.error(e)
|
|
331
|
+
process.exit(1)
|
|
332
|
+
})
|
|
333
|
+
|
package/src/sip.cpp
CHANGED
|
@@ -426,9 +426,10 @@ static void server_on_evsub_rx_refresh(pjsip_evsub *sub, pjsip_rx_data *rdata, i
|
|
|
426
426
|
|
|
427
427
|
bool dlg_create(pjsip_dialog **dlg, Transport *transport, const char *from_uri, const char *to_uri, const char *request_uri, const char *realm, const char *username, const char *password, const char *local_contact);
|
|
428
428
|
|
|
429
|
-
static int call_create(Transport *t, unsigned flags, pjsip_dialog *dlg, const char *proxy_uri,
|
|
429
|
+
static int call_create(Transport *t, unsigned flags, pjsip_dialog *dlg, const char *proxy_uri, Document &document);
|
|
430
430
|
|
|
431
|
-
bool
|
|
431
|
+
bool subscription_subscribe_no_headers(Subscription *s, int expires);
|
|
432
|
+
bool subscription_subscribe(Subscription *s, int expires, Document &document);
|
|
432
433
|
|
|
433
434
|
static pjmedia_transport *create_media_transport(const pj_str_t *addr);
|
|
434
435
|
void close_media_transport(pjmedia_transport *med_transport);
|
|
@@ -446,11 +447,12 @@ bool set_proxy(pjsip_dialog *dlg, const char *proxy_uri);
|
|
|
446
447
|
void build_local_contact(char *dest, pjsip_transport *transport, const char *contact_username);
|
|
447
448
|
void build_local_contact_from_tpfactory(char *dest, pjsip_tpfactory *tpfactory, const char *contact_username, pjsip_transport_type_e type);
|
|
448
449
|
|
|
449
|
-
pj_bool_t add_additional_headers(pj_pool_t *pool, pjsip_tx_data *tdata, const char *additional_headers);
|
|
450
|
+
//pj_bool_t add_additional_headers(pj_pool_t *pool, pjsip_tx_data *tdata, const char *additional_headers);
|
|
451
|
+
pj_bool_t add_headers(pj_pool_t *pool, pjsip_tx_data *tdata, Document &document);
|
|
450
452
|
|
|
451
|
-
pj_bool_t
|
|
453
|
+
pj_bool_t add_headers_for_account(pjsip_regc* regc, Document &document);
|
|
452
454
|
|
|
453
|
-
pj_bool_t
|
|
455
|
+
pj_bool_t get_content_type_and_subtype_from_headers(Document &document, char *type, char *subtype);
|
|
454
456
|
|
|
455
457
|
bool build_subscribe_info(ostringstream *oss, pjsip_rx_data *rdata, Subscriber *s);
|
|
456
458
|
//bool build_notify_info(pjsip_rx_data *rdata, Subscription *s);
|
|
@@ -1256,7 +1258,6 @@ int pjw_account_create(int t_id, const char *json, int *out_acc_id)
|
|
|
1256
1258
|
char *password;
|
|
1257
1259
|
char *c_to_uri = NULL;
|
|
1258
1260
|
int expires = 60;
|
|
1259
|
-
char *additional_headers = NULL;
|
|
1260
1261
|
|
|
1261
1262
|
pj_str_t server_uri;
|
|
1262
1263
|
pj_str_t from_uri;
|
|
@@ -1322,11 +1323,8 @@ int pjw_account_create(int t_id, const char *json, int *out_acc_id)
|
|
|
1322
1323
|
goto out;
|
|
1323
1324
|
}
|
|
1324
1325
|
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
set_error("add_additional_headers_for_account failed");
|
|
1328
|
-
goto out;
|
|
1329
|
-
}
|
|
1326
|
+
if(!add_headers_for_account(regc, document)) {
|
|
1327
|
+
goto out;
|
|
1330
1328
|
}
|
|
1331
1329
|
|
|
1332
1330
|
if(!g_account_ids.add((long)regc, acc_id)){
|
|
@@ -1542,8 +1540,6 @@ int pjw_call_respond(long call_id, const char *json)
|
|
|
1542
1540
|
|
|
1543
1541
|
Call *call;
|
|
1544
1542
|
|
|
1545
|
-
char *additional_headers = NULL;
|
|
1546
|
-
|
|
1547
1543
|
char buffer[MAX_JSON_INPUT];
|
|
1548
1544
|
|
|
1549
1545
|
Document document;
|
|
@@ -1602,7 +1598,7 @@ int pjw_call_respond(long call_id, const char *json)
|
|
|
1602
1598
|
goto out;
|
|
1603
1599
|
}
|
|
1604
1600
|
|
|
1605
|
-
if(!
|
|
1601
|
+
if(!add_headers(call->inv->dlg->pool, tdata, document)) {
|
|
1606
1602
|
goto out;
|
|
1607
1603
|
}
|
|
1608
1604
|
}
|
|
@@ -1634,8 +1630,6 @@ int pjw_call_terminate(long call_id, const char *json)
|
|
|
1634
1630
|
char *reason = (char*)"";
|
|
1635
1631
|
pj_str_t r;// = pj_str((char*)reason);
|
|
1636
1632
|
|
|
1637
|
-
const char *additional_headers;
|
|
1638
|
-
|
|
1639
1633
|
Call *call;
|
|
1640
1634
|
|
|
1641
1635
|
char buffer[MAX_JSON_INPUT];
|
|
@@ -1677,8 +1671,7 @@ int pjw_call_terminate(long call_id, const char *json)
|
|
|
1677
1671
|
goto out;
|
|
1678
1672
|
}
|
|
1679
1673
|
|
|
1680
|
-
if(!
|
|
1681
|
-
set_error("add_additional_headers failed");
|
|
1674
|
+
if(!add_headers(call->inv->dlg->pool, tdata, document)) {
|
|
1682
1675
|
goto out;
|
|
1683
1676
|
}
|
|
1684
1677
|
|
|
@@ -1720,8 +1713,6 @@ int pjw_call_create(long t_id, const char *json, long *out_call_id, char *out_si
|
|
|
1720
1713
|
char *request_uri = NULL;
|
|
1721
1714
|
char *proxy_uri = NULL;
|
|
1722
1715
|
|
|
1723
|
-
char *headers = NULL;
|
|
1724
|
-
|
|
1725
1716
|
char *realm = NULL;
|
|
1726
1717
|
char *username = NULL;
|
|
1727
1718
|
char *password = NULL;
|
|
@@ -1761,16 +1752,6 @@ int pjw_call_create(long t_id, const char *json, long *out_call_id, char *out_si
|
|
|
1761
1752
|
goto out;
|
|
1762
1753
|
}
|
|
1763
1754
|
|
|
1764
|
-
/*
|
|
1765
|
-
const Value& headers = document["headers"];
|
|
1766
|
-
if(document.HasMember("headers") {
|
|
1767
|
-
if(!headers.IsArray()) {
|
|
1768
|
-
set_error("headers must be an array");
|
|
1769
|
-
goto out;
|
|
1770
|
-
}
|
|
1771
|
-
}
|
|
1772
|
-
*/
|
|
1773
|
-
|
|
1774
1755
|
if(document.HasMember("auth")) {
|
|
1775
1756
|
if(!document["auth"].IsObject()) {
|
|
1776
1757
|
set_error("Parameter auth must be an object");
|
|
@@ -1828,7 +1809,7 @@ int pjw_call_create(long t_id, const char *json, long *out_call_id, char *out_si
|
|
|
1828
1809
|
goto out;
|
|
1829
1810
|
}
|
|
1830
1811
|
|
|
1831
|
-
call_id = call_create(t, flags, dlg, proxy_uri,
|
|
1812
|
+
call_id = call_create(t, flags, dlg, proxy_uri, document);
|
|
1832
1813
|
if(call_id < 0) {
|
|
1833
1814
|
goto out;
|
|
1834
1815
|
}
|
|
@@ -2007,7 +1988,7 @@ bool dlg_create(pjsip_dialog **dlg, Transport *transport, const char *from_uri,
|
|
|
2007
1988
|
}
|
|
2008
1989
|
|
|
2009
1990
|
|
|
2010
|
-
int call_create(Transport *t, unsigned flags, pjsip_dialog *dlg, const char *proxy_uri,
|
|
1991
|
+
int call_create(Transport *t, unsigned flags, pjsip_dialog *dlg, const char *proxy_uri, Document &document)
|
|
2011
1992
|
{
|
|
2012
1993
|
pjsip_inv_session *inv;
|
|
2013
1994
|
//in_addr addr;
|
|
@@ -2092,7 +2073,7 @@ int call_create(Transport *t, unsigned flags, pjsip_dialog *dlg, const char *pro
|
|
|
2092
2073
|
|
|
2093
2074
|
|
|
2094
2075
|
|
|
2095
|
-
if(!
|
|
2076
|
+
if(!add_headers(dlg->pool, tdata, document)) {
|
|
2096
2077
|
g_call_ids.remove(call_id, (long &)call);
|
|
2097
2078
|
close_media_transport(med_transport); //Todo:
|
|
2098
2079
|
status = pjsip_dlg_terminate(dlg); //ToDo:
|
|
@@ -2382,7 +2363,6 @@ int pjw_call_send_request(long call_id, const char *json)
|
|
|
2382
2363
|
clear_error();
|
|
2383
2364
|
|
|
2384
2365
|
char *method = NULL;
|
|
2385
|
-
char *additional_headers = NULL;
|
|
2386
2366
|
char *body = NULL;
|
|
2387
2367
|
char *ct_type = NULL;
|
|
2388
2368
|
char *ct_subtype = NULL;
|
|
@@ -2454,7 +2434,7 @@ int pjw_call_send_request(long call_id, const char *json)
|
|
|
2454
2434
|
goto out;
|
|
2455
2435
|
}
|
|
2456
2436
|
|
|
2457
|
-
if(!
|
|
2437
|
+
if(!add_headers(call->inv->dlg->pool, tdata, document)) {
|
|
2458
2438
|
goto out;
|
|
2459
2439
|
}
|
|
2460
2440
|
|
|
@@ -3704,17 +3684,13 @@ static void on_rx_offer(pjsip_inv_session *inv, const pjmedia_sdp_session *offer
|
|
|
3704
3684
|
// Keep call on-hold by setting 'sendonly' attribute.
|
|
3705
3685
|
// (See RFC 3264 Section 8.4 and RFC 4317 Section 3.1)
|
|
3706
3686
|
if(call->remote_hold) {
|
|
3707
|
-
printf("p1\n");
|
|
3708
3687
|
attr = pjmedia_sdp_attr_create(inv->pool, "inactive", NULL);
|
|
3709
3688
|
} else {
|
|
3710
|
-
printf("p2\n");
|
|
3711
3689
|
attr = pjmedia_sdp_attr_create(inv->pool, "sendonly", NULL);
|
|
3712
3690
|
}
|
|
3713
3691
|
} else if(call->remote_hold) {
|
|
3714
|
-
printf("p3\n");
|
|
3715
3692
|
attr = pjmedia_sdp_attr_create(inv->pool, "recvonly", NULL);
|
|
3716
3693
|
} else {
|
|
3717
|
-
printf("p4\n");
|
|
3718
3694
|
attr = pjmedia_sdp_attr_create(inv->pool, "sendrecv", NULL);
|
|
3719
3695
|
}
|
|
3720
3696
|
pjmedia_sdp_media_add_attr(answer->media[0], attr);
|
|
@@ -4433,7 +4409,7 @@ static void on_client_refresh( pjsip_evsub *sub ) {
|
|
|
4433
4409
|
goto out;
|
|
4434
4410
|
}
|
|
4435
4411
|
|
|
4436
|
-
if(!
|
|
4412
|
+
if(!subscription_subscribe_no_headers(subscription, -1)) {
|
|
4437
4413
|
goto out;
|
|
4438
4414
|
}
|
|
4439
4415
|
|
|
@@ -4852,7 +4828,6 @@ int pjw_call_refer(long call_id, const char *json, long *out_subscription_id)
|
|
|
4852
4828
|
clear_error();
|
|
4853
4829
|
|
|
4854
4830
|
char *dest_uri;
|
|
4855
|
-
char *additional_headers;
|
|
4856
4831
|
|
|
4857
4832
|
long val;
|
|
4858
4833
|
Call *call;
|
|
@@ -4895,7 +4870,7 @@ int pjw_call_refer(long call_id, const char *json, long *out_subscription_id)
|
|
|
4895
4870
|
s_dest_uri = pj_str((char*)dest_uri);
|
|
4896
4871
|
status = pjsip_xfer_initiate(sub, &s_dest_uri, &tdata);
|
|
4897
4872
|
|
|
4898
|
-
if(!
|
|
4873
|
+
if(!add_headers(call->inv->dlg->pool, tdata, document)) {
|
|
4899
4874
|
goto out;
|
|
4900
4875
|
}
|
|
4901
4876
|
|
|
@@ -4960,7 +4935,7 @@ int pjw_call_get_info(long call_id, const char *required_info, char *out_info)
|
|
|
4960
4935
|
return 0;
|
|
4961
4936
|
}
|
|
4962
4937
|
|
|
4963
|
-
bool notify(pjsip_evsub *evsub, const char *content_type, const char *body, int subscription_state, const char *reason,
|
|
4938
|
+
bool notify(pjsip_evsub *evsub, const char *content_type, const char *body, int subscription_state, const char *reason, Document &document) {
|
|
4964
4939
|
//pj_str_t s_content_type;
|
|
4965
4940
|
//pj_str_t s_body;
|
|
4966
4941
|
pj_str_t s_reason;
|
|
@@ -5014,7 +4989,9 @@ bool notify(pjsip_evsub *evsub, const char *content_type, const char *body, int
|
|
|
5014
4989
|
}
|
|
5015
4990
|
s_content_type_subtype = pj_str(tok);
|
|
5016
4991
|
|
|
5017
|
-
|
|
4992
|
+
if(!add_headers(tdata->pool, tdata, document)) {
|
|
4993
|
+
return false;
|
|
4994
|
+
}
|
|
5018
4995
|
|
|
5019
4996
|
msg_body->content_type.type = s_content_type_type;
|
|
5020
4997
|
msg_body->content_type.subtype = s_content_type_subtype;
|
|
@@ -5045,7 +5022,6 @@ int pjw_notify(long subscriber_id, const char *json)
|
|
|
5045
5022
|
char *body = NULL;
|
|
5046
5023
|
int subscription_state;
|
|
5047
5024
|
char *reason = NULL;
|
|
5048
|
-
char *additional_headers = NULL;
|
|
5049
5025
|
|
|
5050
5026
|
long val;
|
|
5051
5027
|
|
|
@@ -5086,7 +5062,7 @@ int pjw_notify(long subscriber_id, const char *json)
|
|
|
5086
5062
|
goto out;
|
|
5087
5063
|
}
|
|
5088
5064
|
|
|
5089
|
-
if(!notify(subscriber->evsub, content_type, body, subscription_state, reason,
|
|
5065
|
+
if(!notify(subscriber->evsub, content_type, body, subscription_state, reason, document)){
|
|
5090
5066
|
goto out;
|
|
5091
5067
|
}
|
|
5092
5068
|
|
|
@@ -5174,6 +5150,7 @@ out:
|
|
|
5174
5150
|
return 0;
|
|
5175
5151
|
}
|
|
5176
5152
|
|
|
5153
|
+
/*
|
|
5177
5154
|
pj_bool_t add_additional_headers(pj_pool_t *pool, pjsip_tx_data *tdata, const char *additional_headers) {
|
|
5178
5155
|
|
|
5179
5156
|
if(additional_headers && additional_headers[0]){
|
|
@@ -5210,94 +5187,133 @@ pj_bool_t add_additional_headers(pj_pool_t *pool, pjsip_tx_data *tdata, const ch
|
|
|
5210
5187
|
}
|
|
5211
5188
|
return PJ_TRUE;
|
|
5212
5189
|
}
|
|
5190
|
+
*/
|
|
5213
5191
|
|
|
5214
|
-
pj_bool_t add_additional_headers_for_account(pjsip_regc *regc, const char *additional_headers) {
|
|
5215
5192
|
|
|
5216
|
-
|
|
5217
|
-
|
|
5218
|
-
|
|
5193
|
+
pj_bool_t add_headers(pj_pool_t *pool, pjsip_tx_data *tdata, Document &document) {
|
|
5194
|
+
if(!document.HasMember("headers")) {
|
|
5195
|
+
return PJ_TRUE;
|
|
5196
|
+
}
|
|
5219
5197
|
|
|
5220
|
-
|
|
5221
|
-
|
|
5222
|
-
|
|
5198
|
+
if(!document["headers"].IsObject()) {
|
|
5199
|
+
set_error("Parameter headers must be an object");
|
|
5200
|
+
return PJ_FALSE;
|
|
5201
|
+
}
|
|
5223
5202
|
|
|
5224
|
-
|
|
5225
|
-
strcpy(buf,additional_headers);
|
|
5226
|
-
char *saved;
|
|
5227
|
-
char *token = strtok_r(buf, "\n", &saved);
|
|
5228
|
-
while(token){
|
|
5229
|
-
char *name = strtok(token, ":");
|
|
5230
|
-
char *value = strtok(NULL, "\n");
|
|
5231
|
-
//addon_log(LOG_LEVEL_DEBUG, "Adding %s:%s\n", name, value);
|
|
5203
|
+
Value headers = document["headers"].GetObject();
|
|
5232
5204
|
|
|
5233
|
-
|
|
5234
|
-
|
|
5235
|
-
return PJ_FALSE;
|
|
5236
|
-
}
|
|
5205
|
+
for (Value::ConstMemberIterator itr = headers.MemberBegin(); itr != headers.MemberEnd(); ++itr) {
|
|
5206
|
+
printf("%s => '%s'\n", itr->name.GetString(), itr->value.GetString());
|
|
5237
5207
|
|
|
5238
|
-
|
|
5239
|
-
|
|
5240
|
-
|
|
5241
|
-
|
|
5242
|
-
|
|
5243
|
-
NULL);
|
|
5208
|
+
const char *name = itr->name.GetString();
|
|
5209
|
+
if(!itr->value.IsString()) {
|
|
5210
|
+
set_error("Parameter headers key '%s' found with non-string value", name);
|
|
5211
|
+
return PJ_FALSE;
|
|
5212
|
+
}
|
|
5244
5213
|
|
|
5245
|
-
|
|
5246
|
-
|
|
5247
|
-
|
|
5248
|
-
|
|
5249
|
-
|
|
5250
|
-
|
|
5251
|
-
|
|
5252
|
-
|
|
5253
|
-
|
|
5254
|
-
|
|
5214
|
+
const char *value = itr->value.GetString();
|
|
5215
|
+
|
|
5216
|
+
pj_str_t hname = pj_str((char*)name);
|
|
5217
|
+
pjsip_hdr *hdr = (pjsip_hdr*)pjsip_parse_hdr(pool,
|
|
5218
|
+
&hname,
|
|
5219
|
+
(char*)value,
|
|
5220
|
+
strlen(value),
|
|
5221
|
+
NULL);
|
|
5222
|
+
|
|
5223
|
+
if(!hdr) {
|
|
5224
|
+
set_error("Failed to parse header '%s' => '%s'", name, value);
|
|
5225
|
+
return PJ_FALSE;
|
|
5226
|
+
}
|
|
5227
|
+
pjsip_hdr *clone_hdr = (pjsip_hdr*) pjsip_hdr_clone(pool, hdr);
|
|
5228
|
+
pjsip_msg_add_hdr(tdata->msg, clone_hdr);
|
|
5229
|
+
}
|
|
5255
5230
|
return PJ_TRUE;
|
|
5256
5231
|
}
|
|
5257
5232
|
|
|
5258
|
-
pj_bool_t
|
|
5233
|
+
pj_bool_t add_headers_for_account(pjsip_regc *regc, Document &document) {
|
|
5234
|
+
pjsip_hdr hdr_list;
|
|
5235
|
+
pj_list_init(&hdr_list);
|
|
5259
5236
|
|
|
5260
|
-
|
|
5261
|
-
|
|
5262
|
-
|
|
5263
|
-
}
|
|
5237
|
+
char pool_buf[4096];
|
|
5238
|
+
pj_pool_t *pool;
|
|
5239
|
+
pool = pj_pool_create_on_buf(NULL, pool_buf, sizeof(pool_buf));
|
|
5264
5240
|
|
|
5265
|
-
|
|
5266
|
-
|
|
5267
|
-
|
|
5268
|
-
char *token = strtok_r(buf, "\n", &saved);
|
|
5269
|
-
while(token){
|
|
5270
|
-
char *name = strtok(token, ":");
|
|
5271
|
-
char *value = strtok(NULL, " ");
|
|
5272
|
-
addon_log(LOG_LEVEL_DEBUG, "Checking %s: %s\n", name, value);
|
|
5273
|
-
|
|
5274
|
-
if(!name || !value) {
|
|
5275
|
-
set_error("Invalid additional_header");
|
|
5276
|
-
return PJ_FALSE;
|
|
5277
|
-
}
|
|
5241
|
+
if(!document.HasMember("headers")) {
|
|
5242
|
+
return PJ_TRUE;
|
|
5243
|
+
}
|
|
5278
5244
|
|
|
5279
|
-
|
|
5280
|
-
|
|
5281
|
-
|
|
5282
|
-
|
|
5283
|
-
return PJ_FALSE;
|
|
5284
|
-
}
|
|
5285
|
-
|
|
5286
|
-
char *token_subtype = strtok(NULL, "\n");
|
|
5287
|
-
if(!token_subtype) {
|
|
5288
|
-
set_error("No subtype specified in header Content-Type");
|
|
5289
|
-
return PJ_FALSE;
|
|
5290
|
-
}
|
|
5245
|
+
if(!document["headers"].IsObject()) {
|
|
5246
|
+
set_error("Parameter headers must be an object");
|
|
5247
|
+
return PJ_FALSE;
|
|
5248
|
+
}
|
|
5291
5249
|
|
|
5292
|
-
|
|
5293
|
-
|
|
5294
|
-
|
|
5295
|
-
|
|
5296
|
-
|
|
5297
|
-
|
|
5250
|
+
Value headers = document["headers"].GetObject();
|
|
5251
|
+
|
|
5252
|
+
for (Value::ConstMemberIterator itr = headers.MemberBegin(); itr != headers.MemberEnd(); ++itr) {
|
|
5253
|
+
printf("%s => '%s'\n", itr->name.GetString(), itr->value.GetString());
|
|
5254
|
+
|
|
5255
|
+
const char *name = itr->name.GetString();
|
|
5256
|
+
if(!itr->value.IsString()) {
|
|
5257
|
+
set_error("Parameter headers key '%s' found with non-string value", name);
|
|
5258
|
+
return PJ_FALSE;
|
|
5259
|
+
}
|
|
5260
|
+
|
|
5261
|
+
const char *value = itr->value.GetString();
|
|
5262
|
+
|
|
5263
|
+
pj_str_t hname = pj_str((char*)name);
|
|
5264
|
+
pjsip_hdr *hdr = (pjsip_hdr*)pjsip_parse_hdr(pool,
|
|
5265
|
+
&hname,
|
|
5266
|
+
(char*)value,
|
|
5267
|
+
strlen(value),
|
|
5268
|
+
NULL);
|
|
5269
|
+
|
|
5270
|
+
if(!hdr) {
|
|
5271
|
+
set_error("Failed to parse header %s", name);
|
|
5272
|
+
return PJ_FALSE;
|
|
5273
|
+
}
|
|
5274
|
+
|
|
5275
|
+
pj_list_push_back(&hdr_list, hdr);
|
|
5298
5276
|
}
|
|
5299
|
-
|
|
5300
|
-
|
|
5277
|
+
|
|
5278
|
+
pjsip_regc_add_headers(regc, &hdr_list);
|
|
5279
|
+
return PJ_TRUE;
|
|
5280
|
+
}
|
|
5281
|
+
|
|
5282
|
+
pj_bool_t get_content_type_and_subtype_from_headers(Document &document, char *type, char *subtype) {
|
|
5283
|
+
if(!document.HasMember("headers")) {
|
|
5284
|
+
set_error("Parameter headers absent");
|
|
5285
|
+
return PJ_FALSE;
|
|
5286
|
+
}
|
|
5287
|
+
|
|
5288
|
+
if(!document["headers"].IsObject()) {
|
|
5289
|
+
set_error("Parameter headers must be an object");
|
|
5290
|
+
return PJ_FALSE;
|
|
5291
|
+
}
|
|
5292
|
+
|
|
5293
|
+
Value headers = document["headers"].GetObject();
|
|
5294
|
+
|
|
5295
|
+
if(!headers.HasMember("Content-Type")) {
|
|
5296
|
+
set_error("Parameter headers doesn't contain key Content-Type");
|
|
5297
|
+
return PJ_FALSE;
|
|
5298
|
+
}
|
|
5299
|
+
|
|
5300
|
+
const char *content_type = headers["Content-Type"].GetString();
|
|
5301
|
+
|
|
5302
|
+
const char *slash;
|
|
5303
|
+
int index;
|
|
5304
|
+
|
|
5305
|
+
slash = strchr(content_type, '/');
|
|
5306
|
+
if(!slash) {
|
|
5307
|
+
set_error("Invalid header Content-Type");
|
|
5308
|
+
return PJ_FALSE;
|
|
5309
|
+
}
|
|
5310
|
+
|
|
5311
|
+
index = (int)(slash - content_type);
|
|
5312
|
+
|
|
5313
|
+
strncpy(type, content_type, index-1);
|
|
5314
|
+
strcpy(subtype, content_type+index);
|
|
5315
|
+
addon_log(LOG_LEVEL_DEBUG, "Checking parsing of Content-Type. type=%s: subtype=%s\n", type, subtype);
|
|
5316
|
+
return PJ_TRUE;
|
|
5301
5317
|
}
|
|
5302
5318
|
|
|
5303
5319
|
|
|
@@ -5505,7 +5521,37 @@ out:
|
|
|
5505
5521
|
return 0;
|
|
5506
5522
|
}
|
|
5507
5523
|
|
|
5508
|
-
bool
|
|
5524
|
+
bool subscription_subscribe_no_headers(Subscription *s, int expires) {
|
|
5525
|
+
pj_status_t status;
|
|
5526
|
+
pjsip_tx_data *tdata;
|
|
5527
|
+
|
|
5528
|
+
status = pjsip_evsub_initiate(s->evsub,
|
|
5529
|
+
NULL,
|
|
5530
|
+
expires,
|
|
5531
|
+
&tdata);
|
|
5532
|
+
if(status != PJ_SUCCESS) {
|
|
5533
|
+
set_error("pjsip_evsub_initiate failed");
|
|
5534
|
+
return false;
|
|
5535
|
+
}
|
|
5536
|
+
|
|
5537
|
+
status = pjsip_evsub_send_request(s->evsub, tdata);
|
|
5538
|
+
if(status != PJ_SUCCESS) {
|
|
5539
|
+
set_error("pjsip_inv_send_msg failed");
|
|
5540
|
+
return false;
|
|
5541
|
+
}
|
|
5542
|
+
|
|
5543
|
+
//Without this, on_rx_response will not be called
|
|
5544
|
+
status = pjsip_dlg_add_usage(s->dlg, &mod_tester, s);
|
|
5545
|
+
if(status != PJ_SUCCESS) {
|
|
5546
|
+
set_error("pjsip_dlg_add_usage failed");
|
|
5547
|
+
return false;
|
|
5548
|
+
}
|
|
5549
|
+
|
|
5550
|
+
return true;
|
|
5551
|
+
}
|
|
5552
|
+
|
|
5553
|
+
|
|
5554
|
+
bool subscription_subscribe(Subscription *s, int expires, Document &document) {
|
|
5509
5555
|
pj_status_t status;
|
|
5510
5556
|
pjsip_tx_data *tdata;
|
|
5511
5557
|
|
|
@@ -5518,7 +5564,7 @@ bool subscription_subscribe(Subscription *s, int expires, const char *additional
|
|
|
5518
5564
|
return false;
|
|
5519
5565
|
}
|
|
5520
5566
|
|
|
5521
|
-
if(!
|
|
5567
|
+
if(!add_headers(s->dlg->pool, tdata, document)) {
|
|
5522
5568
|
return false;
|
|
5523
5569
|
}
|
|
5524
5570
|
|
|
@@ -5544,7 +5590,6 @@ int pjw_subscription_subscribe(long subscription_id, const char *json) {
|
|
|
5544
5590
|
clear_error();
|
|
5545
5591
|
|
|
5546
5592
|
int expires;
|
|
5547
|
-
char *additional_headers = NULL;
|
|
5548
5593
|
|
|
5549
5594
|
Subscription *subscription;
|
|
5550
5595
|
|
|
@@ -5568,7 +5613,7 @@ int pjw_subscription_subscribe(long subscription_id, const char *json) {
|
|
|
5568
5613
|
goto out;
|
|
5569
5614
|
}
|
|
5570
5615
|
|
|
5571
|
-
if(!subscription_subscribe(subscription, expires,
|
|
5616
|
+
if(!subscription_subscribe(subscription, expires, document)) {
|
|
5572
5617
|
goto out;
|
|
5573
5618
|
}
|
|
5574
5619
|
|