sip-lab 1.2.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.
Files changed (41) hide show
  1. package/README.md +38 -0
  2. package/a.js +280 -0
  3. package/binding.gyp +101 -0
  4. package/devjournal +435 -0
  5. package/index.js +68 -0
  6. package/install.sh +32 -0
  7. package/package.json +30 -0
  8. package/samples/late_negotiation.js +278 -0
  9. package/samples/simple.js +280 -0
  10. package/samples/sip_cancel.js +111 -0
  11. package/src/Makefile +42 -0
  12. package/src/README +3 -0
  13. package/src/addon.cpp +1418 -0
  14. package/src/event_templates.cpp +55 -0
  15. package/src/event_templates.hpp +27 -0
  16. package/src/idmanager.cpp +76 -0
  17. package/src/idmanager.hpp +26 -0
  18. package/src/log.cpp +18 -0
  19. package/src/log.hpp +15 -0
  20. package/src/packetdumper.cpp +234 -0
  21. package/src/packetdumper.hpp +67 -0
  22. package/src/pjmedia/Makefile +37 -0
  23. package/src/pjmedia/devjournal +26 -0
  24. package/src/pjmedia/include/chainlink/README +3 -0
  25. package/src/pjmedia/include/chainlink/chainlink.h +11 -0
  26. package/src/pjmedia/include/chainlink/chainlink_dtmfdet.h +56 -0
  27. package/src/pjmedia/include/chainlink/chainlink_tonegen.h +178 -0
  28. package/src/pjmedia/include/chainlink/chainlink_wav_port.h +231 -0
  29. package/src/pjmedia/include/chainlink/chainlink_wire_port.h +50 -0
  30. package/src/pjmedia/include/pjmedia/README +3 -0
  31. package/src/pjmedia/include/pjmedia/dtmfdet.h +74 -0
  32. package/src/pjmedia/src/chainlink/chainlink_dtmfdet.c +125 -0
  33. package/src/pjmedia/src/chainlink/chainlink_tonegen.c +901 -0
  34. package/src/pjmedia/src/chainlink/chainlink_wav_player.c +688 -0
  35. package/src/pjmedia/src/chainlink/chainlink_wav_writer.c +442 -0
  36. package/src/pjmedia/src/chainlink/chainlink_wire_port.c +93 -0
  37. package/src/pjmedia/src/pjmedia/dtmfdet.c +129 -0
  38. package/src/pjmedia/src/pjmedia/simpleua_dtmfdet.c +753 -0
  39. package/src/pjmedia/src/pjmedia/tonegen_dtmfdet.c +263 -0
  40. package/src/sip.cpp +4891 -0
  41. package/src/sip.hpp +64 -0
