summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYorhel <git@yorhel.nl>2015-12-20 18:02:12 +0100
committerYorhel <git@yorhel.nl>2015-12-20 18:03:42 +0100
commitd9ebdd4921ed7f0c328b9606d90d1dc14ec11e9e (patch)
tree2ebcbfc95cad34ff44c857f8329bfa53af0f42b2
parent36f4c73123e70e437628f424a1c47877278ab335 (diff)
Handle more FastCGI records + set CLOEXEC|NONBLOCK on all sockets
Properly using CLOEXEC everywhere is mandatory when spawning (Fast)CGI processes later on.
-rw-r--r--src/app.c5
-rw-r--r--src/fconn_fastcgi.c72
-rw-r--r--src/util.c42
-rw-r--r--src/util.h2
4 files changed, 72 insertions, 49 deletions
diff --git a/src/app.c b/src/app.c
index ac3d217..0d3afda 100644
--- a/src/app.c
+++ b/src/app.c
@@ -39,6 +39,11 @@ static void front_accept_cb(EV_P_ ev_io *w, int revents) {
if(fd < 0 && (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN))
return;
+ if(util_fd_flags(fd, FCGY_NONBLOCK|FCGY_CLOEXEC) < 0) {
+ close(fd);
+ fd = -1;
+ }
+
if(fd < 0) {
fprintf(stderr, "Error accept()'ing: %s.\n", strerror(errno));
ev_io_stop(EV_A_ w);
diff --git a/src/fconn_fastcgi.c b/src/fconn_fastcgi.c
index 1d21603..e0f4132 100644
--- a/src/fconn_fastcgi.c
+++ b/src/fconn_fastcgi.c
@@ -26,25 +26,37 @@
#define req_cmp(c, val) (((int)(c)->reqs.a[i]->fconn_id) - ((int)val))
-static void handle_begin_request(fconn_fastcgi *c, uint16_t id, size_t len, const char *buf) {
- if(id == 0 || len < 8 || *buf != 0 || buf[1] < 1 || buf[1] > 3) {
+static void handle_get_values(fconn_fastcgi *c, fcgy_req *req, fastcgi_header h, const char *buf) {
+ /* TODO */
+}
+
+
+static void handle_begin_request(fconn_fastcgi *c, fcgy_req *req, fastcgi_header h, const char *buf) {
+ if(h.requestId == 0 || h.contentLength < 8 || *buf != 0 || buf[1] < 1 || buf[1] > 3) {
fprintf(stderr, "Invalid BEGIN_REQUEST record\n");
fconn_fastcgi_destroy(c);
return;
}
size_t n;
- vec_search_insert(c->reqs, n, req_cmp(c, id));
- if(n < c->reqs.n && c->reqs.a[n]->fconn_id == id) {
+ vec_search_insert(c->reqs, n, req_cmp(c, h.requestId));
+ if(n < c->reqs.n && c->reqs.a[n]->fconn_id == h.requestId) {
fprintf(stderr, "BEGIN_REQUEST record for existing request ID\n");
fconn_fastcgi_destroy(c);
return;
}
- *vec_insert_orderp(c->reqs, n) = req_create(c, id);
+ *vec_insert_orderp(c->reqs, n) = req_create(c, h.requestId);
+}
+
+
+static void handle_abort_request(fconn_fastcgi *c, fcgy_req *req, fastcgi_header h, const char *buf) {
+ req_unset_front(req);
+ vec_search(c->reqs, req_cmp(c, h.requestId), vec_remove_order(c->reqs, i));
}
-static void handle_params(fconn_fastcgi *c, fcgy_req *req, size_t len, const char *buf) {
+static void handle_params(fconn_fastcgi *c, fcgy_req *req, fastcgi_header h, const char *buf) {
+ size_t len = h.contentLength;
if(!len) /* End of param list. Should signal this to fcgy_req? */
return;
@@ -67,9 +79,8 @@ static void handle_params(fconn_fastcgi *c, fcgy_req *req, size_t len, const cha
}
-static fcgy_req *get_request(fconn_fastcgi *c, uint16_t id) {
- vec_search(c->reqs, req_cmp(c, id), return c->reqs.a[i]);
- return NULL;
+static void handle_data(fconn_fastcgi *c, fcgy_req *req, fastcgi_header h, const char *buf) {
+ /* TODO */
}
@@ -85,24 +96,43 @@ static void read_cb(fastcgi_reader *r, ssize_t len, fastcgi_header h, const char
fprintf(stderr, "Got FastCGI record: len = %4u, version = %u, type = %2u, requestId = %2u, contentLength = %4u\n",
(unsigned)len, (unsigned)h.version, (unsigned)h.type, (unsigned)h.requestId, (unsigned)h.contentLength);
- /* TODO: Handle management records here */
+ static const struct {
+ uint8_t type;
+ bool req; /* Must have an existing request object */
+ void (*cb)(fconn_fastcgi *, fcgy_req *, fastcgi_header, const char *);
+ } *handler = NULL, types[] = {
+ { FCGI_GET_VALUES, false, handle_get_values },
+ { FCGI_BEGIN_REQUEST, false, handle_begin_request },
+ { FCGI_ABORT_REQUEST, true, handle_abort_request },
+ { FCGI_PARAMS, true, handle_params },
+ { FCGI_STDIN, true, handle_data },
+ { FCGI_DATA, true, handle_data }
+ };
- if(h.type == FCGI_BEGIN_REQUEST) {
- handle_begin_request(c, h.requestId, h.contentLength, buf);
- return;
- }
+ size_t i;
+ for(i=0; i<sizeof(types)/sizeof(*types); i++)
+ if(types[i].type == h.type) {
+ handler = types+i;
+ break;
+ }
- fcgy_req *req = get_request(c, h.requestId);
- if(!req) {
- fprintf(stderr, "Received record for unknown request id (%u)\n", (unsigned)h.requestId);
- fconn_fastcgi_destroy(c);
+ if(!handler) {
+ fprintf(stderr, "Unknown record type %u\n", (unsigned)h.type);
+ /* TODO: Reply with FCGI_UNKNOWN_TYPE */
return;
}
- if(h.type == FCGI_PARAMS)
- handle_params(c, req, h.contentLength, buf);
+ fcgy_req *req = NULL;
+ if(handler->req) {
+ vec_search(c->reqs, req_cmp(c, h.requestId), req = c->reqs.a[i]);
+ if(!req) {
+ fprintf(stderr, "Received record for unknown request id (type = %u, id = %u)\n", (unsigned)h.type, (unsigned)h.requestId);
+ fconn_fastcgi_destroy(c);
+ return;
+ }
+ }
- /* TODO: Handle other request records here */
+ handler->cb(c, req, h, buf);
}
diff --git a/src/util.c b/src/util.c
index b789822..4f594df 100644
--- a/src/util.c
+++ b/src/util.c
@@ -23,49 +23,37 @@
#include "fcgy.h"
-int util_socket(int d, int t, int p, uint32_t flags) {
- int r = socket(d, t, p),
- fd = r;
+/* Only sets the flags, can't unset anything currently. */
+int util_fd_flags(int fd, uint32_t flags) {
+ int r;
- if(r >= 0 && flags & FCGY_NONBLOCK) {
- r = fcntl(fd, F_GETFL);
- if(r >= 0)
- r = fcntl(fd, F_SETFL, r|O_NONBLOCK);
- }
+ if(flags & FCGY_NONBLOCK)
+ if((r = fcntl(fd, F_GETFL)) < 0 || fcntl(fd, F_SETFL, r|O_NONBLOCK) < 0)
+ return -1;
- if(r >= 0 && flags & FCGY_CLOEXEC) {
- r = fcntl(fd, F_GETFD);
- if(r >= 0)
- r = fcntl(fd, F_SETFD, r|FD_CLOEXEC);
- }
+ if(flags & FCGY_CLOEXEC)
+ if((r = fcntl(fd, F_GETFD)) < 0 || fcntl(fd, F_SETFD, r|FD_CLOEXEC) < 0)
+ return -1;
- if(r < 0) {
- if(fd >= 0)
- close(fd);
- return r;
- }
- return fd;
+ return 0;
}
int util_serversock(int domain, void *addr, socklen_t addrlen, uint32_t flags) {
- int fd = util_socket(domain, SOCK_STREAM, 0, flags);
+ int fd = socket(domain, SOCK_STREAM, 0);
if(fd < 0)
return fd;
int r = 1;
- if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &r, sizeof(int)) < 0) {
- close(fd);
- return -1;
- }
-
#ifdef IPV6_V6ONLY
/* Can fail, ignore error */
- r = 1;
setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &r, sizeof(int));
#endif
- if(bind(fd, addr, addrlen) < 0 || listen(fd, 64) < 0) {
+ if(util_fd_flags(fd, flags) < 0
+ || setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &r, sizeof(int)) < 0
+ || bind(fd, addr, addrlen) < 0
+ || listen(fd, 64) < 0) {
close(fd);
return -1;
}
diff --git a/src/util.h b/src/util.h
index 091d1ff..d0c1867 100644
--- a/src/util.h
+++ b/src/util.h
@@ -26,7 +26,7 @@
#define FCGY_NONBLOCK 1
#define FCGY_CLOEXEC 2
-int util_socket(int, int, int, uint32_t);
+int util_fd_flags(int, uint32_t);
int util_serversock(int, void *, socklen_t, uint32_t);
#endif