7 # include <sys/socket.h>
8 # include <netinet/in.h>
9 # include <netinet/tcp.h>
20 #include <event2/buffer.h>
21 #include <event2/bufferevent.h>
22 #include <event2/event.h>
23 #include <event2/listener.h>
24 #include <event2/util.h>
26 #include "dnscrypt_client.h"
27 #include "dnscrypt_proxy.h"
30 #include "tcp_request.h"
31 #include "tcp_request_p.h"
32 #include "udp_request.h"
34 # include "plugin_support.h"
38 tcp_request_free(TCPRequest
* const tcp_request
)
40 ProxyContext
*proxy_context
;
42 if (tcp_request
->timeout_timer
!= NULL
) {
43 event_free(tcp_request
->timeout_timer
);
44 tcp_request
->timeout_timer
= NULL
;
46 if (tcp_request
->client_proxy_bev
!= NULL
) {
47 DNSCRYPT_PROXY_REQUEST_TCP_DONE(tcp_request
);
48 bufferevent_free(tcp_request
->client_proxy_bev
);
49 tcp_request
->client_proxy_bev
= NULL
;
51 if (tcp_request
->proxy_resolver_bev
!= NULL
) {
52 DNSCRYPT_PROXY_REQUEST_TCP_PROXY_RESOLVER_DONE(tcp_request
);
53 bufferevent_free(tcp_request
->proxy_resolver_bev
);
54 tcp_request
->proxy_resolver_bev
= NULL
;
56 if (tcp_request
->proxy_resolver_query_evbuf
!= NULL
) {
57 evbuffer_free(tcp_request
->proxy_resolver_query_evbuf
);
58 tcp_request
->proxy_resolver_query_evbuf
= NULL
;
60 proxy_context
= tcp_request
->proxy_context
;
61 if (tcp_request
->status
.is_in_queue
!= 0) {
62 assert(! TAILQ_EMPTY(&proxy_context
->tcp_request_queue
));
63 TAILQ_REMOVE(&proxy_context
->tcp_request_queue
, tcp_request
, queue
);
64 assert(proxy_context
->connections_count
> 0U);
65 proxy_context
->connections_count
--;
66 DNSCRYPT_PROXY_STATUS_REQUESTS_ACTIVE(proxy_context
->connections_count
,
67 proxy_context
->connections_count_max
);
69 tcp_request
->proxy_context
= NULL
;
74 tcp_request_kill(TCPRequest
* const tcp_request
)
76 if (tcp_request
== NULL
|| tcp_request
->status
.is_dying
) {
79 tcp_request
->status
.is_dying
= 1;
80 tcp_request_free(tcp_request
);
84 tcp_tune(evutil_socket_t handle
)
89 setsockopt(handle
, IPPROTO_TCP
, TCP_NODELAY
,
90 (void *) (int []) { 1 }, sizeof (int));
94 timeout_timer_cb(evutil_socket_t timeout_timer_handle
, short ev_flags
,
95 void * const tcp_request_
)
97 TCPRequest
* const tcp_request
= tcp_request_
;
100 (void) timeout_timer_handle
;
101 DNSCRYPT_PROXY_REQUEST_TCP_TIMEOUT(tcp_request
);
102 logger_noformat(tcp_request
->proxy_context
, LOG_DEBUG
,
103 "resolver timeout (TCP)");
104 tcp_request_kill(tcp_request
);
108 proxy_resolver_event_cb(struct bufferevent
* const proxy_resolver_bev
,
109 const short events
, void * const tcp_request_
)
111 TCPRequest
* const tcp_request
= tcp_request_
;
113 (void) proxy_resolver_bev
;
114 if ((events
& BEV_EVENT_ERROR
) != 0) {
115 DNSCRYPT_PROXY_REQUEST_TCP_PROXY_RESOLVER_NETWORK_ERROR(tcp_request
);
116 tcp_request_kill(tcp_request
);
119 if ((events
& BEV_EVENT_CONNECTED
) == 0) {
120 DNSCRYPT_PROXY_REQUEST_TCP_PROXY_RESOLVER_CONNECTED(tcp_request
);
121 tcp_tune(bufferevent_getfd(proxy_resolver_bev
));
127 resolver_proxy_read_cb(struct bufferevent
* const proxy_resolver_bev
,
128 void * const tcp_request_
)
130 uint8_t dns_reply_len_buf
[2];
131 uint8_t dns_uncurved_reply_len_buf
[2];
133 TCPRequest
*tcp_request
= tcp_request_
;
134 ProxyContext
*proxy_context
= tcp_request
->proxy_context
;
135 struct evbuffer
*input
= bufferevent_get_input(proxy_resolver_bev
);
136 size_t available_size
;
137 size_t dns_reply_len
;
140 if (tcp_request
->status
.has_dns_reply_len
== 0) {
141 assert(evbuffer_get_length(input
) >= (size_t) 2U);
142 evbuffer_remove(input
, dns_reply_len_buf
, sizeof dns_reply_len_buf
);
143 tcp_request
->dns_reply_len
= (size_t)
144 ((dns_reply_len_buf
[0] << 8) | dns_reply_len_buf
[1]);
145 tcp_request
->status
.has_dns_reply_len
= 1;
147 assert(tcp_request
->status
.has_dns_reply_len
!= 0);
148 dns_reply_len
= tcp_request
->dns_reply_len
;
150 (size_t) DNS_HEADER_SIZE
+ dnscrypt_response_header_size()) {
151 logger_noformat(proxy_context
, LOG_WARNING
, "Short reply received");
152 DNSCRYPT_PROXY_REQUEST_TCP_PROXY_RESOLVER_GOT_INVALID_REPLY(tcp_request
);
153 tcp_request_kill(tcp_request
);
156 available_size
= evbuffer_get_length(input
);
157 if (available_size
< dns_reply_len
) {
158 bufferevent_setwatermark(tcp_request
->proxy_resolver_bev
,
159 EV_READ
, dns_reply_len
, dns_reply_len
);
162 DNSCRYPT_PROXY_REQUEST_TCP_PROXY_RESOLVER_REPLIED(tcp_request
);
163 assert(available_size
>= dns_reply_len
);
164 dns_reply
= evbuffer_pullup(input
, (ssize_t
) dns_reply_len
);
165 if (dns_reply
== NULL
) {
166 tcp_request_kill(tcp_request
);
169 uncurved_len
= dns_reply_len
;
170 DNSCRYPT_PROXY_REQUEST_UNCURVE_START(tcp_request
, uncurved_len
);
171 if (dnscrypt_client_uncurve(&proxy_context
->dnscrypt_client
,
172 tcp_request
->client_nonce
,
173 dns_reply
, &uncurved_len
) != 0) {
174 DNSCRYPT_PROXY_REQUEST_UNCURVE_ERROR(tcp_request
);
175 DNSCRYPT_PROXY_REQUEST_TCP_PROXY_RESOLVER_GOT_INVALID_REPLY(tcp_request
);
176 logger_noformat(tcp_request
->proxy_context
, LOG_WARNING
,
177 "Received a suspicious reply from the resolver");
178 tcp_request_kill(tcp_request
);
181 DNSCRYPT_PROXY_REQUEST_UNCURVE_DONE(tcp_request
, uncurved_len
);
182 memset(tcp_request
->client_nonce
, 0, sizeof tcp_request
->client_nonce
);
183 assert(uncurved_len
<= dns_reply_len
);
184 dns_reply_len
= uncurved_len
;
186 const size_t max_reply_size_for_filter
= tcp_request
->dns_reply_len
;
187 DCPluginDNSPacket dcp_packet
= {
188 .client_sockaddr
= &tcp_request
->client_sockaddr
,
189 .dns_packet
= dns_reply
,
190 .dns_packet_len_p
= &dns_reply_len
,
191 .client_sockaddr_len_s
= (size_t) tcp_request
->client_sockaddr_len
,
192 .dns_packet_max_len
= max_reply_size_for_filter
194 DNSCRYPT_PROXY_REQUEST_PLUGINS_POST_START(tcp_request
, dns_reply_len
,
195 max_reply_size_for_filter
);
196 assert(proxy_context
->app_context
->dcps_context
!= NULL
);
197 const DCPluginSyncFilterResult res
=
198 plugin_support_context_apply_sync_post_filters
199 (proxy_context
->app_context
->dcps_context
, &dcp_packet
);
200 assert(dns_reply_len
> (size_t) 0U &&
201 dns_reply_len
<= tcp_request
->dns_reply_len
&&
202 dns_reply_len
<= max_reply_size_for_filter
);
203 if (res
!= DCP_SYNC_FILTER_RESULT_OK
) {
204 DNSCRYPT_PROXY_REQUEST_PLUGINS_POST_ERROR(tcp_request
, res
);
205 tcp_request_kill(tcp_request
);
208 DNSCRYPT_PROXY_REQUEST_PLUGINS_POST_DONE(tcp_request
, dns_reply_len
,
209 max_reply_size_for_filter
);
211 dns_uncurved_reply_len_buf
[0] = (dns_reply_len
>> 8) & 0xff;
212 dns_uncurved_reply_len_buf
[1] = dns_reply_len
& 0xff;
213 if (bufferevent_write(tcp_request
->client_proxy_bev
,
214 dns_uncurved_reply_len_buf
, (size_t) 2U) != 0 ||
215 bufferevent_write(tcp_request
->client_proxy_bev
, dns_reply
,
216 dns_reply_len
) != 0) {
217 tcp_request_kill(tcp_request
);
220 bufferevent_enable(tcp_request
->client_proxy_bev
, EV_WRITE
);
221 DNSCRYPT_PROXY_REQUEST_TCP_PROXY_RESOLVER_DONE(tcp_request
);
222 bufferevent_free(tcp_request
->proxy_resolver_bev
);
223 tcp_request
->proxy_resolver_bev
= NULL
;
227 client_proxy_event_cb(struct bufferevent
* const client_proxy_bev
,
228 const short events
, void * const tcp_request_
)
230 TCPRequest
* const tcp_request
= tcp_request_
;
232 (void) client_proxy_bev
;
234 tcp_request_kill(tcp_request
);
238 client_proxy_write_cb(struct bufferevent
* const client_proxy_bev
,
239 void * const tcp_request_
)
241 TCPRequest
* const tcp_request
= tcp_request_
;
243 (void) client_proxy_bev
;
244 DNSCRYPT_PROXY_REQUEST_TCP_REPLIED(tcp_request
);
245 tcp_request_kill(tcp_request
);
250 proxy_to_client_direct(TCPRequest
* const tcp_request
,
251 const uint8_t * const dns_reply
,
252 const size_t dns_reply_len
)
254 uint8_t dns_reply_len_buf
[2];
256 DNSCRYPT_PROXY_REQUEST_TCP_PROXY_RESOLVER_DONE(tcp_request
);
257 bufferevent_free(tcp_request
->proxy_resolver_bev
);
258 tcp_request
->proxy_resolver_bev
= NULL
;
260 dns_reply_len_buf
[0] = (dns_reply_len
>> 8) & 0xff;
261 dns_reply_len_buf
[1] = dns_reply_len
& 0xff;
262 if (bufferevent_write(tcp_request
->client_proxy_bev
,
263 dns_reply_len_buf
, (size_t) 2U) != 0 ||
264 bufferevent_write(tcp_request
->client_proxy_bev
, dns_reply
,
265 dns_reply_len
) != 0) {
266 tcp_request_kill(tcp_request
);
269 bufferevent_enable(tcp_request
->client_proxy_bev
, EV_WRITE
);
270 assert(tcp_request
->proxy_resolver_bev
== NULL
);
275 client_proxy_read_cb(struct bufferevent
* const client_proxy_bev
,
276 void * const tcp_request_
)
278 uint8_t dns_query
[DNS_MAX_PACKET_SIZE_TCP
- 2U];
279 uint8_t dns_query_len_buf
[2];
280 uint8_t dns_curved_query_len_buf
[2];
281 TCPRequest
*tcp_request
= tcp_request_
;
282 ProxyContext
*proxy_context
= tcp_request
->proxy_context
;
283 struct evbuffer
*input
= bufferevent_get_input(client_proxy_bev
);
285 size_t available_size
;
286 size_t dns_query_len
;
287 size_t max_query_size
;
289 if (tcp_request
->status
.has_dns_query_len
== 0) {
290 assert(evbuffer_get_length(input
) >= (size_t) 2U);
291 evbuffer_remove(input
, dns_query_len_buf
, sizeof dns_query_len_buf
);
292 tcp_request
->dns_query_len
= (size_t)
293 ((dns_query_len_buf
[0] << 8) | dns_query_len_buf
[1]);
294 tcp_request
->status
.has_dns_query_len
= 1;
296 assert(tcp_request
->status
.has_dns_query_len
!= 0);
297 dns_query_len
= tcp_request
->dns_query_len
;
298 if (dns_query_len
< (size_t) DNS_HEADER_SIZE
) {
299 logger_noformat(proxy_context
, LOG_WARNING
, "Short query received");
300 tcp_request_kill(tcp_request
);
303 available_size
= evbuffer_get_length(input
);
304 if (available_size
< dns_query_len
) {
305 bufferevent_setwatermark(tcp_request
->client_proxy_bev
,
306 EV_READ
, dns_query_len
, dns_query_len
);
309 assert(available_size
>= dns_query_len
);
310 bufferevent_disable(tcp_request
->client_proxy_bev
, EV_READ
);
311 assert(tcp_request
->proxy_resolver_query_evbuf
== NULL
);
312 if ((tcp_request
->proxy_resolver_query_evbuf
= evbuffer_new()) == NULL
) {
313 tcp_request_kill(tcp_request
);
317 evbuffer_remove_buffer(input
, tcp_request
->proxy_resolver_query_evbuf
,
318 dns_query_len
) != (ssize_t
) dns_query_len
) {
319 tcp_request_kill(tcp_request
);
322 assert(dns_query_len
<= sizeof dns_query
);
323 if ((ssize_t
) evbuffer_remove(tcp_request
->proxy_resolver_query_evbuf
,
324 dns_query
, dns_query_len
)
325 != (ssize_t
) dns_query_len
) {
326 tcp_request_kill(tcp_request
);
329 max_query_size
= sizeof dns_query
;
330 assert(max_query_size
< DNS_MAX_PACKET_SIZE_TCP
);
332 size_t max_query_size_for_filter
= dns_query_len
;
333 if (max_query_size
> DNSCRYPT_MAX_PADDING
+ dnscrypt_query_header_size()) {
334 max_query_size_for_filter
= max_query_size
-
335 (DNSCRYPT_MAX_PADDING
+ dnscrypt_query_header_size());
337 DCPluginDNSPacket dcp_packet
= {
338 .client_sockaddr
= &tcp_request
->client_sockaddr
,
339 .dns_packet
= dns_query
,
340 .dns_packet_len_p
= &dns_query_len
,
341 .client_sockaddr_len_s
= (size_t) tcp_request
->client_sockaddr_len
,
342 .dns_packet_max_len
= max_query_size_for_filter
344 DNSCRYPT_PROXY_REQUEST_PLUGINS_PRE_START(tcp_request
, dns_query_len
,
345 max_query_size_for_filter
);
346 assert(proxy_context
->app_context
->dcps_context
!= NULL
);
347 const DCPluginSyncFilterResult res
=
348 plugin_support_context_apply_sync_pre_filters
349 (proxy_context
->app_context
->dcps_context
, &dcp_packet
);
350 assert(dns_query_len
> (size_t) 0U && dns_query_len
<= max_query_size
&&
351 dns_query_len
<= max_query_size_for_filter
);
353 case DCP_SYNC_FILTER_RESULT_OK
:
355 case DCP_SYNC_FILTER_RESULT_DIRECT
:
356 DNSCRYPT_PROXY_REQUEST_PLUGINS_PRE_DONE(tcp_request
, dns_query_len
,
357 max_query_size_for_filter
);
358 proxy_to_client_direct(tcp_request
, dns_query
, dns_query_len
);
361 DNSCRYPT_PROXY_REQUEST_PLUGINS_PRE_ERROR(tcp_request
, res
);
362 tcp_request_kill(tcp_request
);
365 DNSCRYPT_PROXY_REQUEST_PLUGINS_PRE_DONE(tcp_request
, dns_query_len
,
366 max_query_size_for_filter
);
368 assert(SIZE_MAX
- DNSCRYPT_MAX_PADDING
- dnscrypt_query_header_size()
370 size_t max_len
= dns_query_len
+ DNSCRYPT_MAX_PADDING
+
371 dnscrypt_query_header_size();
372 if (max_len
> max_query_size
) {
373 max_len
= max_query_size
;
375 if (dns_query_len
+ dnscrypt_query_header_size() > max_len
) {
376 tcp_request_kill(tcp_request
);
379 assert(max_len
<= DNS_MAX_PACKET_SIZE_TCP
- 2U);
380 assert(max_len
<= sizeof dns_query
);
381 assert(dns_query_len
<= max_len
);
382 DNSCRYPT_PROXY_REQUEST_CURVE_START(tcp_request
, dns_query_len
);
384 dnscrypt_client_curve(&proxy_context
->dnscrypt_client
,
385 tcp_request
->client_nonce
,
386 dns_query
, dns_query_len
, max_len
);
387 if (curve_ret
<= (ssize_t
) 0) {
388 DNSCRYPT_PROXY_REQUEST_CURVE_ERROR(tcp_request
);
389 tcp_request_kill(tcp_request
);
392 DNSCRYPT_PROXY_REQUEST_CURVE_DONE(tcp_request
, (size_t) curve_ret
);
393 dns_curved_query_len_buf
[0] = (curve_ret
>> 8) & 0xff;
394 dns_curved_query_len_buf
[1] = curve_ret
& 0xff;
395 if (bufferevent_write(tcp_request
->proxy_resolver_bev
,
396 dns_curved_query_len_buf
, (size_t) 2U) != 0 ||
397 bufferevent_write(tcp_request
->proxy_resolver_bev
, dns_query
,
398 (size_t) curve_ret
) != 0) {
399 tcp_request_kill(tcp_request
);
402 bufferevent_enable(tcp_request
->proxy_resolver_bev
, EV_READ
);
406 tcp_connection_cb(struct evconnlistener
* const tcp_conn_listener
,
407 evutil_socket_t handle
,
408 struct sockaddr
* const client_sockaddr
,
409 const int client_sockaddr_len_int
,
410 void * const proxy_context_
)
412 ProxyContext
*proxy_context
= proxy_context_
;
413 TCPRequest
*tcp_request
;
415 (void) tcp_conn_listener
;
416 (void) client_sockaddr
;
417 (void) client_sockaddr_len_int
;
418 if ((tcp_request
= calloc((size_t) 1U, sizeof *tcp_request
)) == NULL
) {
421 tcp_request
->proxy_context
= proxy_context
;
422 tcp_request
->timeout_timer
= NULL
;
423 tcp_request
->proxy_resolver_query_evbuf
= NULL
;
425 assert(client_sockaddr_len_int
>= 0 &&
426 sizeof tcp_request
->client_sockaddr
>=
427 (size_t) client_sockaddr_len_int
);
428 memcpy(&tcp_request
->client_sockaddr
, client_sockaddr
,
429 (size_t) client_sockaddr_len_int
);
430 tcp_request
->client_sockaddr_len
= (ev_socklen_t
) client_sockaddr_len_int
;
432 tcp_request
->client_proxy_bev
=
433 bufferevent_socket_new(proxy_context
->event_loop
, handle
,
434 BEV_OPT_CLOSE_ON_FREE
);
435 if (tcp_request
->client_proxy_bev
== NULL
) {
436 evutil_closesocket(handle
);
440 tcp_request
->proxy_resolver_bev
= bufferevent_socket_new
441 (proxy_context
->event_loop
, -1, BEV_OPT_CLOSE_ON_FREE
);
442 if (tcp_request
->proxy_resolver_bev
== NULL
) {
443 bufferevent_free(tcp_request
->client_proxy_bev
);
444 tcp_request
->client_proxy_bev
= NULL
;
448 if (proxy_context
->connections_count
>=
449 proxy_context
->connections_count_max
) {
450 DNSCRYPT_PROXY_REQUEST_TCP_OVERLOADED();
451 if (tcp_listener_kill_oldest_request(proxy_context
) != 0) {
452 udp_listener_kill_oldest_request(proxy_context
);
455 proxy_context
->connections_count
++;
456 assert(proxy_context
->connections_count
457 <= proxy_context
->connections_count_max
);
458 DNSCRYPT_PROXY_STATUS_REQUESTS_ACTIVE(proxy_context
->connections_count
,
459 proxy_context
->connections_count_max
);
460 DNSCRYPT_PROXY_REQUEST_TCP_START(tcp_request
);
461 TAILQ_INSERT_TAIL(&proxy_context
->tcp_request_queue
,
463 memset(&tcp_request
->status
, 0, sizeof tcp_request
->status
);
464 tcp_request
->status
.is_in_queue
= 1;
465 if ((tcp_request
->timeout_timer
=
466 evtimer_new(tcp_request
->proxy_context
->event_loop
,
467 timeout_timer_cb
, tcp_request
)) == NULL
) {
468 tcp_request_kill(tcp_request
);
471 const struct timeval tv
= {
472 .tv_sec
= (time_t) DNS_QUERY_TIMEOUT
, .tv_usec
= 0
474 evtimer_add(tcp_request
->timeout_timer
, &tv
);
475 bufferevent_setwatermark(tcp_request
->client_proxy_bev
,
476 EV_READ
, (size_t) 2U,
477 (size_t) DNS_MAX_PACKET_SIZE_TCP
);
478 bufferevent_setcb(tcp_request
->client_proxy_bev
,
479 client_proxy_read_cb
, client_proxy_write_cb
,
480 client_proxy_event_cb
, tcp_request
);
481 if (bufferevent_socket_connect
482 (tcp_request
->proxy_resolver_bev
,
483 (struct sockaddr
*) &proxy_context
->resolver_sockaddr
,
484 (int) proxy_context
->resolver_sockaddr_len
) != 0) {
485 tcp_request_kill(tcp_request
);
488 bufferevent_setwatermark(tcp_request
->proxy_resolver_bev
,
489 EV_READ
, (size_t) 2U,
490 (size_t) DNS_MAX_PACKET_SIZE_TCP
);
491 bufferevent_setcb(tcp_request
->proxy_resolver_bev
,
492 resolver_proxy_read_cb
, NULL
, proxy_resolver_event_cb
,
494 DNSCRYPT_PROXY_REQUEST_TCP_PROXY_RESOLVER_START(tcp_request
);
495 bufferevent_enable(tcp_request
->client_proxy_bev
, EV_READ
);
499 tcp_accept_timer_cb(evutil_socket_t handle
, const short event
,
500 void * const proxy_context_
)
502 ProxyContext
*proxy_context
= proxy_context_
;
506 event_free(proxy_context
->tcp_accept_timer
);
507 proxy_context
->tcp_accept_timer
= NULL
;
508 evconnlistener_enable(proxy_context
->tcp_conn_listener
);
512 tcp_accept_error_cb(struct evconnlistener
* const tcp_conn_listener
,
513 void * const proxy_context_
)
515 ProxyContext
*proxy_context
= proxy_context_
;
517 (void) tcp_conn_listener
;
518 DNSCRYPT_PROXY_REQUEST_TCP_NETWORK_ERROR(NULL
);
519 if (proxy_context
->tcp_accept_timer
== NULL
) {
520 proxy_context
->tcp_accept_timer
= evtimer_new
521 (proxy_context
->event_loop
, tcp_accept_timer_cb
, proxy_context
);
522 if (proxy_context
->tcp_accept_timer
== NULL
) {
526 if (evtimer_pending(proxy_context
->tcp_accept_timer
, NULL
)) {
529 evconnlistener_disable(proxy_context
->tcp_conn_listener
);
531 const struct timeval tv
= { .tv_sec
= (time_t) 1, .tv_usec
= 0 };
532 evtimer_add(proxy_context
->tcp_accept_timer
, &tv
);
536 tcp_listener_kill_oldest_request(ProxyContext
* const proxy_context
)
538 if (TAILQ_EMPTY(&proxy_context
->tcp_request_queue
)) {
541 tcp_request_kill(TAILQ_FIRST(&proxy_context
->tcp_request_queue
));
547 tcp_listener_bind(ProxyContext
* const proxy_context
)
549 assert(proxy_context
->tcp_conn_listener
== NULL
);
550 #ifndef LEV_OPT_DEFERRED_ACCEPT
551 # define LEV_OPT_DEFERRED_ACCEPT 0
553 proxy_context
->tcp_conn_listener
=
554 evconnlistener_new_bind(proxy_context
->event_loop
,
555 tcp_connection_cb
, proxy_context
,
556 LEV_OPT_CLOSE_ON_FREE
|
557 LEV_OPT_CLOSE_ON_EXEC
|
559 LEV_OPT_DEFERRED_ACCEPT
,
562 &proxy_context
->local_sockaddr
,
563 (int) proxy_context
->local_sockaddr_len
);
564 if (proxy_context
->tcp_conn_listener
== NULL
) {
565 logger(NULL
, LOG_ERR
, "Unable to bind (TCP)");
568 if (evconnlistener_disable(proxy_context
->tcp_conn_listener
) != 0) {
569 evconnlistener_free(proxy_context
->tcp_conn_listener
);
570 proxy_context
->tcp_conn_listener
= NULL
;
573 evconnlistener_set_error_cb(proxy_context
->tcp_conn_listener
,
574 tcp_accept_error_cb
);
575 TAILQ_INIT(&proxy_context
->tcp_request_queue
);
581 tcp_listener_start(ProxyContext
* const proxy_context
)
583 assert(proxy_context
->tcp_conn_listener
!= NULL
);
584 if (evconnlistener_enable(proxy_context
->tcp_conn_listener
) != 0) {
591 tcp_listener_stop(ProxyContext
* const proxy_context
)
593 evconnlistener_free(proxy_context
->tcp_conn_listener
);
594 proxy_context
->tcp_conn_listener
= NULL
;
595 while (tcp_listener_kill_oldest_request(proxy_context
) != 0) { }
596 logger_noformat(proxy_context
, LOG_INFO
, "TCP listener shut down");