File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / lighttpd / src / connections.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Nov 2 10:35:00 2016 UTC (7 years, 8 months ago) by misho
Branches: lighttpd, MAIN
CVS tags: v1_4_41p8, HEAD
lighttpd 1.4.41

    1: #include "first.h"
    2: 
    3: #include "buffer.h"
    4: #include "server.h"
    5: #include "log.h"
    6: #include "connections.h"
    7: #include "fdevent.h"
    8: 
    9: #include "configfile.h"
   10: #include "request.h"
   11: #include "response.h"
   12: #include "network.h"
   13: #include "http_chunk.h"
   14: #include "stat_cache.h"
   15: #include "joblist.h"
   16: 
   17: #include "plugin.h"
   18: 
   19: #include "inet_ntop_cache.h"
   20: 
   21: #include <sys/stat.h>
   22: 
   23: #include <stdlib.h>
   24: #include <stdio.h>
   25: #include <unistd.h>
   26: #include <errno.h>
   27: #include <string.h>
   28: #include <fcntl.h>
   29: #include <assert.h>
   30: 
   31: #ifdef USE_OPENSSL
   32: # include <openssl/ssl.h>
   33: # include <openssl/err.h>
   34: #endif
   35: 
   36: #ifdef HAVE_SYS_FILIO_H
   37: # include <sys/filio.h>
   38: #endif
   39: 
   40: #include "sys-socket.h"
   41: 
   42: typedef struct {
   43: 	        PLUGIN_DATA;
   44: } plugin_data;
   45: 
   46: static connection *connections_get_new_connection(server *srv) {
   47: 	connections *conns = srv->conns;
   48: 	size_t i;
   49: 
   50: 	if (conns->size == 0) {
   51: 		conns->size = 128;
   52: 		conns->ptr = NULL;
   53: 		conns->ptr = malloc(sizeof(*conns->ptr) * conns->size);
   54: 		force_assert(NULL != conns->ptr);
   55: 		for (i = 0; i < conns->size; i++) {
   56: 			conns->ptr[i] = connection_init(srv);
   57: 		}
   58: 	} else if (conns->size == conns->used) {
   59: 		conns->size += 128;
   60: 		conns->ptr = realloc(conns->ptr, sizeof(*conns->ptr) * conns->size);
   61: 		force_assert(NULL != conns->ptr);
   62: 
   63: 		for (i = conns->used; i < conns->size; i++) {
   64: 			conns->ptr[i] = connection_init(srv);
   65: 		}
   66: 	}
   67: 
   68: 	connection_reset(srv, conns->ptr[conns->used]);
   69: #if 0
   70: 	fprintf(stderr, "%s.%d: add: ", __FILE__, __LINE__);
   71: 	for (i = 0; i < conns->used + 1; i++) {
   72: 		fprintf(stderr, "%d ", conns->ptr[i]->fd);
   73: 	}
   74: 	fprintf(stderr, "\n");
   75: #endif
   76: 
   77: 	conns->ptr[conns->used]->ndx = conns->used;
   78: 	return conns->ptr[conns->used++];
   79: }
   80: 
   81: static int connection_del(server *srv, connection *con) {
   82: 	size_t i;
   83: 	connections *conns = srv->conns;
   84: 	connection *temp;
   85: 
   86: 	if (con == NULL) return -1;
   87: 
   88: 	if (-1 == con->ndx) return -1;
   89: 
   90: 	buffer_reset(con->uri.authority);
   91: 	buffer_reset(con->uri.path);
   92: 	buffer_reset(con->uri.query);
   93: 	buffer_reset(con->request.orig_uri);
   94: 
   95: 	i = con->ndx;
   96: 
   97: 	/* not last element */
   98: 
   99: 	if (i != conns->used - 1) {
  100: 		temp = conns->ptr[i];
  101: 		conns->ptr[i] = conns->ptr[conns->used - 1];
  102: 		conns->ptr[conns->used - 1] = temp;
  103: 
  104: 		conns->ptr[i]->ndx = i;
  105: 		conns->ptr[conns->used - 1]->ndx = -1;
  106: 	}
  107: 
  108: 	conns->used--;
  109: 
  110: 	con->ndx = -1;
  111: #if 0
  112: 	fprintf(stderr, "%s.%d: del: (%d)", __FILE__, __LINE__, conns->used);
  113: 	for (i = 0; i < conns->used; i++) {
  114: 		fprintf(stderr, "%d ", conns->ptr[i]->fd);
  115: 	}
  116: 	fprintf(stderr, "\n");
  117: #endif
  118: 	return 0;
  119: }
  120: 
  121: static int connection_close(server *srv, connection *con) {
  122: #ifdef USE_OPENSSL
  123: 	server_socket *srv_sock = con->srv_socket;
  124: 	if (srv_sock->is_ssl) {
  125: 		if (con->ssl) SSL_free(con->ssl);
  126: 		con->ssl = NULL;
  127: 	}
  128: #endif
  129: 
  130: 	fdevent_event_del(srv->ev, &(con->fde_ndx), con->fd);
  131: 	fdevent_unregister(srv->ev, con->fd);
  132: #ifdef __WIN32
  133: 	if (closesocket(con->fd)) {
  134: 		log_error_write(srv, __FILE__, __LINE__, "sds",
  135: 				"(warning) close:", con->fd, strerror(errno));
  136: 	}
  137: #else
  138: 	if (close(con->fd)) {
  139: 		log_error_write(srv, __FILE__, __LINE__, "sds",
  140: 				"(warning) close:", con->fd, strerror(errno));
  141: 	}
  142: #endif
  143: 	con->fd = -1;
  144: 
  145: 	srv->cur_fds--;
  146: #if 0
  147: 	log_error_write(srv, __FILE__, __LINE__, "sd",
  148: 			"closed()", con->fd);
  149: #endif
  150: 
  151: 	connection_del(srv, con);
  152: 	connection_set_state(srv, con, CON_STATE_CONNECT);
  153: 
  154: 	return 0;
  155: }
  156: 
  157: static void connection_handle_close_state(server *srv, connection *con) {
  158: 	/* we have to do the linger_on_close stuff regardless
  159: 	 * of con->keep_alive; even non-keepalive sockets may
  160: 	 * still have unread data, and closing before reading
  161: 	 * it will make the client not see all our output.
  162: 	 */
  163: 	int len;
  164: 	char buf[1024];
  165: 
  166: 	len = read(con->fd, buf, sizeof(buf));
  167: 	if (len == 0 || (len < 0 && errno != EAGAIN && errno != EINTR) ) {
  168: 		con->close_timeout_ts = srv->cur_ts - (HTTP_LINGER_TIMEOUT+1);
  169: 	}
  170: 
  171: 	if (srv->cur_ts - con->close_timeout_ts > HTTP_LINGER_TIMEOUT) {
  172: 		connection_close(srv, con);
  173: 
  174: 		if (srv->srvconf.log_state_handling) {
  175: 			log_error_write(srv, __FILE__, __LINE__, "sd",
  176: 					"connection closed for fd", con->fd);
  177: 		}
  178: 	}
  179: }
  180: 
  181: static void connection_handle_shutdown(server *srv, connection *con) {
  182: 	int r;
  183: 
  184: #ifdef USE_OPENSSL
  185: 	server_socket *srv_sock = con->srv_socket;
  186: 	if (srv_sock->is_ssl) {
  187: 		int ret, ssl_r;
  188: 		unsigned long err;
  189: 		ERR_clear_error();
  190: 		switch ((ret = SSL_shutdown(con->ssl))) {
  191: 		case 1:
  192: 			/* ok */
  193: 			break;
  194: 		case 0:
  195: 			/* wait for fd-event
  196: 			 *
  197: 			 * FIXME: wait for fdevent and call SSL_shutdown again
  198: 			 *
  199: 			 */
  200: 			ERR_clear_error();
  201: 			if (-1 != (ret = SSL_shutdown(con->ssl))) break;
  202: 
  203: 			/* fall through */
  204: 		default:
  205: 
  206: 			switch ((ssl_r = SSL_get_error(con->ssl, ret))) {
  207: 			case SSL_ERROR_ZERO_RETURN:
  208: 				break;
  209: 			case SSL_ERROR_WANT_WRITE:
  210: 				/*con->is_writable = -1;*//*(no effect; shutdown() called below)*/
  211: 			case SSL_ERROR_WANT_READ:
  212: 				break;
  213: 			case SSL_ERROR_SYSCALL:
  214: 				/* perhaps we have error waiting in our error-queue */
  215: 				if (0 != (err = ERR_get_error())) {
  216: 					do {
  217: 						log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
  218: 								ssl_r, ret,
  219: 								ERR_error_string(err, NULL));
  220: 					} while((err = ERR_get_error()));
  221: 				} else if (errno != 0) { /* ssl bug (see lighttpd ticket #2213): sometimes errno == 0 */
  222: 					switch(errno) {
  223: 					case EPIPE:
  224: 					case ECONNRESET:
  225: 						break;
  226: 					default:
  227: 						log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):",
  228: 							ssl_r, ret, errno,
  229: 							strerror(errno));
  230: 						break;
  231: 					}
  232: 				}
  233: 
  234: 				break;
  235: 			default:
  236: 				while((err = ERR_get_error())) {
  237: 					log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
  238: 							ssl_r, ret,
  239: 							ERR_error_string(err, NULL));
  240: 				}
  241: 
  242: 				break;
  243: 			}
  244: 		}
  245: 		ERR_clear_error();
  246: 	}
  247: #endif
  248: 
  249: 	switch(r = plugins_call_handle_connection_close(srv, con)) {
  250: 	case HANDLER_GO_ON:
  251: 	case HANDLER_FINISHED:
  252: 		break;
  253: 	default:
  254: 		log_error_write(srv, __FILE__, __LINE__, "sd", "unhandling return value", r);
  255: 		break;
  256: 	}
  257: 
  258: 	srv->con_closed++;
  259: 	connection_reset(srv, con);
  260: 
  261: 	/* close the connection */
  262: 	if ((0 == shutdown(con->fd, SHUT_WR))) {
  263: 		con->close_timeout_ts = srv->cur_ts;
  264: 		connection_set_state(srv, con, CON_STATE_CLOSE);
  265: 
  266: 		if (srv->srvconf.log_state_handling) {
  267: 			log_error_write(srv, __FILE__, __LINE__, "sd",
  268: 					"shutdown for fd", con->fd);
  269: 		}
  270: 	} else {
  271: 		connection_close(srv, con);
  272: 	}
  273: }
  274: 
  275: static void connection_handle_response_end_state(server *srv, connection *con) {
  276:         /* log the request */
  277:         /* (even if error, connection dropped, still write to access log if http_status) */
  278: 	if (con->http_status) {
  279: 		plugins_call_handle_request_done(srv, con);
  280: 	}
  281: 
  282: 	if (con->state != CON_STATE_ERROR) srv->con_written++;
  283: 
  284: 	if ((con->request.content_length
  285: 	     && (off_t)con->request.content_length > con->request_content_queue->bytes_in)
  286: 	    || con->state == CON_STATE_ERROR) {
  287: 		/* request body is present and has not been read completely */
  288: 		con->keep_alive = 0;
  289: 	}
  290: 
  291:         if (con->keep_alive) {
  292: 		connection_reset(srv, con);
  293: #if 0
  294: 		con->request_start = srv->cur_ts;
  295: 		con->read_idle_ts = srv->cur_ts;
  296: #endif
  297: 		connection_set_state(srv, con, CON_STATE_REQUEST_START);
  298: 	} else {
  299: 		connection_handle_shutdown(srv, con);
  300: 	}
  301: }
  302: 
  303: static void connection_handle_errdoc_init(server *srv, connection *con) {
  304: 	/* modules that produce headers required with error response should
  305: 	 * typically also produce an error document.  Make an exception for
  306: 	 * mod_auth WWW-Authenticate response header. */
  307: 	buffer *www_auth = NULL;
  308: 	if (401 == con->http_status) {
  309: 		data_string *ds = (data_string *)array_get_element(con->response.headers, "WWW-Authenticate");
  310: 		if (NULL != ds) {
  311: 			www_auth = buffer_init_buffer(ds->value);
  312: 		}
  313: 	}
  314: 
  315: 	con->response.transfer_encoding = 0;
  316: 	buffer_reset(con->physical.path);
  317: 	array_reset(con->response.headers);
  318: 	chunkqueue_reset(con->write_queue);
  319: 
  320: 	if (NULL != www_auth) {
  321: 		response_header_insert(srv, con, CONST_STR_LEN("WWW-Authenticate"), CONST_BUF_LEN(www_auth));
  322: 		buffer_free(www_auth);
  323: 	}
  324: }
  325: 
  326: static int connection_handle_write_prepare(server *srv, connection *con) {
  327: 	if (con->mode == DIRECT) {
  328: 		/* static files */
  329: 		switch(con->request.http_method) {
  330: 		case HTTP_METHOD_GET:
  331: 		case HTTP_METHOD_POST:
  332: 		case HTTP_METHOD_HEAD:
  333: 			break;
  334: 		case HTTP_METHOD_OPTIONS:
  335: 			/*
  336: 			 * 400 is coming from the request-parser BEFORE uri.path is set
  337: 			 * 403 is from the response handler when noone else catched it
  338: 			 *
  339: 			 * */
  340: 			if ((!con->http_status || con->http_status == 200) && !buffer_string_is_empty(con->uri.path) &&
  341: 			    con->uri.path->ptr[0] != '*') {
  342: 				response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("OPTIONS, GET, HEAD, POST"));
  343: 
  344: 				con->response.transfer_encoding &= ~HTTP_TRANSFER_ENCODING_CHUNKED;
  345: 				con->parsed_response &= ~HTTP_CONTENT_LENGTH;
  346: 
  347: 				con->http_status = 200;
  348: 				con->file_finished = 1;
  349: 
  350: 				chunkqueue_reset(con->write_queue);
  351: 			}
  352: 			break;
  353: 		default:
  354: 			if (0 == con->http_status) {
  355: 				con->http_status = 501;
  356: 			}
  357: 			break;
  358: 		}
  359: 	}
  360: 
  361: 	if (con->http_status == 0) {
  362: 		con->http_status = 403;
  363: 	}
  364: 
  365: 	switch(con->http_status) {
  366: 	case 204: /* class: header only */
  367: 	case 205:
  368: 	case 304:
  369: 		/* disable chunked encoding again as we have no body */
  370: 		con->response.transfer_encoding &= ~HTTP_TRANSFER_ENCODING_CHUNKED;
  371: 		con->parsed_response &= ~HTTP_CONTENT_LENGTH;
  372: 		chunkqueue_reset(con->write_queue);
  373: 
  374: 		con->file_finished = 1;
  375: 		break;
  376: 	default: /* class: header + body */
  377: 		if (con->mode != DIRECT) break;
  378: 
  379: 		/* only custom body for 4xx and 5xx */
  380: 		if (con->http_status < 400 || con->http_status >= 600) break;
  381: 
  382: 		con->file_finished = 0;
  383: 
  384: 		connection_handle_errdoc_init(srv, con);
  385: 
  386: 		/* try to send static errorfile */
  387: 		if (!buffer_string_is_empty(con->conf.errorfile_prefix)) {
  388: 			stat_cache_entry *sce = NULL;
  389: 
  390: 			buffer_copy_buffer(con->physical.path, con->conf.errorfile_prefix);
  391: 			buffer_append_int(con->physical.path, con->http_status);
  392: 			buffer_append_string_len(con->physical.path, CONST_STR_LEN(".html"));
  393: 
  394: 			if (0 == http_chunk_append_file(srv, con, con->physical.path)) {
  395: 				con->file_finished = 1;
  396: 				if (HANDLER_ERROR != stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
  397: 					response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type));
  398: 				}
  399: 			}
  400: 		}
  401: 
  402: 		if (!con->file_finished) {
  403: 			buffer *b;
  404: 
  405: 			buffer_reset(con->physical.path);
  406: 
  407: 			con->file_finished = 1;
  408: 			b = buffer_init();
  409: 
  410: 			/* build default error-page */
  411: 			buffer_copy_string_len(b, CONST_STR_LEN(
  412: 					   "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"
  413: 					   "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n"
  414: 					   "         \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
  415: 					   "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n"
  416: 					   " <head>\n"
  417: 					   "  <title>"));
  418: 			buffer_append_int(b, con->http_status);
  419: 			buffer_append_string_len(b, CONST_STR_LEN(" - "));
  420: 			buffer_append_string(b, get_http_status_name(con->http_status));
  421: 
  422: 			buffer_append_string_len(b, CONST_STR_LEN(
  423: 					     "</title>\n"
  424: 					     " </head>\n"
  425: 					     " <body>\n"
  426: 					     "  <h1>"));
  427: 			buffer_append_int(b, con->http_status);
  428: 			buffer_append_string_len(b, CONST_STR_LEN(" - "));
  429: 			buffer_append_string(b, get_http_status_name(con->http_status));
  430: 
  431: 			buffer_append_string_len(b, CONST_STR_LEN("</h1>\n"
  432: 					     " </body>\n"
  433: 					     "</html>\n"
  434: 					     ));
  435: 
  436: 			(void)http_chunk_append_buffer(srv, con, b);
  437: 			buffer_free(b);
  438: 
  439: 			response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
  440: 		}
  441: 		break;
  442: 	}
  443: 
  444: 	if (con->file_finished) {
  445: 		/* we have all the content and chunked encoding is not used, set a content-length */
  446: 
  447: 		if ((!(con->parsed_response & HTTP_CONTENT_LENGTH)) &&
  448: 		    (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) == 0) {
  449: 			off_t qlen = chunkqueue_length(con->write_queue);
  450: 
  451: 			/**
  452: 			 * The Content-Length header only can be sent if we have content:
  453: 			 * - HEAD doesn't have a content-body (but have a content-length)
  454: 			 * - 1xx, 204 and 304 don't have a content-body (RFC 2616 Section 4.3)
  455: 			 *
  456: 			 * Otherwise generate a Content-Length header as chunked encoding is not 
  457: 			 * available
  458: 			 */
  459: 			if ((con->http_status >= 100 && con->http_status < 200) ||
  460: 			    con->http_status == 204 ||
  461: 			    con->http_status == 304) {
  462: 				data_string *ds;
  463: 				/* no Content-Body, no Content-Length */
  464: 				if (NULL != (ds = (data_string*) array_get_element(con->response.headers, "Content-Length"))) {
  465: 					buffer_reset(ds->value); /* Headers with empty values are ignored for output */
  466: 				}
  467: 			} else if (qlen > 0 || con->request.http_method != HTTP_METHOD_HEAD) {
  468: 				/* qlen = 0 is important for Redirects (301, ...) as they MAY have
  469: 				 * a content. Browsers are waiting for a Content otherwise
  470: 				 */
  471: 				buffer_copy_int(srv->tmp_buf, qlen);
  472: 
  473: 				response_header_overwrite(srv, con, CONST_STR_LEN("Content-Length"), CONST_BUF_LEN(srv->tmp_buf));
  474: 			}
  475: 		}
  476: 	} else {
  477: 		/**
  478: 		 * the file isn't finished yet, but we have all headers
  479: 		 *
  480: 		 * to get keep-alive we either need:
  481: 		 * - Content-Length: ... (HTTP/1.0 and HTTP/1.0) or
  482: 		 * - Transfer-Encoding: chunked (HTTP/1.1)
  483: 		 */
  484: 
  485: 		if (((con->parsed_response & HTTP_CONTENT_LENGTH) == 0) &&
  486: 		    ((con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) == 0)) {
  487: 			if (con->request.http_version == HTTP_VERSION_1_1) {
  488: 				off_t qlen = chunkqueue_length(con->write_queue);
  489: 				con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
  490: 				if (qlen) {
  491: 					/* create initial Transfer-Encoding: chunked segment */
  492: 					buffer *b = srv->tmp_chunk_len;
  493: 					buffer_string_set_length(b, 0);
  494: 					buffer_append_uint_hex(b, (uintmax_t)qlen);
  495: 					buffer_append_string_len(b, CONST_STR_LEN("\r\n"));
  496: 					chunkqueue_prepend_buffer(con->write_queue, b);
  497: 					chunkqueue_append_mem(con->write_queue, CONST_STR_LEN("\r\n"));
  498: 				}
  499: 			} else {
  500: 				con->keep_alive = 0;
  501: 			}
  502: 		}
  503: 
  504: 		/**
  505: 		 * if the backend sent a Connection: close, follow the wish
  506: 		 *
  507: 		 * NOTE: if the backend sent Connection: Keep-Alive, but no Content-Length, we
  508: 		 * will close the connection. That's fine. We can always decide the close 
  509: 		 * the connection
  510: 		 *
  511: 		 * FIXME: to be nice we should remove the Connection: ... 
  512: 		 */
  513: 		if (con->parsed_response & HTTP_CONNECTION) {
  514: 			/* a subrequest disable keep-alive although the client wanted it */
  515: 			if (con->keep_alive && !con->response.keep_alive) {
  516: 				con->keep_alive = 0;
  517: 			}
  518: 		}
  519: 	}
  520: 
  521: 	if (con->request.http_method == HTTP_METHOD_HEAD) {
  522: 		/**
  523: 		 * a HEAD request has the same as a GET 
  524: 		 * without the content
  525: 		 */
  526: 		con->file_finished = 1;
  527: 
  528: 		chunkqueue_reset(con->write_queue);
  529: 		con->response.transfer_encoding &= ~HTTP_TRANSFER_ENCODING_CHUNKED;
  530: 	}
  531: 
  532: 	http_response_write_header(srv, con);
  533: 
  534: 	return 0;
  535: }
  536: 
  537: static int connection_handle_write(server *srv, connection *con) {
  538: 	switch(network_write_chunkqueue(srv, con, con->write_queue, MAX_WRITE_LIMIT)) {
  539: 	case 0:
  540: 		con->write_request_ts = srv->cur_ts;
  541: 		if (con->file_finished) {
  542: 			connection_set_state(srv, con, CON_STATE_RESPONSE_END);
  543: 		}
  544: 		break;
  545: 	case -1: /* error on our side */
  546: 		log_error_write(srv, __FILE__, __LINE__, "sd",
  547: 				"connection closed: write failed on fd", con->fd);
  548: 		connection_set_state(srv, con, CON_STATE_ERROR);
  549: 		break;
  550: 	case -2: /* remote close */
  551: 		connection_set_state(srv, con, CON_STATE_ERROR);
  552: 		break;
  553: 	case 1:
  554: 		con->write_request_ts = srv->cur_ts;
  555: 		con->is_writable = 0;
  556: 
  557: 		/* not finished yet -> WRITE */
  558: 		break;
  559: 	}
  560: 
  561: 	return 0;
  562: }
  563: 
  564: 
  565: 
  566: connection *connection_init(server *srv) {
  567: 	connection *con;
  568: 
  569: 	UNUSED(srv);
  570: 
  571: 	con = calloc(1, sizeof(*con));
  572: 	force_assert(NULL != con);
  573: 
  574: 	con->fd = 0;
  575: 	con->ndx = -1;
  576: 	con->fde_ndx = -1;
  577: 	con->bytes_written = 0;
  578: 	con->bytes_read = 0;
  579: 	con->bytes_header = 0;
  580: 	con->loops_per_request = 0;
  581: 
  582: #define CLEAN(x) \
  583: 	con->x = buffer_init();
  584: 
  585: 	CLEAN(request.uri);
  586: 	CLEAN(request.request_line);
  587: 	CLEAN(request.request);
  588: 	CLEAN(request.pathinfo);
  589: 
  590: 	CLEAN(request.orig_uri);
  591: 
  592: 	CLEAN(uri.scheme);
  593: 	CLEAN(uri.authority);
  594: 	CLEAN(uri.path);
  595: 	CLEAN(uri.path_raw);
  596: 	CLEAN(uri.query);
  597: 
  598: 	CLEAN(physical.doc_root);
  599: 	CLEAN(physical.path);
  600: 	CLEAN(physical.basedir);
  601: 	CLEAN(physical.rel_path);
  602: 	CLEAN(physical.etag);
  603: 	CLEAN(parse_request);
  604: 
  605: 	CLEAN(server_name);
  606: 	CLEAN(dst_addr_buf);
  607: #if defined USE_OPENSSL && ! defined OPENSSL_NO_TLSEXT
  608: 	CLEAN(tlsext_server_name);
  609: #endif
  610: 
  611: #undef CLEAN
  612: 	con->write_queue = chunkqueue_init();
  613: 	con->read_queue = chunkqueue_init();
  614: 	con->request_content_queue = chunkqueue_init();
  615: 
  616: 	con->request.headers      = array_init();
  617: 	con->response.headers     = array_init();
  618: 	con->environment     = array_init();
  619: 
  620: 	/* init plugin specific connection structures */
  621: 
  622: 	con->plugin_ctx = calloc(1, (srv->plugins.used + 1) * sizeof(void *));
  623: 	force_assert(NULL != con->plugin_ctx);
  624: 
  625: 	con->cond_cache = calloc(srv->config_context->used, sizeof(cond_cache_t));
  626: 	force_assert(NULL != con->cond_cache);
  627: 	config_setup_connection(srv, con);
  628: 
  629: 	return con;
  630: }
  631: 
  632: void connections_free(server *srv) {
  633: 	connections *conns = srv->conns;
  634: 	size_t i;
  635: 
  636: 	for (i = 0; i < conns->size; i++) {
  637: 		connection *con = conns->ptr[i];
  638: 
  639: 		connection_reset(srv, con);
  640: 
  641: 		chunkqueue_free(con->write_queue);
  642: 		chunkqueue_free(con->read_queue);
  643: 		chunkqueue_free(con->request_content_queue);
  644: 		array_free(con->request.headers);
  645: 		array_free(con->response.headers);
  646: 		array_free(con->environment);
  647: 
  648: #define CLEAN(x) \
  649: 	buffer_free(con->x);
  650: 
  651: 		CLEAN(request.uri);
  652: 		CLEAN(request.request_line);
  653: 		CLEAN(request.request);
  654: 		CLEAN(request.pathinfo);
  655: 
  656: 		CLEAN(request.orig_uri);
  657: 
  658: 		CLEAN(uri.scheme);
  659: 		CLEAN(uri.authority);
  660: 		CLEAN(uri.path);
  661: 		CLEAN(uri.path_raw);
  662: 		CLEAN(uri.query);
  663: 
  664: 		CLEAN(physical.doc_root);
  665: 		CLEAN(physical.path);
  666: 		CLEAN(physical.basedir);
  667: 		CLEAN(physical.etag);
  668: 		CLEAN(physical.rel_path);
  669: 		CLEAN(parse_request);
  670: 
  671: 		CLEAN(server_name);
  672: 		CLEAN(dst_addr_buf);
  673: #if defined USE_OPENSSL && ! defined OPENSSL_NO_TLSEXT
  674: 		CLEAN(tlsext_server_name);
  675: #endif
  676: #undef CLEAN
  677: 		free(con->plugin_ctx);
  678: 		free(con->cond_cache);
  679: 
  680: 		free(con);
  681: 	}
  682: 
  683: 	free(conns->ptr);
  684: }
  685: 
  686: 
  687: int connection_reset(server *srv, connection *con) {
  688: 	size_t i;
  689: 
  690: 	plugins_call_connection_reset(srv, con);
  691: 
  692: 	con->is_readable = 1;
  693: 	con->is_writable = 1;
  694: 	con->http_status = 0;
  695: 	con->file_finished = 0;
  696: 	con->file_started = 0;
  697: 	con->got_response = 0;
  698: 
  699: 	con->parsed_response = 0;
  700: 
  701: 	con->bytes_written = 0;
  702: 	con->bytes_written_cur_second = 0;
  703: 	con->bytes_read = 0;
  704: 	con->bytes_header = 0;
  705: 	con->loops_per_request = 0;
  706: 
  707: 	con->request.http_method = HTTP_METHOD_UNSET;
  708: 	con->request.http_version = HTTP_VERSION_UNSET;
  709: 
  710: 	con->request.http_if_modified_since = NULL;
  711: 	con->request.http_if_none_match = NULL;
  712: 
  713: 	con->response.keep_alive = 0;
  714: 	con->response.content_length = -1;
  715: 	con->response.transfer_encoding = 0;
  716: 
  717: 	con->mode = DIRECT;
  718: 
  719: #define CLEAN(x) \
  720: 	if (con->x) buffer_reset(con->x);
  721: 
  722: 	CLEAN(request.uri);
  723: 	CLEAN(request.request_line);
  724: 	CLEAN(request.pathinfo);
  725: 	CLEAN(request.request);
  726: 
  727: 	/* CLEAN(request.orig_uri); */
  728: 
  729: 	CLEAN(uri.scheme);
  730: 	/* CLEAN(uri.authority); */
  731: 	/* CLEAN(uri.path); */
  732: 	CLEAN(uri.path_raw);
  733: 	/* CLEAN(uri.query); */
  734: 
  735: 	CLEAN(physical.doc_root);
  736: 	CLEAN(physical.path);
  737: 	CLEAN(physical.basedir);
  738: 	CLEAN(physical.rel_path);
  739: 	CLEAN(physical.etag);
  740: 
  741: 	CLEAN(parse_request);
  742: 
  743: 	CLEAN(server_name);
  744: #if defined USE_OPENSSL && ! defined OPENSSL_NO_TLSEXT
  745: 	CLEAN(tlsext_server_name);
  746: #endif
  747: #undef CLEAN
  748: 
  749: #define CLEAN(x) \
  750: 	if (con->x) con->x->used = 0;
  751: 
  752: #undef CLEAN
  753: 
  754: #define CLEAN(x) \
  755: 		con->request.x = NULL;
  756: 
  757: 	CLEAN(http_host);
  758: 	CLEAN(http_range);
  759: 	CLEAN(http_content_type);
  760: #undef CLEAN
  761: 	con->request.content_length = 0;
  762: 
  763: 	array_reset(con->request.headers);
  764: 	array_reset(con->response.headers);
  765: 	array_reset(con->environment);
  766: 
  767: 	chunkqueue_reset(con->write_queue);
  768: 	chunkqueue_reset(con->request_content_queue);
  769: 
  770: 	/* the plugins should cleanup themself */
  771: 	for (i = 0; i < srv->plugins.used; i++) {
  772: 		plugin *p = ((plugin **)(srv->plugins.ptr))[i];
  773: 		plugin_data *pd = p->data;
  774: 
  775: 		if (!pd) continue;
  776: 
  777: 		if (con->plugin_ctx[pd->id] != NULL) {
  778: 			log_error_write(srv, __FILE__, __LINE__, "sb", "missing cleanup in", p->name);
  779: 		}
  780: 
  781: 		con->plugin_ctx[pd->id] = NULL;
  782: 	}
  783: 
  784: 	/* The cond_cache gets reset in response.c */
  785: 	/* config_cond_cache_reset(srv, con); */
  786: 
  787: 	con->header_len = 0;
  788: 	con->error_handler_saved_status = 0;
  789: 	/*con->error_handler_saved_method = HTTP_METHOD_UNSET;*/
  790: 	/*(error_handler_saved_method value is not valid unless error_handler_saved_status is set)*/
  791: 
  792: 	config_setup_connection(srv, con);
  793: 
  794: 	return 0;
  795: }
  796: 
  797: /**
  798:  * handle all header and content read
  799:  *
  800:  * we get called by the state-engine and by the fdevent-handler
  801:  */
  802: static int connection_handle_read_state(server *srv, connection *con)  {
  803: 	chunk *c, *last_chunk;
  804: 	off_t last_offset;
  805: 	chunkqueue *cq = con->read_queue;
  806: 	int is_closed = 0; /* the connection got closed, if we don't have a complete header, -> error */
  807: 	/* when in CON_STATE_READ: about to receive first byte for a request: */
  808: 	int is_request_start = chunkqueue_is_empty(cq);
  809: 
  810: 	if (con->is_readable) {
  811: 		con->read_idle_ts = srv->cur_ts;
  812: 
  813: 		switch(connection_handle_read(srv, con)) {
  814: 		case -1:
  815: 			return -1;
  816: 		case -2:
  817: 			is_closed = 1;
  818: 			break;
  819: 		default:
  820: 			break;
  821: 		}
  822: 	}
  823: 
  824: 	chunkqueue_remove_finished_chunks(cq);
  825: 
  826: 	/* we might have got several packets at once
  827: 	 */
  828: 
  829: 	/* update request_start timestamp when first byte of
  830: 	 * next request is received on a keep-alive connection */
  831: 	if (con->request_count > 1 && is_request_start) {
  832: 		con->request_start = srv->cur_ts;
  833: 		if (con->conf.high_precision_timestamps)
  834: 			log_clock_gettime_realtime(&con->request_start_hp);
  835: 	}
  836: 
  837: 		/* if there is a \r\n\r\n in the chunkqueue
  838: 		 *
  839: 		 * scan the chunk-queue twice
  840: 		 * 1. to find the \r\n\r\n
  841: 		 * 2. to copy the header-packet
  842: 		 *
  843: 		 */
  844: 
  845: 		last_chunk = NULL;
  846: 		last_offset = 0;
  847: 
  848: 		for (c = cq->first; c; c = c->next) {
  849: 			size_t i;
  850: 			size_t len = buffer_string_length(c->mem) - c->offset;
  851: 			const char *b = c->mem->ptr + c->offset;
  852: 
  853: 			for (i = 0; i < len; ++i) {
  854: 				char ch = b[i];
  855: 
  856: 				if ('\r' == ch) {
  857: 					/* chec if \n\r\n follows */
  858: 					size_t j = i+1;
  859: 					chunk *cc = c;
  860: 					const char header_end[] = "\r\n\r\n";
  861: 					int header_end_match_pos = 1;
  862: 
  863: 					for ( ; cc; cc = cc->next, j = 0 ) {
  864: 						size_t bblen = buffer_string_length(cc->mem) - cc->offset;
  865: 						const char *bb = cc->mem->ptr + cc->offset;
  866: 
  867: 						for ( ; j < bblen; j++) {
  868: 							ch = bb[j];
  869: 
  870: 							if (ch == header_end[header_end_match_pos]) {
  871: 								header_end_match_pos++;
  872: 								if (4 == header_end_match_pos) {
  873: 									last_chunk = cc;
  874: 									last_offset = j+1;
  875: 									goto found_header_end;
  876: 								}
  877: 							} else {
  878: 								goto reset_search;
  879: 							}
  880: 						}
  881: 					}
  882: 				}
  883: reset_search: ;
  884: 			}
  885: 		}
  886: found_header_end:
  887: 
  888: 		/* found */
  889: 		if (last_chunk) {
  890: 			buffer_reset(con->request.request);
  891: 
  892: 			for (c = cq->first; c; c = c->next) {
  893: 				size_t len = buffer_string_length(c->mem) - c->offset;
  894: 
  895: 				if (c == last_chunk) {
  896: 					len = last_offset;
  897: 				}
  898: 
  899: 				buffer_append_string_len(con->request.request, c->mem->ptr + c->offset, len);
  900: 				c->offset += len;
  901: 				cq->bytes_out += len;
  902: 
  903: 				if (c == last_chunk) break;
  904: 			}
  905: 
  906: 			connection_set_state(srv, con, CON_STATE_REQUEST_END);
  907: 		} else if (chunkqueue_length(cq) > 64 * 1024) {
  908: 			log_error_write(srv, __FILE__, __LINE__, "s", "oversized request-header -> sending Status 414");
  909: 
  910: 			con->http_status = 414; /* Request-URI too large */
  911: 			con->keep_alive = 0;
  912: 			connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
  913: 		} else if (is_closed) {
  914: 			/* the connection got closed and we didn't got enough data to leave CON_STATE_READ;
  915: 			 * the only way is to leave here */
  916: 			connection_set_state(srv, con, CON_STATE_ERROR);
  917: 		}
  918: 
  919: 	chunkqueue_remove_finished_chunks(cq);
  920: 
  921: 	return 0;
  922: }
  923: 
  924: static handler_t connection_handle_fdevent(server *srv, void *context, int revents) {
  925: 	connection *con = context;
  926: 
  927: 	joblist_append(srv, con);
  928: 
  929: 	if (con->srv_socket->is_ssl) {
  930: 		/* ssl may read and write for both reads and writes */
  931: 		if (revents & (FDEVENT_IN | FDEVENT_OUT)) {
  932: 			con->is_readable = 1;
  933: 			con->is_writable = 1;
  934: 		}
  935: 	} else {
  936: 		if (revents & FDEVENT_IN) {
  937: 			con->is_readable = 1;
  938: 		}
  939: 		if (revents & FDEVENT_OUT) {
  940: 			con->is_writable = 1;
  941: 			/* we don't need the event twice */
  942: 		}
  943: 	}
  944: 
  945: 
  946: 	if (revents & ~(FDEVENT_IN | FDEVENT_OUT)) {
  947: 		/* looks like an error */
  948: 
  949: 		/* FIXME: revents = 0x19 still means that we should read from the queue */
  950: 		if (revents & FDEVENT_HUP) {
  951: 			if (con->state == CON_STATE_CLOSE) {
  952: 				con->close_timeout_ts = srv->cur_ts - (HTTP_LINGER_TIMEOUT+1);
  953: 			} else {
  954: 				/* sigio reports the wrong event here
  955: 				 *
  956: 				 * there was no HUP at all
  957: 				 */
  958: #ifdef USE_LINUX_SIGIO
  959: 				if (srv->ev->in_sigio == 1) {
  960: 					log_error_write(srv, __FILE__, __LINE__, "sd",
  961: 						"connection closed: poll() -> HUP", con->fd);
  962: 				} else {
  963: 					connection_set_state(srv, con, CON_STATE_ERROR);
  964: 				}
  965: #else
  966: 				connection_set_state(srv, con, CON_STATE_ERROR);
  967: #endif
  968: 
  969: 			}
  970: 		} else if (revents & FDEVENT_ERR) {
  971: 			/* error, connection reset, whatever... we don't want to spam the logfile */
  972: #if 0
  973: 			log_error_write(srv, __FILE__, __LINE__, "sd",
  974: 					"connection closed: poll() -> ERR", con->fd);
  975: #endif
  976: 			connection_set_state(srv, con, CON_STATE_ERROR);
  977: 		} else {
  978: 			log_error_write(srv, __FILE__, __LINE__, "sd",
  979: 					"connection closed: poll() -> ???", revents);
  980: 		}
  981: 	}
  982: 
  983: 	if (con->state == CON_STATE_READ) {
  984: 		connection_handle_read_state(srv, con);
  985: 	}
  986: 
  987: 	if (con->state == CON_STATE_WRITE &&
  988: 	    !chunkqueue_is_empty(con->write_queue) &&
  989: 	    con->is_writable) {
  990: 
  991: 		if (-1 == connection_handle_write(srv, con)) {
  992: 			connection_set_state(srv, con, CON_STATE_ERROR);
  993: 
  994: 			log_error_write(srv, __FILE__, __LINE__, "ds",
  995: 					con->fd,
  996: 					"handle write failed.");
  997: 		}
  998: 	}
  999: 
 1000: 	if (con->state == CON_STATE_CLOSE) {
 1001: 		/* flush the read buffers */
 1002: 		int len;
 1003: 		char buf[1024];
 1004: 
 1005: 		len = read(con->fd, buf, sizeof(buf));
 1006: 		if (len == 0 || (len < 0 && errno != EAGAIN && errno != EINTR) ) {
 1007: 			con->close_timeout_ts = srv->cur_ts - (HTTP_LINGER_TIMEOUT+1);
 1008: 		}
 1009: 	}
 1010: 
 1011: 	return HANDLER_FINISHED;
 1012: }
 1013: 
 1014: 
 1015: connection *connection_accept(server *srv, server_socket *srv_socket) {
 1016: 	/* accept everything */
 1017: 
 1018: 	/* search an empty place */
 1019: 	int cnt;
 1020: 	sock_addr cnt_addr;
 1021: 	socklen_t cnt_len;
 1022: 	/* accept it and register the fd */
 1023: 
 1024: 	/**
 1025: 	 * check if we can still open a new connections
 1026: 	 *
 1027: 	 * see #1216
 1028: 	 */
 1029: 
 1030: 	if (srv->conns->used >= srv->max_conns) {
 1031: 		return NULL;
 1032: 	}
 1033: 
 1034: 	cnt_len = sizeof(cnt_addr);
 1035: 
 1036: 	if (-1 == (cnt = accept(srv_socket->fd, (struct sockaddr *) &cnt_addr, &cnt_len))) {
 1037: 		switch (errno) {
 1038: 		case EAGAIN:
 1039: #if EWOULDBLOCK != EAGAIN
 1040: 		case EWOULDBLOCK:
 1041: #endif
 1042: 		case EINTR:
 1043: 			/* we were stopped _before_ we had a connection */
 1044: 		case ECONNABORTED: /* this is a FreeBSD thingy */
 1045: 			/* we were stopped _after_ we had a connection */
 1046: 			break;
 1047: 		case EMFILE:
 1048: 			/* out of fds */
 1049: 			break;
 1050: 		default:
 1051: 			log_error_write(srv, __FILE__, __LINE__, "ssd", "accept failed:", strerror(errno), errno);
 1052: 		}
 1053: 		return NULL;
 1054: 	} else {
 1055: 		if (cnt_addr.plain.sa_family != AF_UNIX) {
 1056: 			network_accept_tcp_nagle_disable(cnt);
 1057: 		}
 1058: 		return connection_accepted(srv, srv_socket, &cnt_addr, cnt);
 1059: 	}
 1060: }
 1061: 
 1062: connection *connection_accepted(server *srv, server_socket *srv_socket, sock_addr *cnt_addr, int cnt) {
 1063: 		connection *con;
 1064: 
 1065: 		srv->cur_fds++;
 1066: 
 1067: 		/* ok, we have the connection, register it */
 1068: #if 0
 1069: 		log_error_write(srv, __FILE__, __LINE__, "sd",
 1070: 				"appected()", cnt);
 1071: #endif
 1072: 		srv->con_opened++;
 1073: 
 1074: 		con = connections_get_new_connection(srv);
 1075: 
 1076: 		con->fd = cnt;
 1077: 		con->fde_ndx = -1;
 1078: 		fdevent_register(srv->ev, con->fd, connection_handle_fdevent, con);
 1079: 
 1080: 		connection_set_state(srv, con, CON_STATE_REQUEST_START);
 1081: 
 1082: 		con->connection_start = srv->cur_ts;
 1083: 		con->dst_addr = *cnt_addr;
 1084: 		buffer_copy_string(con->dst_addr_buf, inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
 1085: 		con->srv_socket = srv_socket;
 1086: 
 1087: 		if (-1 == (fdevent_fcntl_set(srv->ev, con->fd))) {
 1088: 			log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed: ", strerror(errno));
 1089: 			return NULL;
 1090: 		}
 1091: #ifdef USE_OPENSSL
 1092: 		/* connect FD to SSL */
 1093: 		if (srv_socket->is_ssl) {
 1094: 			if (NULL == (con->ssl = SSL_new(srv_socket->ssl_ctx))) {
 1095: 				log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
 1096: 						ERR_error_string(ERR_get_error(), NULL));
 1097: 
 1098: 				return NULL;
 1099: 			}
 1100: 
 1101: 			con->renegotiations = 0;
 1102: 			SSL_set_app_data(con->ssl, con);
 1103: 			SSL_set_accept_state(con->ssl);
 1104: 
 1105: 			if (1 != (SSL_set_fd(con->ssl, cnt))) {
 1106: 				log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
 1107: 						ERR_error_string(ERR_get_error(), NULL));
 1108: 				return NULL;
 1109: 			}
 1110: 		}
 1111: #endif
 1112: 		return con;
 1113: }
 1114: 
 1115: 
 1116: int connection_state_machine(server *srv, connection *con) {
 1117: 	int done = 0, r;
 1118: 
 1119: 	if (srv->srvconf.log_state_handling) {
 1120: 		log_error_write(srv, __FILE__, __LINE__, "sds",
 1121: 				"state at start",
 1122: 				con->fd,
 1123: 				connection_get_state(con->state));
 1124: 	}
 1125: 
 1126: 	while (done == 0) {
 1127: 		size_t ostate = con->state;
 1128: 
 1129: 		if (srv->srvconf.log_state_handling) {
 1130: 			log_error_write(srv, __FILE__, __LINE__, "sds",
 1131: 					"state for fd", con->fd, connection_get_state(con->state));
 1132: 		}
 1133: 
 1134: 		switch (con->state) {
 1135: 		case CON_STATE_REQUEST_START: /* transient */
 1136: 			con->request_start = srv->cur_ts;
 1137: 			con->read_idle_ts = srv->cur_ts;
 1138: 			if (con->conf.high_precision_timestamps)
 1139: 				log_clock_gettime_realtime(&con->request_start_hp);
 1140: 
 1141: 			con->request_count++;
 1142: 			con->loops_per_request = 0;
 1143: 
 1144: 			connection_set_state(srv, con, CON_STATE_READ);
 1145: 
 1146: 			break;
 1147: 		case CON_STATE_REQUEST_END: /* transient */
 1148: 			buffer_reset(con->uri.authority);
 1149: 			buffer_reset(con->uri.path);
 1150: 			buffer_reset(con->uri.query);
 1151: 			buffer_reset(con->request.orig_uri);
 1152: 
 1153: 			if (http_request_parse(srv, con)) {
 1154: 				/* we have to read some data from the POST request */
 1155: 
 1156: 				connection_set_state(srv, con, CON_STATE_READ_POST);
 1157: 
 1158: 				break;
 1159: 			}
 1160: 
 1161: 			connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
 1162: 
 1163: 			break;
 1164: 		case CON_STATE_READ_POST:
 1165: 		case CON_STATE_HANDLE_REQUEST:
 1166: 			/*
 1167: 			 * the request is parsed
 1168: 			 *
 1169: 			 * decided what to do with the request
 1170: 			 * -
 1171: 			 *
 1172: 			 *
 1173: 			 */
 1174: 
 1175: 			switch (r = http_response_prepare(srv, con)) {
 1176: 			case HANDLER_WAIT_FOR_EVENT:
 1177: 				if (!con->file_finished && (!con->file_started || 0 == con->conf.stream_response_body)) {
 1178: 					break; /* come back here */
 1179: 				}
 1180: 				/* response headers received from backend; fall through to start response */
 1181: 			case HANDLER_FINISHED:
 1182: 				if (con->error_handler_saved_status > 0) {
 1183: 					con->request.http_method = con->error_handler_saved_method;
 1184: 				}
 1185: 				if (con->mode == DIRECT) {
 1186: 					if (con->error_handler_saved_status) {
 1187: 						if (con->error_handler_saved_status > 0) {
 1188: 							con->http_status = con->error_handler_saved_status;
 1189: 						} else if (con->http_status == 404 || con->http_status == 403) {
 1190: 							/* error-handler-404 is a 404 */
 1191: 							con->http_status = -con->error_handler_saved_status;
 1192: 						} else {
 1193: 							/* error-handler-404 is back and has generated content */
 1194: 							/* if Status: was set, take it otherwise use 200 */
 1195: 						}
 1196: 					} else if (con->http_status >= 400) {
 1197: 						buffer *error_handler = NULL;
 1198: 						if (!buffer_string_is_empty(con->conf.error_handler)) {
 1199: 							error_handler = con->conf.error_handler;
 1200: 						} else if ((con->http_status == 404 || con->http_status == 403)
 1201: 							   && !buffer_string_is_empty(con->conf.error_handler_404)) {
 1202: 							error_handler = con->conf.error_handler_404;
 1203: 						}
 1204: 
 1205: 						if (error_handler) {
 1206: 							/* call error-handler */
 1207: 
 1208: 							/* set REDIRECT_STATUS to save current HTTP status code
 1209: 							 * for access by dynamic handlers
 1210: 							 * https://redmine.lighttpd.net/issues/1828 */
 1211: 							data_string *ds;
 1212: 							if (NULL == (ds = (data_string *)array_get_unused_element(con->environment, TYPE_STRING))) {
 1213: 								ds = data_string_init();
 1214: 							}
 1215: 							buffer_copy_string_len(ds->key, CONST_STR_LEN("REDIRECT_STATUS"));
 1216: 							buffer_append_int(ds->value, con->http_status);
 1217: 							array_insert_unique(con->environment, (data_unset *)ds);
 1218: 
 1219: 							if (error_handler == con->conf.error_handler) {
 1220: 								plugins_call_connection_reset(srv, con);
 1221: 
 1222: 								if (con->request.content_length) {
 1223: 									if ((off_t)con->request.content_length != chunkqueue_length(con->request_content_queue)) {
 1224: 										con->keep_alive = 0;
 1225: 									}
 1226: 									con->request.content_length = 0;
 1227: 									chunkqueue_reset(con->request_content_queue);
 1228: 								}
 1229: 
 1230: 								con->is_writable = 1;
 1231: 								con->file_finished = 0;
 1232: 								con->file_started = 0;
 1233: 								con->got_response = 0;
 1234: 								con->parsed_response = 0;
 1235: 								con->response.keep_alive = 0;
 1236: 								con->response.content_length = -1;
 1237: 								con->response.transfer_encoding = 0;
 1238: 
 1239: 								con->error_handler_saved_status = con->http_status;
 1240: 								con->error_handler_saved_method = con->request.http_method;
 1241: 
 1242: 								con->request.http_method = HTTP_METHOD_GET;
 1243: 							} else { /*(preserve behavior for server.error-handler-404)*/
 1244: 								con->error_handler_saved_status = -con->http_status; /*(negative to flag old behavior)*/
 1245: 							}
 1246: 
 1247: 							buffer_copy_buffer(con->request.uri, error_handler);
 1248: 							connection_handle_errdoc_init(srv, con);
 1249: 							con->http_status = 0; /*(after connection_handle_errdoc_init())*/
 1250: 
 1251: 							done = -1;
 1252: 							break;
 1253: 						}
 1254: 					}
 1255: 				}
 1256: 				if (con->http_status == 0) con->http_status = 200;
 1257: 
 1258: 				/* we have something to send, go on */
 1259: 				connection_set_state(srv, con, CON_STATE_RESPONSE_START);
 1260: 				break;
 1261: 			case HANDLER_WAIT_FOR_FD:
 1262: 				srv->want_fds++;
 1263: 
 1264: 				fdwaitqueue_append(srv, con);
 1265: 
 1266: 				break;
 1267: 			case HANDLER_COMEBACK:
 1268: 				done = -1;
 1269: 				break;
 1270: 			case HANDLER_ERROR:
 1271: 				/* something went wrong */
 1272: 				connection_set_state(srv, con, CON_STATE_ERROR);
 1273: 				break;
 1274: 			default:
 1275: 				log_error_write(srv, __FILE__, __LINE__, "sdd", "unknown ret-value: ", con->fd, r);
 1276: 				break;
 1277: 			}
 1278: 
 1279: 			break;
 1280: 		case CON_STATE_RESPONSE_START:
 1281: 			/*
 1282: 			 * the decision is done
 1283: 			 * - create the HTTP-Response-Header
 1284: 			 *
 1285: 			 */
 1286: 
 1287: 			if (-1 == connection_handle_write_prepare(srv, con)) {
 1288: 				connection_set_state(srv, con, CON_STATE_ERROR);
 1289: 
 1290: 				break;
 1291: 			}
 1292: 
 1293: 			connection_set_state(srv, con, CON_STATE_WRITE);
 1294: 			break;
 1295: 		case CON_STATE_RESPONSE_END: /* transient */
 1296: 		case CON_STATE_ERROR:        /* transient */
 1297: 			connection_handle_response_end_state(srv, con);
 1298: 			break;
 1299: 		case CON_STATE_CONNECT:
 1300: 			chunkqueue_reset(con->read_queue);
 1301: 
 1302: 			con->request_count = 0;
 1303: 
 1304: 			break;
 1305: 		case CON_STATE_CLOSE:
 1306: 			connection_handle_close_state(srv, con);
 1307: 			break;
 1308: 		case CON_STATE_READ:
 1309: 			connection_handle_read_state(srv, con);
 1310: 			break;
 1311: 		case CON_STATE_WRITE:
 1312: 			do {
 1313: 				/* only try to write if we have something in the queue */
 1314: 				if (!chunkqueue_is_empty(con->write_queue)) {
 1315: 					if (con->is_writable) {
 1316: 						if (-1 == connection_handle_write(srv, con)) {
 1317: 							log_error_write(srv, __FILE__, __LINE__, "ds",
 1318: 									con->fd,
 1319: 									"handle write failed.");
 1320: 							connection_set_state(srv, con, CON_STATE_ERROR);
 1321: 							break;
 1322: 						}
 1323: 						if (con->state != CON_STATE_WRITE) break;
 1324: 					}
 1325: 				} else if (con->file_finished) {
 1326: 					connection_set_state(srv, con, CON_STATE_RESPONSE_END);
 1327: 					break;
 1328: 				}
 1329: 
 1330: 				if (con->mode != DIRECT && !con->file_finished) {
 1331: 					switch(r = plugins_call_handle_subrequest(srv, con)) {
 1332: 					case HANDLER_WAIT_FOR_EVENT:
 1333: 					case HANDLER_FINISHED:
 1334: 					case HANDLER_GO_ON:
 1335: 						break;
 1336: 					case HANDLER_WAIT_FOR_FD:
 1337: 						srv->want_fds++;
 1338: 						fdwaitqueue_append(srv, con);
 1339: 						break;
 1340: 					case HANDLER_COMEBACK:
 1341: 					default:
 1342: 						log_error_write(srv, __FILE__, __LINE__, "sdd", "unexpected subrequest handler ret-value: ", con->fd, r);
 1343: 						/* fall through */
 1344: 					case HANDLER_ERROR:
 1345: 						connection_set_state(srv, con, CON_STATE_ERROR);
 1346: 						break;
 1347: 					}
 1348: 				}
 1349: 			} while (con->state == CON_STATE_WRITE && (!chunkqueue_is_empty(con->write_queue) ? con->is_writable : con->file_finished));
 1350: 
 1351: 			break;
 1352: 		default:
 1353: 			log_error_write(srv, __FILE__, __LINE__, "sdd",
 1354: 					"unknown state:", con->fd, con->state);
 1355: 
 1356: 			break;
 1357: 		}
 1358: 
 1359: 		if (done == -1) {
 1360: 			done = 0;
 1361: 		} else if (ostate == con->state) {
 1362: 			done = 1;
 1363: 		}
 1364: 	}
 1365: 
 1366: 	if (srv->srvconf.log_state_handling) {
 1367: 		log_error_write(srv, __FILE__, __LINE__, "sds",
 1368: 				"state at exit:",
 1369: 				con->fd,
 1370: 				connection_get_state(con->state));
 1371: 	}
 1372: 
 1373: 	r = 0;
 1374: 	switch(con->state) {
 1375: 	case CON_STATE_READ:
 1376: 	case CON_STATE_CLOSE:
 1377: 		r = FDEVENT_IN;
 1378: 		break;
 1379: 	case CON_STATE_WRITE:
 1380: 		/* request write-fdevent only if we really need it
 1381: 		 * - if we have data to write
 1382: 		 * - if the socket is not writable yet
 1383: 		 */
 1384: 		if (!chunkqueue_is_empty(con->write_queue) &&
 1385: 		    (con->is_writable == 0) &&
 1386: 		    (con->traffic_limit_reached == 0)) {
 1387: 			r |= FDEVENT_OUT;
 1388: 		}
 1389: 		/* fall through */
 1390: 	case CON_STATE_READ_POST:
 1391: 		if (con->conf.stream_request_body & FDEVENT_STREAM_REQUEST_POLLIN) {
 1392: 			r |= FDEVENT_IN;
 1393: 		}
 1394: 		break;
 1395: 	default:
 1396: 		break;
 1397: 	}
 1398: 	if (-1 != con->fd) {
 1399: 		const int events = fdevent_event_get_interest(srv->ev, con->fd);
 1400: 		if (con->is_readable < 0) {
 1401: 			con->is_readable = 0;
 1402: 			r |= FDEVENT_IN;
 1403: 		}
 1404: 		if (con->is_writable < 0) {
 1405: 			con->is_writable = 0;
 1406: 			r |= FDEVENT_OUT;
 1407: 		}
 1408: 		if (r != events) {
 1409: 			/* update timestamps when enabling interest in events */
 1410: 			if ((r & FDEVENT_IN) && !(events & FDEVENT_IN)) {
 1411: 				con->read_idle_ts = srv->cur_ts;
 1412: 			}
 1413: 			if ((r & FDEVENT_OUT) && !(events & FDEVENT_OUT)) {
 1414: 				con->write_request_ts = srv->cur_ts;
 1415: 			}
 1416: 			fdevent_event_set(srv->ev, &con->fde_ndx, con->fd, r);
 1417: 		}
 1418: 	}
 1419: 
 1420: 	return 0;
 1421: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>