Hi I had a bit of trouble with this, but seems to be in good condition now.
plugins/cgi/cgi.c | 15 ++++++-- plugins/cgi/cgi.h | 10 ++++- plugins/cgi/event.c | 96 ++++++++++++++++++++++++++++++++++++++++++------ plugins/cgi/request.c | 5 ++- 4 files changed, 108 insertions(+), 18 deletions(-) - Lauri
>From 93baa9a15c94aa8c7599e5e701cfd814a37edf05 Mon Sep 17 00:00:00 2001 From: Lauri Kasanen <[email protected]> Date: Fri, 6 Jul 2012 14:49:25 +0300 Subject: [PATCH] cgi: Pass headers through monkey, support chunked encoding Signed-off-by: Lauri Kasanen <[email protected]> --- plugins/cgi/cgi.c | 15 ++++++-- plugins/cgi/cgi.h | 10 ++++- plugins/cgi/event.c | 96 ++++++++++++++++++++++++++++++++++++++++++------ plugins/cgi/request.c | 5 ++- 4 files changed, 108 insertions(+), 18 deletions(-) diff --git a/plugins/cgi/cgi.c b/plugins/cgi/cgi.c index 41865b4..409a71a 100644 --- a/plugins/cgi/cgi.c +++ b/plugins/cgi/cgi.c @@ -233,9 +233,18 @@ static int do_cgi(const char * const __restrict__ file, const char * const __res } - struct cgi_request *r = cgi_req_create(readpipe[0], socket); + struct cgi_request *r = cgi_req_create(readpipe[0], socket, sr, cs); if (!r) return 403; + if (r->sr->protocol >= HTTP_PROTOCOL_11 && + (r->sr->headers.status < MK_REDIR_MULTIPLE || + r->sr->headers.status > MK_REDIR_USE_PROXY)) + { + r->sr->headers.transfer_encoding = MK_HEADER_TE_TYPE_CHUNKED; + r->chunked = 1; + } + + cgi_req_add(r); mk_api->event_add(readpipe[0], MK_EPOLL_READ, plugin, cs, sr, MK_EPOLL_LEVEL_TRIGGERED); @@ -243,7 +252,7 @@ static int do_cgi(const char * const __restrict__ file, const char * const __res requests_by_socket[socket] = r; /* We have nothing to write yet */ - mk_api->event_socket_change_mode(socket, MK_EPOLL_READ, MK_EPOLL_LEVEL_TRIGGERED); + mk_api->event_socket_change_mode(socket, MK_EPOLL_SLEEP, MK_EPOLL_LEVEL_TRIGGERED); return 200; } @@ -402,7 +411,7 @@ int _mkp_stage_30(struct plugin *plugin, struct client_session *cs, if (status != 200) return MK_PLUGIN_RET_END; - sr->close_now = MK_TRUE; + sr->headers.cgi = SH_CGI; return MK_PLUGIN_RET_CONTINUE; } diff --git a/plugins/cgi/cgi.h b/plugins/cgi/cgi.h index 38a1bf9..cd7bbd8 100644 --- a/plugins/cgi/cgi.h +++ b/plugins/cgi/cgi.h @@ -43,19 +43,25 @@ struct cgi_request { struct mk_list _head; + struct session_request *sr; + struct client_session *cs; + unsigned int in_len; int fd; /* From the CGI app */ int socket; - unsigned char headers_done; + unsigned char status_done; + unsigned char all_headers_done; + unsigned char chunked; }; extern struct cgi_request **requests_by_socket; int swrite(const int fd, const void *buf, const size_t count); -struct cgi_request *cgi_req_create(int fd, int socket); +struct cgi_request *cgi_req_create(int fd, int socket, struct session_request *sr, + struct client_session *cs); void cgi_req_add(struct cgi_request *r); int cgi_req_del(struct cgi_request *r); diff --git a/plugins/cgi/event.c b/plugins/cgi/event.c index f14c12f..d8f4389 100644 --- a/plugins/cgi/event.c +++ b/plugins/cgi/event.c @@ -30,6 +30,11 @@ static int hangup(int socket) mk_api->event_del(r->fd); + if (r->chunked) + { + swrite(r->socket, "0\r\n\r\n", 5); + } + mk_api->http_request_end(r->socket); mk_api->socket_close(r->fd); @@ -52,26 +57,90 @@ int _mkp_event_write(int socket) mk_api->socket_cork_flag(socket, TCP_CORK_ON); - const char *buf = r->in_buf, *outptr = r->in_buf; + const char * const buf = r->in_buf, *outptr = r->in_buf; + + if (!r->status_done && r->in_len >= 8) { + if (memcmp(buf, "Status: ", 8) == 0) { + int status = atoi(buf + 8); + mk_api->header_set_http_status(r->sr, status); + + char *endl = memchr(buf + 8, '\n', r->in_len - 8); + if (!endl) { + return MK_PLUGIN_RET_EVENT_OWNED; + } + else { + endl++; + outptr = endl; + r->in_len -= endl - buf; + } - if (!r->headers_done) { - if (r->in_len >= 8 && memcmp(buf, "Status: ", 8) == 0) { - swrite(socket, "HTTP/1.0 ", 9); - outptr += 8; - r->in_len -= 8; - r->headers_done = 1; } - else if (r->in_len >= 4) { - if (memcmp(buf, "HTTP", 4) != 0) { - swrite(socket, "HTTP/1.0 200 OK\r\n", sizeof("HTTP/1.0 200 OK\r\n") - 1); + else if (memcmp(buf, "HTTP", 4) == 0) { + int status = atoi(buf + 9); + mk_api->header_set_http_status(r->sr, status); + + char *endl = memchr(buf + 8, '\n', r->in_len - 8); + if (!endl) { + return MK_PLUGIN_RET_EVENT_OWNED; + } + else { + endl++; + outptr = endl; + r->in_len -= endl - buf; } - r->headers_done = 1; } + + mk_api->header_send(socket, r->cs, r->sr); + + r->status_done = 1; + } + + if (!r->all_headers_done) + { + // Write the rest of the headers without chunking + char *end = strstr(outptr, MK_IOV_CRLFCRLF); + if (!end) end = strstr(outptr, MK_IOV_LFLFLFLF); + if (!end) + { + swrite(socket, outptr, r->in_len); + r->in_len = 0; + mk_api->event_socket_change_mode(socket, MK_EPOLL_SLEEP, MK_EPOLL_LEVEL_TRIGGERED); + return MK_PLUGIN_RET_EVENT_OWNED; + } + + end += 4; + + int len = end - outptr; + + swrite(socket, outptr, len); + outptr += len; + r->in_len -= len; + + r->all_headers_done = 1; + + if (r->in_len == 0) + { + mk_api->event_socket_change_mode(socket, MK_EPOLL_SLEEP, MK_EPOLL_LEVEL_TRIGGERED); + return MK_PLUGIN_RET_EVENT_OWNED; + } + } + + if (r->chunked) + { + char tmp[16]; + int len = snprintf(tmp, 16, "%x%s", r->in_len, MK_CRLF); + swrite(socket, tmp, len); } swrite(socket, outptr, r->in_len); r->in_len = 0; - mk_api->event_socket_change_mode(socket, MK_EPOLL_READ, MK_EPOLL_LEVEL_TRIGGERED); + mk_api->event_socket_change_mode(socket, MK_EPOLL_SLEEP, MK_EPOLL_LEVEL_TRIGGERED); + mk_api->event_socket_change_mode(r->fd, MK_EPOLL_READ, MK_EPOLL_LEVEL_TRIGGERED); + + if (r->chunked) + { + swrite(socket, MK_CRLF, 2); + } mk_api->socket_cork_flag(socket, TCP_CORK_OFF); } @@ -88,7 +157,10 @@ int _mkp_event_read(int fd) /* Too much to read? Start writing. */ if (count < 1) + { + mk_api->event_socket_change_mode(r->fd, MK_EPOLL_SLEEP, MK_EPOLL_LEVEL_TRIGGERED); goto out; + } int n = read(r->fd, r->in_buf + r->in_len, count); diff --git a/plugins/cgi/request.c b/plugins/cgi/request.c index 614df1d..20be3d4 100644 --- a/plugins/cgi/request.c +++ b/plugins/cgi/request.c @@ -19,13 +19,16 @@ #include "cgi.h" -struct cgi_request *cgi_req_create(int fd, int socket) +struct cgi_request *cgi_req_create(int fd, int socket, struct session_request *sr, + struct client_session *cs) { struct cgi_request *newcgi = mk_api->mem_alloc_z(sizeof(struct cgi_request)); if (!newcgi) return NULL; newcgi->fd = fd; newcgi->socket = socket; + newcgi->sr = sr; + newcgi->cs = cs; return newcgi; } -- 1.7.2.1
_______________________________________________ Monkey mailing list [email protected] http://lists.monkey-project.com/listinfo/monkey
