commit - 3096da4ef4418dc57f3e0b1fb1f89dceb2ca426a
commit + 4cd25209651f224be8c34d6006ef689963ce37d5
blob - 59943d75405ccea4ffd8ce6ece65376ae1fb2bbb
blob + d89026a80f709b253a27880d697b288bf61de822
--- ex.c
+++ ex.c
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);
}
blob - 26da55cc33e4a0ecb4aaec6391320f5f8f6208b4
blob + 5e2ba5770fcd420374804073b8b738615c5bddfb
--- fcgi.c
+++ fcgi.c
#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)
{
+ int id = 1;
+
memset(h, 0, sizeof(*h));
- /*
- * id=0 is reserved for status messages.
- */
- id++;
-
h->version = FCGI_VERSION_1;
h->type = type;
h->req_id1 = (id >> 8);
}
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;
}
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;
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 ||
}
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
}
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
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;
}
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;
}
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
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;
struct tm tminfo;
struct envlist *p;
- f->pending++;
-
e = getnameinfo((struct sockaddr*)&c->addr, sizeof(c->addr),
addr, sizeof(addr),
NULL, 0,
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);
}
blob - d9d07ff1e9c7fe814928fde45c9cbccefe87a241
blob + c8d1b57df6cabd0e171e8e51531ee6b87868df98
--- gmid.c
+++ gmid.c
fcgi[i].path = NULL;
fcgi[i].port = NULL;
fcgi[i].prog = NULL;
-
- fcgi[i].pending = 0;
- fcgi[i].s = FCGI_OFF;
}
tls_free(ctx);
blob - 53fbca92887ec87d403105d8c5d1c9c8886c02eb
blob + 43c684fec0d931c7f6845d1a37fb8ee624a2db59
--- gmid.h
+++ gmid.h
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];
int fd, pfd;
struct dirent **dir;
int dirlen, diroff;
- int fcgi;
/* big enough to store STATUS + SPACE + META + CRLF */
char sbuf[1029];
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);
blob - 879a2b49e341c1fb3f2530612adc27b90fae8168
blob + 66202c460bbf1104741d192306a0c680e81a48c2
--- server.c
+++ server.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;
}
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;
* 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);
c->pfd = -1;
c->dir = NULL;
c->addr = addr;
- c->fcgi = -1;
event_once(c->fd, EV_READ|EV_WRITE, handle_handshake,
c, NULL);
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);
+ if ((c = try_client_by_id(id)) == NULL) {
+ if (imsg->fd != -1)
+ close(imsg->fd);
+ return;
+ }
- 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->pfd = imsg->fd) == -1) {
+ start_reply(c, CGI_ERROR, "CGI error");
+ return;
}
- for (i = 0; i < MAX_USERS; ++i) {
- c = &clients[i];
- if (c->fd == -1)
- continue;
- if (c->fcgi != id)
- continue;
+ mark_nonblock(c->pfd);
- if (f->s == FCGI_OFF) {
- c->fcgi = -1;
- start_reply(c, TEMP_FAILURE, "internal server error");
- } else
- fcgi_req(f, c);
+ 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;
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