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);