@@ -0,0 +1,55 @@
1
+ #include <stdio.h>
2
+ #include <string.h>
3
+
4
+ int make_evt_incoming_call(char *dest, int size, long transport_id, long call_id, int sip_msg_len, char *sip_msg) {
5
+ return snprintf(dest, size, "{\"event\": \"incoming_call\", \"transport_id\": %i, \"call_id\": %i}\n%.*s", transport_id, call_id, sip_msg_len, sip_msg);
6
+ }
7
+
8
+ int make_evt_request(char *dest, int size, char *entity_type, long id, int sip_msg_len, char *sip_msg) {
9
+ return snprintf(dest, size, "{\"event\": \"request\", \"%s_id\": %i}\n%.*s", entity_type, id, sip_msg_len, sip_msg);
10
+ }
11
+
12
+ int make_evt_response(char *dest, int size, char *entity_type, long id, int mname_len, char *mname, int sip_msg_len, char *sip_msg) {
13
+ return snprintf(dest, size, "{\"event\": \"response\", \"%s_id\": %i, \"method\": \"%.*s\"}\n%.*s", entity_type, id, mname_len, mname, sip_msg_len, sip_msg);
14
+ }
15
+
16
+ int make_evt_media_status(char *dest, int size, long call_id, char *status, char *local_mode, char *remote_mode) {
17
+ if(strcmp(status, "setup_ok") == 0) {
18
+ return snprintf(dest, size, "{\"event\": \"media_status\", \"call_id\": %i, \"status\": \"%s\", \"local_mode\": \"%s\", \"remote_mode\": \"%s\"}", call_id, status, local_mode, remote_mode);
19
+ } else {
20
+ return snprintf(dest, size, "{\"event\": \"media_status\", \"call_id\": %i, \"status\": \"%s\"}", call_id, status);
21
+ }
22
+ }
23
+
24
+ int make_evt_dtmf(char *dest, int size, long call_id, int digits_len, char *digits, int mode) {
25
+ return snprintf(dest, size, "{\"event\": \"dtmf\", \"call_id\": %i, \"digits\": \"%.*s\", \"mode\": %i}", call_id, digits_len, digits, mode);
26
+ }
27
+
28
+ int make_evt_call_ended(char *dest, int size, long call_id, int sip_msg_len, char *sip_msg) {
29
+ printf("sip_msg_len=%i sip_msg=%x\n", sip_msg_len, sip_msg);
30
+ if(sip_msg_len > 500 && sip_msg_len < 2000 && sip_msg) {
31
+ /* sip_msg_len sometimes show up as a large value like sip_msg_len=11560297 which seems to be a bug in pjsip */
32
+ return snprintf(dest, size, "{\"event\": \"call_ended\", \"call_id\": %i}\n%.*s", call_id, sip_msg_len, sip_msg);
33
+ } else {
34
+ return snprintf(dest, size, "{\"event\": \"call_ended\", \"call_id\": %i}", call_id);
35
+ }
36
+ }
37
+
38
+ int make_evt_non_dialog_request(char *dest, int size, int sip_msg_len, char *sip_msg) {
39
+ return snprintf(dest, size, "{\"event\": \"non_dialog_request\"}\n%.*s", sip_msg_len, sip_msg);
40
+ }
41
+
42
+ int make_evt_internal_error(char *dest, int size, char *msg) {
43
+ return snprintf(dest, size, "{\"event\": \"internal_error\", \"error\": \"%s\"}", msg);
44
+ }
45
+
46
+ /*
47
+ int make_evt_reinvite(char *dest, int size, long call_id, char *type) {
48
+ return snprintf(dest, size, "{\"event\": \"reinvite\", \"call_id\": %i, \"type\": \"%s\"}", call_id, type);
49
+ }
50
+ */
51
+
52
+ int make_evt_registration_status(char *dest, int size, long account_id, int code, char *reason, int expires) {
53
+ return snprintf(dest, size, "{\"event\": \"registration_status\", \"account_id\": %i, \"code\": %i, \"reason\": \"%s\", \"expires\": %i}", account_id, code, reason, expires);
54
+ }
55
+
@@ -0,0 +1,27 @@
1
+ #ifndef __EVENT_TEMPLATES__
2
+ #define __EVENT_TEMPLATES__
3
+
4
+
5
+ int make_evt_incoming_call(char *dest, int size, long transport_id, long call_id, int sip_msg_len, char *sip_msg);
6
+
7
+ int make_evt_request(char *dest, int size, char *entity_type, long id, int sip_msg_len, char *sip_msg);
8
+
9
+ int make_evt_response(char *dest, int size, char *entity_type, long id, int mname_len, char *mname, int sip_msg_len, char *sip_msg);
10
+
11
+ int make_evt_media_status(char *dest, int size, long call_id, char *status, char *local_media_mode, char *remote_media_mode);
12
+
13
+ int make_evt_dtmf(char *dest, int size, long call_id, int digits_len, char *digits, int mode);
14
+
15
+ int make_evt_call_ended(char *dest, int size, long call_id, int sip_msg_len, char *sip_msg);
16
+
17
+ int make_evt_non_dialog_request(char *dest, int size, int sip_msg_len, char *sip_msg);
18
+
19
+ int make_evt_internal_error(char *dest, int size, char *msg);
20
+
21
+ //int make_evt_reinvite(char *dest, int size, long call_id, char *type);
22
+
23
+ int make_evt_registration_status(char *dest, int size, long account_id, int code, char *reason, int expires);
24
+
25
+ #endif
26
+
27
+
@@ -0,0 +1,76 @@
1
+ #include "idmanager.hpp"
2
+
3
+ IdManager::IdManager(long max)
4
+ : ids(max) {
5
+ for(long i=0; i<max ;++i) ids.push_back(i);
6
+ };
7
+
8
+ IdManager::~IdManager() {};
9
+
10
+ bool IdManager::add(long val, long &id){
11
+ if(ids.empty()) return false;
12
+
13
+ long new_id = ids[0];
14
+ ids.pop_front();
15
+
16
+ id_map[new_id] = val;
17
+ id = new_id;
18
+ return true;
19
+ }
20
+
21
+ bool IdManager::remove(long id, long &val){
22
+ map<long,long>::iterator pos = id_map.begin();
23
+ while(pos != id_map.end()){
24
+ if(pos->first == id){
25
+ val = pos->second;
26
+ ids.push_back(id);
27
+ id_map.erase(pos);
28
+ return true;
29
+ }
30
+ ++pos;
31
+ }
32
+ return false;
33
+ }
34
+
35
+ bool IdManager::remove_by_val(long val, long &id){
36
+ map<long,long>::iterator pos = id_map.begin();
37
+ while(pos != id_map.end()){
38
+ if(pos->second == val){
39
+ id = pos->first;
40
+ ids.push_back(id);
41
+ id_map.erase(pos);
42
+ return true;
43
+ }
44
+ ++pos;
45
+ }
46
+ return false;
47
+ }
48
+
49
+ bool IdManager::get(long id, long &val){
50
+ map<long,long>::iterator pos = id_map.find(id);
51
+ if(pos == id_map.end()) return false;
52
+
53
+ val = pos->second;
54
+ return true;
55
+ }
56
+
57
+ bool IdManager::get_id(long val, long &id){
58
+ map<long,long>::iterator pos = id_map.begin();
59
+ while(pos != id_map.end()){
60
+ if(pos->second == val){
61
+ id = pos->first;
62
+ return true;
63
+ }
64
+ ++pos;
65
+ }
66
+ return false;
67
+ }
68
+
69
+ void IdManager::iterate( void (*f)(long id, long val) ){
70
+ map<long,long>::iterator pos = id_map.begin();
71
+ while(pos != id_map.end()){
72
+ f(pos->first, pos->second);
73
+ ++pos;
74
+ }
75
+ }
76
+
@@ -0,0 +1,26 @@
1
+ #ifndef __IDMANAGER_H__
2
+ #define __IDMANAGER_H__
3
+
4
+ #include <map>
5
+
6
+ using namespace std;
7
+
8
+ #include <boost/circular_buffer.hpp>
9
+
10
+ class IdManager {
11
+ public:
12
+ IdManager(long max);
13
+ ~IdManager();
14
+ bool add(long val, long &id);
15
+ bool remove(long id, long &val);
16
+ bool remove_by_val(long val, long &id);
17
+ bool get(long id, long &val);
18
+ bool get_id(long val, long &id);
19
+ void iterate( void (*f)(long id, long val) );
20
+
21
+ map<long, long> id_map; //hack to test tcpdumper
22
+ private:
23
+ boost::circular_buffer<long> ids;
24
+ };
25
+
26
+ #endif
package/src/log.cpp ADDED
@@ -0,0 +1,18 @@
1
+ #include "log.hpp"
2
+ #include <stdio.h>
3
+
4
+ void _addon_log(int level, const char *fmt, ...) {
5
+ va_list args;
6
+
7
+ /* Check if the message should be logged */
8
+ if (level > _log_level)
9
+ return;
10
+
11
+ va_start(args, fmt);
12
+ flockfile(stdout);
13
+ printf(fmt, args);
14
+ funlockfile(stdout);
15
+ va_end(args);
16
+ }
17
+
18
+
package/src/log.hpp ADDED
@@ -0,0 +1,15 @@
1
+ #ifndef __LOG_H__
2
+ #define __LOG_H__
3
+
4
+ #include <stdarg.h>
5
+
6
+ #define LOG_LEVEL_INFO 0
7
+ #define LOG_LEVEL_DEBUG 1
8
+
9
+ static int _log_level = LOG_LEVEL_DEBUG;
10
+
11
+ void _addon_log(int level, const char *fmt, ...);
12
+
13
+ #define addon_log(level, fmt, ...) _addon_log(level, fmt"\n", ##__VA_ARGS__)
14
+
15
+ #endif
@@ -0,0 +1,234 @@
1
+ #include <stdio.h>
2
+ #include <pcap.h>
3
+ #include <sys/socket.h>
4
+ #include <arpa/inet.h>
5
+ #include <netinet/if_ether.h>
6
+ #include <netinet/udp.h>
7
+
8
+ #include <pthread.h>
9
+
10
+ #include "packetdumper.hpp"
11
+
12
+ #include "boost/mem_fn.hpp"
13
+
14
+
15
+ #define LOCK() pthread_mutex_lock(&_mutex);
16
+ #define UNLOCK() pthread_mutex_unlock(&_mutex);
17
+
18
+ PacketDumper::PacketDumper()
19
+ : _handler(0), _dumper(0), _end_flag(false)
20
+ {
21
+ }
22
+
23
+ PacketDumper::~PacketDumper()
24
+ {
25
+ _end_flag = true;
26
+ pthread_join(_thread, NULL);
27
+ //printf("PacketDumper destroyed\n");
28
+ }
29
+
30
+ bool PacketDumper::init(string dev, string file) {
31
+ if(_handler){ return false; } // already initialized
32
+
33
+ char errbuf[PCAP_ERRBUF_SIZE];
34
+
35
+ _dev = dev;
36
+
37
+ _handler = pcap_open_live(_dev.c_str(), 2000, 0, 0, errbuf);
38
+ if(!_handler){
39
+ printf("pcap_open_live(): %s\n", errbuf);
40
+ return false;
41
+ }
42
+
43
+ this->datalink = pcap_datalink(_handler);
44
+ //printf("pcap_datalink: %d\n",this->datalink);
45
+ if(this->datalink != DLT_EN10MB && this->datalink != DLT_LINUX_SLL) {
46
+ printf("pcap_datalink: unsupported datalink %d\n",this->datalink);
47
+ return false;
48
+ }
49
+
50
+ if( pcap_setnonblock(_handler, 1, errbuf) == -1){
51
+ printf("pcap_setnonblock(): %s\n", errbuf);
52
+ return false;
53
+ }
54
+
55
+ _dumper = pcap_dump_open(_handler, file.c_str());
56
+ if(!_dumper){
57
+ printf("pcap_dump_open(): %s\n", pcap_geterr(_handler));
58
+ return false;
59
+ }
60
+
61
+ bpf_u_int32 mask;
62
+ bpf_u_int32 net;
63
+
64
+ //if(pcap_lookupnet(_dev.c_str(), &net, &mask, errbuf) == -1){
65
+ if(pcap_lookupnet(_dev.c_str(), &net, &mask, errbuf) < 0){
66
+ printf("Couldn't get netmask for device %s: %s\n",
67
+ _dev.c_str(), errbuf);
68
+ return false;
69
+ }
70
+
71
+ if( pcap_compile(_handler, &_filter_program, "udp", 0, net) == -1 ) {
72
+ printf("Failed to compile filter: %s\n", pcap_geterr(_handler));
73
+ return false;
74
+ }
75
+
76
+ if(pcap_setfilter(_handler, &_filter_program) == -1) {
77
+ printf("Couldn't install filter: %s\n", pcap_geterr(_handler));
78
+ pcap_freecode(&_filter_program);
79
+ return false;
80
+ }
81
+
82
+ pthread_mutex_init(&_mutex, NULL);
83
+
84
+ if( pthread_create(&_thread, NULL, &thread_func, (void*)this) ){
85
+ printf("pthread_create() failed\n");
86
+ return false;
87
+ }
88
+
89
+ //printf("phread_create ok\n");
90
+ return true;
91
+ }
92
+
93
+ bool PacketDumper::add_endpoint(uint32_t ipaddr, uint16_t port){
94
+ LOCK();
95
+ ipaddr_map::iterator iter = _awaited_endpoints.find(ipaddr);
96
+ if( _awaited_endpoints.end() == iter ) {
97
+ //printf("PacketDumper: adding IP MAP %X\n", ipaddr);
98
+ port_set ps;
99
+ ps.insert(port);
100
+ _awaited_endpoints.insert( make_pair(ipaddr, ps) );
101
+ } else {
102
+ iter->second.insert(port);
103
+ }
104
+ //printf("PacketDumper: adding port %X:%d\n", ipaddr, port);
105
+ UNLOCK();
106
+ return true;
107
+ }
108
+
109
+ bool PacketDumper::remove_endpoint(uint32_t ipaddr, uint16_t port){
110
+ bool res = false;
111
+ LOCK();
112
+ ipaddr_map::iterator im_iter = _awaited_endpoints.find(ipaddr);
113
+ if( _awaited_endpoints.end() != im_iter ) {
114
+ port_set::iterator ps_iter = im_iter->second.find(port);
115
+ if( im_iter->second.end() != ps_iter ) {
116
+ im_iter->second.erase(ps_iter);
117
+ //printf("PacketDumper: Removing port %X:%d\n", ipaddr, port);
118
+ res = true;
119
+ }
120
+ if(0 == im_iter->second.size()) {
121
+ _awaited_endpoints.erase(im_iter);
122
+ //printf("PacketDumper: Removing IP MAP %X\n", ipaddr);
123
+ }
124
+ }
125
+ UNLOCK();
126
+ return res;
127
+ }
128
+
129
+ void PacketDumper::process(){
130
+ const u_char *packet;
131
+ pcap_pkthdr hdr;
132
+ ip_header* ip_h;
133
+ udphdr *udp_h;
134
+
135
+ packet = pcap_next(_handler, &hdr);
136
+ if(packet)
137
+ {
138
+ bool dumpit;
139
+ if(DLT_EN10MB == this->datalink) {
140
+ ip_h = (ip_header*)(packet + sizeof(ether_header));
141
+ u_int size_ip = IP_HL(ip_h)*4;
142
+ udp_h = (udphdr*)(packet + sizeof(ether_header) + size_ip);
143
+ } else {
144
+ //Linux SLL cooked
145
+ ip_h = (ip_header*)(packet + sizeof(dlt_linux_sll));
146
+ u_int size_ip = IP_HL(ip_h)*4;
147
+ udp_h = (udphdr*)(packet + sizeof(dlt_linux_sll) + size_ip);
148
+ }
149
+
150
+
151
+ //if(ip_h->ip_src == 0xb905adca || ip_h->ip_dst == 0xb905adca) {
152
+ // printf("PacketDumper: packet received src=%X:%d dst=%X:%d\n", ip_h->ip_src, udp_h->source, ip_h->ip_dst, udp_h->dest);
153
+ //}
154
+
155
+ ipaddr_map::iterator im_iter;
156
+
157
+ //Check packet source
158
+ im_iter = _awaited_endpoints.find( ip_h->ip_src );
159
+ if( im_iter != _awaited_endpoints.end() ) {
160
+ port_set::iterator ps_iter = im_iter->second.find( udp_h->source);
161
+ if( ps_iter != im_iter->second.end() ) {
162
+ pcap_dump((u_char*)_dumper, &hdr, packet);
163
+ if( pcap_dump_flush(_dumper) == -1){
164
+ printf("pcap_dump_flush() error\n");
165
+ }
166
+ return;
167
+ }
168
+ }
169
+
170
+
171
+ //Check packet dest
172
+ im_iter = _awaited_endpoints.find( ip_h->ip_dst );
173
+ if( im_iter != _awaited_endpoints.end() ) {
174
+ port_set::iterator ps_iter = im_iter->second.find( udp_h->dest);
175
+ if( ps_iter != im_iter->second.end() ) {
176
+ pcap_dump((u_char*)_dumper, &hdr, packet);
177
+ if( pcap_dump_flush(_dumper) == -1){
178
+ printf("pcap_dump_flush() error\n");
179
+ }
180
+ return;
181
+ }
182
+ }
183
+
184
+
185
+ }
186
+ }
187
+
188
+ static void *thread_func(void *vptr_args){
189
+ //printf("entering thread_func\n");
190
+ PacketDumper *t = (PacketDumper*)vptr_args;
191
+ while(!t->_end_flag){
192
+ usleep(10);
193
+ pthread_mutex_lock(&t->_mutex);
194
+ t->process();
195
+ pthread_mutex_unlock(&t->_mutex);
196
+ }
197
+
198
+ if(t->_handler){
199
+ pcap_close(t->_handler);
200
+ }
201
+ if(t->_dumper){
202
+ pcap_dump_close(t->_dumper);
203
+ }
204
+
205
+ //printf("exiting thread_func\n");
206
+ }
207
+
208
+ int test() {
209
+ PacketDumper pd;
210
+ pd.init("bond1", "x.cap");
211
+
212
+ uint32_t ip_host = 0xc0a8581c;
213
+ uint32_t ip_net = htonl(ip_host);
214
+ printf("net:%X\n",ip_net);
215
+
216
+ uint16_t port_host = 5060;
217
+ uint16_t port_net = htons(port_host);
218
+ printf("net:%X\n",port_net);
219
+
220
+ pd.add_endpoint( inet_addr("192.168.88.2"), htons(5060) );
221
+ pd.add_endpoint( inet_addr("192.168.88.8"), htons(5060) );
222
+ pd.add_endpoint( inet_addr("192.168.88.3"), htons(5060) );
223
+ pd.add_endpoint( inet_addr("192.168.88.28"), htons(5060) );
224
+ pd.add_endpoint( inet_addr("192.168.88.4"), htons(5060) );
225
+ pd.add_endpoint( inet_addr("192.168.88.66"), htons(5060) );
226
+ pd.add_endpoint( inet_addr("192.168.88.64"), htons(5060) );
227
+ pd.add_endpoint( inet_addr("192.168.88.62"), htons(5060) );
228
+
229
+ pd.remove_endpoint( inet_addr("192.168.88.4"), htons(5060) );
230
+ pd.remove_endpoint( inet_addr("192.168.88.66"), htons(5060) );
231
+ for(;;) {
232
+ ;
233
+ }
234
+ }
@@ -0,0 +1,67 @@
1
+ #ifndef __TCPDUMPER_H__
2
+ #define __TCPDUMPER_H__
3
+
4
+ #include <pcap.h>
5
+
6
+ #include <string>
7
+ #include <pthread.h>
8
+ #include "boost/bind.hpp"
9
+
10
+ #include <set>
11
+ #include <map>
12
+
13
+ using namespace std;
14
+
15
+ class PacketDumper
16
+ {
17
+ public:
18
+ PacketDumper();
19
+ ~PacketDumper();
20
+ bool init(string dev, string file);
21
+ bool add_endpoint(uint32_t ipaddr, uint16_t port);
22
+ bool remove_endpoint(uint32_t ipaddr, uint16_t port);
23
+ void process();
24
+ pthread_mutex_t _mutex;
25
+ bool _end_flag;
26
+ string _dev;
27
+ pcap_t *_handler;
28
+ pcap_dumper_t *_dumper;
29
+ private:
30
+ string _filter;
31
+ bpf_program _filter_program;
32
+ pthread_t _thread;
33
+ int datalink;
34
+ typedef set<uint16_t> port_set;
35
+ typedef map <uint32_t, port_set> ipaddr_map;
36
+ ipaddr_map _awaited_endpoints;
37
+ };
38
+
39
+ static void *thread_func(void *vptr_args);
40
+
41
+ struct dlt_linux_sll {
42
+ u_short packet_type;
43
+ u_short ARPHRD;
44
+ u_short slink_length;
45
+ u_char bytes[8];
46
+ u_short ether_type;
47
+ };
48
+
49
+ struct ip_header {
50
+ u_char ip_version_headerlength; // version << 4 | header length >> 2
51
+ #define IP_HL(ip) (((ip)->ip_version_headerlength) & 0x0f)
52
+ #define IP_V(ip) (((ip)->ip_version_headerlength) >> 4)
53
+ u_char ip_tos; //Type of service
54
+ u_short ip_len; // total length
55
+ u_short ip_id; // identification
56
+ u_short ip_off; //fragment offset field
57
+
58
+ u_char ip_ttl;
59
+ u_char ip_p;
60
+ u_short ip_sum;
61
+ u_int ip_src;
62
+ u_int ip_dst;
63
+ };
64
+
65
+
66
+
67
+ #endif
@@ -0,0 +1,37 @@
1
+ #Modify this to point to the PJSIP location.
2
+ PJBASE=/usr/local/src/svn/pjproject
3
+
4
+ include $(PJBASE)/build.mak
5
+
6
+ CC = g++
7
+ LDFLAGS = $(APP_LDFLAGS)
8
+ LDLIBS = $(APP_LDLIBS)
9
+ CFLAGS = $(APP_CFLAGS)
10
+ CPPFLAGS= -O0 -g -fPIC -I include/chainlink ${CFLAGS}
11
+
12
+ CHAINLINK_CPPFLAGS = -I include/chainlink
13
+
14
+ vpath %.c src/chainlink
15
+ vpath %.h include/chainlink
16
+
17
+ all: libchainlink.a
18
+
19
+ #libchainlink.a: chainlink_wire_port.o chainlink_dtmfdet.o chainlink_tonegen.o chainlink_wav_player.o
20
+ #libchainlink.a: chainlink_wire_port.o chainlink_dtmfdet.o chainlink_tonegen.o
21
+ libchainlink.a: chainlink_wire_port.o chainlink_dtmfdet.o chainlink_wav_player.o chainlink_wav_writer.o chainlink_tonegen.o
22
+ ar rcs $@ $^
23
+
24
+ chainlink_wire_port.o:
25
+
26
+ chainlink_dtmfdet.o:
27
+
28
+ chainlink_wav_player.o:
29
+
30
+ chainlink_wav_writer.o:
31
+
32
+ chainlink_tonegen.o:
33
+
34
+ clean:
35
+ rm -f *.o
36
+ rm -f *.a
37
+
@@ -0,0 +1,26 @@
1
+ 2009/06/18: takeshi
2
+
3
+ When compiling chainlink_dtmfdet.c using g++, it failed with:
4
+
5
+ g++ -DPJ_AUTOCONF=1 -O2 -I/usr/local/src/svn/pjproject/pjlib/include -I/usr/local/src/svn/pjproject/pjlib-util/include -I/usr/local/
6
+ src/svn/pjproject/pjnath/include -I/usr/local/src/svn/pjproject/pjmedia/include -I/usr/local/src/svn/pjproject/pjsip/include -I incl
7
+ ude/pjmedia -DPJ_AUTOCONF=1 -O2 -I/usr/local/src/svn/pjproject/pjlib/include -I/usr/local/src/svn/pjproject/pjlib-util/include -I/us
8
+ r/local/src/svn/pjproject/pjnath/include -I/usr/local/src/svn/pjproject/pjmedia/include -I/usr/local/src/svn/pjproject/pjsip/include
9
+ -c -o chainlink_dtmfdet.o src/pjmedia/chainlink_dtmfdet.c
10
+ /usr/local/include/spandsp/dc_restore.h: In function ât16_t saturate(int32_t)â/usr/local/include/spandsp/dc_restore.h:129: error: âT16_MAXâas not declared in this scope
11
+ /usr/local/include/spandsp/dc_restore.h:131: error: âT16_MINâas not declared in this scope
12
+ /usr/local/include/spandsp/dc_restore.h: In function ât16_t fsaturatef(float)â/usr/local/include/spandsp/dc_restore.h:138: error: âT16_MAXâas not declared in this scope
13
+ /usr/local/include/spandsp/dc_restore.h:140: error: âT16_MINâas not declared in this scope
14
+ /usr/local/include/spandsp/dc_restore.h: In function ât16_t fsaturate(double)â/usr/local/include/spandsp/dc_restore.h:148: error: âT16_MAXâas not declared in this scope
15
+ /usr/local/include/spandsp/dc_restore.h:150: error: âT16_MINâas not declared in this scope
16
+
17
+ Using gcc, I was able to compile it, but this will cause problems with linking to sip-tester (which is compiled using g++) due to name mangling. So, to resolve the above problem I added the definitions before the call to include spandsp.h:
18
+
19
+ #define INT16_MAX 0x7fff
20
+ #define INT16_MIN (-INT16_MAX - 1)
21
+ #include <spandsp.h>
22
+
23
+
24
+
25
+
26
+
@@ -0,0 +1,3 @@
1
+ Q: What is chainlink?
2
+ A: there is a shortcoming of the pjmedia_port implementation that the ports don't propagate calls to put_frame/get_frame to the downstream port (the other port they are connected to). So this complicates things when you need to do simultaneous media operations (there is some things that may help like the bidirectional port). So, to resolve this, we reimplemented the ports we needed with this capability of being chained to each other so that when put_frame/get_frame is called, the call is propagated between them. And to avoid collision of names, we renamed our implementation with the prefix 'chainlink_'.
3
+
@@ -0,0 +1,11 @@
1
+ #ifndef __CHAINLINK_H__
2
+ #define __CHAINLINK_H__
3
+
4
+ #include <pjmedia/port.h>
5
+
6
+ struct chainlink {
7
+ pjmedia_port port;
8
+ pjmedia_port *next;
9
+ };
10
+
11
+ #endif /* __CHAINLINK_H__ */
@@ -0,0 +1,56 @@
1
+ #ifndef __CHAINLINK_DTMFDET_H__
2
+ #define __CHAINLINK_DTMFDET_H__
3
+
4
+ /**
5
+ * @file chainlink_dtmfdet.h
6
+ * @brief DTMF Detection port.
7
+ */
8
+ #include <pjmedia/port.h>
9
+
10
+
11
+
12
+ /**
13
+ * @defgroup PJMEDIA_DTMFDET_PORT DTMF Detection
14
+ * @ingroup PJMEDIA_PORT
15
+ * @brief DTMF Detection port
16
+ * @{
17
+ */
18
+
19
+
20
+ PJ_BEGIN_DECL
21
+
22
+
23
+ /**
24
+ * Create DTMF Detection port
25
+ *
26
+ * @param pool Pool to allocate memory.
27
+ * @param sampling_rate Sampling rate of the port.
28
+ * @param channel_count Number of channels.
29
+ * @param samples_per_frame Number of samples per frame.
30
+ * @param bits_per_sample Number of bits per sample.
31
+ * @param cb Callback to be called upon detection of digits.o * @user_data User data to be passed in the callback
32
+ * @param p_port Pointer to receive the port instance.
33
+ *
34
+ * @return PJ_SUCCESS on success.
35
+ */
36
+ PJ_DECL(pj_status_t) chainlink_dtmfdet_create( pj_pool_t *pool,
37
+ unsigned clock_rate,
38
+ unsigned channel_count,
39
+ unsigned samples_per_frame,
40
+ unsigned bits_per_sample,
41
+ void (*cb)(pjmedia_port*,
42
+ void *user_data,
43
+ char digit),
44
+ void *user_data,
45
+ pjmedia_port **p_port);
46
+
47
+
48
+
49
+ PJ_END_DECL
50
+
51
+ /**
52
+ * @}
53
+ */
54
+
55
+
56
+ #endif /* __CHAINLINK_DTMFDET_H__ */