mirror of https://github.com/omar-polo/gmid.git
one FastCGI connection per client
FastCGI is designed to multiplex requests over a single connection, so ideally the server can open only one connection per worker to the FastCGI application and that's that. Doing this kind of multiplexing makes the code harder to follow and easier to break/leak etc on the gmid side however. OpenBSD' httpd seems to open one connection per client, so why can't we too? One connection per request is still way better (lighter) than using CGI, and we can avoid all the pitfalls of the multiplexing (keeping track of "live ids", properly shut down etc...)
This commit is contained in:
parent
3096da4ef4
commit
4cd2520965
2
ex.c
2
ex.c
|
@ -420,7 +420,7 @@ handle_imsg_fcgi_req(struct imsgbuf *ibuf, struct imsg *imsg, size_t datalen)
|
||||||
else
|
else
|
||||||
fd = fcgi_open_sock(f);
|
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);
|
imsg_flush(ibuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
145
fcgi.c
145
fcgi.c
|
@ -127,15 +127,12 @@ struct fcgi_end_req_body {
|
||||||
#define FCGI_MPXS_CONNS "FCGI_MPXS_CONNS"
|
#define FCGI_MPXS_CONNS "FCGI_MPXS_CONNS"
|
||||||
|
|
||||||
static int
|
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)
|
size_t padding)
|
||||||
{
|
{
|
||||||
memset(h, 0, sizeof(*h));
|
int id = 1;
|
||||||
|
|
||||||
/*
|
memset(h, 0, sizeof(*h));
|
||||||
* id=0 is reserved for status messages.
|
|
||||||
*/
|
|
||||||
id++;
|
|
||||||
|
|
||||||
h->version = FCGI_VERSION_1;
|
h->version = FCGI_VERSION_1;
|
||||||
h->type = type;
|
h->type = type;
|
||||||
|
@ -149,16 +146,12 @@ prepare_header(struct fcgi_header *h, int type, int id, size_t size,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
fcgi_begin_request(struct bufferevent *bev, int id)
|
fcgi_begin_request(struct bufferevent *bev)
|
||||||
{
|
{
|
||||||
struct fcgi_begin_req_record r;
|
struct fcgi_begin_req_record r;
|
||||||
|
|
||||||
if (id > UINT16_MAX)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
memset(&r, 0, sizeof(r));
|
memset(&r, 0, sizeof(r));
|
||||||
prepare_header(&r.header, FCGI_BEGIN_REQUEST, id,
|
prepare_header(&r.header, FCGI_BEGIN_REQUEST, sizeof(r.body), 0);
|
||||||
sizeof(r.body), 0);
|
|
||||||
assert(sizeof(r.body) == FCGI_HEADER_LEN);
|
assert(sizeof(r.body) == FCGI_HEADER_LEN);
|
||||||
|
|
||||||
r.body.role1 = 0;
|
r.body.role1 = 0;
|
||||||
|
@ -171,7 +164,7 @@ fcgi_begin_request(struct bufferevent *bev, int id)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
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)
|
const char *value)
|
||||||
{
|
{
|
||||||
struct fcgi_header h;
|
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[6] = ((vallen >> 8) & 0xFF);
|
||||||
s[7] = ( vallen & 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 ||
|
if (bufferevent_write(bev, &h, sizeof(h)) == -1 ||
|
||||||
bufferevent_write(bev, s, sizeof(s)) == -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
|
static int
|
||||||
fcgi_end_param(struct bufferevent *bev, int id)
|
fcgi_end_param(struct bufferevent *bev)
|
||||||
{
|
{
|
||||||
struct fcgi_header h;
|
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)
|
if (bufferevent_write(bev, &h, sizeof(h)) == -1)
|
||||||
return -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)
|
if (bufferevent_write(bev, &h, sizeof(h)) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return 0;
|
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
|
static inline int
|
||||||
recid(struct fcgi_header *h)
|
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
|
static inline int
|
||||||
|
@ -249,25 +228,13 @@ reclen(struct fcgi_header *h)
|
||||||
return h->content_len0 + (h->content_len1 << 8);
|
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
|
void
|
||||||
fcgi_read(struct bufferevent *bev, void *d)
|
fcgi_read(struct bufferevent *bev, void *d)
|
||||||
{
|
{
|
||||||
struct fcgi *fcgi = d;
|
struct client *c = d;
|
||||||
struct evbuffer *src = EVBUFFER_INPUT(bev);
|
struct evbuffer *src = EVBUFFER_INPUT(bev);
|
||||||
struct fcgi_header hdr;
|
struct fcgi_header hdr;
|
||||||
struct fcgi_end_req_body end;
|
struct fcgi_end_req_body end;
|
||||||
struct client *c;
|
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
#if DEBUG_FCGI
|
#if DEBUG_FCGI
|
||||||
|
@ -292,11 +259,10 @@ fcgi_read(struct bufferevent *bev, void *d)
|
||||||
|
|
||||||
memcpy(&hdr, EVBUFFER_DATA(src), sizeof(hdr));
|
memcpy(&hdr, EVBUFFER_DATA(src), sizeof(hdr));
|
||||||
|
|
||||||
c = try_client_by_id(recid(&hdr));
|
if (recid(&hdr) != 1) {
|
||||||
if (c == NULL) {
|
|
||||||
log_err(NULL,
|
log_err(NULL,
|
||||||
"got invalid client id %d from fcgi backend %d",
|
"got invalid client id %d from fcgi backend",
|
||||||
recid(&hdr), fcgi->id);
|
recid(&hdr));
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -322,8 +288,6 @@ fcgi_read(struct bufferevent *bev, void *d)
|
||||||
bufferevent_read(bev, &end, sizeof(end));
|
bufferevent_read(bev, &end, sizeof(end));
|
||||||
|
|
||||||
/* TODO: do something with the status? */
|
/* TODO: do something with the status? */
|
||||||
fcgi->pending--;
|
|
||||||
c->fcgi = -1;
|
|
||||||
c->type = REQUEST_DONE;
|
c->type = REQUEST_DONE;
|
||||||
client_write(c->bev, c);
|
client_write(c->bev, c);
|
||||||
break;
|
break;
|
||||||
|
@ -345,15 +309,10 @@ fcgi_read(struct bufferevent *bev, void *d)
|
||||||
}
|
}
|
||||||
|
|
||||||
evbuffer_drain(src, hdr.padding);
|
evbuffer_drain(src, hdr.padding);
|
||||||
|
|
||||||
if (fcgi->pending == 0 && shutting_down) {
|
|
||||||
fcgi_error(bev, EVBUFFER_EOF, fcgi);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err:
|
err:
|
||||||
fcgi_error(bev, EVBUFFER_ERROR, fcgi);
|
fcgi_error(bev, EVBUFFER_ERROR, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -368,31 +327,21 @@ fcgi_write(struct bufferevent *bev, void *d)
|
||||||
void
|
void
|
||||||
fcgi_error(struct bufferevent *bev, short err, void *d)
|
fcgi_error(struct bufferevent *bev, short err, void *d)
|
||||||
{
|
{
|
||||||
struct fcgi *fcgi = d;
|
struct client *c = d;
|
||||||
struct client *c;
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
if (!(err & (EVBUFFER_ERROR|EVBUFFER_EOF)))
|
if (!(err & (EVBUFFER_ERROR|EVBUFFER_EOF)))
|
||||||
log_warn(NULL, "unknown event error (%x): %s",
|
log_warn(NULL, "unknown event error (%x): %s",
|
||||||
err, strerror(errno));
|
err, strerror(errno));
|
||||||
|
|
||||||
for (i = 0; i < MAX_USERS; ++i) {
|
c->type = REQUEST_DONE;
|
||||||
c = &clients[i];
|
if (c->code != 0)
|
||||||
|
client_close(c);
|
||||||
if (c->fcgi != fcgi->id)
|
else
|
||||||
continue;
|
start_reply(c, CGI_ERROR, "CGI error");
|
||||||
|
|
||||||
if (c->code != 0)
|
|
||||||
client_close(c);
|
|
||||||
else
|
|
||||||
start_reply(c, CGI_ERROR, "CGI error");
|
|
||||||
}
|
|
||||||
|
|
||||||
fcgi_close_backend(fcgi);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
fcgi_req(struct fcgi *f, struct client *c)
|
fcgi_req(struct client *c)
|
||||||
{
|
{
|
||||||
char addr[NI_MAXHOST], buf[22];
|
char addr[NI_MAXHOST], buf[22];
|
||||||
int e;
|
int e;
|
||||||
|
@ -400,8 +349,6 @@ fcgi_req(struct fcgi *f, struct client *c)
|
||||||
struct tm tminfo;
|
struct tm tminfo;
|
||||||
struct envlist *p;
|
struct envlist *p;
|
||||||
|
|
||||||
f->pending++;
|
|
||||||
|
|
||||||
e = getnameinfo((struct sockaddr*)&c->addr, sizeof(c->addr),
|
e = getnameinfo((struct sockaddr*)&c->addr, sizeof(c->addr),
|
||||||
addr, sizeof(addr),
|
addr, sizeof(addr),
|
||||||
NULL, 0,
|
NULL, 0,
|
||||||
|
@ -410,50 +357,50 @@ fcgi_req(struct fcgi *f, struct client *c)
|
||||||
fatal("getnameinfo failed: %s (%s)",
|
fatal("getnameinfo failed: %s (%s)",
|
||||||
gai_strerror(e), strerror(errno));
|
gai_strerror(e), strerror(errno));
|
||||||
|
|
||||||
fcgi_begin_request(f->bev, c->id);
|
fcgi_begin_request(c->cgibev);
|
||||||
fcgi_send_param(f->bev, c->id, "GATEWAY_INTERFACE", "CGI/1.1");
|
fcgi_send_param(c->cgibev, "GATEWAY_INTERFACE", "CGI/1.1");
|
||||||
fcgi_send_param(f->bev, c->id, "GEMINI_URL_PATH", c->iri.path);
|
fcgi_send_param(c->cgibev, "GEMINI_URL_PATH", c->iri.path);
|
||||||
fcgi_send_param(f->bev, c->id, "QUERY_STRING", c->iri.query);
|
fcgi_send_param(c->cgibev, "QUERY_STRING", c->iri.query);
|
||||||
fcgi_send_param(f->bev, c->id, "REMOTE_ADDR", addr);
|
fcgi_send_param(c->cgibev, "REMOTE_ADDR", addr);
|
||||||
fcgi_send_param(f->bev, c->id, "REMOTE_HOST", addr);
|
fcgi_send_param(c->cgibev, "REMOTE_HOST", addr);
|
||||||
fcgi_send_param(f->bev, c->id, "REQUEST_METHOD", "");
|
fcgi_send_param(c->cgibev, "REQUEST_METHOD", "");
|
||||||
fcgi_send_param(f->bev, c->id, "SERVER_NAME", c->iri.host);
|
fcgi_send_param(c->cgibev, "SERVER_NAME", c->iri.host);
|
||||||
fcgi_send_param(f->bev, c->id, "SERVER_PROTOCOL", "GEMINI");
|
fcgi_send_param(c->cgibev, "SERVER_PROTOCOL", "GEMINI");
|
||||||
fcgi_send_param(f->bev, c->id, "SERVER_SOFTWARE", GMID_VERSION);
|
fcgi_send_param(c->cgibev, "SERVER_SOFTWARE", GMID_VERSION);
|
||||||
|
|
||||||
if (tls_peer_cert_provided(c->ctx)) {
|
if (tls_peer_cert_provided(c->ctx)) {
|
||||||
fcgi_send_param(f->bev, c->id, "AUTH_TYPE", "CERTIFICATE");
|
fcgi_send_param(c->cgibev, "AUTH_TYPE", "CERTIFICATE");
|
||||||
fcgi_send_param(f->bev, c->id, "REMOTE_USER",
|
fcgi_send_param(c->cgibev, "REMOTE_USER",
|
||||||
tls_peer_cert_subject(c->ctx));
|
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));
|
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));
|
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));
|
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));
|
tls_conn_cipher(c->ctx));
|
||||||
|
|
||||||
snprintf(buf, sizeof(buf), "%d",
|
snprintf(buf, sizeof(buf), "%d",
|
||||||
tls_conn_cipher_strength(c->ctx));
|
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);
|
tim = tls_peer_cert_notbefore(c->ctx);
|
||||||
strftime(buf, sizeof(buf), "%FT%TZ",
|
strftime(buf, sizeof(buf), "%FT%TZ",
|
||||||
gmtime_r(&tim, &tminfo));
|
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);
|
tim = tls_peer_cert_notafter(c->ctx);
|
||||||
strftime(buf, sizeof(buf), "%FT%TZ",
|
strftime(buf, sizeof(buf), "%FT%TZ",
|
||||||
gmtime_r(&tim, &tminfo));
|
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) {
|
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
|
} 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)
|
if (fcgi_end_param(c->cgibev) == -1)
|
||||||
fcgi_error(f->bev, EVBUFFER_ERROR, f);
|
fcgi_error(c->cgibev, EVBUFFER_ERROR, c);
|
||||||
}
|
}
|
||||||
|
|
3
gmid.c
3
gmid.c
|
@ -332,9 +332,6 @@ free_config(void)
|
||||||
fcgi[i].path = NULL;
|
fcgi[i].path = NULL;
|
||||||
fcgi[i].port = NULL;
|
fcgi[i].port = NULL;
|
||||||
fcgi[i].prog = NULL;
|
fcgi[i].prog = NULL;
|
||||||
|
|
||||||
fcgi[i].pending = 0;
|
|
||||||
fcgi[i].s = FCGI_OFF;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tls_free(ctx);
|
tls_free(ctx);
|
||||||
|
|
16
gmid.h
16
gmid.h
|
@ -79,17 +79,6 @@ struct fcgi {
|
||||||
char *path;
|
char *path;
|
||||||
char *port;
|
char *port;
|
||||||
char *prog;
|
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];
|
extern struct fcgi fcgi[FCGI_MAX];
|
||||||
|
|
||||||
|
@ -230,7 +219,6 @@ struct client {
|
||||||
int fd, pfd;
|
int fd, pfd;
|
||||||
struct dirent **dir;
|
struct dirent **dir;
|
||||||
int dirlen, diroff;
|
int dirlen, diroff;
|
||||||
int fcgi;
|
|
||||||
|
|
||||||
/* big enough to store STATUS + SPACE + META + CRLF */
|
/* big enough to store STATUS + SPACE + META + CRLF */
|
||||||
char sbuf[1029];
|
char sbuf[1029];
|
||||||
|
@ -366,12 +354,10 @@ int recv_fd(int);
|
||||||
int executor_main(struct imsgbuf*);
|
int executor_main(struct imsgbuf*);
|
||||||
|
|
||||||
/* fcgi.c */
|
/* fcgi.c */
|
||||||
void fcgi_abort_request(struct client *);
|
|
||||||
void fcgi_close_backend(struct fcgi *);
|
|
||||||
void fcgi_read(struct bufferevent *, void *);
|
void fcgi_read(struct bufferevent *, void *);
|
||||||
void fcgi_write(struct bufferevent *, void *);
|
void fcgi_write(struct bufferevent *, void *);
|
||||||
void fcgi_error(struct bufferevent *, short, void *);
|
void fcgi_error(struct bufferevent *, short, void *);
|
||||||
void fcgi_req(struct fcgi *, struct client *);
|
void fcgi_req(struct client *);
|
||||||
|
|
||||||
/* sandbox.c */
|
/* sandbox.c */
|
||||||
void sandbox_server_process(void);
|
void sandbox_server_process(void);
|
||||||
|
|
95
server.c
95
server.c
|
@ -612,24 +612,14 @@ apply_fastcgi(struct client *c)
|
||||||
if ((id = vhost_fastcgi(c->host, c->iri.path)) == -1)
|
if ((id = vhost_fastcgi(c->host, c->iri.path)) == -1)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
switch ((f = &fcgi[id])->s) {
|
f = &fcgi[id];
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1058,9 +1048,6 @@ client_error(struct bufferevent *bev, short error, void *d)
|
||||||
{
|
{
|
||||||
struct client *c = d;
|
struct client *c = d;
|
||||||
|
|
||||||
if (c->type == REQUEST_FCGI)
|
|
||||||
fcgi_abort_request(c);
|
|
||||||
|
|
||||||
c->type = REQUEST_DONE;
|
c->type = REQUEST_DONE;
|
||||||
|
|
||||||
if (error & EVBUFFER_TIMEOUT) {
|
if (error & EVBUFFER_TIMEOUT) {
|
||||||
|
@ -1178,9 +1165,6 @@ client_close(struct client *c)
|
||||||
* this point.
|
* this point.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (c->type == REQUEST_FCGI)
|
|
||||||
fcgi_abort_request(c);
|
|
||||||
|
|
||||||
if (c->cgibev != NULL) {
|
if (c->cgibev != NULL) {
|
||||||
bufferevent_disable(c->cgibev, EVBUFFER_READ|EVBUFFER_WRITE);
|
bufferevent_disable(c->cgibev, EVBUFFER_READ|EVBUFFER_WRITE);
|
||||||
bufferevent_free(c->cgibev);
|
bufferevent_free(c->cgibev);
|
||||||
|
@ -1317,7 +1301,6 @@ do_accept(int sock, short et, void *d)
|
||||||
c->pfd = -1;
|
c->pfd = -1;
|
||||||
c->dir = NULL;
|
c->dir = NULL;
|
||||||
c->addr = addr;
|
c->addr = addr;
|
||||||
c->fcgi = -1;
|
|
||||||
|
|
||||||
event_once(c->fd, EV_READ|EV_WRITE, handle_handshake,
|
event_once(c->fd, EV_READ|EV_WRITE, handle_handshake,
|
||||||
c, NULL);
|
c, NULL);
|
||||||
|
@ -1370,51 +1353,37 @@ static void
|
||||||
handle_imsg_fcgi_fd(struct imsgbuf *ibuf, struct imsg *imsg, size_t len)
|
handle_imsg_fcgi_fd(struct imsgbuf *ibuf, struct imsg *imsg, size_t len)
|
||||||
{
|
{
|
||||||
struct client *c;
|
struct client *c;
|
||||||
struct fcgi *f;
|
int id;
|
||||||
int i, id;
|
|
||||||
|
|
||||||
id = imsg->hdr.peerid;
|
id = imsg->hdr.peerid;
|
||||||
f = &fcgi[id];
|
|
||||||
|
|
||||||
if ((f->fd = imsg->fd) == -1)
|
if ((c = try_client_by_id(id)) == NULL) {
|
||||||
f->s = FCGI_OFF;
|
if (imsg->fd != -1)
|
||||||
else {
|
close(imsg->fd);
|
||||||
mark_nonblock(f->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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < MAX_USERS; ++i) {
|
if ((c->pfd = imsg->fd) == -1) {
|
||||||
c = &clients[i];
|
start_reply(c, CGI_ERROR, "CGI error");
|
||||||
if (c->fd == -1)
|
return;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
static void
|
||||||
handle_imsg_quit(struct imsgbuf *ibuf, struct imsg *imsg, size_t len)
|
handle_imsg_quit(struct imsgbuf *ibuf, struct imsg *imsg, size_t len)
|
||||||
{
|
{
|
||||||
size_t i;
|
|
||||||
|
|
||||||
(void)imsg;
|
(void)imsg;
|
||||||
(void)len;
|
(void)len;
|
||||||
|
|
||||||
|
@ -1432,16 +1401,6 @@ handle_imsg_quit(struct imsgbuf *ibuf, struct imsg *imsg, size_t len)
|
||||||
signal_del(&siginfo);
|
signal_del(&siginfo);
|
||||||
event_del(&imsgev);
|
event_del(&imsgev);
|
||||||
signal_del(&sigusr2);
|
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
|
static void
|
||||||
|
|
Loading…
Reference in New Issue