summaryrefslogtreecommitdiffstats
path: root/src/web_client.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/web_client.c')
-rw-r--r--src/web_client.c103
1 files changed, 56 insertions, 47 deletions
diff --git a/src/web_client.c b/src/web_client.c
index 7da080705..6ec3e11e3 100644
--- a/src/web_client.c
+++ b/src/web_client.c
@@ -17,10 +17,11 @@ unsigned long long web_clients_count = 0;
static inline int web_client_crock_socket(struct web_client *w) {
#ifdef TCP_CORK
- if(likely(!w->tcp_cork && w->ofd != -1)) {
+ if(likely(web_client_is_corkable(w) && !w->tcp_cork && w->ofd != -1)) {
w->tcp_cork = 1;
if(unlikely(setsockopt(w->ofd, IPPROTO_TCP, TCP_CORK, (char *) &w->tcp_cork, sizeof(int)) != 0)) {
error("%llu: failed to enable TCP_CORK on socket.", w->id);
+
w->tcp_cork = 0;
return -1;
}
@@ -78,7 +79,7 @@ struct web_client *web_client_create(int listener) {
w->response.header = buffer_create(HTTP_RESPONSE_HEADER_SIZE);
w->response.header_output = buffer_create(HTTP_RESPONSE_HEADER_SIZE);
w->origin[0] = '*';
- w->wait_receive = 1;
+ web_client_enable_wait_receive(w);
if(web_clients) web_clients->prev = w;
w->next = web_clients;
@@ -150,9 +151,9 @@ void web_client_reset(struct web_client *w) {
w->mode = WEB_CLIENT_MODE_NORMAL;
w->tcp_cork = 0;
- w->donottrack = 0;
- w->tracking_required = 0;
- w->keepalive = 0;
+ web_client_disable_donottrack(w);
+ web_client_disable_tracking_required(w);
+ web_client_disable_keepalive(w);
w->decoded_url[0] = '\0';
buffer_reset(w->response.header_output);
@@ -162,8 +163,8 @@ void web_client_reset(struct web_client *w) {
w->response.sent = 0;
w->response.code = 0;
- w->wait_receive = 1;
- w->wait_send = 0;
+ web_client_enable_wait_receive(w);
+ web_client_disable_wait_send(w);
w->response.zoutput = 0;
@@ -210,14 +211,18 @@ uid_t web_files_uid(void) {
static uid_t owner_uid = 0;
if(unlikely(!web_owner)) {
- web_owner = config_get(CONFIG_SECTION_WEB, "web files owner", config_get(CONFIG_SECTION_GLOBAL, "run as user", ""));
+ // getpwuid() is not thread safe,
+ // but we have called this function once
+ // while single threaded
+ struct passwd *pw = getpwuid(geteuid());
+ web_owner = config_get(CONFIG_SECTION_WEB, "web files owner", (pw)?(pw->pw_name?pw->pw_name:""):"");
if(!web_owner || !*web_owner)
owner_uid = geteuid();
else {
// getpwnam() is not thread safe,
// but we have called this function once
// while single threaded
- struct passwd *pw = getpwnam(web_owner);
+ pw = getpwnam(web_owner);
if(!pw) {
error("User '%s' is not present. Ignoring option.", web_owner);
owner_uid = geteuid();
@@ -237,14 +242,18 @@ gid_t web_files_gid(void) {
static gid_t owner_gid = 0;
if(unlikely(!web_group)) {
- web_group = config_get(CONFIG_SECTION_WEB, "web files group", config_get(CONFIG_SECTION_WEB, "web files owner", ""));
+ // getgrgid() is not thread safe,
+ // but we have called this function once
+ // while single threaded
+ struct group *gr = getgrgid(getegid());
+ web_group = config_get(CONFIG_SECTION_WEB, "web files group", (gr)?(gr->gr_name?gr->gr_name:""):"");
if(!web_group || !*web_group)
owner_gid = getegid();
else {
// getgrnam() is not thread safe,
// but we have called this function once
// while single threaded
- struct group *gr = getgrnam(web_group);
+ gr = getgrnam(web_group);
if(!gr) {
error("Group '%s' is not present. Ignoring option.", web_group);
owner_gid = getegid();
@@ -383,8 +392,8 @@ int mysendfile(struct web_client *w, char *filename) {
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);
w->mode = WEB_CLIENT_MODE_FILECOPY;
- w->wait_receive = 1;
- w->wait_send = 0;
+ web_client_enable_wait_receive(w);
+ web_client_disable_wait_send(w);
buffer_flush(w->response.data);
w->response.rlen = stat.st_size;
#ifdef __APPLE__
@@ -723,11 +732,11 @@ static inline char *http_header_parse(struct web_client *w, char *s) {
else if(hash == hash_connection && !strcasecmp(s, "Connection")) {
if(strcasestr(v, "keep-alive"))
- w->keepalive = 1;
+ web_client_enable_keepalive(w);
}
else if(respect_web_browser_do_not_track_policy && hash == hash_donottrack && !strcasecmp(s, "DNT")) {
- if(*v == '0') w->donottrack = 0;
- else if(*v == '1') w->donottrack = 1;
+ if(*v == '0') web_client_disable_donottrack(w);
+ else if(*v == '1') web_client_enable_donottrack(w);
}
#ifdef NETDATA_WITH_ZLIB
else if(hash == hash_accept_encoding && !strcasecmp(s, "Accept-Encoding")) {
@@ -776,7 +785,7 @@ static inline HTTP_VALIDATION http_request_validate(struct web_client *w) {
w->mode = WEB_CLIENT_MODE_STREAM;
}
else {
- w->wait_receive = 0;
+ web_client_disable_wait_receive(w);
return HTTP_VALIDATION_NOT_SUPPORTED;
}
@@ -792,7 +801,7 @@ static inline HTTP_VALIDATION http_request_validate(struct web_client *w) {
// incomplete requests
if(unlikely(!*s)) {
- w->wait_receive = 1;
+ web_client_enable_wait_receive(w);
return HTTP_VALIDATION_INCOMPLETE;
}
@@ -823,7 +832,7 @@ static inline HTTP_VALIDATION http_request_validate(struct web_client *w) {
// FIXME -- we should avoid it
strncpyz(w->last_url, w->decoded_url, URL_MAX);
- w->wait_receive = 0;
+ web_client_disable_wait_receive(w);
return HTTP_VALIDATION_OK;
}
@@ -833,7 +842,7 @@ static inline HTTP_VALIDATION http_request_validate(struct web_client *w) {
}
// incomplete request
- w->wait_receive = 1;
+ web_client_enable_wait_receive(w);
return HTTP_VALIDATION_INCOMPLETE;
}
@@ -876,7 +885,7 @@ static inline void web_client_send_http_header(struct web_client *w) {
"Content-Type: %s\r\n"
"Date: %s\r\n"
, w->response.code, code_msg
- , w->keepalive?"keep-alive":"close"
+ , web_client_has_keepalive(w)?"keep-alive":"close"
, w->origin
, content_type_string
, date
@@ -904,7 +913,7 @@ static inline void web_client_send_http_header(struct web_client *w) {
}
else {
if(respect_web_browser_do_not_track_policy) {
- if(w->tracking_required)
+ if(web_client_has_tracking_required(w))
buffer_sprintf(w->response.header_output,
"Tk: T;cookies\r\n");
else
@@ -946,7 +955,7 @@ static inline void web_client_send_http_header(struct web_client *w) {
}
else {
// we don't know the content length, disable keep-alive
- w->keepalive = 0;
+ web_client_disable_keepalive(w);
}
}
@@ -1234,8 +1243,8 @@ void web_client_process_request(struct web_client *w) {
web_client_send_http_header(w);
// enable sending immediately if we have data
- if(w->response.data->len) w->wait_send = 1;
- else w->wait_send = 0;
+ if(w->response.data->len) web_client_enable_wait_send(w);
+ else web_client_disable_wait_send(w);
switch(w->mode) {
case WEB_CLIENT_MODE_STREAM:
@@ -1253,7 +1262,7 @@ void web_client_process_request(struct web_client *w) {
case WEB_CLIENT_MODE_FILECOPY:
if(w->response.rlen) {
debug(D_WEB_CLIENT, "%llu: Done preparing the response. Will be sending data file of %zu bytes to client.", w->id, w->response.rlen);
- w->wait_receive = 1;
+ web_client_enable_wait_receive(w);
/*
// utilize the kernel sendfile() for copying the file to the socket.
@@ -1368,14 +1377,14 @@ ssize_t web_client_send_deflate(struct web_client *w)
if(t < 0) return t;
}
- if(w->mode == WEB_CLIENT_MODE_FILECOPY && w->wait_receive && w->response.rlen && w->response.rlen > w->response.data->len) {
+ if(w->mode == WEB_CLIENT_MODE_FILECOPY && web_client_has_wait_receive(w) && w->response.rlen && w->response.rlen > w->response.data->len) {
// we have to wait, more data will come
debug(D_WEB_CLIENT, "%llu: Waiting for more data to become available.", w->id);
- w->wait_send = 0;
+ web_client_disable_wait_send(w);
return t;
}
- if(unlikely(!w->keepalive)) {
+ if(unlikely(!web_client_has_keepalive(w))) {
debug(D_WEB_CLIENT, "%llu: Closing (keep-alive is not enabled). %zu bytes sent.", w->id, w->response.sent);
WEB_CLIENT_IS_DEAD(w);
return t;
@@ -1411,7 +1420,7 @@ ssize_t web_client_send_deflate(struct web_client *w)
// ask for FINISH if we have all the input
int flush = Z_SYNC_FLUSH;
if(w->mode == WEB_CLIENT_MODE_NORMAL
- || (w->mode == WEB_CLIENT_MODE_FILECOPY && !w->wait_receive && w->response.data->len == w->response.rlen)) {
+ || (w->mode == WEB_CLIENT_MODE_FILECOPY && !web_client_has_wait_receive(w) && w->response.data->len == w->response.rlen)) {
flush = Z_FINISH;
debug(D_DEFLATE, "%llu: Requesting Z_FINISH, if possible.", w->id);
}
@@ -1480,14 +1489,14 @@ ssize_t web_client_send(struct web_client *w) {
// A. we have done everything
// B. we temporarily have nothing to send, waiting for the buffer to be filled by ifd
- if(w->mode == WEB_CLIENT_MODE_FILECOPY && w->wait_receive && w->response.rlen && w->response.rlen > w->response.data->len) {
+ if(w->mode == WEB_CLIENT_MODE_FILECOPY && web_client_has_wait_receive(w) && w->response.rlen && w->response.rlen > w->response.data->len) {
// we have to wait, more data will come
debug(D_WEB_CLIENT, "%llu: Waiting for more data to become available.", w->id);
- w->wait_send = 0;
+ web_client_disable_wait_send(w);
return 0;
}
- if(unlikely(!w->keepalive)) {
+ if(unlikely(!web_client_has_keepalive(w))) {
debug(D_WEB_CLIENT, "%llu: Closing (keep-alive is not enabled). %zu bytes sent.", w->id, w->response.sent);
WEB_CLIENT_IS_DEAD(w);
return 0;
@@ -1541,10 +1550,10 @@ ssize_t web_client_receive(struct web_client *w)
debug(D_WEB_DATA, "%llu: Received data: '%s'.", w->id, &w->response.data->buffer[old]);
if(w->mode == WEB_CLIENT_MODE_FILECOPY) {
- w->wait_send = 1;
+ web_client_enable_wait_send(w);
if(w->response.rlen && w->response.data->len >= w->response.rlen)
- w->wait_receive = 0;
+ web_client_disable_wait_receive(w);
}
}
else if(likely(bytes == 0)) {
@@ -1557,7 +1566,7 @@ ssize_t web_client_receive(struct web_client *w)
if(w->mode == WEB_CLIENT_MODE_FILECOPY) {
// we are copying data from ifd to ofd
// let it finish copying...
- w->wait_receive = 0;
+ web_client_disable_wait_receive(w);
debug(D_WEB_CLIENT, "%llu: Read the whole file.", w->id);
if(w->ifd != w->ofd) close(w->ifd);
@@ -1603,11 +1612,11 @@ void *web_client_main(void *ptr)
for(;;) {
if(unlikely(netdata_exit)) break;
- if(unlikely(w->dead)) {
+ if(unlikely(web_client_check_dead(w))) {
debug(D_WEB_CLIENT, "%llu: client is dead.", w->id);
break;
}
- else if(unlikely(!w->wait_receive && !w->wait_send)) {
+ else if(unlikely(!web_client_has_wait_receive(w) && !web_client_has_wait_send(w))) {
debug(D_WEB_CLIENT, "%llu: client is not set for neither receiving nor sending data.", w->id);
break;
}
@@ -1622,8 +1631,8 @@ void *web_client_main(void *ptr)
fds[0].events = 0;
fds[0].revents = 0;
- if(w->wait_receive) fds[0].events |= POLLIN;
- if(w->wait_send) fds[0].events |= POLLOUT;
+ if(web_client_has_wait_receive(w)) fds[0].events |= POLLIN;
+ if(web_client_has_wait_send(w)) fds[0].events |= POLLOUT;
fds[1].fd = -1;
fds[1].events = 0;
@@ -1637,19 +1646,19 @@ void *web_client_main(void *ptr)
fds[0].fd = w->ifd;
fds[0].events = 0;
fds[0].revents = 0;
- if(w->wait_receive) fds[0].events |= POLLIN;
+ if(web_client_has_wait_receive(w)) fds[0].events |= POLLIN;
ifd = &fds[0];
fds[1].fd = w->ofd;
fds[1].events = 0;
fds[1].revents = 0;
- if(w->wait_send) fds[1].events |= POLLOUT;
+ if(web_client_has_wait_send(w)) fds[1].events |= POLLOUT;
ofd = &fds[1];
fdmax = 2;
}
- debug(D_WEB_CLIENT, "%llu: Waiting socket async I/O for %s %s", w->id, w->wait_receive?"INPUT":"", w->wait_send?"OUTPUT":"");
+ 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":"");
errno = 0;
timeout = web_client_timeout * 1000;
retval = poll(fds, fdmax, timeout);
@@ -1666,14 +1675,14 @@ void *web_client_main(void *ptr)
break;
}
else if(unlikely(!retval)) {
- 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":"");
+ 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":"");
break;
}
if(unlikely(netdata_exit)) break;
int used = 0;
- if(w->wait_send && ofd->revents & POLLOUT) {
+ if(web_client_has_wait_send(w) && ofd->revents & POLLOUT) {
used++;
if(web_client_send(w) < 0) {
debug(D_WEB_CLIENT, "%llu: Cannot send data to client. Closing client.", w->id);
@@ -1683,7 +1692,7 @@ void *web_client_main(void *ptr)
if(unlikely(netdata_exit)) break;
- if(w->wait_receive && (ifd->revents & POLLIN || ifd->revents & POLLPRI)) {
+ if(web_client_has_wait_receive(w) && (ifd->revents & POLLIN || ifd->revents & POLLPRI)) {
used++;
if(web_client_receive(w) < 0) {
debug(D_WEB_CLIENT, "%llu: Cannot receive data from client. Closing client.", w->id);
@@ -1724,7 +1733,7 @@ void *web_client_main(void *ptr)
w->ifd = -1;
w->ofd = -1;
- w->obsolete = 1;
+ WEB_CLIENT_IS_OBSOLETE(w);
pthread_exit(NULL);
return NULL;