commit - a6f2cfe7927f8385938f220016280629d3e8a6d9
commit + 0f7fdd21050e3795db896b99e542523c84e075d7
blob - 9452e306aa4eb3545ae87c9a4dd30836e029723a
blob + 7a141a58fe7808af08033bb33aa9643e5e19b143
--- fcgi.c
+++ fcgi.c
#include "gmid.h"
#include <assert.h>
+#include <ctype.h>
#include <errno.h>
#include <string.h>
reclen(struct fcgi_header *h)
{
return h->content_len0 + (h->content_len1 << 8);
+}
+
+static void
+fcgi_handle_stdout(struct client *c, struct evbuffer *src, size_t len)
+{
+ struct bufferevent *bev = c->cgibev;
+ char *t;
+ size_t l;
+ int code;
+
+ if (c->code == 0) {
+ l = len;
+ if (l > sizeof(c->sbuf) - c->soff)
+ l = sizeof(c->sbuf) - c->soff;
+
+ memcpy(&c->sbuf[c->soff], EVBUFFER_DATA(src), l);
+ c->soff += l;
+ evbuffer_drain(src, l);
+ len -= l;
+
+ if ((t = memmem(c->sbuf, c->soff, "\r\n", 2)) == NULL) {
+ if (c->soff == sizeof(c->sbuf)) {
+ log_warnx("FastCGI application is trying to"
+ " send a header that's too long.");
+ fcgi_error(bev, EVBUFFER_ERROR, c);
+ }
+
+ /* wait a bit */
+ return;
+ }
+ *t = '\0';
+ t += 2; /* skip CRLF */
+
+ if (!isdigit((unsigned char)c->sbuf[0]) ||
+ !isdigit((unsigned char)c->sbuf[1]) ||
+ c->sbuf[2] != ' ') {
+ fcgi_error(bev, EVBUFFER_ERROR, c);
+ return;
+ }
+
+ code = (c->sbuf[0] - '0') * 10 + (c->sbuf[1] - '0');
+ if (code < 10 || code >= 70) {
+ log_warnx("FastCGI application is trying to send an"
+ " invalid reply code: %d", code);
+ fcgi_error(bev, EVBUFFER_ERROR, c);
+ return;
+ }
+
+ start_reply(c, code, c->sbuf + 3);
+ if (c->code < 20 || c->code > 29) {
+ fcgi_error(bev, EVBUFFER_EOF, c);
+ return;
+ }
+
+ bufferevent_write(c->bev, t, &c->sbuf[c->soff] - t);
+ }
+
+ bufferevent_write(c->bev, EVBUFFER_DATA(src), len);
+ evbuffer_drain(src, len);
}
void
break;
case FCGI_STDOUT:
- bufferevent_write(c->bev, EVBUFFER_DATA(src), len);
- evbuffer_drain(src, len);
+ fcgi_handle_stdout(c, src, len);
break;
default:
{
struct client *c = d;
- if (!(err & (EVBUFFER_ERROR|EVBUFFER_EOF)))
- log_warn("unknown event error (%x)", err);
+ /*
+ * If we're here it means that some kind of non-recoverable
+ * error happened.
+ */
- c->type = REQUEST_DONE;
- if (c->code != 0)
- client_close(c);
- else
+ bufferevent_free(bev);
+ c->cgibev = NULL;
+
+ close(c->pfd);
+ c->pfd = -1;
+
+ /* EOF and no header */
+ if (c->code == 0) {
start_reply(c, CGI_ERROR, "CGI error");
+ return;
+ }
+
+ c->type = REQUEST_DONE;
+ client_write(c->bev, c);
}
void
blob - 885a7a7d669e99bb45a7818e2104d0e7beaff221
blob + 770deeae94340a541a8e2827b2574e8d371488e2
--- gmid.h
+++ gmid.h
/* big enough to store STATUS + SPACE + META + CRLF */
char sbuf[1029];
- ssize_t len, off;
+ size_t soff;
struct sockaddr_storage raddr;
socklen_t raddrlen;