diff options
Diffstat (limited to 'src/mod_proxy_backend_fastcgi.c')
-rw-r--r-- | src/mod_proxy_backend_fastcgi.c | 819 |
1 files changed, 0 insertions, 819 deletions
diff --git a/src/mod_proxy_backend_fastcgi.c b/src/mod_proxy_backend_fastcgi.c deleted file mode 100644 index 3ba7c5e6..00000000 --- a/src/mod_proxy_backend_fastcgi.c +++ /dev/null @@ -1,819 +0,0 @@ -#include <stdlib.h> -#include <string.h> -#include <assert.h> - -#include "sys-strings.h" -#include "inet_ntop_cache.h" -#include "mod_proxy_core.h" -#include "mod_proxy_core_protocol.h" -#include "buffer.h" -#include "log.h" -#include "fastcgi.h" -#include "array.h" - -#define CORE_PLUGIN "mod_proxy_core" - -typedef struct { - PLUGIN_DATA; - - proxy_protocol *protocol; -} protocol_plugin_data; - -/** - * we aren't supporting multiplexing - * - * use always the same request-id - */ -#define PROXY_FASTCGI_REQUEST_ID 1 -#if 1 -#define PROXY_FASTCGI_USE_KEEP_ALIVE 1 -#endif - -typedef struct { - size_t len; - off_t offset; - int type; - int padding; - size_t request_id; -} fastcgi_packet; - -/** - * The fastcgi protocol decoder will use this struct for storing state variables - * used in decoding the stream - */ -typedef struct { - buffer *buf; /* holds raw header bytes or used to buffer STDERR */ - fastcgi_packet packet; /* parsed info about current packet. */ - int is_complete; -} fcgi_state_data; - -static fcgi_state_data *fcgi_state_data_init(void) { - fcgi_state_data *data; - - data = calloc(1, sizeof(*data)); - data->buf = buffer_init(); - - return data; -} - -static void fcgi_state_data_free(fcgi_state_data *data) { - buffer_free(data->buf); - free(data); -} - -static void fcgi_state_data_reset(fcgi_state_data *data) { - buffer_reset(data->buf); - data->packet.len = 0; - data->packet.offset = 0; - data->packet.type = 0; - data->packet.padding = 0; - data->packet.request_id = 0; - data->is_complete = 0; -} - -PROXY_CONNECTION_FUNC(proxy_fastcgi_init) { - UNUSED(srv); - - if(!proxy_con->protocol_data) { - proxy_con->protocol_data = fcgi_state_data_init(); - } - return 1; -} - -PROXY_CONNECTION_FUNC(proxy_fastcgi_cleanup) { - UNUSED(srv); - - if(proxy_con->protocol_data) { - fcgi_state_data_free((fcgi_state_data *)proxy_con->protocol_data); - proxy_con->protocol_data = NULL; - } - return 1; -} - -static int proxy_fastcgi_get_env_fastcgi(server *srv, connection *con, plugin_data *p, proxy_session *sess) { - char buf[32]; - const char *s; - server_socket *srv_sock = con->srv_socket; -#ifdef HAVE_IPV6 - char b2[INET6_ADDRSTRLEN + 1]; -#endif - - sock_addr our_addr; - socklen_t our_addr_len; - - array_set_key_value(sess->env_headers, CONST_STR_LEN("SERVER_SOFTWARE"), CONST_STR_LEN(PACKAGE_NAME"/"PACKAGE_VERSION)); - - if (con->server_name->used) { - size_t len = con->server_name->used - 1; - char *colon = strchr(con->server_name->ptr, ':'); - if (colon) len = colon - con->server_name->ptr; - - array_set_key_value(sess->env_headers, CONST_STR_LEN("SERVER_NAME"), con->server_name->ptr, len); - } else { -#ifdef HAVE_IPV6 - s = inet_ntop(srv_sock->addr.plain.sa_family, - srv_sock->addr.plain.sa_family == AF_INET6 ? - (const void *) &(srv_sock->addr.ipv6.sin6_addr) : - (const void *) &(srv_sock->addr.ipv4.sin_addr), - b2, sizeof(b2)-1); -#else - s = inet_ntoa(srv_sock->addr.ipv4.sin_addr); -#endif - array_set_key_value(sess->env_headers, CONST_STR_LEN("SERVER_NAME"), s, strlen(s)); - } - - array_set_key_value(sess->env_headers, CONST_STR_LEN("GATEWAY_INTERFACE"), CONST_STR_LEN("CGI/1.1")); - - LI_ltostr(buf, -#ifdef HAVE_IPV6 - ntohs(srv_sock->addr.plain.sa_family ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port) -#else - ntohs(srv_sock->addr.ipv4.sin_port) -#endif - ); - - array_set_key_value(sess->env_headers, CONST_STR_LEN("SERVER_PORT"), buf, strlen(buf)); - - /* get the server-side of the connection to the client */ - our_addr_len = sizeof(our_addr); - - if (-1 == getsockname(con->sock->fd, &(our_addr.plain), &our_addr_len)) { - s = inet_ntop_cache_get_ip(srv, &(srv_sock->addr)); - } else { - s = inet_ntop_cache_get_ip(srv, &(our_addr)); - } - array_set_key_value(sess->env_headers, CONST_STR_LEN("SERVER_ADDR"), s, strlen(s)); - - LI_ltostr(buf, -#ifdef HAVE_IPV6 - ntohs(con->dst_addr.plain.sa_family ? con->dst_addr.ipv6.sin6_port : con->dst_addr.ipv4.sin_port) -#else - ntohs(con->dst_addr.ipv4.sin_port) -#endif - ); - - array_set_key_value(sess->env_headers, CONST_STR_LEN("REMOTE_PORT"), buf, strlen(buf)); - - s = inet_ntop_cache_get_ip(srv, &(con->dst_addr)); - array_set_key_value(sess->env_headers, CONST_STR_LEN("REMOTE_ADDR"), s, strlen(s)); - - if (!buffer_is_empty(con->authed_user)) { - array_set_key_value(sess->env_headers, CONST_STR_LEN("REMOTE_USER"), - CONST_BUF_LEN(con->authed_user)); - } - - if (con->request.content_length > 0) { - /* CGI-SPEC 6.1.2 and FastCGI spec 6.3 */ - - /* request.content_length < SSIZE_MAX, see request.c */ - LI_ltostr(buf, con->request.content_length); - array_set_key_value(sess->env_headers, CONST_STR_LEN("CONTENT_LENGTH"), buf, strlen(buf)); - } - - - /* - * SCRIPT_NAME, PATH_INFO and PATH_TRANSLATED according to - * http://cgi-spec.golux.com/draft-coar-cgi-v11-03-clean.html - * (6.1.14, 6.1.6, 6.1.7) - * For AUTHORIZER mode these headers should be omitted. - */ - - array_set_key_value(sess->env_headers, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path)); - - if (!buffer_is_empty(con->request.pathinfo)) { - array_set_key_value(sess->env_headers, CONST_STR_LEN("PATH_INFO"), CONST_BUF_LEN(con->request.pathinfo)); - - /* PATH_TRANSLATED is only defined if PATH_INFO is set */ - - buffer_copy_string_buffer(p->tmp_buf, con->physical.doc_root); - buffer_append_string_buffer(p->tmp_buf, con->request.pathinfo); - array_set_key_value(sess->env_headers, CONST_STR_LEN("PATH_TRANSLATED"), CONST_BUF_LEN(p->tmp_buf)); - } else { - array_set_key_value(sess->env_headers, CONST_STR_LEN("PATH_INFO"), CONST_STR_LEN("")); - } - - /* - * SCRIPT_FILENAME and DOCUMENT_ROOT for php. The PHP manual - * http://www.php.net/manual/en/reserved.variables.php - * treatment of PATH_TRANSLATED is different from the one of CGI specs. - * TODO: this code should be checked against cgi.fix_pathinfo php - * parameter. - */ - - if (1) { - array_set_key_value(sess->env_headers, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(con->physical.path)); - array_set_key_value(sess->env_headers, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(con->physical.doc_root)); - } - - array_set_key_value(sess->env_headers, CONST_STR_LEN("REQUEST_URI"), CONST_BUF_LEN(con->request.orig_uri)); - - if (!buffer_is_equal(sess->request_uri, con->request.orig_uri)) { - array_set_key_value(sess->env_headers, CONST_STR_LEN("REDIRECT_URI"), CONST_BUF_LEN(sess->request_uri)); - } - if (!buffer_is_empty(con->uri.query)) { - array_set_key_value(sess->env_headers, CONST_STR_LEN("QUERY_STRING"), CONST_BUF_LEN(con->uri.query)); - } else { - array_set_key_value(sess->env_headers, CONST_STR_LEN("QUERY_STRING"), CONST_STR_LEN("")); - } - - s = get_http_method_name(con->request.http_method); - array_set_key_value(sess->env_headers, CONST_STR_LEN("REQUEST_METHOD"), s, strlen(s)); - array_set_key_value(sess->env_headers, CONST_STR_LEN("REDIRECT_STATUS"), CONST_STR_LEN("200")); /* if php is compiled with --force-redirect */ - s = get_http_version_name(con->request.http_version); - array_set_key_value(sess->env_headers, CONST_STR_LEN("SERVER_PROTOCOL"), s, strlen(s)); - -#ifdef USE_OPENSSL - if (srv_sock->is_ssl) { - array_set_key_value(sess->env_headers, CONST_STR_LEN("HTTPS"), CONST_STR_LEN("on")); - } -#endif - - return 0; -} - -/** - * transform the HTTP-Request headers into CGI notation - */ -static int proxy_fastcgi_get_env_request(server *srv, connection *con, plugin_data *p, proxy_session *sess) { - size_t i; - - UNUSED(srv); - UNUSED(con); - - /* the request header got already copied into the sess->request_headers for us - * no extra filter is needed - * - * prepend a HTTP_ and uppercase the keys - */ - for (i = 0; i < sess->request_headers->used; i++) { - data_string *ds; - size_t j; - - ds = (data_string *)sess->request_headers->data[i]; - - buffer_reset(p->tmp_buf); - - if (0 != strcasecmp(ds->key->ptr, "CONTENT-TYPE")) { - buffer_copy_string_len(p->tmp_buf, CONST_STR_LEN("HTTP_")); - p->tmp_buf->used--; - } - - buffer_prepare_append(p->tmp_buf, ds->key->used + 2); - for (j = 0; j < ds->key->used - 1; j++) { - char c = '_'; - if (light_isalpha(ds->key->ptr[j])) { - /* upper-case */ - c = ds->key->ptr[j] & ~32; - } else if (light_isdigit(ds->key->ptr[j])) { - /* copy */ - c = ds->key->ptr[j]; - } - p->tmp_buf->ptr[p->tmp_buf->used++] = c; - } - p->tmp_buf->ptr[p->tmp_buf->used++] = '\0'; - - array_set_key_value(sess->env_headers, CONST_BUF_LEN(p->tmp_buf), CONST_BUF_LEN(ds->value)); - } - - for (i = 0; i < con->environment->used; i++) { - data_string *ds; - size_t j; - - ds = (data_string *)con->environment->data[i]; - - buffer_reset(p->tmp_buf); - - buffer_prepare_append(p->tmp_buf, ds->key->used + 2); - for (j = 0; j < ds->key->used - 1; j++) { - char c = '_'; - if (light_isalpha(ds->key->ptr[j])) { - /* upper-case */ - c = ds->key->ptr[j] & ~32; - } else if (light_isdigit(ds->key->ptr[j])) { - /* copy */ - c = ds->key->ptr[j]; - } - p->tmp_buf->ptr[p->tmp_buf->used++] = c; - } - p->tmp_buf->ptr[p->tmp_buf->used++] = '\0'; - - array_set_key_value(sess->env_headers, CONST_BUF_LEN(p->tmp_buf), CONST_BUF_LEN(ds->value)); - } - - return 0; -} - - -/** - * add a key-value pair to the fastcgi-buffer - */ - -static int fcgi_env_add(buffer *env, const char *key, size_t key_len, const char *val, size_t val_len) { - size_t len; - - if (!key || !val) return -1; - - len = key_len + val_len; - - len += key_len > 127 ? 4 : 1; - len += val_len > 127 ? 4 : 1; - - /** - * ensure we don't create a longer packet than fastcgi can handle - */ - if (env->used + len >= FCGI_MAX_LENGTH) { - return -1; - } - - buffer_prepare_append(env, len); - - if (key_len > 127) { - env->ptr[env->used++] = ((key_len >> 24) & 0xff) | 0x80; - env->ptr[env->used++] = (key_len >> 16) & 0xff; - env->ptr[env->used++] = (key_len >> 8) & 0xff; - env->ptr[env->used++] = (key_len >> 0) & 0xff; - } else { - env->ptr[env->used++] = (key_len >> 0) & 0xff; - } - - if (val_len > 127) { - env->ptr[env->used++] = ((val_len >> 24) & 0xff) | 0x80; - env->ptr[env->used++] = (val_len >> 16) & 0xff; - env->ptr[env->used++] = (val_len >> 8) & 0xff; - env->ptr[env->used++] = (val_len >> 0) & 0xff; - } else { - env->ptr[env->used++] = (val_len >> 0) & 0xff; - } - - memcpy(env->ptr + env->used, key, key_len); - env->used += key_len; - memcpy(env->ptr + env->used, val, val_len); - env->used += val_len; - - return 0; -} - -/** - * init the FCGI_header - */ -static int fcgi_header(FCGI_Header * header, unsigned char type, size_t request_id, int contentLength, unsigned char paddingLength) { - header->version = FCGI_VERSION_1; - header->type = type; - header->requestIdB0 = request_id & 0xff; - header->requestIdB1 = (request_id >> 8) & 0xff; - header->contentLengthB0 = contentLength & 0xff; - header->contentLengthB1 = (contentLength >> 8) & 0xff; - header->paddingLength = paddingLength; - header->reserved = 0; - - return 0; -} - - -PROXY_STREAM_ENCODER_FUNC(proxy_fastcgi_encode_request_headers) { - proxy_connection *proxy_con = sess->proxy_con; - chunkqueue *out = proxy_con->send; - connection *con = sess->remote_con; - buffer *b, *packet; - size_t i; - FCGI_BeginRequestRecord beginRecord; - FCGI_Header header; - plugin_data *p = sess->p; - - UNUSED(srv); - UNUSED(in); - - b = chunkqueue_get_append_buffer(out); - /* send FCGI_BEGIN_REQUEST */ - - fcgi_header(&(beginRecord.header), FCGI_BEGIN_REQUEST, PROXY_FASTCGI_REQUEST_ID, sizeof(beginRecord.body), 0); - beginRecord.body.roleB0 = FCGI_RESPONDER; - beginRecord.body.roleB1 = 0; -#ifdef PROXY_FASTCGI_USE_KEEP_ALIVE - if (p->conf.max_keep_alive_requests && p->conf.max_pool_size) { - /** - * only announce keep-alive if we really can handle it - */ - beginRecord.body.flags = FCGI_KEEP_CONN; - } else { - beginRecord.body.flags = 0; - } -#else - beginRecord.body.flags = 0; -#endif - memset(beginRecord.body.reserved, 0, sizeof(beginRecord.body.reserved)); - - buffer_copy_string_len(b, (const char *)&beginRecord, sizeof(beginRecord)); - out->bytes_in += sizeof(beginRecord); - - /* send FCGI_PARAMS */ - b = chunkqueue_get_append_buffer(out); - buffer_prepare_copy(b, 1024); - - /* fill the sess->env_headers */ - array_reset(sess->env_headers); - proxy_fastcgi_get_env_request(srv, con, p, sess); - proxy_fastcgi_get_env_fastcgi(srv, con, p, sess); - - packet = buffer_init(); - - for (i = 0; i < sess->env_headers->used; i++) { - data_string *ds; - - ds = (data_string *)sess->env_headers->data[i]; - fcgi_env_add(packet, CONST_BUF_LEN(ds->key), CONST_BUF_LEN(ds->value)); - } - - fcgi_header(&(header), FCGI_PARAMS, PROXY_FASTCGI_REQUEST_ID, packet->used, 0); - buffer_append_memory(b, (const char *)&header, sizeof(header)); - buffer_append_memory(b, (const char *)packet->ptr, packet->used); - out->bytes_in += sizeof(header); - out->bytes_in += packet->used - 1; - - buffer_free(packet); - - fcgi_header(&(header), FCGI_PARAMS, PROXY_FASTCGI_REQUEST_ID, 0, 0); - buffer_append_memory(b, (const char *)&header, sizeof(header)); - b->used++; - out->bytes_in += sizeof(header) + 1; - - return HANDLER_FINISHED; -} - -/** - * parse the HTTP response header - */ -static handler_t proxy_fastcgi_http_response_headers(proxy_session *sess, chunkqueue *in) { - http_response_reset(sess->resp); - - /* http response parser. */ - switch(http_response_parse_cq(in, sess->resp)) { - case PARSE_ERROR: - /* bad gateway */ - http_response_reset(sess->resp); - sess->have_response_headers = 1; - sess->resp->status = 502; - return HANDLER_ERROR; - case PARSE_NEED_MORE: - return HANDLER_GO_ON; - case PARSE_SUCCESS: - default: - /* finished parsing response headers. */ - sess->have_response_headers = 1; - return HANDLER_FINISHED; - } -} - -PROXY_STREAM_DECODER_FUNC(proxy_fastcgi_stream_decoder_internal) { - proxy_connection *proxy_con = sess->proxy_con; - fcgi_state_data *data = (fcgi_state_data *)proxy_con->protocol_data; - chunkqueue *in = proxy_con->recv; - FCGI_Header *header; - off_t we_have = 0, we_need = 0; - handler_t rc = HANDLER_GO_ON; - chunk *c; - - UNUSED(srv); - - if ((in->bytes_in == in->bytes_out) && in->is_closed) { - /* everything got passed through, - * - * as we usually have a FIN packet we should expect to get a is_closed within the - * fcgi-stream. Looks like the remote side crashed - * */ - out->is_closed = 1; - - TRACE("%jd / %jd -> %d", - (intmax_t) in->bytes_in, (intmax_t) in->bytes_out, - in->is_closed); - - - ERROR("looks like the fastcgi-backend (%s) terminated before it sent a FIN packet", SAFE_BUF_STR(sess->request_uri)); - - return HANDLER_FINISHED; - } - - /* no data ? */ - if (!in->first) return HANDLER_GO_ON; - - /* a single network packet might contain multiple fcgi packets */ - if(!data->is_complete) { - we_need = (FCGI_HEADER_LEN - data->packet.offset); - - /** - * a the fcgi header might spread over multiple network packets - */ - for (c = in->first; c && we_need > 0; c = c->next) { - if (c->mem->used == 0) continue; - - we_have = c->mem->used - c->offset - 1; - if (we_have == 0) continue; - if (we_have > we_need) we_have = we_need; - - buffer_append_string_len(data->buf, c->mem->ptr + c->offset, we_have); - data->packet.offset += we_have; - c->offset += we_have; - in->bytes_out += we_have; - we_need -= we_have; - } - /* make sure we have the full fastcgi header. */ - if(we_need > 0) { - chunkqueue_remove_finished_chunks(in); - /* we need more data to parse the header. */ - return HANDLER_GO_ON; - } - - /* parse raw header. */ - header = (FCGI_Header *)(data->buf->ptr); - - data->packet.len = (header->contentLengthB0 | (header->contentLengthB1 << 8)); - data->packet.request_id = (header->requestIdB0 | (header->requestIdB1 << 8)); - data->packet.type = header->type; - data->packet.padding = header->paddingLength; - data->is_complete = 1; - - /* Finished parsing raw header bytes. */ - buffer_reset(data->buf); - } - - /* proccess the packet's contents. */ - we_need = data->packet.len - (data->packet.offset - FCGI_HEADER_LEN); - - switch (data->packet.type) { - case FCGI_STDOUT: - if (we_need > 0) { - /* copy packet contents */ - we_have = chunkqueue_steal_chunks_len(out, in->first, we_need); - data->packet.offset += we_have; - we_need -= we_have; - in->bytes_out += we_have; - out->bytes_in += we_have; - } else { - /** - * we might come here again if the padding is part of the next packet - * - * read(15, "\1\6\0\1\1D\4\0", 16384) = 8 - * read(15, "Status: 200 Ok\r\nCache-contro... - * read(15, "\0\0\0\0\1\6\0\1\37\370\0\0", 16384) = 12 - * - */ -#if 0 - /* FIXME: for which case did we set this to 1 ? */ - out->is_closed = 1; -#endif - } - - /* parse response headers. */ - if (!sess->have_response_headers) { - /* check if we have all the response headers */ - switch (proxy_fastcgi_http_response_headers(sess, out)) { - case HANDLER_FINISHED: - /* the headers are complete */ - - rc = HANDLER_GO_ON; - break; - case HANDLER_GO_ON: - /* no finished yet */ - rc = HANDLER_GO_ON; - break; - default: - /* something failed */ - rc = HANDLER_ERROR; - break; - } - } else { - rc = HANDLER_GO_ON; - } - break; - case FCGI_STDERR: - if(we_need > 0) { - buffer *b = buffer_init(); - buffer_prepare_append(b, we_need); - for (c = in->first; c && we_need > 0; c = c->next) { - if (c->mem->used == 0) continue; - - we_have = c->mem->used - c->offset - 1; - if (we_have == 0) continue; - if (we_have > we_need) we_have = we_need; - - buffer_append_string_len(b, c->mem->ptr + c->offset, we_have); - data->packet.offset += we_have; - c->offset += we_have; - in->bytes_out += we_have; - we_need -= we_have; - } -/** -==18752== Conditional jump or move depends on uninitialised value(s) -==18752== at 0x401D255: strlen (mc_replace_strmem.c:246) -==18752== by 0x42B7A1B: vfprintf (in /lib/tls/i686/cmov/libc-2.3.6.so) -==18752== by 0x42D6280: vsnprintf (in /lib/tls/i686/cmov/libc-2.3.6.so) -==18752== by 0x805EAAD: log_trace (log.c:325) -==18752== by 0x4513C5B: proxy_fastcgi_stream_decoder (mod_proxy_backend_fastcgi.c:594) -==18752== by 0x4565130: proxy_stream_decoder (mod_proxy_core.c:587) -==18752== by 0x4565D46: proxy_stream_encode_decode (mod_proxy_core.c:855) -==18752== by 0x4567D69: proxy_state_engine (mod_proxy_core.c:1567) -==18752== by 0x45686C7: mod_proxy_core_start_backend (mod_proxy_core.c:2397) -==18752== by 0x4568CBC: mod_proxy_send_request_content (mod_proxy_core.c:2441) -==18752== by 0x80634EC: plugins_call_handle_send_request_content (plugin.c:387) -==18752== by 0x8054CE7: connection_state_machine (connections.c:1192) -==18752== -==18752== Syscall param write(buf) points to uninitialised byte(s) -==18752== at 0x4000792: (within /lib/ld-2.3.6.so) -==18752== by 0x4513C5B: proxy_fastcgi_stream_decoder (mod_proxy_backend_fastcgi.c:594) -==18752== by 0x4565130: proxy_stream_decoder (mod_proxy_core.c:587) -==18752== by 0x4565D46: proxy_stream_encode_decode (mod_proxy_core.c:855) -==18752== by 0x4567D69: proxy_state_engine (mod_proxy_core.c:1567) -==18752== by 0x45686C7: mod_proxy_core_start_backend (mod_proxy_core.c:2397) -==18752== by 0x4568CBC: mod_proxy_send_request_content (mod_proxy_core.c:2441) -==18752== by 0x80634EC: plugins_call_handle_send_request_content (plugin.c:387) -==18752== by 0x8054CE7: connection_state_machine (connections.c:1192) -==18752== by 0x804F5D8: lighty_mainloop (server.c:1001) -==18752== by 0x80517AE: main (server.c:1705) -==18752== Address 0x4A7C899 is 81 bytes inside a block of size 4,160 alloc'd -==18752== at 0x401C4B0: malloc (vg_replace_malloc.c:149) -==18752== by 0x805DCFA: buffer_prepare_copy (buffer.c:85) -==18752== by 0x805EA7E: log_trace (log.c:321) -==18752== by 0x4513C5B: proxy_fastcgi_stream_decoder (mod_proxy_backend_fastcgi.c:594) -==18752== by 0x4565130: proxy_stream_decoder (mod_proxy_core.c:587) -==18752== by 0x4565D46: proxy_stream_encode_decode (mod_proxy_core.c:855) -==18752== by 0x4567D69: proxy_state_engine (mod_proxy_core.c:1567) -==18752== by 0x45686C7: mod_proxy_core_start_backend (mod_proxy_core.c:2397) -==18752== by 0x4568CBC: mod_proxy_send_request_content (mod_proxy_core.c:2441) -==18752== by 0x80634EC: plugins_call_handle_send_request_content (plugin.c:387) -==18752== by 0x8054CE7: connection_state_machine (connections.c:1192) -==18752== by 0x804F5D8: lighty_mainloop (server.c:1001) -mod_proxy_backend_fastcgi.c.597: (trace) (stderr from 127.0.0.1:9090 for /trac/) SERVER_ADDR -*/ - TRACE("(stderr from %s for %s) %s", - SAFE_BUF_STR(proxy_con->address->name), - SAFE_BUF_STR(sess->remote_con->uri.path), - SAFE_BUF_STR(b)); - buffer_free(b); - } - rc = HANDLER_GO_ON; - break; - case FCGI_END_REQUEST: - /* ignore packet content. */ - if(we_need > 0) { - we_have = chunkqueue_skip(in, we_need); - data->packet.offset += we_have; - we_need -= we_have; - in->bytes_out += we_have; - } - if(we_need == 0) { -#ifndef PROXY_FASTCGI_USE_KEEP_ALIVE - sess->is_closing = 1; -#endif - sess->have_response_headers = 1; - sess->is_request_finished = 1; - in->is_closed = 1; - out->is_closed = 1; - rc = HANDLER_FINISHED; - } - break; - default: - TRACE("unknown packet.type: %d", data->packet.type); - rc = HANDLER_ERROR; - break; - } - - /* skip packet padding, once content has been processed. */ - if(we_need == 0 && data->packet.padding > 0) { - we_have = chunkqueue_skip(in, data->packet.padding); - data->packet.padding -= we_have; - in->bytes_out += we_have; - } - - if(we_need == 0 && data->packet.padding == 0) { - /* packet finished, reset state for next packet */ - fcgi_state_data_reset(data); - } - - chunkqueue_remove_finished_chunks(in); - - return rc; -} - -PROXY_STREAM_DECODER_FUNC(proxy_fastcgi_stream_decoder) { - proxy_connection *proxy_con = sess->proxy_con; - chunkqueue *in = proxy_con->recv; - int res; - - if(out->is_closed) return HANDLER_FINISHED; - /* decode the whole packet stream */ - do { - /* decode the packet */ - res = proxy_fastcgi_stream_decoder_internal(srv, sess, out); - } while (in->first && res == HANDLER_GO_ON); - - return res; -} - -/** - * transform the content-stream into a valid FastCGI STDIN content-stream - * - * as we don't apply chunked-encoding here, pass it on AS IS - */ -PROXY_STREAM_ENCODER_FUNC(proxy_fastcgi_stream_encoder) { - proxy_connection *proxy_con = sess->proxy_con; - chunkqueue *out = proxy_con->send; - chunk *c; - buffer *b; - FCGI_Header header; - off_t we_need = 0, we_have = 0; - - UNUSED(srv); - - /* output queue closed, can't encode any more data. */ - if(out->is_closed) return HANDLER_FINISHED; - - /* encode data into output queue. */ - for (c = in->first; in->bytes_out < in->bytes_in; ) { - /* - * write fcgi header - */ - if(we_need == 0) { - we_need = in->bytes_in - in->bytes_out; - if(we_need > FCGI_MAX_LENGTH) we_need = FCGI_MAX_LENGTH; - - b = chunkqueue_get_append_buffer(out); - fcgi_header(&(header), FCGI_STDIN, PROXY_FASTCGI_REQUEST_ID, we_need, 0); - buffer_copy_memory(b, (const char *)&header, sizeof(header) + 1); - out->bytes_in += sizeof(header); - } - - we_have = chunkqueue_steal_chunks_len(out, c, we_need); - in->bytes_out += we_have; - out->bytes_in += we_have; - we_need -= we_have; - } - - if (in->bytes_in == in->bytes_out && in->is_closed && !out->is_closed) { - /* send the closing packet */ - b = chunkqueue_get_append_buffer(out); - /* terminate STDIN */ - fcgi_header(&(header), FCGI_STDIN, PROXY_FASTCGI_REQUEST_ID, 0, 0); - buffer_copy_memory(b, (const char *)&header, sizeof(header) + 1); - - out->bytes_in += sizeof(header); - out->is_closed = 1; - return HANDLER_FINISHED; - } - - return HANDLER_GO_ON; -} - -INIT_FUNC(mod_proxy_backend_fastcgi_init) { - mod_proxy_core_plugin_data *core_data; - protocol_plugin_data *p; - - /* get the plugin_data of the core-plugin */ - core_data = plugin_get_config(srv, CORE_PLUGIN); - if(!core_data) return NULL; - - p = calloc(1, sizeof(*p)); - - /* define protocol handler callbacks */ - p->protocol = core_data->proxy_register_protocol("fastcgi"); - - p->protocol->proxy_stream_init = proxy_fastcgi_init; - p->protocol->proxy_stream_cleanup = proxy_fastcgi_cleanup; - p->protocol->proxy_stream_decoder = proxy_fastcgi_stream_decoder; - p->protocol->proxy_stream_encoder = proxy_fastcgi_stream_encoder; - p->protocol->proxy_encode_request_headers = proxy_fastcgi_encode_request_headers; - - return p; -} - -FREE_FUNC(mod_proxy_backend_fastcgi_free) { - protocol_plugin_data *p = p_d; - - UNUSED(srv); - - if (!p) return HANDLER_GO_ON; - - free(p); - - return HANDLER_GO_ON; -} - -LI_EXPORT int mod_proxy_backend_fastcgi_plugin_init(plugin *p); -LI_EXPORT int mod_proxy_backend_fastcgi_plugin_init(plugin *p) { - data_string *ds; - - p->version = LIGHTTPD_VERSION_ID; - p->name = buffer_init_string("mod_proxy_backend_fastcgi"); - - p->init = mod_proxy_backend_fastcgi_init; - p->cleanup = mod_proxy_backend_fastcgi_free; - - p->data = NULL; - - ds = data_string_init(); - buffer_copy_string_len(ds->value, CONST_STR_LEN(CORE_PLUGIN)); - array_insert_unique(p->required_plugins, (data_unset *)ds); - - return 0; -} - - |