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

    1: #include "first.h"
    2: 
    3: #include "base.h"
    4: #include "connections.h"
    5: #include "joblist.h"
    6: #include "log.h"
    7: 
    8: #include <errno.h>
    9: 
   10: #ifdef USE_OPENSSL
   11: # include <openssl/ssl.h>
   12: # include <openssl/err.h>
   13: #endif
   14: 
   15: const char *connection_get_state(connection_state_t state) {
   16: 	switch (state) {
   17: 	case CON_STATE_CONNECT: return "connect";
   18: 	case CON_STATE_READ: return "read";
   19: 	case CON_STATE_READ_POST: return "readpost";
   20: 	case CON_STATE_WRITE: return "write";
   21: 	case CON_STATE_CLOSE: return "close";
   22: 	case CON_STATE_ERROR: return "error";
   23: 	case CON_STATE_HANDLE_REQUEST: return "handle-req";
   24: 	case CON_STATE_REQUEST_START: return "req-start";
   25: 	case CON_STATE_REQUEST_END: return "req-end";
   26: 	case CON_STATE_RESPONSE_START: return "resp-start";
   27: 	case CON_STATE_RESPONSE_END: return "resp-end";
   28: 	default: return "(unknown)";
   29: 	}
   30: }
   31: 
   32: const char *connection_get_short_state(connection_state_t state) {
   33: 	switch (state) {
   34: 	case CON_STATE_CONNECT: return ".";
   35: 	case CON_STATE_READ: return "r";
   36: 	case CON_STATE_READ_POST: return "R";
   37: 	case CON_STATE_WRITE: return "W";
   38: 	case CON_STATE_CLOSE: return "C";
   39: 	case CON_STATE_ERROR: return "E";
   40: 	case CON_STATE_HANDLE_REQUEST: return "h";
   41: 	case CON_STATE_REQUEST_START: return "q";
   42: 	case CON_STATE_REQUEST_END: return "Q";
   43: 	case CON_STATE_RESPONSE_START: return "s";
   44: 	case CON_STATE_RESPONSE_END: return "S";
   45: 	default: return "x";
   46: 	}
   47: }
   48: 
   49: int connection_set_state(server *srv, connection *con, connection_state_t state) {
   50: 	UNUSED(srv);
   51: 
   52: 	con->state = state;
   53: 
   54: 	return 0;
   55: }
   56: 
   57: #if 0
   58: static void dump_packet(const unsigned char *data, size_t len) {
   59: 	size_t i, j;
   60: 
   61: 	if (len == 0) return;
   62: 
   63: 	for (i = 0; i < len; i++) {
   64: 		if (i % 16 == 0) fprintf(stderr, "  ");
   65: 
   66: 		fprintf(stderr, "%02x ", data[i]);
   67: 
   68: 		if ((i + 1) % 16 == 0) {
   69: 			fprintf(stderr, "  ");
   70: 			for (j = 0; j <= i % 16; j++) {
   71: 				unsigned char c;
   72: 
   73: 				if (i-15+j >= len) break;
   74: 
   75: 				c = data[i-15+j];
   76: 
   77: 				fprintf(stderr, "%c", c > 32 && c < 128 ? c : '.');
   78: 			}
   79: 
   80: 			fprintf(stderr, "\n");
   81: 		}
   82: 	}
   83: 
   84: 	if (len % 16 != 0) {
   85: 		for (j = i % 16; j < 16; j++) {
   86: 			fprintf(stderr, "   ");
   87: 		}
   88: 
   89: 		fprintf(stderr, "  ");
   90: 		for (j = i & ~0xf; j < len; j++) {
   91: 			unsigned char c;
   92: 
   93: 			c = data[j];
   94: 			fprintf(stderr, "%c", c > 32 && c < 128 ? c : '.');
   95: 		}
   96: 		fprintf(stderr, "\n");
   97: 	}
   98: }
   99: #endif
  100: 
  101: static int connection_handle_read_ssl(server *srv, connection *con) {
  102: #ifdef USE_OPENSSL
  103: 	int r, ssl_err, len;
  104: 	char *mem = NULL;
  105: 	size_t mem_len = 0;
  106: 
  107: 	if (!con->srv_socket->is_ssl) return -1;
  108: 
  109: 	ERR_clear_error();
  110: 	do {
  111: 		chunkqueue_get_memory(con->read_queue, &mem, &mem_len, 0, SSL_pending(con->ssl));
  112: #if 0
  113: 		/* overwrite everything with 0 */
  114: 		memset(mem, 0, mem_len);
  115: #endif
  116: 
  117: 		len = SSL_read(con->ssl, mem, mem_len);
  118: 		if (len > 0) {
  119: 			chunkqueue_use_memory(con->read_queue, len);
  120: 			con->bytes_read += len;
  121: 		} else {
  122: 			chunkqueue_use_memory(con->read_queue, 0);
  123: 		}
  124: 
  125: 		if (con->renegotiations > 1 && con->conf.ssl_disable_client_renegotiation) {
  126: 			log_error_write(srv, __FILE__, __LINE__, "s", "SSL: renegotiation initiated by client, killing connection");
  127: 			connection_set_state(srv, con, CON_STATE_ERROR);
  128: 			return -1;
  129: 		}
  130: 	} while (len > 0);
  131: 
  132: 	if (len < 0) {
  133: 		int oerrno = errno;
  134: 		switch ((r = SSL_get_error(con->ssl, len))) {
  135: 		case SSL_ERROR_WANT_WRITE:
  136: 			con->is_writable = -1;
  137: 		case SSL_ERROR_WANT_READ:
  138: 			con->is_readable = 0;
  139: 
  140: 			/* the manual says we have to call SSL_read with the same arguments next time.
  141: 			 * we ignore this restriction; no one has complained about it in 1.5 yet, so it probably works anyway.
  142: 			 */
  143: 
  144: 			return 0;
  145: 		case SSL_ERROR_SYSCALL:
  146: 			/**
  147: 			 * man SSL_get_error()
  148: 			 *
  149: 			 * SSL_ERROR_SYSCALL
  150: 			 *   Some I/O error occurred.  The OpenSSL error queue may contain more
  151: 			 *   information on the error.  If the error queue is empty (i.e.
  152: 			 *   ERR_get_error() returns 0), ret can be used to find out more about
  153: 			 *   the error: If ret == 0, an EOF was observed that violates the
  154: 			 *   protocol.  If ret == -1, the underlying BIO reported an I/O error
  155: 			 *   (for socket I/O on Unix systems, consult errno for details).
  156: 			 *
  157: 			 */
  158: 			while((ssl_err = ERR_get_error())) {
  159: 				/* get all errors from the error-queue */
  160: 				log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
  161: 						r, ERR_error_string(ssl_err, NULL));
  162: 			}
  163: 
  164: 			switch(oerrno) {
  165: 			default:
  166: 				log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
  167: 						len, r, oerrno,
  168: 						strerror(oerrno));
  169: 				break;
  170: 			}
  171: 
  172: 			break;
  173: 		case SSL_ERROR_ZERO_RETURN:
  174: 			/* clean shutdown on the remote side */
  175: 
  176: 			if (r == 0) {
  177: 				/* FIXME: later */
  178: 			}
  179: 
  180: 			/* fall thourgh */
  181: 		default:
  182: 			while((ssl_err = ERR_get_error())) {
  183: 				switch (ERR_GET_REASON(ssl_err)) {
  184: 				case SSL_R_SSL_HANDSHAKE_FAILURE:
  185: 			      #ifdef SSL_R_TLSV1_ALERT_UNKNOWN_CA
  186: 				case SSL_R_TLSV1_ALERT_UNKNOWN_CA:
  187: 			      #endif
  188: 			      #ifdef SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN
  189: 				case SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN:
  190: 			      #endif
  191: 			      #ifdef SSL_R_SSLV3_ALERT_BAD_CERTIFICATE
  192: 				case SSL_R_SSLV3_ALERT_BAD_CERTIFICATE:
  193: 			      #endif
  194: 					if (!con->conf.log_ssl_noise) continue;
  195: 					break;
  196: 				default:
  197: 					break;
  198: 				}
  199: 				/* get all errors from the error-queue */
  200: 				log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
  201: 				                r, ERR_error_string(ssl_err, NULL));
  202: 			}
  203: 			break;
  204: 		}
  205: 
  206: 		connection_set_state(srv, con, CON_STATE_ERROR);
  207: 
  208: 		return -1;
  209: 	} else if (len == 0) {
  210: 		con->is_readable = 0;
  211: 		/* the other end close the connection -> KEEP-ALIVE */
  212: 
  213: 		return -2;
  214: 	} else {
  215: 		return 0;
  216: 	}
  217: #else
  218: 	UNUSED(srv);
  219: 	UNUSED(con);
  220: 	return -1;
  221: #endif
  222: }
  223: 
  224: /* 0: everything ok, -1: error, -2: con closed */
  225: int connection_handle_read(server *srv, connection *con) {
  226: 	int len;
  227: 	char *mem = NULL;
  228: 	size_t mem_len = 0;
  229: 	int toread;
  230: 
  231: 	if (con->srv_socket->is_ssl) {
  232: 		return connection_handle_read_ssl(srv, con);
  233: 	}
  234: 
  235: 	/* default size for chunks is 4kb; only use bigger chunks if FIONREAD tells
  236: 	 *  us more than 4kb is available
  237: 	 * if FIONREAD doesn't signal a big chunk we fill the previous buffer
  238: 	 *  if it has >= 1kb free
  239: 	 */
  240: #if defined(__WIN32)
  241: 	chunkqueue_get_memory(con->read_queue, &mem, &mem_len, 0, 4096);
  242: 
  243: 	len = recv(con->fd, mem, mem_len, 0);
  244: #else /* __WIN32 */
  245: 	if (ioctl(con->fd, FIONREAD, &toread) || toread <= 4*1024) {
  246: 		toread = 4096;
  247: 	}
  248: 	else if (toread > MAX_READ_LIMIT) {
  249: 		toread = MAX_READ_LIMIT;
  250: 	}
  251: 	chunkqueue_get_memory(con->read_queue, &mem, &mem_len, 0, toread);
  252: 
  253: 	len = read(con->fd, mem, mem_len);
  254: #endif /* __WIN32 */
  255: 
  256: 	chunkqueue_use_memory(con->read_queue, len > 0 ? len : 0);
  257: 
  258: 	if (len < 0) {
  259: 		con->is_readable = 0;
  260: 
  261: #if defined(__WIN32)
  262: 		{
  263: 			int lastError = WSAGetLastError();
  264: 			switch (lastError) {
  265: 			case EAGAIN:
  266: 				return 0;
  267: 			case EINTR:
  268: 				/* we have been interrupted before we could read */
  269: 				con->is_readable = 1;
  270: 				return 0;
  271: 			case ECONNRESET:
  272: 				/* suppress logging for this error, expected for keep-alive */
  273: 				break;
  274: 			default:
  275: 				log_error_write(srv, __FILE__, __LINE__, "sd", "connection closed - recv failed: ", lastError);
  276: 				break;
  277: 			}
  278: 		}
  279: #else /* __WIN32 */
  280: 		switch (errno) {
  281: 		case EAGAIN:
  282: 			return 0;
  283: 		case EINTR:
  284: 			/* we have been interrupted before we could read */
  285: 			con->is_readable = 1;
  286: 			return 0;
  287: 		case ECONNRESET:
  288: 			/* suppress logging for this error, expected for keep-alive */
  289: 			break;
  290: 		default:
  291: 			log_error_write(srv, __FILE__, __LINE__, "ssd", "connection closed - read failed: ", strerror(errno), errno);
  292: 			break;
  293: 		}
  294: #endif /* __WIN32 */
  295: 
  296: 		connection_set_state(srv, con, CON_STATE_ERROR);
  297: 
  298: 		return -1;
  299: 	} else if (len == 0) {
  300: 		con->is_readable = 0;
  301: 		/* the other end close the connection -> KEEP-ALIVE */
  302: 
  303: 		/* pipelining */
  304: 
  305: 		return -2;
  306: 	} else if (len != (ssize_t) mem_len) {
  307: 		/* we got less then expected, wait for the next fd-event */
  308: 
  309: 		con->is_readable = 0;
  310: 	}
  311: 
  312: 	con->bytes_read += len;
  313: #if 0
  314: 	dump_packet(b->ptr, len);
  315: #endif
  316: 
  317: 	return 0;
  318: }
  319: 
  320: handler_t connection_handle_read_post_state(server *srv, connection *con) {
  321: 	chunkqueue *cq = con->read_queue;
  322: 	chunkqueue *dst_cq = con->request_content_queue;
  323: 
  324: 	int is_closed = 0;
  325: 
  326: 	if (con->is_readable) {
  327: 		con->read_idle_ts = srv->cur_ts;
  328: 
  329: 		switch(connection_handle_read(srv, con)) {
  330: 		case -1:
  331: 			return HANDLER_ERROR;
  332: 		case -2:
  333: 			is_closed = 1;
  334: 			break;
  335: 		default:
  336: 			break;
  337: 		}
  338: 	}
  339: 
  340: 	chunkqueue_remove_finished_chunks(cq);
  341: 
  342: 	if (con->request.content_length <= 64*1024) {
  343: 		/* don't buffer request bodies <= 64k on disk */
  344: 		chunkqueue_steal(dst_cq, cq, (off_t)con->request.content_length - dst_cq->bytes_in);
  345: 	}
  346: 	else if (0 != chunkqueue_steal_with_tempfiles(srv, dst_cq, cq, (off_t)con->request.content_length - dst_cq->bytes_in)) {
  347: 		/* writing to temp file failed */
  348: 		con->http_status = 500; /* Internal Server Error */
  349: 		con->keep_alive = 0;
  350: 		con->mode = DIRECT;
  351: 		chunkqueue_reset(con->write_queue);
  352: 
  353: 		return HANDLER_FINISHED;
  354: 	}
  355: 
  356: 	chunkqueue_remove_finished_chunks(cq);
  357: 
  358: 	if (dst_cq->bytes_in == (off_t)con->request.content_length) {
  359: 		/* Content is ready */
  360: 		con->conf.stream_request_body &= ~FDEVENT_STREAM_REQUEST_POLLIN;
  361: 		if (con->state == CON_STATE_READ_POST) {
  362: 			connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
  363: 		}
  364: 		return HANDLER_GO_ON;
  365: 	} else if (is_closed) {
  366: 	      #if 0
  367: 		con->http_status = 400; /* Bad Request */
  368: 		con->keep_alive = 0;
  369: 		con->mode = DIRECT;
  370: 		chunkqueue_reset(con->write_queue);
  371: 
  372: 		return HANDLER_FINISHED;
  373: 	      #endif
  374: 		return HANDLER_ERROR;
  375: 	} else {
  376: 		con->conf.stream_request_body |= FDEVENT_STREAM_REQUEST_POLLIN;
  377: 		return (con->conf.stream_request_body & FDEVENT_STREAM_REQUEST)
  378: 		  ? HANDLER_GO_ON
  379: 		  : HANDLER_WAIT_FOR_EVENT;
  380: 	}
  381: }
  382: 
  383: void connection_response_reset(server *srv, connection *con) {
  384: 	UNUSED(srv);
  385: 
  386: 	con->http_status = 0;
  387: 	con->is_writable = 1;
  388: 	con->file_finished = 0;
  389: 	con->file_started = 0;
  390: 	con->got_response = 0;
  391: 	con->parsed_response = 0;
  392: 	con->response.keep_alive = 0;
  393: 	con->response.content_length = -1;
  394: 	con->response.transfer_encoding = 0;
  395: 	buffer_reset(con->physical.path);
  396: 	array_reset(con->response.headers);
  397: 	chunkqueue_reset(con->write_queue);
  398: }

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