... | ... |
@@ -90,7 +90,6 @@ void AorBucket::gbc(RegCacheStorageHandler* h, long int now, |
90 | 90 |
del_it->first.c_str(),binding->alias.c_str(), |
91 | 91 |
binding->reg_expire,now); |
92 | 92 |
|
93 |
- if(h) h->onDelete(it->first,del_it->first,binding->alias); |
|
94 | 93 |
delete binding; |
95 | 94 |
aor_e->erase(del_it); |
96 | 95 |
continue; |
... | ... |
@@ -277,46 +277,15 @@ void RegisterDialog::fixUacContactHosts(const AmSipRequest& req, |
277 | 277 |
if(contact_hiding) { |
278 | 278 |
uac_contacts[i].uri_user = encodeUsername(uac_contacts[i], |
279 | 279 |
req,cp,ctx); |
280 |
- |
|
281 |
- list<sip_avp*> uri_params; |
|
282 |
- const string& old_params = uac_contacts[i].uri_param; |
|
283 |
- const char* c = old_params.c_str(); |
|
284 |
- |
|
285 |
- if(parse_gen_params(&uri_params,&c,old_params.length(),0) < 0) { |
|
286 |
- |
|
287 |
- DBG("could not parse Contact URI parameters: '%s'", |
|
288 |
- uac_contacts[i].uri_param.c_str()); |
|
289 |
- free_gen_params(&uri_params); |
|
290 |
- continue; |
|
291 |
- } |
|
292 |
- |
|
293 |
- // Suppress transport parameter |
|
294 |
- // hack to suppress transport=tcp |
|
295 |
- string new_params; |
|
296 |
- for(list<sip_avp*>::iterator p_it = uri_params.begin(); |
|
297 |
- p_it != uri_params.end(); p_it++) { |
|
298 |
- |
|
299 |
- DBG("parsed"); |
|
300 |
- if( ((*p_it)->name.len == (sizeof("transport")-1)) && |
|
301 |
- !memcmp((*p_it)->name.s,"transport",sizeof("transport")-1) ) { |
|
302 |
- continue; |
|
303 |
- } |
|
304 |
- |
|
305 |
- if(!new_params.empty()) new_params += ";"; |
|
306 |
- new_params += c2stlstr((*p_it)->name); |
|
307 |
- if((*p_it)->value.len) { |
|
308 |
- new_params += "=" + c2stlstr((*p_it)->value); |
|
309 |
- } |
|
310 |
- } |
|
311 |
- |
|
312 |
- free_gen_params(&uri_params); |
|
313 |
- uac_contacts[i].uri_param = new_params; |
|
314 | 280 |
} |
315 | 281 |
else if(!reg_caching) { |
316 | 282 |
cp.fix_reg_contact(ctx,req,uac_contacts[i]); |
317 | 283 |
continue; |
318 | 284 |
} |
319 | 285 |
|
286 |
+ // remove 'transport' param from Contact |
|
287 |
+ removeTransport(uac_contacts[i]); |
|
288 |
+ |
|
320 | 289 |
// patch host & port |
321 | 290 |
uac_contacts[i].uri_host = AmConfig::SIP_Ifs[oif].getIP(); |
322 | 291 |
|
... | ... |
@@ -325,11 +294,49 @@ void RegisterDialog::fixUacContactHosts(const AmSipRequest& req, |
325 | 294 |
else |
326 | 295 |
uac_contacts[i].uri_port = int2str(AmConfig::SIP_Ifs[oif].LocalPort); |
327 | 296 |
|
328 |
- DBG("Patching host and port for Contact-HF: host='%s';port='%s'", |
|
297 |
+ DBG("Patching host, port and transport for Contact-HF: host='%s';port='%s'", |
|
329 | 298 |
uac_contacts[i].uri_host.c_str(),uac_contacts[i].uri_port.c_str()); |
330 | 299 |
} |
331 | 300 |
} |
332 | 301 |
|
302 |
+int RegisterDialog::removeTransport(AmUriParser& uri) |
|
303 |
+{ |
|
304 |
+ list<sip_avp*> uri_params; |
|
305 |
+ string old_params = uri.uri_param; |
|
306 |
+ const char* c = old_params.c_str(); |
|
307 |
+ |
|
308 |
+ if(parse_gen_params(&uri_params,&c,old_params.length(),0) < 0) { |
|
309 |
+ |
|
310 |
+ DBG("could not parse Contact URI parameters: '%s'", |
|
311 |
+ uri.uri_param.c_str()); |
|
312 |
+ free_gen_params(&uri_params); |
|
313 |
+ return -1; |
|
314 |
+ } |
|
315 |
+ |
|
316 |
+ // Suppress transport parameter |
|
317 |
+ // hack to suppress transport=tcp |
|
318 |
+ string new_params; |
|
319 |
+ for(list<sip_avp*>::iterator p_it = uri_params.begin(); |
|
320 |
+ p_it != uri_params.end(); p_it++) { |
|
321 |
+ |
|
322 |
+ DBG("parsed"); |
|
323 |
+ if( ((*p_it)->name.len == (sizeof("transport")-1)) && |
|
324 |
+ !memcmp((*p_it)->name.s,"transport",sizeof("transport")-1) ) { |
|
325 |
+ continue; |
|
326 |
+ } |
|
327 |
+ |
|
328 |
+ if(!new_params.empty()) new_params += ";"; |
|
329 |
+ new_params += c2stlstr((*p_it)->name); |
|
330 |
+ if((*p_it)->value.len) { |
|
331 |
+ new_params += "=" + c2stlstr((*p_it)->value); |
|
332 |
+ } |
|
333 |
+ } |
|
334 |
+ |
|
335 |
+ free_gen_params(&uri_params); |
|
336 |
+ uri.uri_param = new_params; |
|
337 |
+ return 0; |
|
338 |
+} |
|
339 |
+ |
|
333 | 340 |
int RegisterDialog::initAor(const AmSipRequest& req) |
334 | 341 |
{ |
335 | 342 |
AmUriParser from_parser; |
... | ... |
@@ -55,6 +55,9 @@ class RegisterDialog |
55 | 55 |
// so that getOutboundIf() can be called |
56 | 56 |
void fixUacContactHosts(const AmSipRequest& req, const SBCCallProfile& cp); |
57 | 57 |
|
58 |
+ // remove the transport parameter from a URI |
|
59 |
+ int removeTransport(AmUriParser& uri); |
|
60 |
+ |
|
58 | 61 |
public: |
59 | 62 |
RegisterDialog(SBCCallProfile &profile, vector<AmDynInvoke*> &cc_modules); |
60 | 63 |
~RegisterDialog(); |
... | ... |
@@ -326,8 +326,10 @@ void AmBasicSipDialog::onRxRequest(const AmSipRequest& req) |
326 | 326 |
if (remote_uri != req.from_uri) { |
327 | 327 |
setRemoteUri(req.from_uri); |
328 | 328 |
if(nat_handling && req.first_hop) { |
329 |
- setNextHop(req.remote_ip + ":" |
|
330 |
- + int2str(req.remote_port)); |
|
329 |
+ string nh = req.remote_ip + ":" |
|
330 |
+ + int2str(req.remote_port) |
|
331 |
+ + "/" + req.trsp; |
|
332 |
+ setNextHop(nh); |
|
331 | 333 |
setNextHop1stReq(false); |
332 | 334 |
} |
333 | 335 |
} |
... | ... |
@@ -470,11 +472,11 @@ void AmBasicSipDialog::updateDialogTarget(const AmSipReply& reply) |
470 | 472 |
(reply.cseq_method == SIP_METH_SUBSCRIBE)) ) { |
471 | 473 |
|
472 | 474 |
setRemoteUri(reply.to_uri); |
473 |
- if(!getNextHop().empty() && !next_hop_fixed) { |
|
474 |
- DBG("updating next_hop from reply to %s:%u\n", |
|
475 |
- reply.remote_ip.c_str(), reply.remote_port); |
|
476 |
- setNextHop(reply.remote_ip + ":" |
|
477 |
- + int2str(reply.remote_port)); |
|
475 |
+ if(!getNextHop().empty()) { |
|
476 |
+ string nh = reply.remote_ip |
|
477 |
+ + ":" + int2str(reply.remote_port) |
|
478 |
+ + "/" + reply.trsp; |
|
479 |
+ setNextHop(nh); |
|
478 | 480 |
} |
479 | 481 |
|
480 | 482 |
string ua = getHeader(reply.hdrs,"Server"); |
... | ... |
@@ -43,6 +43,7 @@ |
43 | 43 |
#include "AmSessionContainer.h" |
44 | 44 |
#include "Am100rel.h" |
45 | 45 |
#include "sip/transport.h" |
46 |
+#include "sip/resolver.h" |
|
46 | 47 |
#include "sip/ip_util.h" |
47 | 48 |
#include "sip/sip_timers.h" |
48 | 49 |
#include "sip/raw_sender.h" |
... | ... |
@@ -91,7 +92,6 @@ bool AmConfig::ForceSymmetricRtp = false; |
91 | 92 |
bool AmConfig::SipNATHandling = false; |
92 | 93 |
bool AmConfig::UseRawSockets = false; |
93 | 94 |
bool AmConfig::IgnoreNotifyLowerCSeq = false; |
94 |
-bool AmConfig::DisableDNSSRV = false; |
|
95 | 95 |
string AmConfig::Signature = ""; |
96 | 96 |
unsigned int AmConfig::MaxForwards = MAX_FORWARDS; |
97 | 97 |
bool AmConfig::SingleCodecInOK = false; |
... | ... |
@@ -386,7 +386,7 @@ int AmConfig::readConfiguration() |
386 | 386 |
} |
387 | 387 |
|
388 | 388 |
if(cfg.hasParameter("disable_dns_srv")) { |
389 |
- DisableDNSSRV = (cfg.getParameter("disable_dns_srv") == "yes"); |
|
389 |
+ _resolver::disable_srv = (cfg.getParameter("disable_dns_srv") == "yes"); |
|
390 | 390 |
} |
391 | 391 |
|
392 | 392 |
|
... | ... |
@@ -713,6 +713,7 @@ int AmConfig::insert_SIP_interface(const SIP_interface& intf) |
713 | 713 |
|
714 | 714 |
return -1; |
715 | 715 |
} |
716 |
+ //FIXME: what happens now? shouldn't we insert the interface???? |
|
716 | 717 |
} |
717 | 718 |
} |
718 | 719 |
|
... | ... |
@@ -769,6 +770,13 @@ static int readSIPInterface(AmConfigReader& cfg, const string& i_name) |
769 | 770 |
intf.SigSockOpts = opts; |
770 | 771 |
} |
771 | 772 |
|
773 |
+ intf.tcp_connect_timeout = |
|
774 |
+ cfg.getParameterInt("tcp_connect_timeout" + suffix, |
|
775 |
+ DEFAULT_TCP_CONNECT_TIMEOUT); |
|
776 |
+ |
|
777 |
+ intf.tcp_idle_timeout = |
|
778 |
+ cfg.getParameterInt("tcp_idle_timeout" + suffix, DEFAULT_TCP_IDLE_TIMEOUT); |
|
779 |
+ |
|
772 | 780 |
if(!i_name.empty()) |
773 | 781 |
intf.name = i_name; |
774 | 782 |
else |
... | ... |
@@ -1171,9 +1179,11 @@ void AmConfig::dump_Ifs() |
1171 | 1179 |
SIP_interface& it_ref = SIP_Ifs[i]; |
1172 | 1180 |
|
1173 | 1181 |
INFO("\t(%i) name='%s'" ";LocalIP='%s'" |
1174 |
- ";LocalPort='%u'" ";PublicIP='%s'", |
|
1182 |
+ ";LocalPort='%u'" ";PublicIP='%s';TCP=%u/%u", |
|
1175 | 1183 |
i,it_ref.name.c_str(),it_ref.LocalIP.c_str(), |
1176 |
- it_ref.LocalPort,it_ref.PublicIP.c_str()); |
|
1184 |
+ it_ref.LocalPort,it_ref.PublicIP.c_str(), |
|
1185 |
+ it_ref.tcp_connect_timeout, |
|
1186 |
+ it_ref.tcp_idle_timeout); |
|
1177 | 1187 |
} |
1178 | 1188 |
|
1179 | 1189 |
INFO("Signaling address map:"); |
... | ... |
@@ -110,6 +110,9 @@ struct AmConfig |
110 | 110 |
*/ |
111 | 111 |
unsigned int SigSockOpts; |
112 | 112 |
|
113 |
+ unsigned int tcp_connect_timeout; |
|
114 |
+ unsigned int tcp_idle_timeout; |
|
115 |
+ |
|
113 | 116 |
/** RTP interface index */ |
114 | 117 |
int RtpInterface; |
115 | 118 |
|
... | ... |
@@ -193,8 +196,6 @@ struct AmConfig |
193 | 196 |
static bool UseRawSockets; |
194 | 197 |
/** Ignore Low CSeq on NOTIFY - for RFC 3265 instead of 5057 */ |
195 | 198 |
static bool IgnoreNotifyLowerCSeq; |
196 |
- /** skip DNS SRV lookup for resolving destination address*/ |
|
197 |
- static bool DisableDNSSRV; |
|
198 | 199 |
/** Server/User-Agent header (optional) */ |
199 | 200 |
static string Signature; |
200 | 201 |
/** Value of Max-Forward header field for new requests */ |
... | ... |
@@ -38,16 +38,6 @@ |
38 | 38 |
#include <strings.h> |
39 | 39 |
#endif |
40 | 40 |
|
41 |
-#include <sys/time.h> |
|
42 |
-#include <sys/poll.h> |
|
43 |
- |
|
44 |
-#ifndef MAX_RTP_SESSIONS |
|
45 |
-#define MAX_RTP_SESSIONS 2048 |
|
46 |
-#endif |
|
47 |
- |
|
48 |
-#define RTP_POLL_TIMEOUT 50 /*50 ms*/ |
|
49 |
- |
|
50 |
- |
|
51 | 41 |
_AmRtpReceiver::_AmRtpReceiver() |
52 | 42 |
{ |
53 | 43 |
n_receivers = AmConfig::RTPReceiverThreads; |
... | ... |
@@ -62,20 +52,20 @@ _AmRtpReceiver::~_AmRtpReceiver() |
62 | 52 |
AmRtpReceiverThread::AmRtpReceiverThread() |
63 | 53 |
: stop_requested(false) |
64 | 54 |
{ |
65 |
- fds = new struct pollfd[MAX_RTP_SESSIONS]; |
|
66 |
- nfds = 0; |
|
55 |
+ // libevent event base |
|
56 |
+ ev_base = event_base_new(); |
|
67 | 57 |
} |
68 | 58 |
|
69 | 59 |
AmRtpReceiverThread::~AmRtpReceiverThread() |
70 | 60 |
{ |
71 |
- delete [] (fds); |
|
61 |
+ event_base_free(ev_base); |
|
72 | 62 |
INFO("RTP receiver has been recycled.\n"); |
73 | 63 |
} |
74 | 64 |
|
75 | 65 |
void AmRtpReceiverThread::on_stop() |
76 | 66 |
{ |
77 | 67 |
INFO("requesting RTP receiver to stop.\n"); |
78 |
- stop_requested.set(true); |
|
68 |
+ event_base_loopbreak(ev_base); |
|
79 | 69 |
} |
80 | 70 |
|
81 | 71 |
void AmRtpReceiverThread::stop_and_wait() |
... | ... |
@@ -97,44 +87,43 @@ void _AmRtpReceiver::dispose() |
97 | 87 |
|
98 | 88 |
void AmRtpReceiverThread::run() |
99 | 89 |
{ |
100 |
- unsigned int tmp_nfds = 0; |
|
101 |
- struct pollfd* tmp_fds = new struct pollfd[MAX_RTP_SESSIONS]; |
|
102 |
- |
|
103 |
- while(!stop_requested.get()){ |
|
104 |
- |
|
105 |
- streams_mut.lock(); |
|
106 |
- tmp_nfds = nfds; |
|
107 |
- memcpy(tmp_fds,fds,nfds*sizeof(struct pollfd)); |
|
108 |
- streams_mut.unlock(); |
|
109 |
- |
|
110 |
- int ret = poll(tmp_fds,tmp_nfds,RTP_POLL_TIMEOUT); |
|
111 |
- if(ret < 0 && errno != EINTR) |
|
112 |
- ERROR("AmRtpReceiver: poll: %s\n",strerror(errno)); |
|
113 |
- |
|
114 |
- if(ret < 1) |
|
115 |
- continue; |
|
116 |
- |
|
117 |
- for(unsigned int i=0; i<tmp_nfds; i++) { |
|
90 |
+ // fake event to prevent the event loop from exiting |
|
91 |
+ int fake_fds[2]; |
|
92 |
+ pipe(fake_fds); |
|
93 |
+ struct event* ev_default = |
|
94 |
+ event_new(ev_base,fake_fds[0], |
|
95 |
+ EV_READ|EV_PERSIST, |
|
96 |
+ NULL,NULL); |
|
97 |
+ event_add(ev_default,NULL); |
|
98 |
+ |
|
99 |
+ // run the event loop |
|
100 |
+ event_base_loop(ev_base,0); |
|
101 |
+ |
|
102 |
+ // clean-up fake fds/event |
|
103 |
+ event_free(ev_default); |
|
104 |
+ close(fake_fds[0]); |
|
105 |
+ close(fake_fds[1]); |
|
106 |
+} |
|
118 | 107 |
|
119 |
- if(!(tmp_fds[i].revents & POLLIN)) |
|
120 |
- continue; |
|
108 |
+void AmRtpReceiverThread::_rtp_receiver_read_cb(evutil_socket_t sd, |
|
109 |
+ short what, void* arg) |
|
110 |
+{ |
|
111 |
+ AmRtpReceiverThread::StreamInfo* p_si = |
|
112 |
+ static_cast<AmRtpReceiverThread::StreamInfo*>(arg); |
|
121 | 113 |
|
122 |
- streams_mut.lock(); |
|
123 |
- Streams::iterator it = streams.find(tmp_fds[i].fd); |
|
124 |
- if(it != streams.end()) { |
|
125 |
- it->second.stream->recvPacket(tmp_fds[i].fd); |
|
126 |
- } |
|
127 |
- streams_mut.unlock(); |
|
128 |
- } |
|
114 |
+ p_si->thread->streams_mut.lock(); |
|
115 |
+ if(!p_si->stream) { |
|
116 |
+ // we are about to get removed... |
|
117 |
+ p_si->thread->streams_mut.unlock(); |
|
118 |
+ return; |
|
129 | 119 |
} |
130 |
- |
|
131 |
- delete[] (tmp_fds); |
|
120 |
+ p_si->stream->recvPacket(sd); |
|
121 |
+ p_si->thread->streams_mut.unlock(); |
|
132 | 122 |
} |
133 | 123 |
|
134 | 124 |
void AmRtpReceiverThread::addStream(int sd, AmRtpStream* stream) |
135 | 125 |
{ |
136 | 126 |
streams_mut.lock(); |
137 |
- |
|
138 | 127 |
if(streams.find(sd) != streams.end()) { |
139 | 128 |
ERROR("trying to insert existing stream [%p] with sd=%i\n", |
140 | 129 |
stream,sd); |
... | ... |
@@ -142,43 +131,50 @@ void AmRtpReceiverThread::addStream(int sd, AmRtpStream* stream) |
142 | 131 |
return; |
143 | 132 |
} |
144 | 133 |
|
145 |
- if(nfds >= MAX_RTP_SESSIONS){ |
|
146 |
- streams_mut.unlock(); |
|
147 |
- ERROR("maximum number of sessions reached (%i)\n", |
|
148 |
- MAX_RTP_SESSIONS); |
|
149 |
- throw string("maximum number of sessions reached"); |
|
150 |
- } |
|
151 |
- |
|
152 |
- fds[nfds].fd = sd; |
|
153 |
- fds[nfds].events = POLLIN; |
|
154 |
- fds[nfds].revents = 0; |
|
155 |
- |
|
156 |
- streams.insert(std::make_pair(sd,StreamInfo(nfds,stream))); |
|
157 |
- nfds++; |
|
158 |
- |
|
134 |
+ StreamInfo& si = streams[sd]; |
|
135 |
+ si.stream = stream; |
|
136 |
+ event* ev_read = event_new(ev_base,sd,EV_READ|EV_PERSIST, |
|
137 |
+ AmRtpReceiverThread::_rtp_receiver_read_cb,&si); |
|
138 |
+ si.ev_read = ev_read; |
|
139 |
+ si.thread = this; |
|
159 | 140 |
streams_mut.unlock(); |
141 |
+ |
|
142 |
+ // This must be done when |
|
143 |
+ // streams_mut is NOT locked |
|
144 |
+ event_add(ev_read,NULL); |
|
160 | 145 |
} |
161 | 146 |
|
162 | 147 |
void AmRtpReceiverThread::removeStream(int sd) |
163 | 148 |
{ |
164 | 149 |
streams_mut.lock(); |
165 |
- |
|
166 | 150 |
Streams::iterator sit = streams.find(sd); |
167 | 151 |
if(sit == streams.end()) { |
168 | 152 |
streams_mut.unlock(); |
169 | 153 |
return; |
170 | 154 |
} |
171 | 155 |
|
172 |
- unsigned int i = sit->second.index; |
|
173 |
- if(--nfds && (i < nfds)) { |
|
174 |
- fds[i] = fds[nfds]; |
|
175 |
- sit = streams.find(fds[nfds].fd); |
|
176 |
- if(sit != streams.end()) { |
|
177 |
- sit->second.index = i; |
|
178 |
- } |
|
156 |
+ StreamInfo& si = sit->second; |
|
157 |
+ if(!si.stream || !si.ev_read){ |
|
158 |
+ streams_mut.unlock(); |
|
159 |
+ return; |
|
179 | 160 |
} |
180 |
- streams.erase(sd); |
|
181 | 161 |
|
162 |
+ si.stream = NULL; |
|
163 |
+ event* ev_read = si.ev_read; |
|
164 |
+ si.ev_read = NULL; |
|
165 |
+ |
|
166 |
+ streams_mut.unlock(); |
|
167 |
+ |
|
168 |
+ // This must be done while |
|
169 |
+ // streams_mut is NOT locked |
|
170 |
+ event_free(ev_read); |
|
171 |
+ |
|
172 |
+ streams_mut.lock(); |
|
173 |
+ // this must be done AFTER event_free() |
|
174 |
+ // so that the StreamInfo does not get |
|
175 |
+ // deleted while in recvPaket() |
|
176 |
+ // (see recv callback) |
|
177 |
+ streams.erase(sd); |
|
182 | 178 |
streams_mut.unlock(); |
183 | 179 |
} |
184 | 180 |
|
... | ... |
@@ -32,7 +32,7 @@ |
32 | 32 |
#include "atomic_types.h" |
33 | 33 |
#include "singleton.h" |
34 | 34 |
|
35 |
-#include <sys/select.h> |
|
35 |
+#include <event2/event.h> |
|
36 | 36 |
|
37 | 37 |
#include <map> |
38 | 38 |
using std::greater; |
... | ... |
@@ -47,37 +47,45 @@ class _AmRtpReceiver; |
47 | 47 |
* that are registered to it. It places the received packets in |
48 | 48 |
* the stream's buffer. |
49 | 49 |
*/ |
50 |
-class AmRtpReceiverThread: public AmThread { |
|
51 |
- |
|
52 |
- struct StreamInfo { |
|
53 |
- unsigned int index; // index into fds table |
|
50 |
+class AmRtpReceiverThread |
|
51 |
+ : public AmThread |
|
52 |
+{ |
|
53 |
+ struct StreamInfo |
|
54 |
+ { |
|
54 | 55 |
AmRtpStream* stream; |
55 |
- |
|
56 |
- StreamInfo(unsigned int i, AmRtpStream* s) |
|
57 |
- : index(i), stream(s) {} |
|
56 |
+ struct event* ev_read; |
|
57 |
+ AmRtpReceiverThread* thread; |
|
58 |
+ |
|
59 |
+ StreamInfo() |
|
60 |
+ : stream(NULL), |
|
61 |
+ ev_read(NULL), |
|
62 |
+ thread(NULL) |
|
63 |
+ {} |
|
58 | 64 |
}; |
59 | 65 |
|
60 |
- typedef std::map<int, StreamInfo, greater<int> > Streams; |
|
66 |
+ typedef std::map<int, StreamInfo> Streams; |
|
67 |
+ |
|
68 |
+ struct event_base* ev_base; |
|
69 |
+ struct event* ev_default; |
|
61 | 70 |
|
62 | 71 |
Streams streams; |
63 | 72 |
AmMutex streams_mut; |
64 | 73 |
|
65 |
- struct pollfd* fds; |
|
66 |
- unsigned int nfds; |
|
67 |
- |
|
74 |
+ AmSharedVar<bool> stop_requested; |
|
75 |
+ |
|
76 |
+ static void _rtp_receiver_read_cb(evutil_socket_t sd, short what, void* arg); |
|
77 |
+ |
|
78 |
+public: |
|
68 | 79 |
AmRtpReceiverThread(); |
69 | 80 |
~AmRtpReceiverThread(); |
70 | 81 |
|
71 | 82 |
void run(); |
72 | 83 |
void on_stop(); |
73 |
- AmSharedVar<bool> stop_requested; |
|
74 | 84 |
|
75 | 85 |
void addStream(int sd, AmRtpStream* stream); |
76 | 86 |
void removeStream(int sd); |
77 | 87 |
|
78 | 88 |
void stop_and_wait(); |
79 |
- |
|
80 |
- friend class _AmRtpReceiver; |
|
81 | 89 |
}; |
82 | 90 |
|
83 | 91 |
class _AmRtpReceiver |
... | ... |
@@ -46,6 +46,7 @@ |
46 | 46 |
#include "sip/msg_hdrs.h" |
47 | 47 |
#include "sip/udp_trsp.h" |
48 | 48 |
#include "sip/ip_util.h" |
49 |
+#include "sip/tcp_trsp.h" |
|
49 | 50 |
|
50 | 51 |
#include "log.h" |
51 | 52 |
|
... | ... |
@@ -60,6 +61,108 @@ |
60 | 61 |
bool _SipCtrlInterface::log_parsed_messages = true; |
61 | 62 |
int _SipCtrlInterface::udp_rcvbuf = -1; |
62 | 63 |
|
64 |
+int _SipCtrlInterface::alloc_udp_structs() |
|
65 |
+{ |
|
66 |
+ udp_sockets = new udp_trsp_socket*[ AmConfig::SIP_Ifs.size() ]; |
|
67 |
+ udp_servers = new udp_trsp* [ AmConfig::SIPServerThreads |
|
68 |
+ * AmConfig::SIP_Ifs.size() ]; |
|
69 |
+ |
|
70 |
+ if(udp_sockets && udp_servers) |
|
71 |
+ return 0; |
|
72 |
+ |
|
73 |
+ return -1; |
|
74 |
+} |
|
75 |
+ |
|
76 |
+int _SipCtrlInterface::init_udp_servers(int if_num) |
|
77 |
+{ |
|
78 |
+ udp_trsp_socket* udp_socket = |
|
79 |
+ new udp_trsp_socket(if_num,AmConfig::SIP_Ifs[if_num].SigSockOpts |
|
80 |
+ | (AmConfig::ForceOutboundIf ? |
|
81 |
+ trsp_socket::force_outbound_if : 0) |
|
82 |
+ | (AmConfig::UseRawSockets ? |
|
83 |
+ trsp_socket::use_raw_sockets : 0), |
|
84 |
+ AmConfig::SIP_Ifs[if_num].NetIfIdx); |
|
85 |
+ |
|
86 |
+ if(!AmConfig::SIP_Ifs[if_num].PublicIP.empty()) { |
|
87 |
+ udp_socket->set_public_ip(AmConfig::SIP_Ifs[if_num].PublicIP); |
|
88 |
+ } |
|
89 |
+ |
|
90 |
+ if(udp_socket->bind(AmConfig::SIP_Ifs[if_num].LocalIP, |
|
91 |
+ AmConfig::SIP_Ifs[if_num].LocalPort) < 0){ |
|
92 |
+ |
|
93 |
+ ERROR("Could not bind SIP/UDP socket to %s:%i", |
|
94 |
+ AmConfig::SIP_Ifs[if_num].LocalIP.c_str(), |
|
95 |
+ AmConfig::SIP_Ifs[if_num].LocalPort); |
|
96 |
+ |
|
97 |
+ delete udp_socket; |
|
98 |
+ return -1; |
|
99 |
+ } |
|
100 |
+ |
|
101 |
+ if(udp_rcvbuf > 0) { |
|
102 |
+ udp_socket->set_recvbuf_size(udp_rcvbuf); |
|
103 |
+ } |
|
104 |
+ |
|
105 |
+ trans_layer::instance()->register_transport(udp_socket); |
|
106 |
+ udp_sockets[if_num] = udp_socket; |
|
107 |
+ inc_ref(udp_socket); |
|
108 |
+ nr_udp_sockets++; |
|
109 |
+ |
|
110 |
+ for(int j=0; j<AmConfig::SIPServerThreads;j++){ |
|
111 |
+ udp_servers[if_num * AmConfig::SIPServerThreads + j] = |
|
112 |
+ new udp_trsp(udp_socket); |
|
113 |
+ nr_udp_servers++; |
|
114 |
+ } |
|
115 |
+ |
|
116 |
+ return 0; |
|
117 |
+} |
|
118 |
+ |
|
119 |
+int _SipCtrlInterface::alloc_tcp_structs() |
|
120 |
+{ |
|
121 |
+ tcp_sockets = new tcp_server_socket*[ AmConfig::SIP_Ifs.size() ]; |
|
122 |
+ tcp_servers = new tcp_trsp* [ AmConfig::SIP_Ifs.size() ]; |
|
123 |
+ |
|
124 |
+ if(tcp_sockets && tcp_servers) |
|
125 |
+ return 0; |
|
126 |
+ |
|
127 |
+ return -1; |
|
128 |
+} |
|
129 |
+ |
|
130 |
+int _SipCtrlInterface::init_tcp_servers(int if_num) |
|
131 |
+{ |
|
132 |
+ tcp_server_socket* tcp_socket = new tcp_server_socket(if_num); |
|
133 |
+ |
|
134 |
+ if(!AmConfig::SIP_Ifs[if_num].PublicIP.empty()) { |
|
135 |
+ tcp_socket->set_public_ip(AmConfig::SIP_Ifs[if_num].PublicIP); |
|
136 |
+ } |
|
137 |
+ |
|
138 |
+ tcp_socket->set_connect_timeout(AmConfig::SIP_Ifs[if_num].tcp_connect_timeout); |
|
139 |
+ tcp_socket->set_idle_timeout(AmConfig::SIP_Ifs[if_num].tcp_idle_timeout); |
|
140 |
+ |
|
141 |
+ if(tcp_socket->bind(AmConfig::SIP_Ifs[if_num].LocalIP, |
|
142 |
+ AmConfig::SIP_Ifs[if_num].LocalPort) < 0){ |
|
143 |
+ |
|
144 |
+ ERROR("Could not bind SIP/TCP socket to %s:%i", |
|
145 |
+ AmConfig::SIP_Ifs[if_num].LocalIP.c_str(), |
|
146 |
+ AmConfig::SIP_Ifs[if_num].LocalPort); |
|
147 |
+ |
|
148 |
+ delete tcp_socket; |
|
149 |
+ return -1; |
|
150 |
+ } |
|
151 |
+ |
|
152 |
+ //TODO: add some more threads |
|
153 |
+ tcp_socket->add_threads(AmConfig::SIPServerThreads); |
|
154 |
+ |
|
155 |
+ trans_layer::instance()->register_transport(tcp_socket); |
|
156 |
+ tcp_sockets[if_num] = tcp_socket; |
|
157 |
+ inc_ref(tcp_socket); |
|
158 |
+ nr_tcp_sockets++; |
|
159 |
+ |
|
160 |
+ tcp_servers[if_num] = new tcp_trsp(tcp_socket); |
|
161 |
+ nr_tcp_servers++; |
|
162 |
+ |
|
163 |
+ return 0; |
|
164 |
+} |
|
165 |
+ |
|
63 | 166 |
int _SipCtrlInterface::load() |
64 | 167 |
{ |
65 | 168 |
if (!AmConfig::OutboundProxy.empty()) { |
... | ... |
@@ -119,48 +222,27 @@ int _SipCtrlInterface::load() |
119 | 222 |
DBG("assuming SIP default settings.\n"); |
120 | 223 |
} |
121 | 224 |
|
122 |
- udp_sockets = new udp_trsp_socket*[AmConfig::SIP_Ifs.size()]; |
|
123 |
- udp_servers = new udp_trsp*[AmConfig::SIPServerThreads * AmConfig::SIP_Ifs.size()]; |
|
225 |
+ if(alloc_udp_structs() < 0) { |
|
226 |
+ ERROR("no enough memory to alloc UDP structs"); |
|
227 |
+ return -1; |
|
228 |
+ } |
|
124 | 229 |
|
125 |
- // Init transport instances |
|
230 |
+ // Init UDP transport instances |
|
126 | 231 |
for(unsigned int i=0; i<AmConfig::SIP_Ifs.size();i++) { |
127 |
- |
|
128 |
- udp_trsp_socket* udp_socket = |
|
129 |
- new udp_trsp_socket(i,AmConfig::SIP_Ifs[i].SigSockOpts |
|
130 |
- | (AmConfig::ForceOutboundIf ? |
|
131 |
- trsp_socket::force_outbound_if : 0) |
|
132 |
- | (AmConfig::UseRawSockets ? |
|
133 |
- trsp_socket::use_raw_sockets : 0), |
|
134 |
- AmConfig::SIP_Ifs[i].NetIfIdx); |
|
135 |
- |
|
136 |
- if(!AmConfig::SIP_Ifs[i].PublicIP.empty()) { |
|
137 |
- udp_socket->set_public_ip(AmConfig::SIP_Ifs[i].PublicIP); |
|
138 |
- } |
|
139 |
- |
|
140 |
- if(udp_socket->bind(AmConfig::SIP_Ifs[i].LocalIP, |
|
141 |
- AmConfig::SIP_Ifs[i].LocalPort) < 0){ |
|
142 |
- |
|
143 |
- ERROR("Could not bind SIP/UDP socket to %s:%i", |
|
144 |
- AmConfig::SIP_Ifs[i].LocalIP.c_str(), |
|
145 |
- AmConfig::SIP_Ifs[i].LocalPort); |
|
146 |
- |
|
147 |
- delete udp_socket; |
|
232 |
+ if(init_udp_servers(i) < 0) { |
|
148 | 233 |
return -1; |
149 | 234 |
} |
235 |
+ } |
|
150 | 236 |
|
151 |
- if(udp_rcvbuf > 0) { |
|
152 |
- udp_socket->set_recvbuf_size(udp_rcvbuf); |
|
153 |
- } |
|
154 |
- |
|
155 |
- trans_layer::instance()->register_transport(udp_socket); |
|
156 |
- udp_sockets[i] = udp_socket; |
|
157 |
- inc_ref(udp_socket); |
|
158 |
- nr_udp_sockets++; |
|
237 |
+ if(alloc_tcp_structs() < 0) { |
|
238 |
+ ERROR("no enough memory to alloc TCP structs"); |
|
239 |
+ return -1; |
|
240 |
+ } |
|
159 | 241 |
|
160 |
- for(int j=0; j<AmConfig::SIPServerThreads;j++){ |
|
161 |
- udp_servers[i*AmConfig::SIPServerThreads + j] = |
|
162 |
- new udp_trsp(udp_socket); |
|
163 |
- nr_udp_servers++; |
|
242 |
+ // Init TCP transport instances |
|
243 |
+ for(unsigned int i=0; i<AmConfig::SIP_Ifs.size();i++) { |
|
244 |
+ if(init_tcp_servers(i) < 0) { |
|
245 |
+ return -1; |
|
164 | 246 |
} |
165 | 247 |
} |
166 | 248 |
|
... | ... |
@@ -168,8 +250,11 @@ int _SipCtrlInterface::load() |
168 | 250 |
} |
169 | 251 |
|
170 | 252 |
_SipCtrlInterface::_SipCtrlInterface() |
171 |
- : stopped(false), udp_servers(NULL), udp_sockets(NULL), |
|
172 |
- nr_udp_sockets(0), nr_udp_servers(0) |
|
253 |
+ : stopped(false), |
|
254 |
+ udp_servers(NULL), udp_sockets(NULL), |
|
255 |
+ nr_udp_sockets(0), nr_udp_servers(0), |
|
256 |
+ tcp_servers(NULL), tcp_sockets(NULL), |
|
257 |
+ nr_tcp_sockets(0), nr_tcp_servers(0) |
|
173 | 258 |
{ |
174 | 259 |
trans_layer::instance()->register_ua(this); |
175 | 260 |
} |
... | ... |
@@ -300,6 +385,12 @@ int _SipCtrlInterface::run() |
300 | 385 |
} |
301 | 386 |
} |
302 | 387 |
|
388 |
+ if (NULL != tcp_servers) { |
|
389 |
+ for(int i=0; i<nr_tcp_servers;i++){ |
|
390 |
+ tcp_servers[i]->start(); |
|
391 |
+ } |
|
392 |
+ } |
|
393 |
+ |
|
303 | 394 |
while (!stopped.get()) { |
304 | 395 |
stopped.wait_for(); |
305 | 396 |
} |
... | ... |
@@ -329,11 +420,22 @@ void _SipCtrlInterface::cleanup() |
329 | 420 |
nr_udp_servers = 0; |
330 | 421 |
} |
331 | 422 |
|
423 |
+ if (NULL != tcp_servers) { |
|
424 |
+ for(int i=0; i<nr_tcp_servers;i++){ |
|
425 |
+ tcp_servers[i]->stop(); |
|
426 |
+ tcp_servers[i]->join(); |
|
427 |
+ delete tcp_servers[i]; |
|
428 |
+ } |
|
429 |
+ |
|
430 |
+ delete [] tcp_servers; |
|
431 |
+ tcp_servers = NULL; |
|
432 |
+ nr_tcp_servers = 0; |
|
433 |
+ } |
|
434 |
+ |
|
332 | 435 |
trans_layer::instance()->clear_transports(); |
333 | 436 |
|
334 | 437 |
if (NULL != udp_sockets) { |
335 | 438 |
for(int i=0; i<nr_udp_sockets;i++){ |
336 |
- //delete udp_sockets[i]; |
|
337 | 439 |
DBG("dec_ref(%p)",udp_sockets[i]); |
338 | 440 |
dec_ref(udp_sockets[i]); |
339 | 441 |
} |
... | ... |
@@ -342,6 +444,17 @@ void _SipCtrlInterface::cleanup() |
342 | 444 |
udp_sockets = NULL; |
343 | 445 |
nr_udp_sockets = 0; |
344 | 446 |
} |
447 |
+ |
|
448 |
+ if (NULL != tcp_sockets) { |
|
449 |
+ for(int i=0; i<nr_tcp_sockets;i++){ |
|
450 |
+ DBG("dec_ref(%p)",tcp_sockets[i]); |
|
451 |
+ dec_ref(tcp_sockets[i]); |
|
452 |
+ } |
|
453 |
+ |
|
454 |
+ delete [] tcp_sockets; |
|
455 |
+ tcp_sockets = NULL; |
|
456 |
+ nr_tcp_sockets = 0; |
|
457 |
+ } |
|
345 | 458 |
} |
346 | 459 |
|
347 | 460 |
int _SipCtrlInterface::send(const AmSipReply &rep, const string& dialog_id, |
... | ... |
@@ -369,8 +482,6 @@ int _SipCtrlInterface::send(const AmSipReply &rep, const string& dialog_id, |
369 | 482 |
} |
370 | 483 |
} |
371 | 484 |
|
372 |
- unsigned int hdrs_len = copy_hdrs_len(msg.hdrs); |
|
373 |
- |
|
374 | 485 |
string body; |
375 | 486 |
string content_type; |
376 | 487 |
if(!rep.body.empty()) { |
... | ... |
@@ -380,34 +491,18 @@ int _SipCtrlInterface::send(const AmSipReply &rep, const string& dialog_id, |
380 | 491 |
ERROR("Reply does not contain a Content-Type whereby body is not empty\n"); |
381 | 492 |
return -1; |
382 | 493 |
} |
383 |
- hdrs_len += content_type_len(stl2cstr(content_type)); |
|
494 |
+ msg.body = stl2cstr(body); |
|
495 |
+ msg.hdrs.push_back(new sip_header(sip_header::H_CONTENT_TYPE, |
|
496 |
+ SIP_HDR_CONTENT_TYPE, |
|
497 |
+ stl2cstr(content_type))); |
|
384 | 498 |
} |
385 | 499 |
|
386 |
- char* hdrs_buf = NULL; |
|
387 |
- char* c = hdrs_buf; |
|
500 |
+ msg.u.reply = new sip_reply(rep.code,stl2cstr(rep.reason)); |
|
388 | 501 |
|
389 |
- if (hdrs_len) { |
|
390 |
- |
|
391 |
- c = hdrs_buf = new char[hdrs_len]; |
|
392 |
- |
|
393 |
- copy_hdrs_wr(&c,msg.hdrs); |
|
394 |
- |
|
395 |
- if(!rep.body.empty()) { |
|
396 |
- content_type_wr(&c,stl2cstr(content_type)); |
|
397 |
- } |
|
398 |
- } |
|
399 |
- |
|
400 |
- int ret = |
|
401 |
- trans_layer::instance()->send_reply((trans_ticket*)&rep.tt, |
|
502 |
+ return |
|
503 |
+ trans_layer::instance()->send_reply(&msg,(trans_ticket*)&rep.tt, |
|
402 | 504 |
stl2cstr(dialog_id), |
403 |
- rep.code,stl2cstr(rep.reason), |
|
404 |
- stl2cstr(rep.to_tag), |
|
405 |
- cstring(hdrs_buf,hdrs_len), |
|
406 |
- stl2cstr(body),logger); |
|
407 |
- |
|
408 |
- delete [] hdrs_buf; |
|
409 |
- |
|
410 |
- return ret; |
|
505 |
+ stl2cstr(rep.to_tag),logger); |
|
411 | 506 |
} |
412 | 507 |
|
413 | 508 |
|
... | ... |
@@ -642,6 +737,9 @@ inline bool _SipCtrlInterface::sip_msg2am_reply(sip_msg *msg, AmSipReply &reply) |
642 | 737 |
reply.local_ip = get_addr_str(&msg->local_ip); |
643 | 738 |
reply.local_port = am_get_port(&msg->local_ip); |
644 | 739 |
|
740 |
+ if(msg->local_socket) |
|
741 |
+ reply.trsp = msg->local_socket->get_transport(); |
|
742 |
+ |
|
645 | 743 |
return true; |
646 | 744 |
} |
647 | 745 |
|
... | ... |
@@ -48,6 +48,9 @@ class trans_ticket; |
48 | 48 |
class udp_trsp_socket; |
49 | 49 |
class udp_trsp; |
50 | 50 |
|
51 |
+class tcp_server_socket; |
|
52 |
+class tcp_trsp; |
|
53 |
+ |
|
51 | 54 |
class _SipCtrlInterface: |
52 | 55 |
public sip_ua |
53 | 56 |
{ |
... | ... |
@@ -67,6 +70,18 @@ class _SipCtrlInterface: |
67 | 70 |
unsigned short nr_udp_servers; |
68 | 71 |
udp_trsp** udp_servers; |
69 | 72 |
|
73 |
+ unsigned short nr_tcp_sockets; |
|
74 |
+ tcp_server_socket** tcp_sockets; |
|
75 |
+ |
|
76 |
+ unsigned short nr_tcp_servers; |
|
77 |
+ tcp_trsp** tcp_servers; |
|
78 |
+ |
|
79 |
+ int alloc_udp_structs(); |
|
80 |
+ int init_udp_servers(int if_num); |
|
81 |
+ |
|
82 |
+ int alloc_tcp_structs(); |
|
83 |
+ int init_tcp_servers(int if_num); |
|
84 |
+ |
|
70 | 85 |
public: |
71 | 86 |
|
72 | 87 |
static string outbound_host; |
... | ... |
@@ -53,12 +53,12 @@ |
53 | 53 |
#include <grp.h> |
54 | 54 |
#include <pwd.h> |
55 | 55 |
|
56 |
-//#include <sys/wait.h> |
|
57 |
-//#include <sys/socket.h> |
|
58 | 56 |
#include <sys/types.h> |
59 | 57 |
#include <sys/stat.h> |
60 | 58 |
#include <fcntl.h> |
61 | 59 |
|
60 |
+#include <event2/thread.h> |
|
61 |
+ |
|
62 | 62 |
#ifdef PROPAGATE_COREDUMP_SETTINGS |
63 | 63 |
#include <sys/resource.h> |
64 | 64 |
#include <sys/prctl.h> |
... | ... |
@@ -572,11 +572,20 @@ int main(int argc, char* argv[]) |
572 | 572 |
INFO("Starting media processor\n"); |
573 | 573 |
AmMediaProcessor::instance()->init(); |
574 | 574 |
|
575 |
+ // init thread usage with libevent |
|
576 |
+ // before it's too late |
|
577 |
+ if(evthread_use_pthreads() != 0) { |
|
578 |
+ ERROR("cannot init thread usage with libevent"); |
|
579 |
+ goto error; |
|
580 |
+ } |
|
581 |
+ |
|
575 | 582 |
INFO("Starting RTP receiver\n"); |
576 | 583 |
AmRtpReceiver::instance()->start(); |
577 | 584 |
|
578 | 585 |
INFO("Starting SIP stack (control interface)\n"); |
579 |
- sip_ctrl.load(); |
|
586 |
+ if(sip_ctrl.load()) { |
|
587 |
+ goto error; |
|
588 |
+ } |
|
580 | 589 |
|
581 | 590 |
INFO("Loading plug-ins\n"); |
582 | 591 |
AmPlugIn::instance()->init(); |
... | ... |
@@ -59,6 +59,27 @@ int copy_hdrs_len_no_via(const list<sip_header*>& hdrs) |
59 | 59 |
return ret; |
60 | 60 |
} |
61 | 61 |
|
62 |
+int copy_hdrs_len_no_via_contact(const list<sip_header*>& hdrs) |
|
63 |
+{ |
|
64 |
+ int ret = 0; |
|
65 |
+ |
|
66 |
+ list<sip_header*>::const_iterator it = hdrs.begin(); |
|
67 |
+ for(;it != hdrs.end(); ++it){ |
|
68 |
+ |
|
69 |
+ switch((*it)->type) { |
|
70 |
+ case sip_header::H_VIA: |
|
71 |
+ case sip_header::H_CONTACT: |
|
72 |
+ continue; |
|
73 |
+ |
|
74 |
+ default: |
|
75 |
+ ret += copy_hdr_len(*it); |
|
76 |
+ break; |
|
77 |
+ } |
|
78 |
+ } |
|
79 |
+ |
|
80 |
+ return ret; |
|
81 |
+} |
|
82 |
+ |
|
62 | 83 |
void copy_hdrs_wr(char** c, const list<sip_header*>& hdrs) |
63 | 84 |
{ |
64 | 85 |
list<sip_header*>::const_iterator it = hdrs.begin(); |
... | ... |
@@ -77,3 +98,20 @@ void copy_hdrs_wr_no_via(char** c, const list<sip_header*>& hdrs) |
77 | 98 |
copy_hdr_wr(c,*it); |
78 | 99 |
} |
79 | 100 |
} |
101 |
+ |
|
102 |
+void copy_hdrs_wr_no_via_contact(char** c, const list<sip_header*>& hdrs) |
|
103 |
+{ |
|
104 |
+ list<sip_header*>::const_iterator it = hdrs.begin(); |
|
105 |
+ for(;it != hdrs.end(); ++it){ |
|
106 |
+ |
|
107 |
+ switch((*it)->type) { |
|
108 |
+ case sip_header::H_VIA: |
|
109 |
+ case sip_header::H_CONTACT: |
|
110 |
+ continue; |
|
111 |
+ |
|
112 |
+ default: |
|
113 |
+ copy_hdr_wr(c,*it); |
|
114 |
+ break; |
|
115 |
+ } |
|
116 |
+ } |
|
117 |
+} |
... | ... |
@@ -73,20 +73,30 @@ inline void contact_wr(char** c,const cstring& contact) |
73 | 73 |
*((*c)++) = LF; |
74 | 74 |
} |
75 | 75 |
|
76 |
-inline int via_len(const cstring& addr, const cstring& branch, bool rport) |
|
76 |
+inline int via_len(const cstring& trsp, const cstring& addr, |
|
77 |
+ const cstring& branch, bool rport) |
|
77 | 78 |
{ |
78 |
- return 19/*'Via: SIP/2.0/UDP ' + CRLF*/ |
|
79 |
+ return 16/* 'Via: SIP/2.0/' + SP + CRLF */ |
|
80 |
+ + trsp.len |
|
79 | 81 |
+ addr.len |
80 | 82 |
+ 8 + MAGIC_BRANCH_LEN/*';branch=' + MAGIC_BRANCH_COOKIE*/ |
81 | 83 |
+ branch.len |
82 | 84 |
+ (rport ? 6/*;rport*/ : 0 ); |
83 | 85 |
} |
84 | 86 |
|
85 |
-inline void via_wr(char** c, const cstring& addr, const cstring& branch, bool rport) |
|
87 |
+inline void via_wr(char** c, const cstring& trsp, const cstring& addr, |
|
88 |
+ const cstring& branch, bool rport) |
|
86 | 89 |
{ |
87 |
- memcpy(*c,"Via: SIP/2.0/UDP ",17); |
|
88 |
- *c += 17/*'Via: SIP/2.0/UDP '*/; |
|
90 |
+ memcpy(*c,"Via: SIP/2.0/",13); |
|
91 |
+ *c += 13/*'Via: SIP/2.0/'*/; |
|
92 |
+ |
|
93 |
+ for(unsigned int i=0; i<trsp.len; i++) { |
|
94 |
+ if(trsp.s[i] >= 'a' && trsp.s[i] <= 'z') |
|
95 |
+ *((*c)++) = trsp.s[i] - 'a' + 'A'; |
|
96 |
+ } |
|
89 | 97 |
|
98 |
+ *((*c)++) = SP; |
|
99 |
+ |
|
90 | 100 |
memcpy(*c,addr.s,addr.len); |
91 | 101 |
*c += addr.len; |
92 | 102 |
|
... | ... |
@@ -169,10 +179,11 @@ using std::list; |
169 | 179 |
|
170 | 180 |
|
171 | 181 |
int copy_hdrs_len(const list<sip_header*>& hdrs); |
172 |
-int copy_hdrs_len_no_via(const list<sip_header*>& hdrs); |
|
182 |
+int copy_hdrs_len_no_via_contact(const list<sip_header*>& hdrs); |
|
173 | 183 |
|
174 | 184 |
void copy_hdrs_wr(char** c, const list<sip_header*>& hdrs); |
175 | 185 |
void copy_hdrs_wr_no_via(char** c, const list<sip_header*>& hdrs); |
186 |
+void copy_hdrs_wr_no_via_contact(char** c, const list<sip_header*>& hdrs); |
|
176 | 187 |
|
177 | 188 |
|
178 | 189 |
#endif |
... | ... |
@@ -113,8 +113,7 @@ using std::list; |
113 | 113 |
enum { |
114 | 114 |
ST_CR=100, |
115 | 115 |
ST_LF, |
116 |
- ST_CRLF, |
|
117 |
- ST_EoL_WSP // [CR] LF WSP |
|
116 |
+ ST_CRLF |
|
118 | 117 |
}; |
119 | 118 |
|
120 | 119 |
#define case_CR_LF \ |
... | ... |
@@ -184,6 +183,11 @@ inline int lower_cmp_n(const char* l, int llen, const char* r, int rlen) |
184 | 183 |
return lower_cmp(l,r,rlen); |
185 | 184 |
} |
186 | 185 |
|
186 |
+inline int lower_cmp_n(const cstring& l, const cstring& r) |
|
187 |
+{ |
|
188 |
+ return lower_cmp_n(l.s,l.len,r.s,r.len); |
|
189 |
+} |
|
190 |
+ |
|
187 | 191 |
int parse_sip_version(const char* beg, int len); |
188 | 192 |
|
189 | 193 |
/** |
... | ... |
@@ -229,6 +229,23 @@ int parse_nameaddr(sip_nameaddr* na, const char** c, int len) |
229 | 229 |
return parse_gen_params_sc(&na->params,c, end-*c, 0); |
230 | 230 |
} |
231 | 231 |
|
232 |
+int parse_nameaddr_uri(sip_nameaddr* na, const char** c, int len) |
|
233 |
+{ |
|
234 |
+ if(parse_nameaddr(na, c, len) < 0) { |
|
235 |
+ |
|
236 |
+ DBG("Parsing name-addr failed\n"); |
|
237 |
+ return -1; |
|
238 |
+ } |
|
239 |
+ |
|
240 |
+ if(parse_uri(&na->uri,na->addr.s,na->addr.len) < 0) { |
|
241 |
+ |
|
242 |
+ DBG("Parsing uri failed\n"); |
|
243 |
+ return -1; |
|
244 |
+ } |
|
245 |
+ |
|
246 |
+ return 0; |
|
247 |
+} |
|
248 |
+ |
|
232 | 249 |
static int skip_2_next_nameaddr(const char*& c, |
233 | 250 |
const char*& na_end, |
234 | 251 |
const char* end) |
... | ... |
@@ -45,6 +45,7 @@ struct sip_nameaddr |
45 | 45 |
}; |
46 | 46 |
|
47 | 47 |
int parse_nameaddr(sip_nameaddr* na, const char** c, int len); |
48 |
+int parse_nameaddr_uri(sip_nameaddr* na, const char** c, int len); |
|
48 | 49 |
int parse_first_nameaddr(sip_nameaddr* na, const char* c, int len); |
49 | 50 |
int parse_nameaddr_list(list<cstring>& nas, const char* c, int len); |
50 | 51 |
|
... | ... |
@@ -12,7 +12,6 @@ int parse_next_hop(const cstring& next_hop, |
12 | 12 |
IPL_V6, |
13 | 13 |
IPL_HOST_SEP, |
14 | 14 |
IPL_PORT, |
15 |
- IPL_TRSP_SEP, |
|
16 | 15 |
IPL_TRSP |
17 | 16 |
}; |
18 | 17 |
|
... | ... |
@@ -54,6 +53,7 @@ int parse_next_hop(const cstring& next_hop, |
54 | 53 |
case '/': |
55 | 54 |
st = IPL_TRSP; |
56 | 55 |
dest.host.set(beg,c-beg); |
56 |
+ beg = c+1; |
|
57 | 57 |
break; |
58 | 58 |
case ',': |
59 | 59 |
st = IPL_BEG; |
... | ... |
@@ -91,7 +91,8 @@ int parse_next_hop(const cstring& next_hop, |
91 | 91 |
dest_list.push_back(dest); |
92 | 92 |
break; |
93 | 93 |
case '/': |
94 |
- st = IPL_TRSP_SEP; |
|
94 |
+ st = IPL_TRSP; |
|
95 |
+ beg = c+1; |
|
95 | 96 |
break; |
96 | 97 |
default: |
97 | 98 |
// syntax error |
... | ... |
@@ -103,7 +104,8 @@ int parse_next_hop(const cstring& next_hop, |
103 | 104 |
case IPL_PORT: |
104 | 105 |
switch(*c){ |
105 | 106 |
case '/': |
106 |
- st = IPL_TRSP_SEP; |
|
107 |
+ st = IPL_TRSP; |
|
108 |
+ beg = c+1; |
|
107 | 109 |
break; |
108 | 110 |
case ',': |
109 | 111 |
st = IPL_BEG; |
... | ... |
@@ -122,21 +124,6 @@ int parse_next_hop(const cstring& next_hop, |
122 | 124 |
} |
123 | 125 |
break; |
124 | 126 |
|
125 |
- case IPL_TRSP_SEP: |
|
126 |
- switch(*c){ |
|
127 |
- case ',': |
|
128 |
- st = IPL_BEG; |
|
129 |
- dest_list.push_back(dest); |
|
130 |
- break; |
|
131 |
- case SP: |
|
132 |
- case HTAB: |
|
133 |
- break; |
|
134 |
- default: |
|
135 |
- beg = c; |
|
136 |
- st = IPL_TRSP; |
|
137 |
- break; |
|
138 |
- } |
|
139 |
- break; |
|
140 | 127 |
|
141 | 128 |
case IPL_TRSP: |
142 | 129 |
switch(*c){ |
... | ... |
@@ -179,11 +179,6 @@ static int parse_sip_uri(sip_uri* uri, const char* beg, int len) |
179 | 179 |
// tmp1.len, tmp1.s, |
180 | 180 |
// tmp2.len, tmp2.s); |
181 | 181 |
|
182 |
- if(!lower_cmp_n(tmp1.s,tmp1.len, |
|
183 |
- "transport",9)) { |
|
184 |
- uri->trsp = uri->params.back(); |
|
185 |
- } |
|
186 |
- |
|
187 | 182 |
tmp1.s = c+1; |
188 | 183 |
st = URI_PNAME; |
189 | 184 |
break; |
... | ... |
@@ -342,6 +337,15 @@ static int parse_sip_uri(sip_uri* uri, const char* beg, int len) |
342 | 337 |
DBG("Converted URI port (%.*s) to int (%i)\n", |
343 | 338 |
uri->port_str.len,uri->port_str.s,uri->port); |
344 | 339 |
|
340 |
+ for(list<sip_avp*>::iterator it = uri->params.begin(); |
|
341 |
+ it != uri->params.end(); it++) { |
|
342 |
+ |
|
343 |
+ if(!lower_cmp_n((*it)->name.s,(*it)->name.len, |
|
344 |
+ "transport",9)) { |
|
345 |
+ uri->trsp = *it; |
|
346 |
+ } |
|
347 |
+ } |
|
348 |
+ |
|
345 | 349 |
return 0; |
346 | 350 |
} |
347 | 351 |
|
... | ... |
@@ -43,10 +43,10 @@ int raw_sender::send(const char* buf, unsigned int len, int sys_if_idx, |
43 | 43 |
return ret; |
44 | 44 |
} |
45 | 45 |
|
46 |
- if((unsigned int)ret < len) { |
|
47 |
- DBG("incomplete udp send (%i instead of %i)",ret,len); |
|
48 |
- return -1; |
|
49 |
- } |
|
46 |
+ // if((unsigned int)ret < len) { |
|
47 |
+ // ERROR("incomplete udp send (%i instead of %i)",ret,len); |
|
48 |
+ // return -1; |
|
49 |
+ // } |
|
50 | 50 |
|
51 | 51 |
return 0; |
52 | 52 |
} |
... | ... |
@@ -31,7 +31,10 @@ |
31 | 31 |
#include "hash.h" |
32 | 32 |
|
33 | 33 |
#include "parse_dns.h" |
34 |
+#include "parse_common.h" |
|
34 | 35 |
#include "ip_util.h" |
36 |
+#include "trans_layer.h" |
|
37 |
+#include "tr_blacklist.h" |
|
35 | 38 |
|
36 | 39 |
#include <sys/socket.h> |
37 | 40 |
#include <netdb.h> |
... | ... |
@@ -95,7 +98,8 @@ int dns_ip_entry::next_ip(dns_handle* h, sockaddr_storage* sa) |
95 | 98 |
} |
96 | 99 |
|
97 | 100 |
int& index = h->ip_n; |
98 |
- if(index >= (int)ip_vec.size()) return -1; |
|
101 |
+ if((index < 0) || (index >= (int)ip_vec.size())) |
|
102 |
+ return -1; |
|
99 | 103 |
|
100 | 104 |
//copy address |
101 | 105 |
((ip_entry*)ip_vec[index++])->to_sa(sa); |
... | ... |
@@ -176,8 +180,6 @@ public: |
176 | 180 |
int next_ip(dns_handle* h, sockaddr_storage* sa) |
177 | 181 |
{ |
178 | 182 |
int& index = h->srv_n; |
179 |
- if(index >= (int)ip_vec.size()) return -1; |
|
180 |
- |
|
181 | 183 |
if(h->srv_e != this){ |
182 | 184 |
if(h->srv_e) dec_ref(h->srv_e); |
183 | 185 |
h->srv_e = this; |
... | ... |
@@ -186,15 +188,17 @@ public: |
186 | 188 |
} |
187 | 189 |
else if(h->ip_n != -1){ |
188 | 190 |
if(h->port) { |
189 |
- DBG("setting port to %i",ntohs(h->port)); |
|
190 | 191 |
((sockaddr_in*)sa)->sin_port = h->port; |
191 | 192 |
} |
192 | 193 |
else { |
193 |
- DBG("setting port to 5060"); |
|
194 | 194 |
((sockaddr_in*)sa)->sin_port = htons(5060); |
195 | 195 |
} |
196 | 196 |
return h->ip_e->next_ip(h,sa); |
197 | 197 |
} |
198 |
+ |
|
199 |
+ if((index < 0) || |
|
200 |
+ (index >= (int)ip_vec.size())) |
|
201 |
+ return -1; |
|
198 | 202 |
|
199 | 203 |
// reset IP record |
200 | 204 |
if(h->ip_e){ |
... | ... |
@@ -269,24 +273,20 @@ public: |
269 | 273 |
//TODO: find a solution for IPv6 |
270 | 274 |
h->port = htons(e->port); |
271 | 275 |
if(h->port) { |
272 |
- DBG("setting port to %i",e->port); |
|
273 | 276 |
((sockaddr_in*)sa)->sin_port = h->port; |
274 | 277 |
} |
275 | 278 |
else { |
276 |
- DBG("setting port to 5060"); |
|
277 | 279 |
((sockaddr_in*)sa)->sin_port = htons(5060); |
278 | 280 |
} |
279 | 281 |
|
280 | 282 |
// check if name is an IP address |
281 | 283 |
if(am_inet_pton(e->target.c_str(),sa) == 1) { |
282 |
- DBG("target is an IP address !!! (%i)", |
|
283 |
- ntohs(((sockaddr_in*)sa)->sin_port)); |
|
284 |
+ // target is an IP address |
|
284 | 285 |
h->ip_n = -1; // flag end of IP list |
285 | 286 |
return 0; |
286 | 287 |
} |
287 | 288 |
|
288 |
- DBG("target must be resolved first !!! (%i)", |
|
289 |
- ntohs(((sockaddr_in*)sa)->sin_port)); |
|
289 |
+ // target must be resolved first |
|
290 | 290 |
return resolver::instance()->resolve_name(e->target.c_str(),h,sa,IPv4); |
291 | 291 |
} |
292 | 292 |
}; |
... | ... |
@@ -417,7 +417,6 @@ static void dns_error(int error, const char* domain) |
417 | 417 |
|
418 | 418 |
void ip_entry::to_sa(sockaddr_storage* sa) |
419 | 419 |
{ |
420 |
- DBG("copying ip_entry..."); |
|
421 | 420 |
switch(type){ |
422 | 421 |
case IPv4: |
423 | 422 |
{ |
... | ... |
@@ -438,7 +437,6 @@ void ip_entry::to_sa(sockaddr_storage* sa) |
438 | 437 |
|
439 | 438 |
void ip_port_entry::to_sa(sockaddr_storage* sa) |
440 | 439 |
{ |
441 |
- DBG("copying ip_port_entry..."); |
|
442 | 440 |
switch(type){ |
443 | 441 |
case IPv4: |
444 | 442 |
{ |
... | ... |
@@ -596,6 +594,84 @@ const dns_handle& dns_handle::operator = (const dns_handle& rh) |
596 | 594 |
return *this; |
597 | 595 |
} |
598 | 596 |
|
597 |
+sip_target::sip_target() {} |
|
598 |
+ |
|
599 |
+sip_target::sip_target(const sip_target& target) |
|
600 |
+{ |
|
601 |
+ *this = target; |
|
602 |
+} |
|
603 |
+ |
|
604 |
+const sip_target& sip_target::operator = (const sip_target& target) |
|
605 |
+{ |
|
606 |
+ memcpy(&ss,&target.ss,sizeof(sockaddr_storage)); |
|
607 |
+ memcpy(trsp,target.trsp,SIP_TRSP_SIZE_MAX+1); |
|
608 |
+ return target; |
|
609 |
+} |
|
610 |
+ |
|
611 |
+void sip_target::clear() |
|
612 |
+{ |
|
613 |
+ memset(&ss,0,sizeof(sockaddr_storage)); |
|
614 |
+ memset(trsp,'\0',SIP_TRSP_SIZE_MAX+1); |
|
615 |
+} |
|
616 |
+ |
|
617 |
+sip_target_set::sip_target_set() |
|
618 |
+ : dest_list(), |
|
619 |
+ dest_list_it(dest_list.begin()) |
|
620 |
+{} |
|
621 |
+ |
|
622 |
+void sip_target_set::reset_iterator() |
|
623 |
+{ |
|
624 |
+ dest_list_it = dest_list.begin(); |
|
625 |
+} |
|
626 |
+ |
|
627 |
+bool sip_target_set::has_next() |
|
628 |
+{ |
|
629 |
+ return dest_list_it != dest_list.end(); |
|
630 |
+} |
|
631 |
+ |
|
632 |
+int sip_target_set::get_next(sockaddr_storage* ss, cstring& next_trsp, |
|
633 |
+ unsigned int flags) |
|
634 |
+{ |
|
635 |
+ do { |
|
636 |
+ if(!has_next()) |
|
637 |
+ return -1; |
|
638 |
+ |
|
639 |
+ sip_target& t = *dest_list_it; |
|
640 |
+ memcpy(ss,&t.ss,sizeof(sockaddr_storage)); |
|
641 |
+ next_trsp = cstring(t.trsp); |
|
642 |
+ |
|
643 |
+ next(); |
|
644 |
+ |
|
645 |
+ // set default transport to UDP |
|
646 |
+ if(!next_trsp.len) |
|
647 |
+ next_trsp = cstring("udp"); |
|
648 |
+ |
|
649 |
+ } while(!(flags & TR_FLAG_DISABLE_BL) && |
|
650 |
+ tr_blacklist::instance()->exist(ss)); |
|
651 |
+ |
|
652 |
+ return 0; |
|
653 |
+} |
|
654 |
+ |
|
655 |
+bool sip_target_set::next() |
|
656 |
+{ |
|
657 |
+ dest_list_it++; |
|
658 |
+ return has_next(); |
|
659 |
+} |
|
660 |
+ |
|
661 |
+void sip_target_set::debug() |
|
662 |
+{ |
|
663 |
+ DBG("target list:"); |
|
664 |
+ |
|
665 |
+ for(list<sip_target>::iterator it = dest_list.begin(); |
|
666 |
+ it != dest_list.end(); it++) { |
|
667 |
+ |
|
668 |
+ DBG("\t%s:%u/%s to target list", |
|
669 |
+ am_inet_ntop(&it->ss).c_str(), |
|
670 |
+ am_get_port(&it->ss),it->trsp); |
|
671 |
+ } |
|
672 |
+} |
|
673 |
+ |
|
674 |
+bool _resolver::disable_srv = false; |
|
599 | 675 |
|
600 | 676 |
_resolver::_resolver() |
601 | 677 |
: cache(DNS_CACHE_SIZE) |
... | ... |
@@ -719,7 +795,8 @@ int _resolver::str2ip(const char* name, |
719 | 795 |
return 1; |
720 | 796 |
} |
721 | 797 |
else if(ret < 0) { |
722 |
- ERROR("while trying to detect an IPv4 address '%s': %s",name,strerror(errno)); |
|
798 |
+ ERROR("while trying to detect an IPv4 address '%s': %s", |
|
799 |
+ name,strerror(errno)); |
|
723 | 800 |
return ret; |
724 | 801 |
} |
725 | 802 |
} |
... | ... |
@@ -731,7 +808,8 @@ int _resolver::str2ip(const char* name, |
731 | 808 |
return 1; |
732 | 809 |
} |
733 | 810 |
else if(ret < 0) { |
734 |
- ERROR("while trying to detect an IPv6 address '%s': %s",name,strerror(errno)); |
|
811 |
+ ERROR("while trying to detect an IPv6 address '%s': %s", |
|
812 |
+ name,strerror(errno)); |
|
735 | 813 |
return ret; |
736 | 814 |
} |
737 | 815 |
} |
... | ... |
@@ -739,6 +817,113 @@ int _resolver::str2ip(const char* name, |
739 | 817 |
return 0; |
740 | 818 |
} |
741 | 819 |
|
820 |
+int _resolver::set_destination_ip(const cstring& next_hop, |
|
821 |
+ unsigned short next_port, |
|
822 |
+ const cstring& next_trsp, |
|
823 |
+ sockaddr_storage* remote_ip, |
|
824 |
+ dns_handle* h_dns) |
|
825 |
+{ |
|
826 |
+ |
|
827 |
+ string nh = c2stlstr(next_hop); |
|
828 |
+ |
|
829 |
+ DBG("checking whether '%s' is IP address...\n", nh.c_str()); |
|
830 |
+ if (am_inet_pton(nh.c_str(), remote_ip) != 1) { |
|
831 |
+ |
|
832 |
+ // nh does NOT contain a valid IP address |
|
833 |
+ |
|
834 |
+ if(!next_port) { |
|
835 |
+ // no explicit port specified, |
|
836 |
+ // try SRV first |
|
837 |
+ if (disable_srv) { |
|
838 |
+ DBG("no port specified, but DNS SRV disabled (skipping).\n"); |
|
839 |
+ } else { |
|
840 |
+ string srv_name = "_sip._"; |
|
841 |
+ if(!next_trsp.len || !lower_cmp_n(next_trsp,"udp")){ |
|
842 |
+ srv_name += "udp"; |
|
843 |
+ } |
|
844 |
+ else if(!lower_cmp_n(next_trsp,"tcp")) { |
|
845 |
+ srv_name += "tcp"; |
|
846 |
+ } |
|
847 |
+ else { |
|
848 |
+ DBG("unsupported transport: skip SRV lookup"); |
|
849 |
+ goto no_SRV; |
|
850 |
+ } |
|
851 |
+ |
|
852 |
+ srv_name += "." + nh; |
|
853 |
+ |
|
854 |
+ DBG("no port specified, looking up SRV '%s'...\n", |
|
855 |
+ srv_name.c_str()); |
|
856 |
+ |
|
857 |
+ if(!resolver::instance()->resolve_name(srv_name.c_str(), |
|
858 |
+ h_dns,remote_ip, |
|
859 |
+ IPv4)){ |
|
860 |
+ return 0; |
|
861 |
+ } |
|
862 |
+ |
|
863 |
+ DBG("no SRV record for %s",srv_name.c_str()); |
|
864 |
+ } |
|
865 |
+ } |
|
866 |
+ |
|
867 |
+ no_SRV: |
|
868 |
+ memset(remote_ip,0,sizeof(sockaddr_storage)); |
|
869 |
+ int err = resolver::instance()->resolve_name(nh.c_str(), |
|
870 |
+ h_dns,remote_ip, |
|
871 |
+ IPv4); |
|
872 |
+ if(err < 0){ |
|
873 |
+ ERROR("Unresolvable Request URI domain\n"); |
|
874 |
+ return -478; |
|
875 |
+ } |
|
876 |
+ } |
|
877 |
+ else { |
|
878 |
+ am_set_port(remote_ip,next_port); |
|
879 |
+ } |
|
880 |
+ |
|
881 |
+ if(!am_get_port(remote_ip)) { |
|
882 |
+ if(!next_port) next_port = 5060; |
|
883 |
+ am_set_port(remote_ip,next_port); |
|
884 |
+ } |
|
885 |
+ |
|
886 |
+ DBG("set destination to %s:%u\n", |
|
887 |
+ nh.c_str(), am_get_port(remote_ip)); |
|
888 |
+ |
|
889 |
+ return 0; |
|
890 |
+} |
|
891 |
+ |
|
892 |
+int _resolver::resolve_targets(const list<sip_destination>& dest_list, |
|
893 |
+ sip_target_set* targets) |
|
894 |
+{ |
|
895 |
+ for(list<sip_destination>::const_iterator it = dest_list.begin(); |
|
896 |
+ it != dest_list.end(); it++) { |
|
897 |
+ |
|
898 |
+ sip_target t; |
|
899 |
+ dns_handle h_dns; |
|