@cryptotaxi247 / netdata-1 / commits / 4c196aa27

reorganize web_client options into a compact flags variable and enable crock only on TCP sockets

Costa Tsaousis (ktsaou) committed Aug 31, 2017 at 02:15 UTC 4c196aa27354ec2efebef045a8dd069ebf077a63
7 files changed +158 -87
src/main.c
+1 -1
@@ -172,7 +172,7 @@ void kill_childs()
172 // it is detached
173 // pthread_join(w->thread, NULL);
174
175 - w->obsolete = 1;
175 + WEB_CLIENT_IS_OBSOLETE(w);
176 }
177
178 int i;
src/socket.c
+28 -10
@@ -99,6 +99,7 @@ int create_listen_socket_unix(const char *path, int listen_backlog) {
99 name.sun_family = AF_UNIX;
100 strncpy(name.sun_path, path, sizeof(name.sun_path)-1);
101
102 + // we have to delete any old socket, or bind() will fail
103 unlink(path);
104
105 if(bind (sock, (struct sockaddr *) &name, sizeof (name)) < 0) {
@@ -107,6 +108,10 @@ int create_listen_socket_unix(const char *path, int listen_backlog) {
108 return -1;
109 }
110
111 + // we have to chmod this to 0777 so that the client will be able
112 + // to read from and write to this socket.
113 + chmod(path, 0777);
114 +
115 if(listen(sock, listen_backlog) < 0) {
116 close(sock);
117 error("LISTENER: UNIX listen() on path '%s' failed.", path);
@@ -213,7 +218,7 @@ int create_listen_socket6(int socktype, uint32_t scope_id, const char *ip, int p
218 return sock;
219 }
220
216 -static inline int listen_sockets_add(LISTEN_SOCKETS *sockets, int fd, int socktype, const char *protocol, const char *ip, int port) {
221 +static inline int listen_sockets_add(LISTEN_SOCKETS *sockets, int fd, int family, int socktype, const char *protocol, const char *ip, int port) {
222 if(sockets->opened >= MAX_LISTEN_FDS) {
223 error("LISTENER: Too many listening sockets. Failed to add listening %s socket at ip '%s' port %d, protocol %s, socktype %d", protocol, ip, port, protocol, socktype);
224 close(fd);
@@ -221,16 +226,27 @@ static inline int listen_sockets_add(LISTEN_SOCKETS *sockets, int fd, int sockty
226 }
227
228 sockets->fds[sockets->opened] = fd;
229 + sockets->fds_types[sockets->opened] = socktype;
230 + sockets->fds_families[sockets->opened] = family;
231
232 char buffer[100 + 1];
233
227 - if(port)
228 - snprintfz(buffer, 100, "%s:[%s]:%d", protocol, ip, port);
229 - else
230 - snprintfz(buffer, 100, "%s:[%s]", protocol, ip);
234 + switch(family) {
235 + case AF_INET:
236 + snprintfz(buffer, 100, "%s:%s:%d", protocol, ip, port);
237 + break;
238 +
239 + case AF_INET6:
240 + default:
241 + snprintfz(buffer, 100, "%s:[%s]:%d", protocol, ip, port);
242 + break;
243 +
244 + case AF_UNIX:
245 + snprintfz(buffer, 100, "%s:%s", protocol, ip);
246 + break;
247 + }
248
249 sockets->fds_names[sockets->opened] = strdupz(buffer);
233 - sockets->fds_types[sockets->opened] = socktype;
250
251 sockets->opened++;
252 return 0;
@@ -311,7 +327,7 @@ static inline int bind_to_this(LISTEN_SOCKETS *sockets, const char *definition,
327 sockets->failed++;
328 }
329 else {
314 - listen_sockets_add(sockets, fd, socktype, protocol_str, path, 0);
330 + listen_sockets_add(sockets, fd, AF_UNIX, socktype, protocol_str, path, 0);
331 added++;
332 }
333 return added;
@@ -372,11 +388,13 @@ static inline int bind_to_this(LISTEN_SOCKETS *sockets, const char *definition,
388
389 for (rp = result; rp != NULL; rp = rp->ai_next) {
390 int fd = -1;
391 + int family = -1;
392
393 char rip[INET_ADDRSTRLEN + INET6_ADDRSTRLEN] = "INVALID";
394 int rport = default_port;
395
379 - switch (rp->ai_addr->sa_family) {
396 + family = rp->ai_addr->sa_family;
397 + switch (family) {
398 case AF_INET: {
399 struct sockaddr_in *sin = (struct sockaddr_in *) rp->ai_addr;
400 inet_ntop(AF_INET, &sin->sin_addr, rip, INET_ADDRSTRLEN);
@@ -396,7 +414,7 @@ static inline int bind_to_this(LISTEN_SOCKETS *sockets, const char *definition,
414 }
415
416 default:
399 - debug(D_LISTENER, "LISTENER: Unknown socket family %d", rp->ai_addr->sa_family);
417 + debug(D_LISTENER, "LISTENER: Unknown socket family %d", family);
418 break;
419 }
420
@@ -405,7 +423,7 @@ static inline int bind_to_this(LISTEN_SOCKETS *sockets, const char *definition,
423 sockets->failed++;
424 }
425 else {
408 - listen_sockets_add(sockets, fd, socktype, protocol_str, rip, rport);
426 + listen_sockets_add(sockets, fd, family, socktype, protocol_str, rip, rport);
427 added++;
428 }
429 }
src/socket.h
+2 -1
@@ -15,7 +15,8 @@ typedef struct listen_sockets {
15 size_t failed; // the number of sockets attempted to open, but failed
16 int fds[MAX_LISTEN_FDS]; // the open sockets
17 char *fds_names[MAX_LISTEN_FDS]; // descriptions for the open sockets
18 - int fds_types[MAX_LISTEN_FDS]; // the socktype for the open sockets
18 + int fds_types[MAX_LISTEN_FDS]; // the socktype for the open sockets (SOCK_STREAM, SOCK_DGRAM)
19 + int fds_families[MAX_LISTEN_FDS]; // the family of the open sockets (AF_UNIX, AF_INET, AF_INET6)
20 } LISTEN_SOCKETS;
21
22 extern int listen_sockets_setup(LISTEN_SOCKETS *sockets);
src/web_api_v1.c
+5 -5
@@ -816,7 +816,7 @@ inline int web_client_api_request_v1_registry(RRDHOST *host, struct web_client *
816 #endif /* NETDATA_INTERNAL_CHECKS */
817 }
818
819 - if(respect_web_browser_do_not_track_policy && w->donottrack) {
819 + if(respect_web_browser_do_not_track_policy && web_client_has_donottrack(w)) {
820 buffer_flush(w->response.data);
821 buffer_sprintf(w->response.data, "Your web browser is sending 'DNT: 1' (Do Not Track). The registry requires persistent cookies on your browser to work.");
822 return 400;
@@ -853,19 +853,19 @@ inline int web_client_api_request_v1_registry(RRDHOST *host, struct web_client *
853
854 switch(action) {
855 case 'A':
856 - w->tracking_required = 1;
856 + web_client_enable_tracking_required(w);
857 return registry_request_access_json(host, w, person_guid, machine_guid, machine_url, url_name, now_realtime_sec());
858
859 case 'D':
860 - w->tracking_required = 1;
860 + web_client_enable_tracking_required(w);
861 return registry_request_delete_json(host, w, person_guid, machine_guid, machine_url, delete_url, now_realtime_sec());
862
863 case 'S':
864 - w->tracking_required = 1;
864 + web_client_enable_tracking_required(w);
865 return registry_request_search_json(host, w, person_guid, machine_guid, machine_url, search_machine_guid, now_realtime_sec());
866
867 case 'W':
868 - w->tracking_required = 1;
868 + web_client_enable_tracking_required(w);
869 return registry_request_switch_json(host, w, person_guid, machine_guid, machine_url, to_person_guid, now_realtime_sec());
870
871 case 'H':
src/web_client.c
+44 -43
@@ -17,10 +17,11 @@ unsigned long long web_clients_count = 0;
17
18 static inline int web_client_crock_socket(struct web_client *w) {
19 #ifdef TCP_CORK
20 - if(likely(!w->tcp_cork && w->ofd != -1)) {
20 + if(likely(web_client_is_corkable(w) && !w->tcp_cork && w->ofd != -1)) {
21 w->tcp_cork = 1;
22 if(unlikely(setsockopt(w->ofd, IPPROTO_TCP, TCP_CORK, (char *) &w->tcp_cork, sizeof(int)) != 0)) {
23 error("%llu: failed to enable TCP_CORK on socket.", w->id);
24 +
25 w->tcp_cork = 0;
26 return -1;
27 }
@@ -78,7 +79,7 @@ struct web_client *web_client_create(int listener) {
79 w->response.header = buffer_create(HTTP_RESPONSE_HEADER_SIZE);
80 w->response.header_output = buffer_create(HTTP_RESPONSE_HEADER_SIZE);
81 w->origin[0] = '*';
81 - w->wait_receive = 1;
82 + web_client_enable_wait_receive(w);
83
84 if(web_clients) web_clients->prev = w;
85 w->next = web_clients;
@@ -150,9 +151,9 @@ void web_client_reset(struct web_client *w) {
151 w->mode = WEB_CLIENT_MODE_NORMAL;
152
153 w->tcp_cork = 0;
153 - w->donottrack = 0;
154 - w->tracking_required = 0;
155 - w->keepalive = 0;
154 + web_client_disable_donottrack(w);
155 + web_client_disable_tracking_required(w);
156 + web_client_disable_keepalive(w);
157 w->decoded_url[0] = '\0';
158
159 buffer_reset(w->response.header_output);
@@ -162,8 +163,8 @@ void web_client_reset(struct web_client *w) {
163 w->response.sent = 0;
164 w->response.code = 0;
165
165 - w->wait_receive = 1;
166 - w->wait_send = 0;
166 + web_client_enable_wait_receive(w);
167 + web_client_disable_wait_send(w);
168
169 w->response.zoutput = 0;
170
@@ -391,8 +392,8 @@ int mysendfile(struct web_client *w, char *filename) {
392 debug(D_WEB_CLIENT_ACCESS, "%llu: Sending file '%s' (%ld bytes, ifd %d, ofd %d).", w->id, webfilename, stat.st_size, w->ifd, w->ofd);
393
394 w->mode = WEB_CLIENT_MODE_FILECOPY;
394 - w->wait_receive = 1;
395 - w->wait_send = 0;
395 + web_client_enable_wait_receive(w);
396 + web_client_disable_wait_send(w);
397 buffer_flush(w->response.data);
398 w->response.rlen = stat.st_size;
399 #ifdef __APPLE__
@@ -731,11 +732,11 @@ static inline char *http_header_parse(struct web_client *w, char *s) {
732
733 else if(hash == hash_connection && !strcasecmp(s, "Connection")) {
734 if(strcasestr(v, "keep-alive"))
734 - w->keepalive = 1;
735 + web_client_enable_keepalive(w);
736 }
737 else if(respect_web_browser_do_not_track_policy && hash == hash_donottrack && !strcasecmp(s, "DNT")) {
737 - if(*v == '0') w->donottrack = 0;
738 - else if(*v == '1') w->donottrack = 1;
738 + if(*v == '0') web_client_disable_donottrack(w);
739 + else if(*v == '1') web_client_enable_donottrack(w);
740 }
741 #ifdef NETDATA_WITH_ZLIB
742 else if(hash == hash_accept_encoding && !strcasecmp(s, "Accept-Encoding")) {
@@ -784,7 +785,7 @@ static inline HTTP_VALIDATION http_request_validate(struct web_client *w) {
785 w->mode = WEB_CLIENT_MODE_STREAM;
786 }
787 else {
787 - w->wait_receive = 0;
788 + web_client_disable_wait_receive(w);
789 return HTTP_VALIDATION_NOT_SUPPORTED;
790 }
791
@@ -800,7 +801,7 @@ static inline HTTP_VALIDATION http_request_validate(struct web_client *w) {
801
802 // incomplete requests
803 if(unlikely(!*s)) {
803 - w->wait_receive = 1;
804 + web_client_enable_wait_receive(w);
805 return HTTP_VALIDATION_INCOMPLETE;
806 }
807
@@ -831,7 +832,7 @@ static inline HTTP_VALIDATION http_request_validate(struct web_client *w) {
832 // FIXME -- we should avoid it
833 strncpyz(w->last_url, w->decoded_url, URL_MAX);
834
834 - w->wait_receive = 0;
835 + web_client_disable_wait_receive(w);
836 return HTTP_VALIDATION_OK;
837 }
838
@@ -841,7 +842,7 @@ static inline HTTP_VALIDATION http_request_validate(struct web_client *w) {
842 }
843
844 // incomplete request
844 - w->wait_receive = 1;
845 + web_client_enable_wait_receive(w);
846 return HTTP_VALIDATION_INCOMPLETE;
847 }
848
@@ -884,7 +885,7 @@ static inline void web_client_send_http_header(struct web_client *w) {
885 "Content-Type: %s\r\n"
886 "Date: %s\r\n"
887 , w->response.code, code_msg
887 - , w->keepalive?"keep-alive":"close"
888 + , web_client_has_keepalive(w)?"keep-alive":"close"
889 , w->origin
890 , content_type_string
891 , date
@@ -912,7 +913,7 @@ static inline void web_client_send_http_header(struct web_client *w) {
913 }
914 else {
915 if(respect_web_browser_do_not_track_policy) {
915 - if(w->tracking_required)
916 + if(web_client_has_tracking_required(w))
917 buffer_sprintf(w->response.header_output,
918 "Tk: T;cookies\r\n");
919 else
@@ -954,7 +955,7 @@ static inline void web_client_send_http_header(struct web_client *w) {
955 }
956 else {
957 // we don't know the content length, disable keep-alive
957 - w->keepalive = 0;
958 + web_client_disable_keepalive(w);
959 }
960 }
961
@@ -1242,8 +1243,8 @@ void web_client_process_request(struct web_client *w) {
1243 web_client_send_http_header(w);
1244
1245 // enable sending immediately if we have data
1245 - if(w->response.data->len) w->wait_send = 1;
1246 - else w->wait_send = 0;
1246 + if(w->response.data->len) web_client_enable_wait_send(w);
1247 + else web_client_disable_wait_send(w);
1248
1249 switch(w->mode) {
1250 case WEB_CLIENT_MODE_STREAM:
@@ -1261,7 +1262,7 @@ void web_client_process_request(struct web_client *w) {
1262 case WEB_CLIENT_MODE_FILECOPY:
1263 if(w->response.rlen) {
1264 debug(D_WEB_CLIENT, "%llu: Done preparing the response. Will be sending data file of %zu bytes to client.", w->id, w->response.rlen);
1264 - w->wait_receive = 1;
1265 + web_client_enable_wait_receive(w);
1266
1267 /*
1268 // utilize the kernel sendfile() for copying the file to the socket.
@@ -1376,14 +1377,14 @@ ssize_t web_client_send_deflate(struct web_client *w)
1377 if(t < 0) return t;
1378 }
1379
1379 - if(w->mode == WEB_CLIENT_MODE_FILECOPY && w->wait_receive && w->response.rlen && w->response.rlen > w->response.data->len) {
1380 + if(w->mode == WEB_CLIENT_MODE_FILECOPY && web_client_has_wait_receive(w) && w->response.rlen && w->response.rlen > w->response.data->len) {
1381 // we have to wait, more data will come
1382 debug(D_WEB_CLIENT, "%llu: Waiting for more data to become available.", w->id);
1382 - w->wait_send = 0;
1383 + web_client_disable_wait_send(w);
1384 return t;
1385 }
1386
1386 - if(unlikely(!w->keepalive)) {
1387 + if(unlikely(!web_client_has_keepalive(w))) {
1388 debug(D_WEB_CLIENT, "%llu: Closing (keep-alive is not enabled). %zu bytes sent.", w->id, w->response.sent);
1389 WEB_CLIENT_IS_DEAD(w);
1390 return t;
@@ -1419,7 +1420,7 @@ ssize_t web_client_send_deflate(struct web_client *w)
1420 // ask for FINISH if we have all the input
1421 int flush = Z_SYNC_FLUSH;
1422 if(w->mode == WEB_CLIENT_MODE_NORMAL
1422 - || (w->mode == WEB_CLIENT_MODE_FILECOPY && !w->wait_receive && w->response.data->len == w->response.rlen)) {
1423 + || (w->mode == WEB_CLIENT_MODE_FILECOPY && !web_client_has_wait_receive(w) && w->response.data->len == w->response.rlen)) {
1424 flush = Z_FINISH;
1425 debug(D_DEFLATE, "%llu: Requesting Z_FINISH, if possible.", w->id);
1426 }
@@ -1488,14 +1489,14 @@ ssize_t web_client_send(struct web_client *w) {
1489 // A. we have done everything
1490 // B. we temporarily have nothing to send, waiting for the buffer to be filled by ifd
1491
1491 - if(w->mode == WEB_CLIENT_MODE_FILECOPY && w->wait_receive && w->response.rlen && w->response.rlen > w->response.data->len) {
1492 + if(w->mode == WEB_CLIENT_MODE_FILECOPY && web_client_has_wait_receive(w) && w->response.rlen && w->response.rlen > w->response.data->len) {
1493 // we have to wait, more data will come
1494 debug(D_WEB_CLIENT, "%llu: Waiting for more data to become available.", w->id);
1494 - w->wait_send = 0;
1495 + web_client_disable_wait_send(w);
1496 return 0;
1497 }
1498
1498 - if(unlikely(!w->keepalive)) {
1499 + if(unlikely(!web_client_has_keepalive(w))) {
1500 debug(D_WEB_CLIENT, "%llu: Closing (keep-alive is not enabled). %zu bytes sent.", w->id, w->response.sent);
1501 WEB_CLIENT_IS_DEAD(w);
1502 return 0;
@@ -1549,10 +1550,10 @@ ssize_t web_client_receive(struct web_client *w)
1550 debug(D_WEB_DATA, "%llu: Received data: '%s'.", w->id, &w->response.data->buffer[old]);
1551
1552 if(w->mode == WEB_CLIENT_MODE_FILECOPY) {
1552 - w->wait_send = 1;
1553 + web_client_enable_wait_send(w);
1554
1555 if(w->response.rlen && w->response.data->len >= w->response.rlen)
1555 - w->wait_receive = 0;
1556 + web_client_disable_wait_receive(w);
1557 }
1558 }
1559 else if(likely(bytes == 0)) {
@@ -1565,7 +1566,7 @@ ssize_t web_client_receive(struct web_client *w)
1566 if(w->mode == WEB_CLIENT_MODE_FILECOPY) {
1567 // we are copying data from ifd to ofd
1568 // let it finish copying...
1568 - w->wait_receive = 0;
1569 + web_client_disable_wait_receive(w);
1570
1571 debug(D_WEB_CLIENT, "%llu: Read the whole file.", w->id);
1572 if(w->ifd != w->ofd) close(w->ifd);
@@ -1611,11 +1612,11 @@ void *web_client_main(void *ptr)
1612 for(;;) {
1613 if(unlikely(netdata_exit)) break;
1614
1614 - if(unlikely(w->dead)) {
1615 + if(unlikely(web_client_check_dead(w))) {
1616 debug(D_WEB_CLIENT, "%llu: client is dead.", w->id);
1617 break;
1618 }
1618 - else if(unlikely(!w->wait_receive && !w->wait_send)) {
1619 + else if(unlikely(!web_client_has_wait_receive(w) && !web_client_has_wait_send(w))) {
1620 debug(D_WEB_CLIENT, "%llu: client is not set for neither receiving nor sending data.", w->id);
1621 break;
1622 }
@@ -1630,8 +1631,8 @@ void *web_client_main(void *ptr)
1631 fds[0].events = 0;
1632 fds[0].revents = 0;
1633
1633 - if(w->wait_receive) fds[0].events |= POLLIN;
1634 - if(w->wait_send) fds[0].events |= POLLOUT;
1634 + if(web_client_has_wait_receive(w)) fds[0].events |= POLLIN;
1635 + if(web_client_has_wait_send(w)) fds[0].events |= POLLOUT;
1636
1637 fds[1].fd = -1;
1638 fds[1].events = 0;
@@ -1645,19 +1646,19 @@ void *web_client_main(void *ptr)
1646 fds[0].fd = w->ifd;
1647 fds[0].events = 0;
1648 fds[0].revents = 0;
1648 - if(w->wait_receive) fds[0].events |= POLLIN;
1649 + if(web_client_has_wait_receive(w)) fds[0].events |= POLLIN;
1650 ifd = &fds[0];
1651
1652 fds[1].fd = w->ofd;
1653 fds[1].events = 0;
1654 fds[1].revents = 0;
1654 - if(w->wait_send) fds[1].events |= POLLOUT;
1655 + if(web_client_has_wait_send(w)) fds[1].events |= POLLOUT;
1656 ofd = &fds[1];
1657
1658 fdmax = 2;
1659 }
1660
1660 - debug(D_WEB_CLIENT, "%llu: Waiting socket async I/O for %s %s", w->id, w->wait_receive?"INPUT":"", w->wait_send?"OUTPUT":"");
1661 + debug(D_WEB_CLIENT, "%llu: Waiting socket async I/O for %s %s", w->id, web_client_has_wait_receive(w)?"INPUT":"", web_client_has_wait_send(w)?"OUTPUT":"");
1662 errno = 0;
1663 timeout = web_client_timeout * 1000;
1664 retval = poll(fds, fdmax, timeout);
@@ -1674,14 +1675,14 @@ void *web_client_main(void *ptr)
1675 break;
1676 }
1677 else if(unlikely(!retval)) {
1677 - debug(D_WEB_CLIENT, "%llu: Timeout while waiting socket async I/O for %s %s", w->id, w->wait_receive?"INPUT":"", w->wait_send?"OUTPUT":"");
1678 + debug(D_WEB_CLIENT, "%llu: Timeout while waiting socket async I/O for %s %s", w->id, web_client_has_wait_receive(w)?"INPUT":"", web_client_has_wait_send(w)?"OUTPUT":"");
1679 break;
1680 }
1681
1682 if(unlikely(netdata_exit)) break;
1683
1684 int used = 0;
1684 - if(w->wait_send && ofd->revents & POLLOUT) {
1685 + if(web_client_has_wait_send(w) && ofd->revents & POLLOUT) {
1686 used++;
1687 if(web_client_send(w) < 0) {
1688 debug(D_WEB_CLIENT, "%llu: Cannot send data to client. Closing client.", w->id);
@@ -1691,7 +1692,7 @@ void *web_client_main(void *ptr)
1692
1693 if(unlikely(netdata_exit)) break;
1694
1694 - if(w->wait_receive && (ifd->revents & POLLIN || ifd->revents & POLLPRI)) {
1695 + if(web_client_has_wait_receive(w) && (ifd->revents & POLLIN || ifd->revents & POLLPRI)) {
1696 used++;
1697 if(web_client_receive(w) < 0) {
1698 debug(D_WEB_CLIENT, "%llu: Cannot receive data from client. Closing client.", w->id);
@@ -1732,7 +1733,7 @@ void *web_client_main(void *ptr)
1733 w->ifd = -1;
1734 w->ofd = -1;
1735
1735 - w->obsolete = 1;
1736 + WEB_CLIENT_IS_OBSOLETE(w);
1737
1738 pthread_exit(NULL);
1739 return NULL;
src/web_client.h
+61 -16
@@ -20,6 +20,66 @@ typedef enum web_client_mode {
20 WEB_CLIENT_MODE_STREAM = 3
21 } WEB_CLIENT_MODE;
22
23 +typedef enum web_client_flags {
24 + WEB_CLIENT_FLAG_OBSOLETE = 1 << 0, // if set, the listener will remove this client
25 + // after setting this, you should not touch
26 + // this web_client
27 +
28 + WEB_CLIENT_FLAG_DEAD = 1 << 1, // if set, this client is dead
29 +
30 + WEB_CLIENT_FLAG_KEEPALIVE = 1 << 2, // if set, the web client will be re-used
31 +
32 + WEB_CLIENT_FLAG_WAIT_RECEIVE = 1 << 3, // if set, we are waiting more input data
33 + WEB_CLIENT_FLAG_WAIT_SEND = 1 << 4, // if set, we have data to send to the client
34 +
35 + WEB_CLIENT_FLAG_DO_NOT_TRACK = 1 << 5, // if set, we should not set cookies on this client
36 + WEB_CLIENT_FLAG_TRACKING_REQUIRED = 1 << 6, // if set, we need to send cookies
37 +
38 + WEB_CLIENT_FLAG_TCP_CLIENT = 1 << 7, // if set, the client is using a TCP socket
39 + WEB_CLIENT_FLAG_UNIX_CLIENT = 1 << 8 // if set, the client is using a UNIX socket
40 +} WEB_CLIENT_FLAGS;
41 +
42 +//#ifdef HAVE_C___ATOMIC
43 +//#define web_client_flag_check(w, flag) (__atomic_load_n(&((w)->flags), __ATOMIC_SEQ_CST) & flag)
44 +//#define web_client_flag_set(w, flag) __atomic_or_fetch(&((w)->flags), flag, __ATOMIC_SEQ_CST)
45 +//#define web_client_flag_clear(w, flag) __atomic_and_fetch(&((w)->flags), ~flag, __ATOMIC_SEQ_CST)
46 +//#else
47 +#define web_client_flag_check(w, flag) ((w)->flags & flag)
48 +#define web_client_flag_set(w, flag) (w)->flags |= flag
49 +#define web_client_flag_clear(w, flag) (w)->flags &= ~flag
50 +//#endif
51 +
52 +#define WEB_CLIENT_IS_OBSOLETE(w) web_client_flag_set(w, WEB_CLIENT_FLAG_OBSOLETE)
53 +#define web_client_check_obsolete(w) web_client_flag_check(w, WEB_CLIENT_FLAG_OBSOLETE)
54 +
55 +#define WEB_CLIENT_IS_DEAD(w) web_client_flag_set(w, WEB_CLIENT_FLAG_DEAD)
56 +#define web_client_check_dead(w) web_client_flag_check(w, WEB_CLIENT_FLAG_DEAD)
57 +
58 +#define web_client_has_keepalive(w) web_client_flag_check(w, WEB_CLIENT_FLAG_KEEPALIVE)
59 +#define web_client_enable_keepalive(w) web_client_flag_set(w, WEB_CLIENT_FLAG_KEEPALIVE)
60 +#define web_client_disable_keepalive(w) web_client_flag_clear(w, WEB_CLIENT_FLAG_KEEPALIVE)
61 +
62 +#define web_client_has_donottrack(w) web_client_flag_check(w, WEB_CLIENT_FLAG_DO_NOT_TRACK)
63 +#define web_client_enable_donottrack(w) web_client_flag_set(w, WEB_CLIENT_FLAG_DO_NOT_TRACK)
64 +#define web_client_disable_donottrack(w) web_client_flag_clear(w, WEB_CLIENT_FLAG_DO_NOT_TRACK)
65 +
66 +#define web_client_has_tracking_required(w) web_client_flag_check(w, WEB_CLIENT_FLAG_TRACKING_REQUIRED)
67 +#define web_client_enable_tracking_required(w) web_client_flag_set(w, WEB_CLIENT_FLAG_TRACKING_REQUIRED)
68 +#define web_client_disable_tracking_required(w) web_client_flag_clear(w, WEB_CLIENT_FLAG_TRACKING_REQUIRED)
69 +
70 +#define web_client_has_wait_receive(w) web_client_flag_check(w, WEB_CLIENT_FLAG_WAIT_RECEIVE)
71 +#define web_client_enable_wait_receive(w) web_client_flag_set(w, WEB_CLIENT_FLAG_WAIT_RECEIVE)
72 +#define web_client_disable_wait_receive(w) web_client_flag_clear(w, WEB_CLIENT_FLAG_WAIT_RECEIVE)
73 +
74 +#define web_client_has_wait_send(w) web_client_flag_check(w, WEB_CLIENT_FLAG_WAIT_SEND)
75 +#define web_client_enable_wait_send(w) web_client_flag_set(w, WEB_CLIENT_FLAG_WAIT_SEND)
76 +#define web_client_disable_wait_send(w) web_client_flag_clear(w, WEB_CLIENT_FLAG_WAIT_SEND)
77 +
78 +#define web_client_set_tcp(w) web_client_flag_set(w, WEB_CLIENT_FLAG_TCP_CLIENT)
79 +#define web_client_set_unix(w) web_client_flag_set(w, WEB_CLIENT_FLAG_UNIX_CLIENT)
80 +
81 +#define web_client_is_corkable(w) web_client_flag_check(w, WEB_CLIENT_FLAG_TCP_CLIENT)
82 +
83 #define URL_MAX 8192
84 #define ZLIB_CHUNK 16384
85 #define HTTP_RESPONSE_HEADER_SIZE 4096
@@ -50,20 +110,7 @@ struct response {
110 struct web_client {
111 unsigned long long id;
112
53 - uint8_t obsolete:1; // if set to 1, the listener will remove this client
54 - // after setting this to 1, you should not touch
55 - // this web_client
56 -
57 - uint8_t dead:1; // if set to 1, this client is dead
58 -
59 - uint8_t keepalive:1; // if set to 1, the web client will be re-used
60 -
61 - uint8_t wait_receive:1; // 1 = we are waiting more input data
62 - uint8_t wait_send:1; // 1 = we have data to send to the client
63 -
64 - uint8_t donottrack:1; // 1 = we should not set cookies on this client
65 - uint8_t tracking_required:1; // 1 = if the request requires cookies
66 -
113 + WEB_CLIENT_FLAGS flags; // status flags for the client
114 WEB_CLIENT_MODE mode; // the operational mode of the client
115
116 int tcp_cork; // 1 = we have a cork on the socket
@@ -94,8 +141,6 @@ struct web_client {
141 struct web_client *next;
142 };
143
97 -#define WEB_CLIENT_IS_DEAD(w) (w)->dead=1
98 -
144 extern struct web_client *web_clients;
145
146 extern uid_t web_files_uid(void);
src/web_server.c
+17 -11
@@ -89,7 +89,7 @@ static inline void cleanup_web_clients(void) {
89 struct web_client *w;
90
91 for (w = web_clients; w;) {
92 - if (w->obsolete) {
92 + if (web_client_check_obsolete(w)) {
93 debug(D_WEB_CLIENT, "%llu: Removing client.", w->id);
94 // pthread_cancel(w->thread);
95 // pthread_join(w->thread, NULL);
@@ -170,11 +170,11 @@ void *socket_listen_main_multi_threaded(void *ptr) {
170
171 if(pthread_create(&w->thread, NULL, web_client_main, w) != 0) {
172 error("%llu: failed to create new thread for web client.", w->id);
173 - w->obsolete = 1;
173 + WEB_CLIENT_IS_OBSOLETE(w);
174 }
175 else if(pthread_detach(w->thread) != 0) {
176 error("%llu: Cannot request detach of newly created web client thread.", w->id);
177 - w->obsolete = 1;
177 + WEB_CLIENT_IS_OBSOLETE(w);
178 }
179 }
180 }
@@ -200,7 +200,7 @@ void *socket_listen_main_multi_threaded(void *ptr) {
200 struct web_client *single_threaded_clients[FD_SETSIZE];
201
202 static inline int single_threaded_link_client(struct web_client *w, fd_set *ifds, fd_set *ofds, fd_set *efds, int *max) {
203 - if(unlikely(w->obsolete || w->dead || (!w->wait_receive && !w->wait_send)))
203 + if(unlikely(web_client_check_obsolete(w) || web_client_check_dead(w) || (!web_client_has_wait_receive(w) && !web_client_has_wait_send(w))))
204 return 1;
205
206 if(unlikely(w->ifd < 0 || w->ifd >= FD_SETSIZE || w->ofd < 0 || w->ofd >= FD_SETSIZE)) {
@@ -216,8 +216,8 @@ static inline int single_threaded_link_client(struct web_client *w, fd_set *ifds
216 FD_SET(w->ofd, efds);
217 }
218
219 - if(w->wait_receive) FD_SET(w->ifd, ifds);
220 - if(w->wait_send) FD_SET(w->ofd, ofds);
219 + if(web_client_has_wait_receive(w)) FD_SET(w->ifd, ifds);
220 + if(web_client_has_wait_send(w)) FD_SET(w->ofd, ofds);
221
222 single_threaded_clients[w->ifd] = w;
223 single_threaded_clients[w->ofd] = w;
@@ -229,13 +229,13 @@ static inline int single_threaded_unlink_client(struct web_client *w, fd_set *if
229 FD_CLR(w->ifd, efds);
230 if(unlikely(w->ifd != w->ofd)) FD_CLR(w->ofd, efds);
231
232 - if(w->wait_receive) FD_CLR(w->ifd, ifds);
233 - if(w->wait_send) FD_CLR(w->ofd, ofds);
232 + if(web_client_has_wait_receive(w)) FD_CLR(w->ifd, ifds);
233 + if(web_client_has_wait_send(w)) FD_CLR(w->ofd, ofds);
234
235 single_threaded_clients[w->ifd] = NULL;
236 single_threaded_clients[w->ofd] = NULL;
237
238 - if(unlikely(w->obsolete || w->dead || (!w->wait_receive && !w->wait_send)))
238 + if(unlikely(web_client_check_obsolete(w) || web_client_check_dead(w) || (!web_client_has_wait_receive(w) && !web_client_has_wait_send(w))))
239 return 1;
240
241 return 0;
@@ -302,6 +302,12 @@ void *socket_listen_main_single_threaded(void *ptr) {
302 if (FD_ISSET(api_sockets.fds[i], &rifds)) {
303 debug(D_WEB_CLIENT_ACCESS, "LISTENER: new connection.");
304 w = web_client_create(api_sockets.fds[i]);
305 +
306 + if(api_sockets.fds_families[i] == AF_UNIX)
307 + web_client_set_unix(w);
308 + else
309 + web_client_set_tcp(w);
310 +
311 if (single_threaded_link_client(w, &ifds, &ofds, &ifds, &fdmax) != 0) {
312 web_client_free(w);
313 }
@@ -326,7 +332,7 @@ void *socket_listen_main_single_threaded(void *ptr) {
332 continue;
333 }
334
329 - if (unlikely(w->wait_receive && FD_ISSET(w->ifd, &rifds))) {
335 + if (unlikely(web_client_has_wait_receive(w) && FD_ISSET(w->ifd, &rifds))) {
336 if (unlikely(web_client_receive(w) < 0)) {
337 web_client_free(w);
338 continue;
@@ -338,7 +344,7 @@ void *socket_listen_main_single_threaded(void *ptr) {
344 }
345 }
346
341 - if (unlikely(w->wait_send && FD_ISSET(w->ofd, &rofds))) {
347 + if (unlikely(web_client_has_wait_send(w) && FD_ISSET(w->ofd, &rofds))) {
348 if (unlikely(web_client_send(w) < 0)) {
349 debug(D_WEB_CLIENT, "%llu: Cannot send data to client. Closing client.", w->id);
350 web_client_free(w);