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 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 libspandsp-dev libpcap-dev libssl-dev uuid-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
- Since running
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
- But if you do so, you will need to set NODE_PATH for node to find it by doing:
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
- '-lspandsp',
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
  },
@@ -0,0 +1,6 @@
1
+ #ifndef __SIPLAB_CONSTANTS_H__
2
+ #define __SIPLAB_CONSTANTS_H__
3
+
4
+ #define FAX_FLAG_TRANSMIT_ON_IDLE 1
5
+
6
+ #endif /* __SIPLAB_CONSTANTS_H__ */
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sip-lab",
3
- "version": "1.12.1",
3
+ "version": "1.12.4",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "engines": {
@@ -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:a@t', to_uri: 'sip:b@127.0.0.1:5092'})
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: 'a',
41
- $fd: 't',
42
- $tU: 'b',
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: 'a',
79
- $fd: 't',
80
- $tU: 'b',
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
- sip.call.start_fax(oc.id, {is_sender: true, file: in_file})
93
- sip.call.start_fax(ic.id, {is_sender: false, file: out_file})
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
- var sip = require ('../index.js')
2
- var Zester = require('zester')
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
- t1 = sip.transport.create({address: "127.0.0.1", port: 5090, type: 'udp'})
19
- t2 = sip.transport.create({address: "127.0.0.1", port: 5092, type: 'udp'})
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
- oc = sip.call.create(t1.id, {from_uri: 'sip:alice@test.com', to_uri: `sip:bob@${t2.address}:${t2.port}`})
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
- ic = {
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: 'call_ended',
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: 'call_ended',
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 -lspandsp -lpcap $(CPPFLAGS) $(LDFLAGS) $(LDLIBS)
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
@@ -14,9 +14,9 @@ PJ_DECL(pj_status_t) chainlink_fax_port_create( pj_pool_t *pool,
14
14
  void *user_data,
15
15
  int result),
16
16
  void *user_data,
17
- int is_caller,
18
17
  int is_sender,
19
18
  const char *file,
19
+ unsigned flags,
20
20
  pjmedia_port **p_port);
21
21
 
22
22
 
@@ -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(t30_state_t* s, void* user_data, int result)
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(t30_state_t* s, void* user_data, int result)
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(t30_state_t* s, void* user_data, int result)
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
- printf("sending result event\n");
98
- fd->fax_cb((pjmedia_port*)fd, fd->fax_cb_user_data, result);
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(t30_state_t* s, void* user_data, int result)
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
- //fd->fax_cb((pjmedia_port*)fd, fd->fax_cb_user_data, result);
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, is_caller);
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
- fax_set_transmit_on_idle(&fd->fax, 1);
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