diff --git a/ex.c b/ex.c index 59943d7..d89026a 100644 --- a/ex.c +++ b/ex.c @@ -420,7 +420,7 @@ handle_imsg_fcgi_req(struct imsgbuf *ibuf, struct imsg *imsg, size_t datalen) else fd = fcgi_open_sock(f); - imsg_compose(ibuf, IMSG_FCGI_FD, id, 0, fd, NULL, 0); + imsg_compose(ibuf, IMSG_FCGI_FD, imsg->hdr.peerid, 0, fd, NULL, 0); imsg_flush(ibuf); } diff --git a/fcgi.c b/fcgi.c index 26da55c..5e2ba57 100644 --- a/fcgi.c +++ b/fcgi.c @@ -127,15 +127,12 @@ struct fcgi_end_req_body { #define FCGI_MPXS_CONNS "FCGI_MPXS_CONNS" static int -prepare_header(struct fcgi_header *h, int type, int id, size_t size, +prepare_header(struct fcgi_header *h, int type, size_t size, size_t padding) { - memset(h, 0, sizeof(*h)); + int id = 1; - /* - * id=0 is reserved for status messages. - */ - id++; + memset(h, 0, sizeof(*h)); h->version = FCGI_VERSION_1; h->type = type; @@ -149,16 +146,12 @@ prepare_header(struct fcgi_header *h, int type, int id, size_t size, } static int -fcgi_begin_request(struct bufferevent *bev, int id) +fcgi_begin_request(struct bufferevent *bev) { struct fcgi_begin_req_record r; - if (id > UINT16_MAX) - return -1; - memset(&r, 0, sizeof(r)); - prepare_header(&r.header, FCGI_BEGIN_REQUEST, id, - sizeof(r.body), 0); + prepare_header(&r.header, FCGI_BEGIN_REQUEST, sizeof(r.body), 0); assert(sizeof(r.body) == FCGI_HEADER_LEN); r.body.role1 = 0; @@ -171,7 +164,7 @@ fcgi_begin_request(struct bufferevent *bev, int id) } static int -fcgi_send_param(struct bufferevent *bev, int id, const char *name, +fcgi_send_param(struct bufferevent *bev, const char *name, const char *value) { struct fcgi_header h; @@ -195,7 +188,7 @@ fcgi_send_param(struct bufferevent *bev, int id, const char *name, s[6] = ((vallen >> 8) & 0xFF); s[7] = ( vallen & 0xFF); - prepare_header(&h, FCGI_PARAMS, id, size, padlen); + prepare_header(&h, FCGI_PARAMS, size, padlen); if (bufferevent_write(bev, &h, sizeof(h)) == -1 || bufferevent_write(bev, s, sizeof(s)) == -1 || @@ -208,39 +201,25 @@ fcgi_send_param(struct bufferevent *bev, int id, const char *name, } static int -fcgi_end_param(struct bufferevent *bev, int id) +fcgi_end_param(struct bufferevent *bev) { struct fcgi_header h; - prepare_header(&h, FCGI_PARAMS, id, 0, 0); + prepare_header(&h, FCGI_PARAMS, 0, 0); if (bufferevent_write(bev, &h, sizeof(h)) == -1) return -1; - prepare_header(&h, FCGI_STDIN, id, 0, 0); + prepare_header(&h, FCGI_STDIN, 0, 0); if (bufferevent_write(bev, &h, sizeof(h)) == -1) return -1; return 0; } -void -fcgi_abort_request(struct client *c) -{ - struct fcgi *f; - struct fcgi_header h; - - f = &fcgi[c->fcgi]; - - prepare_header(&h, FCGI_ABORT_REQUEST, c->id, 0, 0); - - if (bufferevent_write(f->bev, &h, sizeof(h)) == -1) - fcgi_close_backend(f); -} - static inline int recid(struct fcgi_header *h) { - return h->req_id0 + (h->req_id1 << 8) - 1; + return h->req_id0 + (h->req_id1 << 8); } static inline int @@ -249,25 +228,13 @@ reclen(struct fcgi_header *h) return h->content_len0 + (h->content_len1 << 8); } -void -fcgi_close_backend(struct fcgi *f) -{ - bufferevent_free(f->bev); - f->bev = NULL; - close(fcgi->fd); - fcgi->fd = -1; - fcgi->pending = 0; - fcgi->s = FCGI_OFF; -} - void fcgi_read(struct bufferevent *bev, void *d) { - struct fcgi *fcgi = d; + struct client *c = d; struct evbuffer *src = EVBUFFER_INPUT(bev); struct fcgi_header hdr; struct fcgi_end_req_body end; - struct client *c; size_t len; #if DEBUG_FCGI @@ -292,11 +259,10 @@ fcgi_read(struct bufferevent *bev, void *d) memcpy(&hdr, EVBUFFER_DATA(src), sizeof(hdr)); - c = try_client_by_id(recid(&hdr)); - if (c == NULL) { + if (recid(&hdr) != 1) { log_err(NULL, - "got invalid client id %d from fcgi backend %d", - recid(&hdr), fcgi->id); + "got invalid client id %d from fcgi backend", + recid(&hdr)); goto err; } @@ -322,8 +288,6 @@ fcgi_read(struct bufferevent *bev, void *d) bufferevent_read(bev, &end, sizeof(end)); /* TODO: do something with the status? */ - fcgi->pending--; - c->fcgi = -1; c->type = REQUEST_DONE; client_write(c->bev, c); break; @@ -345,15 +309,10 @@ fcgi_read(struct bufferevent *bev, void *d) } evbuffer_drain(src, hdr.padding); - - if (fcgi->pending == 0 && shutting_down) { - fcgi_error(bev, EVBUFFER_EOF, fcgi); - return; - } } err: - fcgi_error(bev, EVBUFFER_ERROR, fcgi); + fcgi_error(bev, EVBUFFER_ERROR, c); } void @@ -368,31 +327,21 @@ fcgi_write(struct bufferevent *bev, void *d) void fcgi_error(struct bufferevent *bev, short err, void *d) { - struct fcgi *fcgi = d; - struct client *c; - size_t i; + struct client *c = d; if (!(err & (EVBUFFER_ERROR|EVBUFFER_EOF))) log_warn(NULL, "unknown event error (%x): %s", err, strerror(errno)); - for (i = 0; i < MAX_USERS; ++i) { - c = &clients[i]; - - if (c->fcgi != fcgi->id) - continue; - - if (c->code != 0) - client_close(c); - else - start_reply(c, CGI_ERROR, "CGI error"); - } - - fcgi_close_backend(fcgi); + c->type = REQUEST_DONE; + if (c->code != 0) + client_close(c); + else + start_reply(c, CGI_ERROR, "CGI error"); } void -fcgi_req(struct fcgi *f, struct client *c) +fcgi_req(struct client *c) { char addr[NI_MAXHOST], buf[22]; int e; @@ -400,8 +349,6 @@ fcgi_req(struct fcgi *f, struct client *c) struct tm tminfo; struct envlist *p; - f->pending++; - e = getnameinfo((struct sockaddr*)&c->addr, sizeof(c->addr), addr, sizeof(addr), NULL, 0, @@ -410,50 +357,50 @@ fcgi_req(struct fcgi *f, struct client *c) fatal("getnameinfo failed: %s (%s)", gai_strerror(e), strerror(errno)); - fcgi_begin_request(f->bev, c->id); - fcgi_send_param(f->bev, c->id, "GATEWAY_INTERFACE", "CGI/1.1"); - fcgi_send_param(f->bev, c->id, "GEMINI_URL_PATH", c->iri.path); - fcgi_send_param(f->bev, c->id, "QUERY_STRING", c->iri.query); - fcgi_send_param(f->bev, c->id, "REMOTE_ADDR", addr); - fcgi_send_param(f->bev, c->id, "REMOTE_HOST", addr); - fcgi_send_param(f->bev, c->id, "REQUEST_METHOD", ""); - fcgi_send_param(f->bev, c->id, "SERVER_NAME", c->iri.host); - fcgi_send_param(f->bev, c->id, "SERVER_PROTOCOL", "GEMINI"); - fcgi_send_param(f->bev, c->id, "SERVER_SOFTWARE", GMID_VERSION); + fcgi_begin_request(c->cgibev); + fcgi_send_param(c->cgibev, "GATEWAY_INTERFACE", "CGI/1.1"); + fcgi_send_param(c->cgibev, "GEMINI_URL_PATH", c->iri.path); + fcgi_send_param(c->cgibev, "QUERY_STRING", c->iri.query); + fcgi_send_param(c->cgibev, "REMOTE_ADDR", addr); + fcgi_send_param(c->cgibev, "REMOTE_HOST", addr); + fcgi_send_param(c->cgibev, "REQUEST_METHOD", ""); + fcgi_send_param(c->cgibev, "SERVER_NAME", c->iri.host); + fcgi_send_param(c->cgibev, "SERVER_PROTOCOL", "GEMINI"); + fcgi_send_param(c->cgibev, "SERVER_SOFTWARE", GMID_VERSION); if (tls_peer_cert_provided(c->ctx)) { - fcgi_send_param(f->bev, c->id, "AUTH_TYPE", "CERTIFICATE"); - fcgi_send_param(f->bev, c->id, "REMOTE_USER", + fcgi_send_param(c->cgibev, "AUTH_TYPE", "CERTIFICATE"); + fcgi_send_param(c->cgibev, "REMOTE_USER", tls_peer_cert_subject(c->ctx)); - fcgi_send_param(f->bev, c->id, "TLS_CLIENT_ISSUER", + fcgi_send_param(c->cgibev, "TLS_CLIENT_ISSUER", tls_peer_cert_issuer(c->ctx)); - fcgi_send_param(f->bev, c->id, "TLS_CLIENT_HASH", + fcgi_send_param(c->cgibev, "TLS_CLIENT_HASH", tls_peer_cert_hash(c->ctx)); - fcgi_send_param(f->bev, c->id, "TLS_VERSION", + fcgi_send_param(c->cgibev, "TLS_VERSION", tls_conn_version(c->ctx)); - fcgi_send_param(f->bev, c->id, "TLS_CIPHER", + fcgi_send_param(c->cgibev, "TLS_CIPHER", tls_conn_cipher(c->ctx)); snprintf(buf, sizeof(buf), "%d", tls_conn_cipher_strength(c->ctx)); - fcgi_send_param(f->bev, c->id, "TLS_CIPHER_STRENGTH", buf); + fcgi_send_param(c->cgibev, "TLS_CIPHER_STRENGTH", buf); tim = tls_peer_cert_notbefore(c->ctx); strftime(buf, sizeof(buf), "%FT%TZ", gmtime_r(&tim, &tminfo)); - fcgi_send_param(f->bev, c->id, "TLS_CLIENT_NOT_BEFORE", buf); + fcgi_send_param(c->cgibev, "TLS_CLIENT_NOT_BEFORE", buf); tim = tls_peer_cert_notafter(c->ctx); strftime(buf, sizeof(buf), "%FT%TZ", gmtime_r(&tim, &tminfo)); - fcgi_send_param(f->bev, c->id, "TLS_CLIENT_NOT_AFTER", buf); + fcgi_send_param(c->cgibev, "TLS_CLIENT_NOT_AFTER", buf); TAILQ_FOREACH(p, &c->host->params, envs) { - fcgi_send_param(f->bev, c->id, p->name, p->value); + fcgi_send_param(c->cgibev, p->name, p->value); } } else - fcgi_send_param(f->bev, c->id, "AUTH_TYPE", ""); + fcgi_send_param(c->cgibev, "AUTH_TYPE", ""); - if (fcgi_end_param(f->bev, c->id) == -1) - fcgi_error(f->bev, EVBUFFER_ERROR, f); + if (fcgi_end_param(c->cgibev) == -1) + fcgi_error(c->cgibev, EVBUFFER_ERROR, c); } diff --git a/gmid.c b/gmid.c index d9d07ff..c8d1b57 100644 --- a/gmid.c +++ b/gmid.c @@ -332,9 +332,6 @@ free_config(void) fcgi[i].path = NULL; fcgi[i].port = NULL; fcgi[i].prog = NULL; - - fcgi[i].pending = 0; - fcgi[i].s = FCGI_OFF; } tls_free(ctx); diff --git a/gmid.h b/gmid.h index 53fbca9..43c684f 100644 --- a/gmid.h +++ b/gmid.h @@ -79,17 +79,6 @@ struct fcgi { char *path; char *port; char *prog; - int fd; - - struct bufferevent *bev; - - /* number of pending clients */ - int pending; - -#define FCGI_OFF 0 -#define FCGI_INFLIGHT 1 -#define FCGI_READY 2 - int s; }; extern struct fcgi fcgi[FCGI_MAX]; @@ -230,7 +219,6 @@ struct client { int fd, pfd; struct dirent **dir; int dirlen, diroff; - int fcgi; /* big enough to store STATUS + SPACE + META + CRLF */ char sbuf[1029]; @@ -366,12 +354,10 @@ int recv_fd(int); int executor_main(struct imsgbuf*); /* fcgi.c */ -void fcgi_abort_request(struct client *); -void fcgi_close_backend(struct fcgi *); void fcgi_read(struct bufferevent *, void *); void fcgi_write(struct bufferevent *, void *); void fcgi_error(struct bufferevent *, short, void *); -void fcgi_req(struct fcgi *, struct client *); +void fcgi_req(struct client *); /* sandbox.c */ void sandbox_server_process(void); diff --git a/server.c b/server.c index 879a2b4..66202c4 100644 --- a/server.c +++ b/server.c @@ -612,24 +612,14 @@ apply_fastcgi(struct client *c) if ((id = vhost_fastcgi(c->host, c->iri.path)) == -1) return 0; - switch ((f = &fcgi[id])->s) { - case FCGI_OFF: - f->s = FCGI_INFLIGHT; - log_info(c, "opening fastcgi connection for (%s,%s,%s)", - f->path, f->port, f->prog); - imsg_compose(&exibuf, IMSG_FCGI_REQ, 0, 0, -1, - &id, sizeof(id)); - imsg_flush(&exibuf); - /* fallthrough */ - case FCGI_INFLIGHT: - c->fcgi = id; - break; - case FCGI_READY: - c->fcgi = id; - fcgi_req(f, c); - break; - } + f = &fcgi[id]; + log_debug(c, "opening fastcgi connection for (%s,%s,%s)", + f->path, f->port, f->prog); + + imsg_compose(&exibuf, IMSG_FCGI_REQ, c->id, 0, -1, + &id, sizeof(id)); + imsg_flush(&exibuf); return 1; } @@ -1058,9 +1048,6 @@ client_error(struct bufferevent *bev, short error, void *d) { struct client *c = d; - if (c->type == REQUEST_FCGI) - fcgi_abort_request(c); - c->type = REQUEST_DONE; if (error & EVBUFFER_TIMEOUT) { @@ -1178,9 +1165,6 @@ client_close(struct client *c) * this point. */ - if (c->type == REQUEST_FCGI) - fcgi_abort_request(c); - if (c->cgibev != NULL) { bufferevent_disable(c->cgibev, EVBUFFER_READ|EVBUFFER_WRITE); bufferevent_free(c->cgibev); @@ -1317,7 +1301,6 @@ do_accept(int sock, short et, void *d) c->pfd = -1; c->dir = NULL; c->addr = addr; - c->fcgi = -1; event_once(c->fd, EV_READ|EV_WRITE, handle_handshake, c, NULL); @@ -1370,51 +1353,37 @@ static void handle_imsg_fcgi_fd(struct imsgbuf *ibuf, struct imsg *imsg, size_t len) { struct client *c; - struct fcgi *f; - int i, id; + int id; id = imsg->hdr.peerid; - f = &fcgi[id]; - if ((f->fd = imsg->fd) == -1) - f->s = FCGI_OFF; - else { - mark_nonblock(f->fd); - - f->s = FCGI_READY; - - f->bev = bufferevent_new(f->fd, fcgi_read, fcgi_write, - fcgi_error, f); - if (f->bev == NULL) { - close(f->fd); - log_err(NULL, "%s: failed to allocate client buffer", - __func__); - f->s = FCGI_OFF; - } - - bufferevent_enable(f->bev, EV_READ|EV_WRITE); + if ((c = try_client_by_id(id)) == NULL) { + if (imsg->fd != -1) + close(imsg->fd); + return; } - for (i = 0; i < MAX_USERS; ++i) { - c = &clients[i]; - if (c->fd == -1) - continue; - if (c->fcgi != id) - continue; - - if (f->s == FCGI_OFF) { - c->fcgi = -1; - start_reply(c, TEMP_FAILURE, "internal server error"); - } else - fcgi_req(f, c); + if ((c->pfd = imsg->fd) == -1) { + start_reply(c, CGI_ERROR, "CGI error"); + return; } + + mark_nonblock(c->pfd); + + c->cgibev = bufferevent_new(c->pfd, fcgi_read, fcgi_write, + fcgi_error, c); + if (c->cgibev == NULL) { + start_reply(c, TEMP_FAILURE, "internal server error"); + return; + } + + bufferevent_enable(c->cgibev, EV_READ|EV_WRITE); + fcgi_req(c); } static void handle_imsg_quit(struct imsgbuf *ibuf, struct imsg *imsg, size_t len) { - size_t i; - (void)imsg; (void)len; @@ -1432,16 +1401,6 @@ handle_imsg_quit(struct imsgbuf *ibuf, struct imsg *imsg, size_t len) signal_del(&siginfo); event_del(&imsgev); signal_del(&sigusr2); - - for (i = 0; i < FCGI_MAX; ++i) { - if (fcgi[i].path == NULL && fcgi[i].prog == NULL) - break; - - if (fcgi[i].bev == NULL || fcgi[i].pending != 0) - continue; - - fcgi_close_backend(&fcgi[i]); - } } static void