sip-lab 1.12.1 → 1.12.4
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/README.md +10 -21
- package/binding.gyp +18 -16
- package/include/siplab_constants.h +6 -0
- package/install.sh +32 -1
- package/package.json +1 -1
- package/samples/send_and_receive_fax.js +10 -9
- package/samples/simple.js +72 -33
- package/src/Makefile +1 -1
- package/src/pjmedia/include/chainlink/chainlink_fax.h +1 -1
- package/src/pjmedia/src/chainlink/chainlink_fax.c +21 -15
- package/src/sip.cpp +34 -4
- package/install_bcg729.sh +0 -18
package/README.md
CHANGED
|
@@ -20,14 +20,7 @@ TODO:
|
|
|
20
20
|
|
|
21
21
|
This will require you to have some libraries installed. So do:
|
|
22
22
|
```
|
|
23
|
-
apt install build-essential automake autoconf libtool libspeex-dev libopus-dev libsdl2-dev libavdevice-dev libswscale-dev libv4l-dev libopencore-amrnb-dev libopencore-amrwb-dev libvo-amrwbenc-dev libopus-dev libsdl2-dev libopencore-amrnb-dev libopencore-amrwb-dev libvo-amrwbenc-dev libboost-dev
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
We will also support G729 codec by installing bcg729.
|
|
27
|
-
|
|
28
|
-
There is a helper script that you can use:
|
|
29
|
-
```
|
|
30
|
-
./install_bcg729.sh
|
|
23
|
+
apt install build-essential automake autoconf libtool libspeex-dev libopus-dev libsdl2-dev libavdevice-dev libswscale-dev libv4l-dev libopencore-amrnb-dev libopencore-amrwb-dev libvo-amrwbenc-dev libopus-dev libsdl2-dev libopencore-amrnb-dev libopencore-amrwb-dev libvo-amrwbenc-dev libboost-dev libtiff-dev libpcap-dev libssl-dev uuid-dev
|
|
31
24
|
```
|
|
32
25
|
|
|
33
26
|
Then install sip-lab by doing:
|
|
@@ -35,6 +28,10 @@ Then install sip-lab by doing:
|
|
|
35
28
|
npm install sip-lab
|
|
36
29
|
```
|
|
37
30
|
|
|
31
|
+
Be patient because we will need to download pjproject and build it.
|
|
32
|
+
|
|
33
|
+
We will also download rapidjson.
|
|
34
|
+
|
|
38
35
|
To test from within this repo just build and install by doing:
|
|
39
36
|
```
|
|
40
37
|
npm install -g node-gyp
|
|
@@ -44,25 +41,17 @@ And run some sample script from subfolder samples:
|
|
|
44
41
|
```
|
|
45
42
|
node samples/simple.js
|
|
46
43
|
```
|
|
44
|
+
The above script has detailed comments.
|
|
45
|
+
Please read it to undestand how to write your own test scripts.
|
|
47
46
|
|
|
48
47
|
The module is known to work properly in Ubuntu 18.04.4, Ubuntu 20.04.4, Debian 8 and Debian 10 (and it is expected to work in Debian 9).
|
|
49
48
|
It was originally developed with node v.10 and tested with v.12 and v16.13.1 and it is expected to work with latest versions of node.
|
|
50
49
|
(it is known to not work with node v.8)
|
|
51
50
|
|
|
52
51
|
|
|
53
|
-
|
|
54
|
-
```
|
|
55
|
-
npm install sip-lab
|
|
56
|
-
```
|
|
57
|
-
takes some time to fetch and build pjproject and the node addon for it, you could install sip-lab globally:
|
|
58
|
-
|
|
59
|
-
```
|
|
60
|
-
npm install -g sip-lab
|
|
61
|
-
```
|
|
52
|
+
### About the code
|
|
62
53
|
|
|
63
|
-
|
|
64
|
-
```
|
|
65
|
-
export NODE_PATH=$(npm root --quiet -g)
|
|
66
|
-
```
|
|
54
|
+
Although the code in written in *.cpp/*.hpp named files, this is not actually a C++ project.
|
|
67
55
|
|
|
56
|
+
It is mostly written in C using some C++ facilities.
|
|
68
57
|
|
package/binding.gyp
CHANGED
|
@@ -17,16 +17,18 @@
|
|
|
17
17
|
'src/pjmedia/src/chainlink/chainlink_fax.c',
|
|
18
18
|
],
|
|
19
19
|
'include_dirs': [
|
|
20
|
-
"pjproject/pjsip/include",
|
|
21
|
-
"pjproject/pjlib/include",
|
|
22
|
-
"pjproject/pjlib-util/include",
|
|
23
|
-
"pjproject/pjnath/include",
|
|
24
|
-
"pjproject/pjmedia/include",
|
|
20
|
+
"3rdParty/pjproject/pjsip/include",
|
|
21
|
+
"3rdParty/pjproject/pjlib/include",
|
|
22
|
+
"3rdParty/pjproject/pjlib-util/include",
|
|
23
|
+
"3rdParty/pjproject/pjnath/include",
|
|
24
|
+
"3rdParty/pjproject/pjmedia/include",
|
|
25
|
+
"include",
|
|
25
26
|
"src",
|
|
26
27
|
"src/pjmedia/include",
|
|
27
28
|
"src/pjmedia/include/pjmedia",
|
|
28
29
|
"src/pjmedia/include/chainlink",
|
|
29
|
-
"rapidjson/include",
|
|
30
|
+
"3rdParty/rapidjson/include",
|
|
31
|
+
"3rdParty/spandsp/src",
|
|
30
32
|
"<!@(node -p \"require('node-addon-api').include\")",
|
|
31
33
|
],
|
|
32
34
|
"dependencies": [
|
|
@@ -48,14 +50,13 @@
|
|
|
48
50
|
],
|
|
49
51
|
'link_settings': {
|
|
50
52
|
'libraries': [
|
|
51
|
-
'-L ../pjproject/pjnath/lib',
|
|
52
|
-
'-L ../pjproject/pjlib/lib',
|
|
53
|
-
'-L ../pjproject/pjlib-util/lib',
|
|
54
|
-
'-L ../pjproject/third_party/lib',
|
|
55
|
-
'-L ../pjproject/pjmedia/lib',
|
|
56
|
-
'-L ../pjproject/pjsip/lib',
|
|
57
|
-
'-L ../pjproject/third_party/lib',
|
|
58
|
-
'-L ../bcg729/src',
|
|
53
|
+
'-L ../3rdParty/pjproject/pjnath/lib',
|
|
54
|
+
'-L ../3rdParty/pjproject/pjlib/lib',
|
|
55
|
+
'-L ../3rdParty/pjproject/pjlib-util/lib',
|
|
56
|
+
'-L ../3rdParty/pjproject/third_party/lib',
|
|
57
|
+
'-L ../3rdParty/pjproject/pjmedia/lib',
|
|
58
|
+
'-L ../3rdParty/pjproject/pjsip/lib',
|
|
59
|
+
'-L ../3rdParty/pjproject/third_party/lib',
|
|
59
60
|
'-l pjnath-x86_64-unknown-linux-gnu',
|
|
60
61
|
'-l ilbccodec-x86_64-unknown-linux-gnu',
|
|
61
62
|
'-l srtp-x86_64-unknown-linux-gnu',
|
|
@@ -77,6 +78,8 @@
|
|
|
77
78
|
'-l pjsua-x86_64-unknown-linux-gnu',
|
|
78
79
|
'-l pj-x86_64-unknown-linux-gnu',
|
|
79
80
|
'-l pjlib-util-x86_64-unknown-linux-gnu',
|
|
81
|
+
'../3rdParty/spandsp/src/.libs/libspandsp.a',
|
|
82
|
+
'../3rdParty/bcg729/src/libbcg729.a',
|
|
80
83
|
'-lstdc++',
|
|
81
84
|
'-lopus',
|
|
82
85
|
'-lssl',
|
|
@@ -84,7 +87,7 @@
|
|
|
84
87
|
'-luuid',
|
|
85
88
|
'-lm',
|
|
86
89
|
'-ldl',
|
|
87
|
-
'-
|
|
90
|
+
'-ltiff',
|
|
88
91
|
'-lpcap',
|
|
89
92
|
'-lrt',
|
|
90
93
|
'-lpthread',
|
|
@@ -100,7 +103,6 @@
|
|
|
100
103
|
'-lopencore-amrwb',
|
|
101
104
|
'-lvo-amrwbenc',
|
|
102
105
|
'-lspeex',
|
|
103
|
-
'-lbcg729',
|
|
104
106
|
],
|
|
105
107
|
},
|
|
106
108
|
},
|
package/install.sh
CHANGED
|
@@ -4,8 +4,27 @@ set -o errexit
|
|
|
4
4
|
set -o nounset
|
|
5
5
|
set -o pipefail
|
|
6
6
|
|
|
7
|
+
|
|
7
8
|
START_DIR=`pwd`
|
|
8
9
|
|
|
10
|
+
|
|
11
|
+
mkdir -p 3rdParty
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
cd $START_DIR/3rdParty
|
|
15
|
+
if [[ ! -d spandsp ]]
|
|
16
|
+
then
|
|
17
|
+
commit=e59ca8fb8b1591e626e6a12fdc60a2ebe83435ed
|
|
18
|
+
git clone https://github.com/freeswitch/spandsp
|
|
19
|
+
cd spandsp
|
|
20
|
+
git checkout $commit
|
|
21
|
+
./bootstrap.sh
|
|
22
|
+
CFLAGS='-O -fPIC' ./configure --enable-shared
|
|
23
|
+
make
|
|
24
|
+
fi
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
cd $START_DIR/3rdParty
|
|
9
28
|
if [[ ! -d pjproject ]]
|
|
10
29
|
then
|
|
11
30
|
git clone https://github.com/pjsip/pjproject
|
|
@@ -28,8 +47,8 @@ EOF
|
|
|
28
47
|
make dep && make clean && make
|
|
29
48
|
fi
|
|
30
49
|
|
|
31
|
-
cd $START_DIR
|
|
32
50
|
|
|
51
|
+
cd $START_DIR/3rdParty
|
|
33
52
|
if [[ ! -d rapidjson ]]
|
|
34
53
|
then
|
|
35
54
|
git clone https://github.com/Tencent/rapidjson
|
|
@@ -37,6 +56,18 @@ then
|
|
|
37
56
|
git checkout 27c3a8dc0e2c9218fe94986d249a12b5ed838f1d
|
|
38
57
|
fi
|
|
39
58
|
|
|
59
|
+
|
|
60
|
+
cd $START_DIR/3rdParty
|
|
61
|
+
if [[ ! -d bcg729 ]]
|
|
62
|
+
then
|
|
63
|
+
git clone https://github.com/MayamaTakeshi/bcg729
|
|
64
|
+
cd bcg729
|
|
65
|
+
git checkout faaa895862165acde6df8add722ba4f85a25007d
|
|
66
|
+
cmake .
|
|
67
|
+
make
|
|
68
|
+
fi
|
|
69
|
+
|
|
70
|
+
|
|
40
71
|
cd $START_DIR
|
|
41
72
|
|
|
42
73
|
node-gyp configure
|
package/package.json
CHANGED
|
@@ -21,7 +21,7 @@ async function test() {
|
|
|
21
21
|
console.log("t1", t1)
|
|
22
22
|
console.log("t2", t2)
|
|
23
23
|
|
|
24
|
-
oc = sip.call.create(t1.id, {from_uri: 'sip:
|
|
24
|
+
oc = sip.call.create(t1.id, {from_uri: 'sip:alice@test.com', to_uri: `sip:bob@${t2.address}:${t2.port}`})
|
|
25
25
|
|
|
26
26
|
await z.wait([
|
|
27
27
|
{
|
|
@@ -37,9 +37,9 @@ async function test() {
|
|
|
37
37
|
$rr: 'Trying',
|
|
38
38
|
'$(hdrcnt(via))': 1,
|
|
39
39
|
'$hdr(call-id)': m.collect('sip_call_id'),
|
|
40
|
-
$fU: '
|
|
41
|
-
$fd: '
|
|
42
|
-
$tU: '
|
|
40
|
+
$fU: 'alice',
|
|
41
|
+
$fd: 'test.com',
|
|
42
|
+
$tU: 'bob',
|
|
43
43
|
'$hdr(l)': '0',
|
|
44
44
|
}),
|
|
45
45
|
},
|
|
@@ -75,9 +75,9 @@ async function test() {
|
|
|
75
75
|
$rs: '200',
|
|
76
76
|
$rr: 'OK',
|
|
77
77
|
'$(hdrcnt(VIA))': 1,
|
|
78
|
-
$fU: '
|
|
79
|
-
$fd: '
|
|
80
|
-
$tU: '
|
|
78
|
+
$fU: 'alice',
|
|
79
|
+
$fd: 'test.com',
|
|
80
|
+
$tU: 'bob',
|
|
81
81
|
'$hdr(content-type)': 'application/sdp',
|
|
82
82
|
$rb: '!{_}a=sendrecv',
|
|
83
83
|
}),
|
|
@@ -89,8 +89,9 @@ async function test() {
|
|
|
89
89
|
var in_file = 'samples/artifacts/this-is-never-ok.tiff'
|
|
90
90
|
var out_file = "received.tiff"
|
|
91
91
|
|
|
92
|
-
|
|
93
|
-
sip.call.start_fax(
|
|
92
|
+
// transmit_on_idle: true/true: OK, true/false: OK, false/true: OK, false/false: NG
|
|
93
|
+
sip.call.start_fax(oc.id, {is_sender: true, file: in_file, transmit_on_idle: false})
|
|
94
|
+
sip.call.start_fax(ic.id, {is_sender: false, file: out_file, transmit_on_idle: true})
|
|
94
95
|
|
|
95
96
|
await z.wait([
|
|
96
97
|
{
|
package/samples/simple.js
CHANGED
|
@@ -1,32 +1,45 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
// This test creates 2 UDP SIP endpoints, makes a call between them and disconeects.
|
|
2
|
+
|
|
3
|
+
const sip = require ('../index.js')
|
|
4
|
+
const Zester = require('zester')
|
|
5
|
+
const m = require('data-matching')
|
|
6
|
+
const sip_msg = require('sip-matching')
|
|
7
|
+
|
|
8
|
+
// here we create our Zester instance
|
|
3
9
|
var z = new Zester()
|
|
4
|
-
var m = require('data-matching')
|
|
5
|
-
var sip_msg = require('sip-matching')
|
|
6
10
|
|
|
7
|
-
async function test() {
|
|
8
|
-
//sip.set_log_level(6)
|
|
9
|
-
sip.dtmf_aggregation_on(500)
|
|
10
11
|
|
|
12
|
+
async function test() {
|
|
13
|
+
// here we set our zester instance to trap events generated by sip-lab event_source
|
|
11
14
|
z.trap_events(sip.event_source, 'event', (evt) => {
|
|
12
15
|
var e = evt.args[0]
|
|
13
16
|
return e
|
|
14
17
|
})
|
|
15
18
|
|
|
19
|
+
// here we start sip-lab
|
|
16
20
|
console.log(sip.start((data) => { console.log(data)} ))
|
|
17
21
|
|
|
18
|
-
|
|
19
|
-
|
|
22
|
+
// Here we create the SIP endpoints (transports).
|
|
23
|
+
// Since we don't specify the port, an available port will be allocated.
|
|
24
|
+
// Since we don't specify the type ('udp' or 'tcp' or 'tls'), 'udp' will be used by default.
|
|
25
|
+
const t1 = sip.transport.create({address: "127.0.0.1"})
|
|
26
|
+
const t2 = sip.transport.create({address: "127.0.0.1"})
|
|
20
27
|
|
|
28
|
+
// here we just print the transports
|
|
21
29
|
console.log("t1", t1)
|
|
22
30
|
console.log("t2", t2)
|
|
23
31
|
|
|
24
|
-
|
|
32
|
+
// make the call from t1 to t2
|
|
33
|
+
const oc = sip.call.create(t1.id, {from_uri: 'sip:alice@test.com', to_uri: `sip:bob@${t2.address}:${t2.port}`})
|
|
25
34
|
|
|
35
|
+
// Here we will wait for the call to arrive at t2
|
|
36
|
+
// We will also get a '100 Trying' that is sent by sip-lab automatically
|
|
37
|
+
// We will wait for at most 1000ms. If all events don't arrive within 1000ms, an exception will be thrown and the test will fail due to timeout.
|
|
26
38
|
await z.wait([
|
|
27
39
|
{
|
|
28
40
|
event: "incoming_call",
|
|
29
41
|
call_id: m.collect("call_id"),
|
|
42
|
+
transport_id: t2.id,
|
|
30
43
|
},
|
|
31
44
|
{
|
|
32
45
|
event: 'response',
|
|
@@ -44,29 +57,39 @@ async function test() {
|
|
|
44
57
|
}),
|
|
45
58
|
},
|
|
46
59
|
], 1000)
|
|
47
|
-
|
|
48
|
-
|
|
60
|
+
// Details about zester wait(list_of_events_to_wait_for, timeout_in_ms):
|
|
61
|
+
// The order of events in the list is irrelevant.
|
|
62
|
+
// What matters is that all events arrive within the specified timeout.
|
|
63
|
+
// When specifying events, you can be as detailed or succinct as you need.
|
|
64
|
+
// For example, the above event 'response' is waiting for a SIP '100 Trying' to arrive,
|
|
65
|
+
// but we are specifying things to match just to show that we can be very detailed when performing a match.
|
|
66
|
+
// But it could have been just like this:
|
|
67
|
+
//
|
|
68
|
+
// {
|
|
69
|
+
// event: 'response',
|
|
70
|
+
// call_id: oc.id,
|
|
71
|
+
// method: 'INVITE',
|
|
72
|
+
// msg: sip_msg({
|
|
73
|
+
// $rs: '100',
|
|
74
|
+
// }),
|
|
75
|
+
// }
|
|
76
|
+
// Regarding the function sip_msg() this is a special matching function provided by https://github.com/MayamaTakeshi/sip-matching that makes it
|
|
77
|
+
// easy to match a SIP message using openser/kamailio/opensips pseudo-variables syntax.
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
// Here we store data for the incoming call
|
|
81
|
+
// just to organize our code (not really needed)
|
|
82
|
+
const ic = {
|
|
49
83
|
id: z.store.call_id,
|
|
50
84
|
sip_call_id: z.store.sip_call_id,
|
|
51
85
|
}
|
|
52
86
|
|
|
87
|
+
// Now we answer the call at t2 side
|
|
53
88
|
sip.call.respond(ic.id, {code: 200, reason: 'OK'})
|
|
54
89
|
|
|
90
|
+
// Then we wait for the '200 OK' at the t1 side
|
|
91
|
+
// We will also get event 'media_status' for both sides indicating media streams (RTP) were set up successfully
|
|
55
92
|
await z.wait([
|
|
56
|
-
{
|
|
57
|
-
event: 'media_status',
|
|
58
|
-
call_id: oc.id,
|
|
59
|
-
status: 'setup_ok',
|
|
60
|
-
local_mode: 'sendrecv',
|
|
61
|
-
remote_mode: 'sendrecv',
|
|
62
|
-
},
|
|
63
|
-
{
|
|
64
|
-
event: 'media_status',
|
|
65
|
-
call_id: ic.id,
|
|
66
|
-
status: 'setup_ok',
|
|
67
|
-
local_mode: 'sendrecv',
|
|
68
|
-
remote_mode: 'sendrecv',
|
|
69
|
-
},
|
|
70
93
|
{
|
|
71
94
|
event: 'response',
|
|
72
95
|
call_id: oc.id,
|
|
@@ -82,19 +105,27 @@ async function test() {
|
|
|
82
105
|
$rb: '!{_}a=sendrecv',
|
|
83
106
|
}),
|
|
84
107
|
},
|
|
85
|
-
], 1000)
|
|
86
|
-
|
|
87
|
-
sip.call.terminate(oc.id)
|
|
88
|
-
|
|
89
|
-
await z.wait([
|
|
90
108
|
{
|
|
91
|
-
event: '
|
|
109
|
+
event: 'media_status',
|
|
92
110
|
call_id: oc.id,
|
|
111
|
+
status: 'setup_ok',
|
|
112
|
+
local_mode: 'sendrecv',
|
|
113
|
+
remote_mode: 'sendrecv',
|
|
93
114
|
},
|
|
94
115
|
{
|
|
95
|
-
event: '
|
|
116
|
+
event: 'media_status',
|
|
96
117
|
call_id: ic.id,
|
|
118
|
+
status: 'setup_ok',
|
|
119
|
+
local_mode: 'sendrecv',
|
|
120
|
+
remote_mode: 'sendrecv',
|
|
97
121
|
},
|
|
122
|
+
], 1000)
|
|
123
|
+
|
|
124
|
+
// now we terminate the call from t1 side
|
|
125
|
+
sip.call.terminate(oc.id)
|
|
126
|
+
|
|
127
|
+
// and wait for termination events
|
|
128
|
+
await z.wait([
|
|
98
129
|
{
|
|
99
130
|
event: 'response',
|
|
100
131
|
call_id: oc.id,
|
|
@@ -104,6 +135,14 @@ async function test() {
|
|
|
104
135
|
$rr: 'OK',
|
|
105
136
|
}),
|
|
106
137
|
},
|
|
138
|
+
{
|
|
139
|
+
event: 'call_ended',
|
|
140
|
+
call_id: oc.id,
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
event: 'call_ended',
|
|
144
|
+
call_id: ic.id,
|
|
145
|
+
},
|
|
107
146
|
], 1000)
|
|
108
147
|
|
|
109
148
|
console.log("Success")
|
package/src/Makefile
CHANGED
|
@@ -34,7 +34,7 @@ sip.o: sip.cpp sip.hpp
|
|
|
34
34
|
$(CC) -fPIC -c -o sip.o sip.cpp $(CPPFLAGS)
|
|
35
35
|
|
|
36
36
|
sip.so: sip.o idmanager.o packetdumper.o event_templates.o chainlink
|
|
37
|
-
$(CC) -fPIC -shared -o sip.so sip.o idmanager.o packetdumper.o event_templates.o pjmedia/libchainlink.a -Wl,-E -lm -ldl -
|
|
37
|
+
$(CC) -fPIC -shared -o sip.so sip.o idmanager.o packetdumper.o event_templates.o pjmedia/libchainlink.a 3rdParty/spandsp/src/.libs/libspandsp.a -Wl,-E -lm -ldl -ltiff -lpcap $(CPPFLAGS) $(LDFLAGS) $(LDLIBS)
|
|
38
38
|
|
|
39
39
|
clean:
|
|
40
40
|
rm -f *.o *.so
|
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
#include <pj/pool.h>
|
|
9
9
|
#include <pj/string.h>
|
|
10
10
|
|
|
11
|
+
#include "siplab_constants.h"
|
|
12
|
+
|
|
11
13
|
#define SPANDSP_EXPOSE_INTERNAL_STRUCTURES
|
|
12
14
|
#include <spandsp.h>
|
|
13
15
|
|
|
@@ -23,7 +25,6 @@
|
|
|
23
25
|
#define FAX_DATA_CHUNK 320
|
|
24
26
|
#define T38_DATA_CHUNK 160
|
|
25
27
|
|
|
26
|
-
|
|
27
28
|
enum
|
|
28
29
|
{
|
|
29
30
|
/*! No compression */
|
|
@@ -48,7 +49,6 @@ enum
|
|
|
48
49
|
T30_SUPPORT_T88_COMPRESSION = 0x200
|
|
49
50
|
};
|
|
50
51
|
|
|
51
|
-
|
|
52
52
|
static pj_status_t fax_get_frame(pjmedia_port *this_port,
|
|
53
53
|
pjmedia_frame *frame);
|
|
54
54
|
static pj_status_t fax_put_frame(pjmedia_port *this_port,
|
|
@@ -61,25 +61,25 @@ struct fax_device
|
|
|
61
61
|
fax_state_t fax;
|
|
62
62
|
void (*fax_cb)(pjmedia_port*, void*, int);
|
|
63
63
|
void *fax_cb_user_data;
|
|
64
|
-
int is_caller;
|
|
65
64
|
int is_sender;
|
|
65
|
+
bool result_sent;
|
|
66
66
|
|
|
67
67
|
pj_lock_t *lock;
|
|
68
68
|
};
|
|
69
69
|
|
|
70
|
-
static int phase_b_handler(
|
|
70
|
+
static int phase_b_handler(void* user_data, int result)
|
|
71
71
|
{
|
|
72
72
|
printf("fax phase_b_handler user_data=%p result=%i\n", user_data, result);
|
|
73
73
|
return T30_ERR_OK;
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
-
static int phase_d_handler(
|
|
76
|
+
static int phase_d_handler(void* user_data, int result)
|
|
77
77
|
{
|
|
78
78
|
printf("fax phase_b_handler user_data=%p result=%i\n", user_data, result);
|
|
79
79
|
return T30_ERR_OK;
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
static void phase_e_handler(
|
|
82
|
+
static void phase_e_handler(void* user_data, int result)
|
|
83
83
|
{
|
|
84
84
|
printf("fax phase_e_handler user_data=%p result=%i\n", user_data, result);
|
|
85
85
|
|
|
@@ -94,11 +94,13 @@ static void phase_e_handler(t30_state_t* s, void* user_data, int result)
|
|
|
94
94
|
return;
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
-
|
|
98
|
-
|
|
97
|
+
if(!fd->result_sent) {
|
|
98
|
+
fd->fax_cb((pjmedia_port*)fd, fd->fax_cb_user_data, result);
|
|
99
|
+
fd->result_sent = true;
|
|
100
|
+
}
|
|
99
101
|
}
|
|
100
102
|
|
|
101
|
-
static int document_handler(
|
|
103
|
+
static int document_handler(void* user_data, int result)
|
|
102
104
|
{
|
|
103
105
|
printf("fax document_handler user_data=%p result=%i\n", user_data, result);
|
|
104
106
|
|
|
@@ -107,7 +109,10 @@ static int document_handler(t30_state_t* s, void* user_data, int result)
|
|
|
107
109
|
struct fax_device *fd = (struct fax_device*)user_data;
|
|
108
110
|
if(!fd->fax_cb) return 0;
|
|
109
111
|
|
|
110
|
-
|
|
112
|
+
if(!fd->result_sent) {
|
|
113
|
+
fd->fax_cb((pjmedia_port*)fd, fd->fax_cb_user_data, result);
|
|
114
|
+
fd->result_sent = true;
|
|
115
|
+
}
|
|
111
116
|
|
|
112
117
|
return 0;
|
|
113
118
|
}
|
|
@@ -121,9 +126,9 @@ PJ_DEF(pj_status_t) chainlink_fax_port_create( pj_pool_t *pool,
|
|
|
121
126
|
void *user_data,
|
|
122
127
|
int result),
|
|
123
128
|
void *user_data,
|
|
124
|
-
int is_caller,
|
|
125
129
|
int is_sender,
|
|
126
130
|
const char *file,
|
|
131
|
+
unsigned flags,
|
|
127
132
|
pjmedia_port **p_port)
|
|
128
133
|
{
|
|
129
134
|
struct fax_device *fd;
|
|
@@ -145,8 +150,7 @@ PJ_DEF(pj_status_t) chainlink_fax_port_create( pj_pool_t *pool,
|
|
|
145
150
|
fd->link.port.put_frame = &fax_put_frame;
|
|
146
151
|
fd->link.port.on_destroy = &fax_on_destroy;
|
|
147
152
|
|
|
148
|
-
fax_init(&fd->fax,
|
|
149
|
-
//fax_set_transmit_on_idle(&fd->fax,1);
|
|
153
|
+
fax_init(&fd->fax, is_sender);
|
|
150
154
|
|
|
151
155
|
t30_state_t *t30 = fax_get_t30_state(&fd->fax);
|
|
152
156
|
|
|
@@ -162,8 +166,8 @@ PJ_DEF(pj_status_t) chainlink_fax_port_create( pj_pool_t *pool,
|
|
|
162
166
|
//printf("setting document_handler with user_data=%p\n", (void*)fd);
|
|
163
167
|
t30_set_document_handler(t30, &document_handler, (void*)fd);
|
|
164
168
|
|
|
165
|
-
fd->is_caller = is_caller;
|
|
166
169
|
fd->is_sender = is_sender;
|
|
170
|
+
fd->result_sent = false;
|
|
167
171
|
|
|
168
172
|
pj_status_t status = pj_lock_create_simple_mutex(pool, "fax", &fd->lock);
|
|
169
173
|
|
|
@@ -181,7 +185,9 @@ PJ_DEF(pj_status_t) chainlink_fax_port_create( pj_pool_t *pool,
|
|
|
181
185
|
t30_set_supported_compressions(t30,T30_SUPPORT_T4_1D_COMPRESSION |
|
|
182
186
|
T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION);
|
|
183
187
|
|
|
184
|
-
|
|
188
|
+
if(flags & FAX_FLAG_TRANSMIT_ON_IDLE) {
|
|
189
|
+
fax_set_transmit_on_idle(&fd->fax, 1);
|
|
190
|
+
}
|
|
185
191
|
|
|
186
192
|
fd->fax_cb = cb;
|
|
187
193
|
fd->fax_cb_user_data = user_data;
|
package/src/sip.cpp
CHANGED
|
@@ -36,6 +36,8 @@
|
|
|
36
36
|
|
|
37
37
|
#include "rapidjson/document.h"
|
|
38
38
|
|
|
39
|
+
#include "siplab_constants.h"
|
|
40
|
+
|
|
39
41
|
using namespace rapidjson;
|
|
40
42
|
using namespace std;
|
|
41
43
|
|
|
@@ -159,6 +161,23 @@ bool json_get_int_param(Document &document, const char *param, bool optional, in
|
|
|
159
161
|
return true;
|
|
160
162
|
}
|
|
161
163
|
|
|
164
|
+
bool json_get_uint_param(Document &document, const char *param, bool optional, unsigned *dest) {
|
|
165
|
+
if(!document.HasMember(param)) {
|
|
166
|
+
if(optional) {
|
|
167
|
+
return true;
|
|
168
|
+
}
|
|
169
|
+
set_error("Parameter %s is required", param);
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if(!document[param].IsUint()) {
|
|
174
|
+
set_error("Parameter %s must be an unsigned integer", param);
|
|
175
|
+
return false;
|
|
176
|
+
}
|
|
177
|
+
*dest = document[param].GetUint();
|
|
178
|
+
return true;
|
|
179
|
+
}
|
|
180
|
+
|
|
162
181
|
bool json_get_bool_param(Document &document, const char *param, bool optional, bool *dest) {
|
|
163
182
|
if(!document.HasMember(param)) {
|
|
164
183
|
if(optional) {
|
|
@@ -478,7 +497,7 @@ bool prepare_tonegen(Call *c);
|
|
|
478
497
|
bool prepare_wav_player(Call *c, const char *file);
|
|
479
498
|
bool prepare_wav_writer(Call *c, const char *file);
|
|
480
499
|
|
|
481
|
-
bool prepare_fax(Call *c, bool is_sender, const char *file);
|
|
500
|
+
bool prepare_fax(Call *c, bool is_sender, const char *file, unsigned flags);
|
|
482
501
|
|
|
483
502
|
void prepare_error_event(ostringstream *oss, char *scope, char *details);
|
|
484
503
|
//void prepare_pjsipcall_error_event(ostringstream *oss, char *scope, char *function, pj_status_t s);
|
|
@@ -2689,6 +2708,8 @@ int pjw_call_start_fax(long call_id, const char *json)
|
|
|
2689
2708
|
|
|
2690
2709
|
bool is_sender;
|
|
2691
2710
|
char *file;
|
|
2711
|
+
unsigned flags = 0;
|
|
2712
|
+
bool flag;
|
|
2692
2713
|
|
|
2693
2714
|
char buffer[MAX_JSON_INPUT];
|
|
2694
2715
|
|
|
@@ -2723,6 +2744,15 @@ int pjw_call_start_fax(long call_id, const char *json)
|
|
|
2723
2744
|
goto out;
|
|
2724
2745
|
}
|
|
2725
2746
|
|
|
2747
|
+
|
|
2748
|
+
flag = false;
|
|
2749
|
+
if(!json_get_bool_param(document, "transmit_on_idle", true, &flag)) {
|
|
2750
|
+
goto out;
|
|
2751
|
+
} else {
|
|
2752
|
+
if(flag) flags |= FAX_FLAG_TRANSMIT_ON_IDLE;
|
|
2753
|
+
}
|
|
2754
|
+
|
|
2755
|
+
|
|
2726
2756
|
status = pjmedia_stream_get_port(call->med_stream,
|
|
2727
2757
|
&stream_port);
|
|
2728
2758
|
if(status != PJ_SUCCESS)
|
|
@@ -2731,7 +2761,7 @@ int pjw_call_start_fax(long call_id, const char *json)
|
|
|
2731
2761
|
goto out;
|
|
2732
2762
|
}
|
|
2733
2763
|
|
|
2734
|
-
if(!prepare_fax(call, is_sender, file)){
|
|
2764
|
+
if(!prepare_fax(call, is_sender, file, flags)){
|
|
2735
2765
|
set_error("prepare_fax failed");
|
|
2736
2766
|
goto out;
|
|
2737
2767
|
}
|
|
@@ -4326,7 +4356,7 @@ bool prepare_wav_writer(Call *c, const char *file) {
|
|
|
4326
4356
|
}
|
|
4327
4357
|
|
|
4328
4358
|
|
|
4329
|
-
bool prepare_fax(Call *c, bool is_sender, const char *file) {
|
|
4359
|
+
bool prepare_fax(Call *c, bool is_sender, const char *file, unsigned flags) {
|
|
4330
4360
|
pj_status_t status;
|
|
4331
4361
|
|
|
4332
4362
|
chainlink *link = (chainlink*)c->fax;
|
|
@@ -4346,9 +4376,9 @@ bool prepare_fax(Call *c, bool is_sender, const char *file) {
|
|
|
4346
4376
|
PJMEDIA_PIA_BITS(&stream_port->info),
|
|
4347
4377
|
on_fax_result,
|
|
4348
4378
|
c,
|
|
4349
|
-
c->outgoing,
|
|
4350
4379
|
is_sender,
|
|
4351
4380
|
file,
|
|
4381
|
+
flags,
|
|
4352
4382
|
(pjmedia_port**)&c->fax);
|
|
4353
4383
|
if(status != PJ_SUCCESS) return false;
|
|
4354
4384
|
|
package/install_bcg729.sh
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
|
|
3
|
-
set -o errexit
|
|
4
|
-
set -o nounset
|
|
5
|
-
set -o pipefail
|
|
6
|
-
|
|
7
|
-
if [[ ! -d bcg729 ]]
|
|
8
|
-
then
|
|
9
|
-
git clone https://github.com/MayamaTakeshi/bcg729
|
|
10
|
-
cd bcg729
|
|
11
|
-
git checkout faaa895862165acde6df8add722ba4f85a25007d
|
|
12
|
-
cmake .
|
|
13
|
-
make
|
|
14
|
-
sudo make install
|
|
15
|
-
sudo ldconfig
|
|
16
|
-
fi
|
|
17
|
-
|
|
18
|
-
echo success
|