diff options
author | Jo-Philipp Wich <jow@openwrt.org> | 2012-07-09 00:08:20 +0000 |
---|---|---|
committer | Jo-Philipp Wich <jow@openwrt.org> | 2012-07-09 00:08:20 +0000 |
commit | 86de034767ea5ce560a55fa1cb59fec9ea6fcc20 (patch) | |
tree | f26e65977da4b840cee9ce51b476c1755b5e5df8 | |
parent | 1f1cf1990b3114f66180fb022dc0f32343728cb3 (diff) | |
download | upstream-86de034767ea5ce560a55fa1cb59fec9ea6fcc20.tar.gz upstream-86de034767ea5ce560a55fa1cb59fec9ea6fcc20.tar.bz2 upstream-86de034767ea5ce560a55fa1cb59fec9ea6fcc20.zip |
uhttpd: various fixes
- avoid closing descriptors before removing them from uloop (#11755, #11830)
- do not auto-initialize ubus if no prefix is set (#11832)
- remove extraneous client context pointer from cgi and lua states
- code cleanups and debug message changes
SVN-Revision: 32651
-rw-r--r-- | package/uhttpd/Makefile | 2 | ||||
-rw-r--r-- | package/uhttpd/src/uhttpd-cgi.c | 83 | ||||
-rw-r--r-- | package/uhttpd/src/uhttpd-cgi.h | 3 | ||||
-rw-r--r-- | package/uhttpd/src/uhttpd-lua.c | 55 | ||||
-rw-r--r-- | package/uhttpd/src/uhttpd-lua.h | 3 | ||||
-rw-r--r-- | package/uhttpd/src/uhttpd-utils.c | 62 | ||||
-rw-r--r-- | package/uhttpd/src/uhttpd-utils.h | 6 | ||||
-rw-r--r-- | package/uhttpd/src/uhttpd.c | 78 | ||||
-rw-r--r-- | package/uhttpd/src/uhttpd.h | 3 |
9 files changed, 153 insertions, 142 deletions
diff --git a/package/uhttpd/Makefile b/package/uhttpd/Makefile index 7cd75807ea..89ca4b69e8 100644 --- a/package/uhttpd/Makefile +++ b/package/uhttpd/Makefile @@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=uhttpd -PKG_RELEASE:=37 +PKG_RELEASE:=38 PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) PKG_CONFIG_DEPENDS := \ diff --git a/package/uhttpd/src/uhttpd-cgi.c b/package/uhttpd/src/uhttpd-cgi.c index aa79478115..e527922624 100644 --- a/package/uhttpd/src/uhttpd-cgi.c +++ b/package/uhttpd/src/uhttpd-cgi.c @@ -128,8 +128,6 @@ static char * uh_cgi_header_lookup(struct http_response *res, static void uh_cgi_shutdown(struct uh_cgi_state *state) { - close(state->rfd); - close(state->wfd); free(state); } @@ -139,38 +137,36 @@ static bool uh_cgi_socket_cb(struct client *cl) char buf[UH_LIMIT_MSGHEAD]; struct uh_cgi_state *state = (struct uh_cgi_state *)cl->priv; - struct http_response *res = &state->cl->response; - struct http_request *req = &state->cl->request; + struct http_response *res = &cl->response; + struct http_request *req = &cl->request; /* there is unread post data waiting */ while (state->content_length > 0) { /* remaining data in http head buffer ... */ - if (state->cl->httpbuf.len > 0) + if (cl->httpbuf.len > 0) { - len = min(state->content_length, state->cl->httpbuf.len); + len = min(state->content_length, cl->httpbuf.len); - D("CGI: Child(%d) feed %d HTTP buffer bytes\n", - state->cl->proc.pid, len); + D("CGI: Child(%d) feed %d HTTP buffer bytes\n", cl->proc.pid, len); - memcpy(buf, state->cl->httpbuf.ptr, len); + memcpy(buf, cl->httpbuf.ptr, len); - state->cl->httpbuf.len -= len; - state->cl->httpbuf.ptr +=len; + cl->httpbuf.len -= len; + cl->httpbuf.ptr +=len; } /* read it from socket ... */ else { - len = uh_tcp_recv(state->cl, buf, + len = uh_tcp_recv(cl, buf, min(state->content_length, sizeof(buf))); if ((len < 0) && ((errno == EAGAIN) || (errno == EWOULDBLOCK))) break; D("CGI: Child(%d) feed %d/%d TCP socket bytes\n", - state->cl->proc.pid, len, - min(state->content_length, sizeof(buf))); + cl->proc.pid, len, min(state->content_length, sizeof(buf))); } if (len) @@ -179,16 +175,16 @@ static bool uh_cgi_socket_cb(struct client *cl) state->content_length = 0; /* ... write to CGI process */ - len = uh_raw_send(state->wfd, buf, len, + len = uh_raw_send(cl->wpipe.fd, buf, len, cl->server->conf->script_timeout); /* explicit EOF notification for the child */ if (state->content_length <= 0) - close(state->wfd); + uh_ufd_remove(&cl->wpipe); } /* try to read data from child */ - while ((len = uh_raw_recv(state->rfd, buf, sizeof(buf), -1)) > 0) + while ((len = uh_raw_recv(cl->rpipe.fd, buf, sizeof(buf), -1)) > 0) { /* we have not pushed out headers yet, parse input */ if (!state->header_sent) @@ -199,7 +195,7 @@ static bool uh_cgi_socket_cb(struct client *cl) if (uh_cgi_header_parse(res, state->httpbuf, len, &hdroff)) { /* write status */ - ensure_out(uh_http_sendf(state->cl, NULL, + ensure_out(uh_http_sendf(cl, NULL, "HTTP/%.1f %03d %s\r\n" "Connection: close\r\n", req->version, res->statuscode, res->statusmsg)); @@ -208,7 +204,7 @@ static bool uh_cgi_socket_cb(struct client *cl) if (!uh_cgi_header_lookup(res, "Location") && !uh_cgi_header_lookup(res, "Content-Type")) { - ensure_out(uh_http_send(state->cl, NULL, + ensure_out(uh_http_send(cl, NULL, "Content-Type: text/plain\r\n", -1)); } @@ -216,19 +212,19 @@ static bool uh_cgi_socket_cb(struct client *cl) if ((req->version > 1.0) && !uh_cgi_header_lookup(res, "Transfer-Encoding")) { - ensure_out(uh_http_send(state->cl, NULL, + ensure_out(uh_http_send(cl, NULL, "Transfer-Encoding: chunked\r\n", -1)); } /* write headers from CGI program */ foreach_header(i, res->headers) { - ensure_out(uh_http_sendf(state->cl, NULL, "%s: %s\r\n", + ensure_out(uh_http_sendf(cl, NULL, "%s: %s\r\n", res->headers[i], res->headers[i+1])); } /* terminate header */ - ensure_out(uh_http_send(state->cl, NULL, "\r\n", -1)); + ensure_out(uh_http_send(cl, NULL, "\r\n", -1)); state->header_sent = true; @@ -236,9 +232,9 @@ static bool uh_cgi_socket_cb(struct client *cl) if (hdroff < len) { D("CGI: Child(%d) relaying %d rest bytes\n", - state->cl->proc.pid, len - hdroff); + cl->proc.pid, len - hdroff); - ensure_out(uh_http_send(state->cl, req, + ensure_out(uh_http_send(cl, req, &buf[hdroff], len - hdroff)); } } @@ -257,7 +253,7 @@ static bool uh_cgi_socket_cb(struct client *cl) * build the required headers here. */ - ensure_out(uh_http_sendf(state->cl, NULL, + ensure_out(uh_http_sendf(cl, NULL, "HTTP/%.1f 200 OK\r\n" "Content-Type: text/plain\r\n" "%s\r\n", @@ -268,18 +264,16 @@ static bool uh_cgi_socket_cb(struct client *cl) state->header_sent = true; D("CGI: Child(%d) relaying %d invalid bytes\n", - state->cl->proc.pid, len); + cl->proc.pid, len); - ensure_out(uh_http_send(state->cl, req, buf, len)); + ensure_out(uh_http_send(cl, req, buf, len)); } } else { /* headers complete, pass through buffer to socket */ - D("CGI: Child(%d) relaying %d normal bytes\n", - state->cl->proc.pid, len); - - ensure_out(uh_http_send(state->cl, req, buf, len)); + D("CGI: Child(%d) relaying %d normal bytes\n", cl->proc.pid, len); + ensure_out(uh_http_send(cl, req, buf, len)); } } @@ -287,8 +281,7 @@ static bool uh_cgi_socket_cb(struct client *cl) if ((len == 0) || ((errno != EAGAIN) && (errno != EWOULDBLOCK) && (len == -1))) { - D("CGI: Child(%d) presumed dead [%s]\n", - state->cl->proc.pid, strerror(errno)); + D("CGI: Child(%d) presumed dead [%s]\n", cl->proc.pid, strerror(errno)); goto out; } @@ -298,17 +291,17 @@ static bool uh_cgi_socket_cb(struct client *cl) out: if (!state->header_sent) { - if (state->cl->timeout.pending) - uh_http_sendhf(state->cl, 502, "Bad Gateway", + if (cl->timeout.pending) + uh_http_sendhf(cl, 502, "Bad Gateway", "The CGI process did not produce any response\n"); else - uh_http_sendhf(state->cl, 504, "Gateway Timeout", + uh_http_sendhf(cl, 504, "Gateway Timeout", "The CGI process took too long to produce a " "response\n"); } else { - uh_http_send(state->cl, req, "", 0); + uh_http_send(cl, req, "", 0); } uh_cgi_shutdown(state); @@ -529,9 +522,13 @@ bool uh_cgi_request(struct client *cl, struct path_info *pi, default: memset(state, 0, sizeof(*state)); - state->cl = cl; - state->cl->pipe.fd = rfd[0]; - state->cl->proc.pid = child; + cl->rpipe.fd = rfd[0]; + cl->wpipe.fd = wfd[1]; + cl->proc.pid = child; + + /* make pipe non-blocking */ + fd_nonblock(cl->rpipe.fd); + fd_nonblock(cl->wpipe.fd); /* close unneeded pipe ends */ close(rfd[1]); @@ -554,12 +551,6 @@ bool uh_cgi_request(struct client *cl, struct path_info *pi, } } - state->rfd = rfd[0]; - fd_nonblock(state->rfd); - - state->wfd = wfd[1]; - fd_nonblock(state->wfd); - cl->cb = uh_cgi_socket_cb; cl->priv = state; diff --git a/package/uhttpd/src/uhttpd-cgi.h b/package/uhttpd/src/uhttpd-cgi.h index 18816bae11..fffcc5d353 100644 --- a/package/uhttpd/src/uhttpd-cgi.h +++ b/package/uhttpd/src/uhttpd-cgi.h @@ -28,9 +28,6 @@ struct uh_cgi_state { - int rfd; - int wfd; - struct client *cl; char httpbuf[UH_LIMIT_MSGHEAD]; int content_length; bool header_sent; diff --git a/package/uhttpd/src/uhttpd-lua.c b/package/uhttpd/src/uhttpd-lua.c index 10d6de402a..94626bb56b 100644 --- a/package/uhttpd/src/uhttpd-lua.c +++ b/package/uhttpd/src/uhttpd-lua.c @@ -250,8 +250,6 @@ lua_State * uh_lua_init(const struct config *conf) static void uh_lua_shutdown(struct uh_lua_state *state) { - close(state->rfd); - close(state->wfd); free(state); } @@ -266,31 +264,28 @@ static bool uh_lua_socket_cb(struct client *cl) while (state->content_length > 0) { /* remaining data in http head buffer ... */ - if (state->cl->httpbuf.len > 0) + if (cl->httpbuf.len > 0) { - len = min(state->content_length, state->cl->httpbuf.len); + len = min(state->content_length, cl->httpbuf.len); - D("Lua: Child(%d) feed %d HTTP buffer bytes\n", - state->cl->proc.pid, len); + D("Lua: Child(%d) feed %d HTTP buffer bytes\n", cl->proc.pid, len); - memcpy(buf, state->cl->httpbuf.ptr, len); + memcpy(buf, cl->httpbuf.ptr, len); - state->cl->httpbuf.len -= len; - state->cl->httpbuf.ptr += len; + cl->httpbuf.len -= len; + cl->httpbuf.ptr += len; } /* read it from socket ... */ else { - len = uh_tcp_recv(state->cl, buf, - min(state->content_length, sizeof(buf))); + len = uh_tcp_recv(cl, buf, min(state->content_length, sizeof(buf))); if ((len < 0) && ((errno == EAGAIN) || (errno == EWOULDBLOCK))) break; D("Lua: Child(%d) feed %d/%d TCP socket bytes\n", - state->cl->proc.pid, len, - min(state->content_length, sizeof(buf))); + cl->proc.pid, len, min(state->content_length, sizeof(buf))); } if (len) @@ -299,20 +294,20 @@ static bool uh_lua_socket_cb(struct client *cl) state->content_length = 0; /* ... write to Lua process */ - len = uh_raw_send(state->wfd, buf, len, + len = uh_raw_send(cl->wpipe.fd, buf, len, cl->server->conf->script_timeout); /* explicit EOF notification for the child */ if (state->content_length <= 0) - close(state->wfd); + uh_ufd_remove(&cl->wpipe); } /* try to read data from child */ - while ((len = uh_raw_recv(state->rfd, buf, sizeof(buf), -1)) > 0) + while ((len = uh_raw_recv(cl->rpipe.fd, buf, sizeof(buf), -1)) > 0) { /* pass through buffer to socket */ - D("Lua: Child(%d) relaying %d normal bytes\n", state->cl->proc.pid, len); - ensure_out(uh_tcp_send(state->cl, buf, len)); + D("Lua: Child(%d) relaying %d normal bytes\n", cl->proc.pid, len); + ensure_out(uh_tcp_send(cl, buf, len)); state->data_sent = true; } @@ -321,7 +316,7 @@ static bool uh_lua_socket_cb(struct client *cl) ((errno != EAGAIN) && (errno != EWOULDBLOCK) && (len == -1))) { D("Lua: Child(%d) presumed dead [%s]\n", - state->cl->proc.pid, strerror(errno)); + cl->proc.pid, strerror(errno)); goto out; } @@ -331,11 +326,11 @@ static bool uh_lua_socket_cb(struct client *cl) out: if (!state->data_sent) { - if (state->cl->timeout.pending) - uh_http_sendhf(state->cl, 502, "Bad Gateway", + if (cl->timeout.pending) + uh_http_sendhf(cl, 502, "Bad Gateway", "The Lua process did not produce any response\n"); else - uh_http_sendhf(state->cl, 504, "Gateway Timeout", + uh_http_sendhf(cl, 504, "Gateway Timeout", "The Lua process took too long to produce a " "response\n"); } @@ -557,9 +552,13 @@ bool uh_lua_request(struct client *cl, lua_State *L) default: memset(state, 0, sizeof(*state)); - state->cl = cl; - state->cl->pipe.fd = rfd[0]; - state->cl->proc.pid = child; + cl->rpipe.fd = rfd[0]; + cl->wpipe.fd = wfd[1]; + cl->proc.pid = child; + + /* make pipe non-blocking */ + fd_nonblock(cl->rpipe.fd); + fd_nonblock(cl->wpipe.fd); /* close unneeded pipe ends */ close(rfd[1]); @@ -582,12 +581,6 @@ bool uh_lua_request(struct client *cl, lua_State *L) } } - state->rfd = rfd[0]; - fd_nonblock(state->rfd); - - state->wfd = wfd[1]; - fd_nonblock(state->wfd); - cl->cb = uh_lua_socket_cb; cl->priv = state; diff --git a/package/uhttpd/src/uhttpd-lua.h b/package/uhttpd/src/uhttpd-lua.h index 9a10933fc7..ae573a3cec 100644 --- a/package/uhttpd/src/uhttpd-lua.h +++ b/package/uhttpd/src/uhttpd-lua.h @@ -33,9 +33,6 @@ struct uh_lua_state { - int rfd; - int wfd; - struct client *cl; char httpbuf[UH_LIMIT_MSGHEAD]; int content_length; bool data_sent; diff --git a/package/uhttpd/src/uhttpd-utils.c b/package/uhttpd/src/uhttpd-utils.c index d31f756d14..50b10e6050 100644 --- a/package/uhttpd/src/uhttpd-utils.c +++ b/package/uhttpd/src/uhttpd-utils.c @@ -119,7 +119,7 @@ bool uh_socket_wait(int fd, int sec, bool write) while (((rv = select(fd+1, write ? NULL : &fds, write ? &fds : NULL, NULL, &timeout)) < 0) && (errno == EINTR)) { - D("IO: Socket(%d) select interrupted: %s\n", + D("IO: FD(%d) select interrupted: %s\n", fd, strerror(errno)); continue; @@ -127,7 +127,7 @@ bool uh_socket_wait(int fd, int sec, bool write) if (rv <= 0) { - D("IO: Socket(%d) appears dead (rv=%d)\n", fd, rv); + D("IO: FD(%d) appears dead (rv=%d)\n", fd, rv); return false; } @@ -146,7 +146,7 @@ static int __uh_raw_send(struct client *cl, const char *buf, int len, int sec, { if (errno == EINTR) { - D("IO: Socket(%d) interrupted\n", cl->fd.fd); + D("IO: FD(%d) interrupted\n", cl->fd.fd); continue; } else if ((sec > 0) && (errno == EAGAIN || errno == EWOULDBLOCK)) @@ -156,7 +156,7 @@ static int __uh_raw_send(struct client *cl, const char *buf, int len, int sec, } else { - D("IO: Socket(%d) write error: %s\n", fd, strerror(errno)); + D("IO: FD(%d) write error: %s\n", fd, strerror(errno)); return -1; } } @@ -168,19 +168,19 @@ static int __uh_raw_send(struct client *cl, const char *buf, int len, int sec, */ else if (rv == 0) { - D("IO: Socket(%d) closed\n", fd); + D("IO: FD(%d) appears closed\n", fd); return 0; } else if (rv < len) { - D("IO: Socket(%d) short write %d/%d bytes\n", fd, rv, len); + D("IO: FD(%d) short write %d/%d bytes\n", fd, rv, len); len -= rv; buf += rv; continue; } else { - D("IO: Socket(%d) sent %d/%d bytes\n", fd, rv, len); + D("IO: FD(%d) sent %d/%d bytes\n", fd, rv, len); return rv; } } @@ -230,18 +230,18 @@ static int __uh_raw_recv(struct client *cl, char *buf, int len, int sec, } else { - D("IO: Socket(%d) read error: %s\n", fd, strerror(errno)); + D("IO: FD(%d) read error: %s\n", fd, strerror(errno)); return -1; } } else if (rv == 0) { - D("IO: Socket(%d) closed\n", fd); + D("IO: FD(%d) appears closed\n", fd); return 0; } else { - D("IO: Socket(%d) read %d bytes\n", fd, rv); + D("IO: FD(%d) read %d bytes\n", fd, rv); return rv; } } @@ -934,6 +934,9 @@ struct client * uh_client_add(int sock, struct listener *serv) new->fd.fd = sock; new->server = serv; + new->rpipe.fd = -1; + new->wpipe.fd = -1; + /* get remote endpoint addr */ sl = sizeof(struct sockaddr_in6); memset(&(new->peeraddr), 0, sl); @@ -948,6 +951,8 @@ struct client * uh_client_add(int sock, struct listener *serv) uh_clients = new; serv->n_clients++; + + D("IO: Client(%d) allocated\n", new->fd.fd); } return new; @@ -996,13 +1001,12 @@ void uh_client_remove(struct client *cl) if (cur->proc.pid) uloop_process_delete(&cur->proc); - if (cur->pipe.fd) - uloop_fd_delete(&cur->pipe); + D("IO: Client(%d) freeing\n", cur->fd.fd); - uloop_fd_delete(&cur->fd); - close(cur->fd.fd); + uh_ufd_remove(&cur->rpipe); + uh_ufd_remove(&cur->wpipe); + uh_ufd_remove(&cur->fd); - D("IO: Socket(%d) closing\n", cur->fd.fd); cur->server->n_clients--; free(cur); @@ -1012,6 +1016,34 @@ void uh_client_remove(struct client *cl) } +void uh_ufd_add(struct uloop_fd *u, uloop_fd_handler h, unsigned int ev) +{ + if (h != NULL) + { + u->cb = h; + uloop_fd_add(u, ev); + D("IO: FD(%d) added to uloop\n", u->fd); + } +} + +void uh_ufd_remove(struct uloop_fd *u) +{ + if (u->cb != NULL) + { + uloop_fd_delete(u); + D("IO: FD(%d) removed from uloop\n", u->fd); + u->cb = NULL; + } + + if (u->fd > -1) + { + close(u->fd); + D("IO: FD(%d) closed\n", u->fd); + u->fd = -1; + } +} + + #ifdef HAVE_CGI static struct interpreter *uh_interpreters = NULL; diff --git a/package/uhttpd/src/uhttpd-utils.h b/package/uhttpd/src/uhttpd-utils.h index 797b07def4..31047f5554 100644 --- a/package/uhttpd/src/uhttpd-utils.h +++ b/package/uhttpd/src/uhttpd-utils.h @@ -23,6 +23,9 @@ #include <pwd.h> #include <sys/stat.h> +#include <libubox/uloop.h> + + #ifdef HAVE_SHADOW #include <shadow.h> #endif @@ -123,7 +126,8 @@ struct client * uh_client_lookup(int sock); void uh_client_shutdown(struct client *cl); void uh_client_remove(struct client *cl); -#define uh_client_gc() uh_client_remove(NULL) +void uh_ufd_add(struct uloop_fd *u, uloop_fd_handler h, unsigned int ev); +void uh_ufd_remove(struct uloop_fd *u); #ifdef HAVE_CGI diff --git a/package/uhttpd/src/uhttpd.c b/package/uhttpd/src/uhttpd.c index 3237fbab57..9e5a574263 100644 --- a/package/uhttpd/src/uhttpd.c +++ b/package/uhttpd/src/uhttpd.c @@ -218,8 +218,7 @@ static int uh_socket_bind(fd_set *serv_fds, int *max_fd, fd_cloexec(sock); *max_fd = max(*max_fd, sock); - l->fd.cb = uh_listener_cb; - uloop_fd_add(&l->fd, ULOOP_READ); + uh_ufd_add(&l->fd, uh_listener_cb, ULOOP_READ); bound++; continue; @@ -514,7 +513,7 @@ static bool uh_dispatch_request(struct client *cl, struct http_request *req) return false; } -static void uh_client_cb(struct uloop_fd *u, unsigned int events); +static void uh_socket_cb(struct uloop_fd *u, unsigned int events); static void uh_listener_cb(struct uloop_fd *u, unsigned int events) { @@ -539,7 +538,8 @@ static void uh_listener_cb(struct uloop_fd *u, unsigned int events) if ((cl = uh_client_add(new_fd, serv)) != NULL) { /* add client socket to global fdset */ - uloop_fd_add(&cl->fd, ULOOP_READ); + uh_ufd_add(&cl->fd, uh_socket_cb, ULOOP_READ); + fd_cloexec(cl->fd.fd); #ifdef HAVE_TLS /* setup client tls context */ @@ -555,9 +555,6 @@ static void uh_listener_cb(struct uloop_fd *u, unsigned int events) } } #endif - - cl->fd.cb = uh_client_cb; - fd_cloexec(new_fd); } /* insufficient resources */ @@ -569,28 +566,33 @@ static void uh_listener_cb(struct uloop_fd *u, unsigned int events) } } -static void uh_pipe_cb(struct uloop_fd *u, unsigned int events) +static void uh_client_cb(struct client *cl, unsigned int events); + +static void uh_rpipe_cb(struct uloop_fd *u, unsigned int events) { - struct client *cl = container_of(u, struct client, pipe); + struct client *cl = container_of(u, struct client, rpipe); - if (!u->error) - { - D("SRV: Client(%d) pipe(%d) readable\n", - cl->fd.fd, cl->pipe.fd); + D("SRV: Client(%d) rpipe readable\n", cl->fd.fd); - uh_client_cb(&cl->fd, ULOOP_WRITE); - } + uh_client_cb(cl, ULOOP_WRITE); +} + +static void uh_socket_cb(struct uloop_fd *u, unsigned int events) +{ + struct client *cl = container_of(u, struct client, fd); + + D("SRV: Client(%d) socket readable\n", cl->fd.fd); + + uh_client_cb(cl, ULOOP_READ); } static void uh_child_cb(struct uloop_process *p, int rv) { struct client *cl = container_of(p, struct client, proc); - D("SRV: Client(%d) child(%d) is dead\n", cl->fd.fd, cl->proc.pid); + D("SRV: Client(%d) child(%d) dead\n", cl->fd.fd, cl->proc.pid); - cl->dead = true; - cl->fd.eof = true; - uh_client_cb(&cl->fd, ULOOP_READ | ULOOP_WRITE); + uh_client_cb(cl, ULOOP_READ | ULOOP_WRITE); } static void uh_kill9_cb(struct uloop_timeout *t) @@ -624,17 +626,15 @@ static void uh_timeout_cb(struct uloop_timeout *t) } } -static void uh_client_cb(struct uloop_fd *u, unsigned int events) +static void uh_client_cb(struct client *cl, unsigned int events) { int i; - struct client *cl; struct config *conf; struct http_request *req; - cl = container_of(u, struct client, fd); conf = cl->server->conf; - D("SRV: Client(%d) enter callback\n", u->fd); + D("SRV: Client(%d) enter callback\n", cl->fd.fd); /* undispatched yet */ if (!cl->dispatched) @@ -642,14 +642,14 @@ static void uh_client_cb(struct uloop_fd *u, unsigned int events) /* we have no headers yet and this was a write event, ignore... */ if (!(events & ULOOP_READ)) { - D("SRV: Client(%d) ignoring write event before headers\n", u->fd); + D("SRV: Client(%d) ignoring write event before headers\n", cl->fd.fd); return; } /* attempt to receive and parse headers */ if (!(req = uh_http_header_recv(cl))) { - D("SRV: Client(%d) failed to receive header\n", u->fd); + D("SRV: Client(%d) failed to receive header\n", cl->fd.fd); uh_client_shutdown(cl); return; } @@ -663,7 +663,7 @@ static void uh_client_cb(struct uloop_fd *u, unsigned int events) if (strcasecmp(req->headers[i+1], "100-continue")) { D("SRV: Client(%d) unknown expect header (%s)\n", - u->fd, req->headers[i+1]); + cl->fd.fd, req->headers[i+1]); uh_http_response(cl, 417, "Precondition Failed"); uh_client_shutdown(cl); @@ -671,7 +671,7 @@ static void uh_client_cb(struct uloop_fd *u, unsigned int events) } else { - D("SRV: Client(%d) sending HTTP/1.1 100 Continue\n", u->fd); + D("SRV: Client(%d) sending HTTP/1.1 100 Continue\n", cl->fd.fd); uh_http_sendf(cl, NULL, "HTTP/1.1 100 Continue\r\n\r\n"); cl->httpbuf.len = 0; /* client will re-send the body */ @@ -694,24 +694,23 @@ static void uh_client_cb(struct uloop_fd *u, unsigned int events) /* dispatch request */ if (!uh_dispatch_request(cl, req)) { - D("SRV: Client(%d) failed to dispach request\n", u->fd); + D("SRV: Client(%d) failed to dispach request\n", cl->fd.fd); uh_client_shutdown(cl); return; } /* request handler spawned a pipe, register handler */ - if (cl->pipe.fd) + if (cl->rpipe.fd > -1) { - D("SRV: Client(%d) pipe(%d) spawned\n", u->fd, cl->pipe.fd); + D("SRV: Client(%d) pipe(%d) spawned\n", cl->fd.fd, cl->rpipe.fd); - cl->pipe.cb = uh_pipe_cb; - uloop_fd_add(&cl->pipe, ULOOP_READ); + uh_ufd_add(&cl->rpipe, uh_rpipe_cb, ULOOP_READ); } /* request handler spawned a child, register handler */ if (cl->proc.pid) { - D("SRV: Client(%d) child(%d) spawned\n", u->fd, cl->proc.pid); + D("SRV: Client(%d) child(%d) spawned\n", cl->fd.fd, cl->proc.pid); cl->proc.cb = uh_child_cb; uloop_process_add(&cl->proc); @@ -721,13 +720,13 @@ static void uh_client_cb(struct uloop_fd *u, unsigned int events) } /* header processing complete */ - D("SRV: Client(%d) dispatched\n", u->fd); + D("SRV: Client(%d) dispatched\n", cl->fd.fd); cl->dispatched = true; } if (!cl->cb(cl)) { - D("SRV: Client(%d) response callback signalized EOF\n", u->fd); + D("SRV: Client(%d) response callback signalized EOF\n", cl->fd.fd); uh_client_shutdown(cl); return; } @@ -1098,7 +1097,7 @@ int main (int argc, char **argv) " -L file Lua handler script, omit to disable Lua\n" #endif #ifdef HAVE_UBUS - " -u string URL prefix for HTTP/JSON handler, default is '/ubus'\n" + " -u string URL prefix for HTTP/JSON handler\n" " -U file Override ubus socket path\n" #endif #ifdef HAVE_CGI @@ -1210,7 +1209,7 @@ int main (int argc, char **argv) "Notice: Unable to load ubus plugin - disabling ubus support! " "(Reason: %s)\n", dlerror()); } - else + else if (conf.ubus_prefix) { /* resolve functions */ if (!(conf.ubus_init = dlsym(lib, "uh_ubus_init")) || @@ -1224,10 +1223,7 @@ int main (int argc, char **argv) exit(1); } - /* default ubus prefix */ - if (!conf.ubus_prefix) - conf.ubus_prefix = "/ubus"; - + /* initialize ubus */ conf.ubus_state = conf.ubus_init(&conf); } #endif diff --git a/package/uhttpd/src/uhttpd.h b/package/uhttpd/src/uhttpd.h index 69fe21a418..fe86b01d40 100644 --- a/package/uhttpd/src/uhttpd.h +++ b/package/uhttpd/src/uhttpd.h @@ -160,7 +160,8 @@ struct client { SSL *tls; #endif struct uloop_fd fd; - struct uloop_fd pipe; + struct uloop_fd rpipe; + struct uloop_fd wpipe; struct uloop_process proc; struct uloop_timeout timeout; bool (*cb)(struct client *); |