-/* $OpenBSD: server_fcgi.c,v 1.5 2014/07/31 18:07:11 reyk Exp $ */
+/* $OpenBSD: server_fcgi.c,v 1.6 2014/08/01 08:34:46 florian Exp $ */
/*
* Copyright (c) 2014 Florian Obser <florian@openbsd.org>
if (connect(fd, (struct sockaddr *)&sun, sizeof(sun)) == -1)
goto fail;
+ clt->clt_fcgi_state = FCGI_READ_HEADER;
+ clt->clt_fcgi_toread = sizeof(struct fcgi_record_header);
+
+ if (clt->clt_srvevb != NULL)
+ evbuffer_free(clt->clt_srvevb);
+
+ clt->clt_srvevb = evbuffer_new();
+ if (clt->clt_srvevb == NULL) {
+ errstr = "failed to allocate evbuffer";
+ goto fail;
+ }
+
if (clt->clt_srvbev != NULL)
bufferevent_free(clt->clt_srvbev);
uint8_t buf[FCGI_RECORD_SIZE];
size_t len;
- len = bufferevent_read(bev, &buf, FCGI_RECORD_SIZE);
- DPRINTF("%s: %lu", __func__, len);
-
- h = (struct fcgi_record_header *) &buf;
- DPRINTF("%s: record header: version %d type %d id %d content len %d",
- __func__, h->version, h->type, ntohs(h->id),
- ntohs(h->content_len));
-
- if (h->type == FCGI_STDOUT && ntohs(h->content_len) > 0) {
- DPRINTF("%s", (char *) &buf +
- sizeof(struct fcgi_record_header));
-
- if (++clt->clt_chunk == 1)
- server_fcgi_header(clt, 200);
- server_bufferevent_write(clt, (char *)&buf +
- sizeof(struct fcgi_record_header),
- len - sizeof(struct fcgi_record_header));
+ len = bufferevent_read(bev, &buf, clt->clt_fcgi_toread);
+ /* XXX error handling */
+ evbuffer_add(clt->clt_srvevb, &buf, len);
+ clt->clt_fcgi_toread -= len;
+ DPRINTF("%s: len: %lu toread: %d state: %d", __func__, len,
+ clt->clt_fcgi_toread, clt->clt_fcgi_state);
+
+ if (clt->clt_fcgi_toread != 0)
+ return;
+
+ switch (clt->clt_fcgi_state) {
+ case FCGI_READ_HEADER:
+ clt->clt_fcgi_state = FCGI_READ_CONTENT;
+ h = (struct fcgi_record_header *)
+ EVBUFFER_DATA(clt->clt_srvevb);
+ DPRINTF("%s: record header: version %d type %d id %d "
+ "content len %d", __func__, h->version, h->type,
+ ntohs(h->id), ntohs(h->content_len));
+ clt->clt_fcgi_type = h->type;
+ clt->clt_fcgi_toread = ntohs(h->content_len);
+ evbuffer_drain(clt->clt_srvevb,
+ EVBUFFER_LENGTH(clt->clt_srvevb));
+ if (clt->clt_fcgi_toread != 0)
+ break;
+
+ /* fallthrough if content_len == 0 */
+ case FCGI_READ_CONTENT:
+ if (clt->clt_fcgi_type == FCGI_STDOUT &&
+ EVBUFFER_LENGTH(clt->clt_srvevb) > 0) {
+ if (++clt->clt_chunk == 1)
+ server_fcgi_header(clt, 200);
+ server_bufferevent_write_buffer(clt,
+ clt->clt_srvevb);
+ }
+ evbuffer_drain(clt->clt_srvevb,
+ EVBUFFER_LENGTH(clt->clt_srvevb));
+ clt->clt_fcgi_state = FCGI_READ_HEADER;
+ clt->clt_fcgi_toread =
+ sizeof(struct fcgi_record_header);
}
}