1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 #include "../public/nsapi.h"
30
31 #include <stdio.h>
32 #include <stdlib.h>
33
34 #include <sys/shm.h>
35 #include <sys/ipc.h>
36 #include <sys/file.h>
37 #include <netinet/tcp.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <fcntl.h>
41 #include <unistd.h>
42 #include <strings.h>
43 #include <stdbool.h>
44 #include <signal.h>
45 #include <pthread.h>
46
47 #include <stdio.h>
48 #include <stdlib.h>
49
50 #include <openssl/rand.h>
51
52 #include <cx/hash_map.h>
53
54 #include "../util/atomic.h"
55 #include "httplistener.h"
56 #include "netsite.h"
57
58 #include "session.h"
59 #include "configmanager.h"
60 #include "log.h"
61
62 #define LISTENER_MAX_PROTOCOL_TOKENS 1024
63
64
65 #define LISTENER_PROTO_IPV4 "ipv4"
66 #define LISTENER_PROTO_IPV6 "ipv6"
67
68
69
70
71
72
73
74
75
76 static CxMap *listener_socket_map;
77
78 static pthread_mutex_t listener_mutex =
PTHREAD_MUTEX_INITIALIZER;
79
80
81 int http_listener_global_init(
void) {
82 listener_socket_map = cxHashMapCreate(cxDefaultAllocator,
CX_STORE_POINTERS,
4);
83 if(!listener_socket_map) {
84 return 1;
85 }
86
87 return 0;
88 }
89
90 int start_all_listener() {
91 ServerConfiguration *conf = cfgmgr_get_server_config();
92 CxList *ls = conf->listeners;
93 CxIterator iter = cxListIterator(ls);
94 cx_foreach(HttpListener *, listener, iter) {
95 http_listener_start(listener);
96 }
97
98 return 0;
99 }
100
101 static HttpSSL* create_http_ssl(ListenerConfig *conf) {
102 SSL_CTX *ctx = SSL_CTX_new(SSLv23_server_method());
103 if(!ctx) {
104 return NULL;
105 }
106 SSL_CTX_set_options(
107 ctx,
108 SSL_OP_SINGLE_DH_USE | SSL_OP_NO_SSLv3);
109 SSL_CTX_set_mode(ctx,
SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
110 SSL_CTX_set_mode(ctx,
SSL_MODE_ENABLE_PARTIAL_WRITE);
111
112 int error =
0;
113 if(conf->disable_proto.ptr) {
114 cxstring *plist =
NULL;
115 ssize_t n = cx_strsplit_a(cxDefaultAllocator, conf->disable_proto, cx_str(
","),
LISTENER_MAX_PROTOCOL_TOKENS, &plist);
116 if(plist) {
117 for(
int i=
0;i<n;i++) {
118 cxstring proto = plist[i];
119 log_ereport(
120 LOG_VERBOSE,
121 "Listener %s: Disable protocol %s",
122 conf->name.ptr,
123 proto.ptr);
124 if(!cx_strcasecmp(cx_strtrim(proto), cx_str(
"SSLv2"))) {
125 SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2);
126 }
else if(!cx_strcasecmp(cx_strtrim(proto), cx_str(
"SSLv3"))) {
127 SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3);
128 }
else if(!cx_strcasecmp(cx_strtrim(proto), cx_str(
"TLSv1"))) {
129 SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1);
130 }
else if(!cx_strcasecmp(cx_strtrim(proto), cx_str(
"TLSv1.1"))) {
131 #ifdef SSL_OP_NO_TLSv1_1
132 SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1_1);
133 #else
134 log_ereport(
135 LOG_WARN,
136 "Listener: %s: TLSv1.1 not supported",
137 conf->name.ptr);
138 #endif
139 }
else if(cx_strcasecmp(cx_strtrim(proto), cx_str(
"TLSv1.2"))) {
140 #ifdef SSL_OP_NO_TLSv1_2
141 SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1_2);
142 #else
143 log_ereport(
144 LOG_WARN,
145 "Listener: %s: TLSv1.2 not supported",
146 conf->name.ptr);
147 #endif
148 }
else if(cx_strcasecmp(cx_strtrim(proto), cx_str(
"TLSv1.3"))) {
149 #ifdef SSL_OP_NO_TLSv1_3
150 SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1_3);
151 #else
152 log_ereport(
153 LOG_WARN,
154 "Listener: %s: TLSv1.3 not supported",
155 conf->name.ptr);
156 #endif
157 }
else {
158 error =
1;
159 log_ereport(
160 LOG_MISCONFIG,
161 "Listener: %s: Unknown protocol %s",
162 conf->name.ptr,
163 proto.ptr);
164 }
165 }
166 free(plist);
167 }
168 }
169
170 if(error) {
171 SSL_CTX_free(ctx);
172 return NULL;
173 }
174
175 int ret;
176 char errbuf[
512];
177
178
179 error =
0;
180 if(conf->chainfile.ptr) {
181 ret = SSL_CTX_use_certificate_chain_file(ctx, conf->chainfile.ptr);
182 if(!ret) {
183 ERR_error_string(ERR_get_error(), errbuf);
184 log_ereport(
LOG_MISCONFIG,
"Cannot load ssl cert file: %s", errbuf);
185 error =
1;
186 }
187 }
else if(conf->certfile.ptr) {
188 ret = SSL_CTX_use_certificate_file(ctx, conf->certfile.ptr,
SSL_FILETYPE_PEM);
189 if(!ret) {
190 ERR_error_string(ERR_get_error(), errbuf);
191 log_ereport(
LOG_MISCONFIG,
"Cannot load ssl chain file: %s", errbuf);
192 error =
1;
193 }
194 }
else {
195 log_ereport(
LOG_MISCONFIG,
"Listener %s: no CertChain/Cert specified", conf->name.ptr);
196 error =
1;
197 }
198
199
200 ret = SSL_CTX_use_PrivateKey_file(ctx, conf->privkeyfile.ptr,
SSL_FILETYPE_PEM);
201 if(!ret) {
202 ERR_error_string(ERR_get_error(), errbuf);
203 log_ereport(
LOG_MISCONFIG,
"Cannot load ssl key file: %s", errbuf);
204 error =
1;
205 }
206
207 if(error) {
208 SSL_CTX_free(ctx);
209 return NULL;
210 }
211
212 HttpSSL *ssl = pool_malloc(conf->cfg->pool,
sizeof(HttpSSL));
213 if(!ssl) {
214 SSL_CTX_free(ctx);
215 return NULL;
216 }
217 ZERO(ssl,
sizeof(HttpSSL));
218 ssl->sslctx = ctx;
219
220 return ssl;
221 }
222
223 static WSSocket* create_socket(ListenerConfig *conf,
const char *protocol) {
224 WSBool ipv4 = !strcmp(protocol,
"ipv4") ?
TRUE :
FALSE;
225
226 int s = -
1;
227 if(ipv4) {
228
229 s = socket(
AF_INET,
SOCK_STREAM,
0);
230 }
else {
231
232 s = socket(
AF_INET6,
SOCK_STREAM,
IPPROTO_TCP);
233 }
234 if(s <
0) {
235 log_ereport(
236 LOG_FAILURE,
237 "cannot create socket: protocol: %s port: %d error: %s",
238 protocol,
239 conf->port,
240 strerror(errno));
241 return NULL;
242 }
243
244
245 int o =
1;
246 setsockopt(
247 s,
248 SOL_SOCKET,
SO_REUSEADDR,
249 &o,
250 sizeof(
int));
251
252 #ifdef LINUX
253 if(!ipv4) {
254 o =
1;
255 setsockopt(
256 s,
257 IPPROTO_IPV6,
258 IPV6_V6ONLY,
259 &o,
260 sizeof(
int));
261 }
262 #endif
263
264
265 union ws_socketaddr addr;
266 struct sockaddr *servaddr;
267 size_t servaddr_size;
268 if(ipv4) {
269
270 memset(&addr.addr4,
0,
sizeof(addr.addr4));
271 addr.addr4.sin_family =
AF_INET;
272 addr.addr4.sin_addr.s_addr = htonl(
INADDR_ANY);
273 addr.addr4.sin_port = htons(conf->port);
274 servaddr = (
struct sockaddr *)&addr.addr4;
275 servaddr_size =
sizeof(addr.addr4);
276 }
else {
277
278 memset(&addr.addr6,
0,
sizeof(addr.addr6));
279 addr.addr6.sin6_family =
AF_INET6;
280 addr.addr6.sin6_addr = in6addr_any;
281 addr.addr6.sin6_port = htons(conf->port);
282 servaddr = (
struct sockaddr *)&addr.addr6;
283 servaddr_size =
sizeof(addr.addr6);
284 }
285
286 if(bind(s, servaddr, servaddr_size)) {
287 log_ereport(
288 LOG_FAILURE,
289 "cannot bind socket: protocol: %s port: %d error: %s",
290 protocol,
291 conf->port,
292 strerror(errno));
293 close(s);
294 return NULL;
295 }
296
297
298 WSSocket *wssocket = malloc(
sizeof(WSSocket));
299 if(!wssocket) {
300 close(s);
301 return NULL;
302 }
303 ZERO(wssocket,
sizeof(WSSocket));
304 wssocket->socket = s;
305 wssocket->addr = addr;
306 if(ipv4) {
307 wssocket->sockaddr = (
struct sockaddr *)&wssocket->addr.addr4;
308 }
else {
309 wssocket->sockaddr = (
struct sockaddr *)&wssocket->addr.addr6;
310 }
311 wssocket->sockaddr_size = servaddr_size;
312
313 return wssocket;
314 }
315
316 static WSSocket* get_socket(ListenerConfig *conf,
const char *protocol) {
317 char key_data[
32];
318 size_t key_len = snprintf(key_data,
32,
"%s:%d", protocol, conf->port);
319 CxHashKey key = cx_hash_key(key_data, key_len);
320
321 WSSocket *sock = cxMapGet(listener_socket_map, key);
322 if(!sock) {
323 sock = create_socket(conf, protocol);
324 if(sock) {
325 cxMapPut(listener_socket_map, key, sock);
326 }
327 }
328 return sock;
329 }
330
331
332
333
334 static HttpSSL* socket_get_ssl(WSSocket *socket1, WSSocket *socket2) {
335 if(socket1 && socket1->ssl) {
336 return socket1->ssl;
337 }
338 if(socket2 && socket2->ssl) {
339 return socket2->ssl;
340 }
341 return NULL;
342 }
343
344 static HttpListener* listener_create(ListenerConfig *conf) {
345 pool_handle_t *pool = conf->cfg->pool;
346 HttpListener *listener = pool_malloc(pool,
sizeof(HttpListener));
347 if(!listener) {
348 return NULL;
349 }
350 ZERO(listener,
sizeof(HttpListener));
351
352 listener->running =
0;
353 listener->cfg = conf->cfg;
354 listener->name = cx_strdup_a(pool_allocator(pool), cx_strcast(conf->name));
355 listener->default_vs.vs_name = pool_strdup(pool, conf->vs.ptr);
356 listener->threadpool =
NULL;
357 if(conf->threadpool.ptr !=
NULL) {
358 listener->threadpool = get_threadpool(cx_strcast(conf->threadpool));
359 }
360 if(listener->threadpool ==
NULL) {
361 listener->threadpool = get_default_threadpool();
362 }
363 if(conf->blockingio) {
364 listener->session_handler = create_basic_session_handler(pool);
365 }
else {
366 listener->session_handler = create_event_session_handler(pool);
367 }
368 listener->nacceptors = conf->nacceptors;
369 listener->port = conf->port;
370 listener->next =
NULL;
371
372
373
374 listener->server_socket = get_socket(conf,
LISTENER_PROTO_IPV4);
375 listener->server_socket6 = get_socket(conf,
LISTENER_PROTO_IPV6);
376 if(!listener->server_socket && !listener->server_socket6) {
377 log_ereport(
LOG_FAILURE,
"Listener %s: no server socket", conf->name.ptr);
378 return NULL;
379 }
380
381 if(listener->server_socket) {
382 wssocket_ref(listener->server_socket);
383 }
384 if(listener->server_socket6) {
385 wssocket_ref(listener->server_socket6);
386 }
387
388
389 if(conf->ssl) {
390 HttpSSL *ssl = socket_get_ssl(listener->server_socket, listener->server_socket6);
391 if(!ssl) {
392 ssl = create_http_ssl(conf);
393 if(!ssl) {
394 log_ereport(
LOG_FAILURE,
"Listener %s: cannot create SSL context", conf->name.ptr);
395 return NULL;
396 }
397 }
398 if(listener->server_socket) {
399 listener->server_socket->ssl = ssl;
400 }
401 if(listener->server_socket6) {
402 listener->server_socket6->ssl = ssl;
403 }
404 }
405
406
407 listener->acceptors = calloc(listener->nacceptors,
sizeof(
void*));
408 listener->acceptors6 = calloc(listener->nacceptors,
sizeof(
void*));
409 for (
int i=
0;i<listener->nacceptors;i++) {
410 listener->acceptors[i] = acceptor_new(listener);
411 listener->acceptors6[i] = acceptor_new(listener);
412 listener->acceptors6[i]->ipv6 =
TRUE;
413 }
414
415 return listener;
416 }
417
418 HttpListener* http_listener_create(ListenerConfig *conf) {
419 pthread_mutex_lock(&listener_mutex);
420 HttpListener *listener = listener_create(conf);
421 pthread_mutex_unlock(&listener_mutex);
422 return listener;
423 }
424
425 void http_listener_destroy(HttpListener *listener) {
426 log_ereport(
LOG_DEBUG,
"destroy http listener: %s config: %p", listener->name.ptr, listener->cfg);
427
428 if(listener->shutdown) {
429 pthread_mutex_destroy(&listener->shutdown_mutex);
430 pthread_cond_destroy(&listener->shutdown_cond);
431 }
432 }
433
434 int http_listener_start(HttpListener *listener) {
435 if(listener->running) {
436 return 0;
437 }
438 log_ereport(
LOG_INFORM,
"start listener on port %d", listener->port);
439
440 WSBool ipv4 = listener->server_socket ?
TRUE :
FALSE;
441 WSBool ipv6 = listener->server_socket6 ?
TRUE:
FALSE;
442
443 if (ipv4 && !listener->server_socket->listening && listen(listener->server_socket->socket,
256) == -
1) {
444 log_ereport(
LOG_FAILURE,
"http_listener_start: listen failed: %s", strerror(errno));
445 return -
1;
446 }
else {
447 listener->server_socket->listening =
TRUE;
448 }
449 if (ipv6 && !listener->server_socket6->listening && listen(listener->server_socket6->socket,
256) == -
1) {
450 log_ereport(
LOG_FAILURE,
"http_listener_start: listen v6 failed: %s", strerror(errno));
451 return -
1;
452 }
else {
453 listener->server_socket6->listening =
TRUE;
454 }
455
456
457 for (
int i=
0;i<listener->nacceptors;i++) {
458 if(ipv4) {
459 acceptor_start(listener->acceptors[i]);
460 }
461 if(ipv6) {
462 acceptor_start(listener->acceptors6[i]);
463 }
464 }
465 listener->running =
TRUE;
466
467 return 0;
468 }
469
470 int http_listener_socket_eq(HttpListener *l1, HttpListener *l2) {
471 if(l1->server_socket && l2->server_socket && l1->server_socket == l2->server_socket) {
472 return TRUE;
473 }
474 if(l1->server_socket6 && l2->server_socket6 && l1->server_socket6 == l2->server_socket6) {
475 return TRUE;
476 }
477 return FALSE;
478 }
479
480 void http_listener_set_next(HttpListener *listener, HttpListener *next) {
481 while(listener->next) {
482 listener = listener->next;
483 }
484 listener->next = next;
485 }
486
487 int http_listener_connect(HttpListener *listener, WSBool ipv6) {
488 int domain = ipv6 ?
AF_INET6 :
AF_INET;
489 int client = socket(domain,
SOCK_STREAM,
0);
490 if(client <
0) {
491 return -
1;
492 }
493
494 struct sockaddr *sockaddr;
495 size_t sockaddr_size;
496 if(ipv6) {
497 sockaddr = listener->server_socket6->sockaddr;
498 sockaddr_size = listener->server_socket6->sockaddr_size;
499 }
else {
500 sockaddr = listener->server_socket->sockaddr;
501 sockaddr_size = listener->server_socket->sockaddr_size;
502 }
503
504 if(connect(client, sockaddr, sockaddr_size) <
0) {
505 close(client);
506 return -
1;
507 }
508
509 return client;
510 }
511
512
513 void http_listener_shutdown_acceptors(HttpListener *listener) {
514 if(pthread_mutex_init(&listener->shutdown_mutex,
NULL)) {
515 log_ereport(
LOG_FAILURE,
"http_listener_shutdown_acceptors: pthread_mutex_init failed: %s", strerror(errno));
516 return;
517 }
518 if(pthread_cond_init(&listener->shutdown_cond,
NULL)) {
519 log_ereport(
LOG_FAILURE,
"http_listener_shutdown_acceptors: pthread_cond_init failed: %s", strerror(errno));
520 return;
521 }
522 listener->shutdown =
TRUE;
523
524 log_ereport(
LOG_INFORM,
"shutdown http listener %s", listener->name.ptr);
525
526 pthread_mutex_lock(&listener->shutdown_mutex);
527
528
529
530
531
532 for(
int i=
0;i<listener->nacceptors;i++) {
533 listener->acceptors[i]->exit =
TRUE;
534 int client4 = http_listener_connect(listener,
FALSE);
535 if(client4 <
0) {
536 log_ereport(
LOG_FAILURE,
"http_listener_shutdown_acceptors: cannot connect to ipv4 server socket: %s", strerror(errno));
537 }
else {
538 close(client4);
539 }
540
541 listener->acceptors6[i]->exit =
TRUE;
542 int client6 = http_listener_connect(listener,
TRUE);
543 if(client6 <
0) {
544 log_ereport(
LOG_FAILURE,
"http_listener_shutdown_acceptors: cannot connect to ipv6 server socket: %s", strerror(errno));
545 }
else {
546 close(client6);
547 }
548 }
549
550
551
552
553
554 struct timespec ts;
555 ts.tv_sec = time(
NULL) +
60;
556 pthread_cond_timedwait(&listener->shutdown_cond, &listener->shutdown_mutex, &ts);
557
558 pthread_mutex_unlock(&listener->shutdown_mutex);
559 }
560
561
562 Acceptor* acceptor_new(HttpListener *listener) {
563 Acceptor *acceptor = malloc(
sizeof(Acceptor));
564 acceptor->listener = listener;
565 acceptor->ipv6 =
WS_FALSE;
566 acceptor->exit =
WS_FALSE;
567 return acceptor;
568 }
569
570 void acceptor_start(Acceptor *a) {
571 cfg_ref(a->listener->cfg);
572 if(pthread_create(
573 &a->tid,
574 NULL,
575 (
void*(*)(
void*))acceptor_thread,
576 a) !=
0)
577 {
578 log_ereport(
LOG_FAILURE,
"Listener %s: acceptor_start: %s acceptor", a->listener->name.ptr, strerror(errno));
579 cfg_unref(a->listener->cfg);
580 }
else {
581 (
void)pthread_detach(a->tid);
582 }
583 }
584
585 void* acceptor_thread(Acceptor *acceptor) {
586 WS_ASSERT(acceptor);
587 WS_ASSERT(acceptor->listener);
588 WS_ASSERT(acceptor->listener->cfg);
589 WS_ASSERT(acceptor->listener->session_handler);
590 WS_ASSERT(acceptor->listener->session_handler->enqueue_connection);
591
592 acceptor->running =
TRUE;
593 HttpListener *listener = acceptor->listener;
594
595 int server_socket;
596 uint32_t *acceptors_running = &listener->nacceptors_running;
597
598 ConnectionAddr ca;
599 struct sockaddr *ca_ptr;
600 socklen_t ca_length;
601 ConnectionAddrType addr_type;
602 HttpSSL *socket_ssl =
NULL;
603 if(acceptor->ipv6) {
604 server_socket = listener->server_socket6->socket;
605 ca_ptr = (
struct sockaddr*)&ca.address_v6;
606 ca_length =
sizeof(ca.address_v6);
607 addr_type =
CONN_ADDR_IPV6;
608 socket_ssl = listener->server_socket6->ssl;
609 }
else {
610 server_socket = listener->server_socket->socket;
611 ca_ptr = (
struct sockaddr*)&ca.address_v4;
612 ca_length =
sizeof(ca.address_v4);
613 addr_type =
CONN_ADDR_IPV4;
614 socket_ssl = listener->server_socket->ssl;
615 }
616
617 log_ereport(
LOG_DEBUG,
"acceptor: %p listener: %p start", acceptor, acceptor->listener);
618 ws_atomic_inc32(acceptors_running);
619
620 for (;;) {
621
622 int clientfd;
623 socklen_t length = ca_length;
624
625
626 clientfd = accept(
627 server_socket,
628 ca_ptr,
629 &length);
630 log_ereport(
LOG_DEBUG,
"acceptor: %p listener: %p: accept(): %d", acceptor, acceptor->listener, clientfd);
631 if (clientfd == -
1) {
632 log_ereport(
LOG_FAILURE,
"accept %s failed: %s", acceptor->ipv6 ?
"ipv6" :
"ipv4", strerror(errno));
633
634 if(acceptor->exit) {
635 log_ereport(
LOG_VERBOSE,
"acceptor thread %p: listener: %p exit", acceptor, acceptor->listener);
636 break;
637 }
638 continue;
639 }
640
641
642
643
644
645
646
647 HttpListener *ls = listener;
648 int acceptor_exit =
0;
649 while(ls->next) {
650 ls = ls->next;
651 acceptor_exit =
1;
652 }
653
654
655 Connection *conn = malloc(
sizeof(Connection));
656 uint32_t conn_id;
657 RAND_bytes((
unsigned char*)&conn->id,
sizeof(conn->id));
658 conn->id <<=
16;
659 conn->address = ca;
660 conn->addr_type = addr_type;
661 conn->fd = clientfd;
662 conn->listener = ls;
663 conn->ssl_accepted =
0;
664 conn->ssl_error =
0;
665 log_ereport(
LOG_DEBUG,
"trace reqid: %016llx connection accepted", (
unsigned long long int)conn->id);
666 if(socket_ssl) {
667
668
669 int flags;
670 if((flags = fcntl(conn->fd,
F_GETFL,
0)) == -
1) {
671 flags =
0;
672 }
673 if(fcntl(conn->fd,
F_SETFL, flags |
O_NONBLOCK)) {
674 log_ereport(
LOG_DEBUG,
"trace reqid: %016llx connection destroyed | fcntl error", (
unsigned long long int)conn->id);
675 log_ereport(
LOG_FAILURE,
"acceptor: fcntl failed: %s", strerror(errno));
676 close(clientfd);
677 free(conn);
678 conn =
NULL;
679 }
else {
680 SSL *ssl = SSL_new(socket_ssl->sslctx);
681 if(ssl) {
682 SSL_set_fd(ssl, clientfd);
683
684 conn->ssl = ssl;
685 conn->read = connection_ssl_read;
686 conn->write = connection_ssl_write;
687 conn->close = connection_ssl_close;
688 }
else {
689 log_ereport(
LOG_DEBUG,
"trace reqid: %016llx connection destroyed | SSL init error", (
unsigned long long int)conn->id);
690 log_ereport(
LOG_FAILURE,
"acceptor: %p listener: %p SSL_new() failed", acceptor, acceptor->listener);
691 free(conn);
692 close(clientfd);
693 conn =
NULL;
694 }
695 }
696 }
else {
697 conn->ssl =
NULL;
698 conn->read = connection_read;
699 conn->write = connection_write;
700 conn->close = connection_close;
701 }
702
703 if(conn) {
704 cfg_ref(ls->cfg);
705
706
707 ls->session_handler->enqueue_connection(
708 ls->session_handler,
709 conn);
710 }
711
712
713
714 if(acceptor_exit || acceptor->exit) {
715
716 log_ereport(
LOG_VERBOSE,
"acceptor thread %p: listener: %p exit", acceptor, acceptor->listener);
717 break;
718 }
719 }
720
721 if(ws_atomic_dec32(acceptors_running) ==
0) {
722
723 if(listener->shutdown) {
724 log_ereport(
LOG_DEBUG,
"last acceptor shutdown: notify cfgmgr");
725 pthread_mutex_lock(&listener->shutdown_mutex);
726 pthread_cond_signal(&listener->shutdown_cond);
727 pthread_mutex_unlock(&listener->shutdown_mutex);
728 }
729 }
730
731 acceptor->running =
FALSE;
732
733 cfg_unref(acceptor->listener->cfg);
734
735 return NULL;
736 }
737
738 void wssocket_ref(WSSocket *ws) {
739 ws_atomic_inc32(&ws->ref);
740 }
741
742 void wssocket_unref(WSSocket *ws) {
743
744
745 ws_atomic_dec32(&ws->ref);
746 }
747
748
749 int http_listener_apply_keep_alive_settings(HttpListener *listener,
int fd) {
750
751 int optval =
1;
752 if (setsockopt(fd,
SOL_SOCKET,
SO_KEEPALIVE, &optval,
sizeof(optval))) {
753 log_ereport(
LOG_FAILURE,
"listener: cannot set SO_KEEPALIVE: %s", strerror(errno));
754 return 1;
755 }
756
757 int keepidle =
240;
758 if (setsockopt(fd,
IPPROTO_TCP,
TCP_KEEPIDLE, &keepidle,
sizeof(keepidle))) {
759 log_ereport(
LOG_FAILURE,
"listener: cannot set TCP_KEEPIDLE to value %d: %s", keepidle, strerror(errno));
760 return 1;
761 }
762
763 int keepintvl =
10;
764 if (setsockopt(fd,
IPPROTO_TCP,
TCP_KEEPINTVL, &keepintvl,
sizeof(keepintvl))) {
765 log_ereport(
LOG_FAILURE,
"listener: cannot set TCP_KEEPINTVL to value %d: %s", keepintvl, strerror(errno));
766 return 1;
767 }
768
769 int keepcnt =
3;
770 if (setsockopt(fd,
IPPROTO_TCP,
TCP_KEEPCNT, &keepcnt,
sizeof(keepcnt))) {
771 log_ereport(
LOG_FAILURE,
"listener: cannot set TCP_KEEPCNT to value %d: %s", keepcnt, strerror(errno));
772 return 1;
773 }
774
775 return 0;
776 }
777