Annotation of embedaddon/lighttpd/src/connections.c, revision 1.1.1.3

1.1.1.3 ! misho       1: #include "first.h"
        !             2: 
1.1       misho       3: #include "buffer.h"
                      4: #include "server.h"
                      5: #include "log.h"
                      6: #include "connections.h"
                      7: #include "fdevent.h"
                      8: 
1.1.1.3 ! misho       9: #include "configfile.h"
1.1       misho      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);
1.1.1.3 ! misho      54:                force_assert(NULL != conns->ptr);
1.1       misho      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);
1.1.1.3 ! misho      61:                force_assert(NULL != conns->ptr);
1.1       misho      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: 
1.1.1.3 ! misho     121: static int connection_close(server *srv, connection *con) {
1.1       misho     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
1.1.1.3 ! misho     143:        con->fd = -1;
1.1       misho     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: 
1.1.1.3 ! misho     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];
1.1       misho     165: 
1.1.1.3 ! misho     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);
1.1       misho     169:        }
                    170: 
1.1.1.3 ! misho     171:        if (srv->cur_ts - con->close_timeout_ts > HTTP_LINGER_TIMEOUT) {
        !           172:                connection_close(srv, con);
1.1       misho     173: 
1.1.1.3 ! misho     174:                if (srv->srvconf.log_state_handling) {
        !           175:                        log_error_write(srv, __FILE__, __LINE__, "sd",
        !           176:                                        "connection closed for fd", con->fd);
1.1       misho     177:                }
                    178:        }
                    179: }
                    180: 
1.1.1.3 ! misho     181: static void connection_handle_shutdown(server *srv, connection *con) {
        !           182:        int r;
1.1       misho     183: 
1.1.1.3 ! misho     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
1.1       misho     196:                         *
1.1.1.3 ! misho     197:                         * FIXME: wait for fdevent and call SSL_shutdown again
1.1       misho     198:                         *
                    199:                         */
1.1.1.3 ! misho     200:                        ERR_clear_error();
        !           201:                        if (-1 != (ret = SSL_shutdown(con->ssl))) break;
1.1       misho     202: 
1.1.1.3 ! misho     203:                        /* fall through */
        !           204:                default:
1.1       misho     205: 
1.1.1.3 ! misho     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:                                }
1.1       misho     233: 
1.1.1.3 ! misho     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));
1.1       misho     240:                                }
1.1.1.3 ! misho     241: 
        !           242:                                break;
1.1       misho     243:                        }
                    244:                }
1.1.1.3 ! misho     245:                ERR_clear_error();
        !           246:        }
        !           247: #endif
1.1       misho     248: 
1.1.1.3 ! misho     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);
1.1       misho     260: 
1.1.1.3 ! misho     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);
1.1       misho     265: 
1.1.1.3 ! misho     266:                if (srv->srvconf.log_state_handling) {
        !           267:                        log_error_write(srv, __FILE__, __LINE__, "sd",
        !           268:                                        "shutdown for fd", con->fd);
        !           269:                }
1.1       misho     270:        } else {
1.1.1.3 ! misho     271:                connection_close(srv, con);
1.1       misho     272:        }
                    273: }
                    274: 
1.1.1.3 ! misho     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);
1.1       misho     280:        }
                    281: 
1.1.1.3 ! misho     282:        if (con->state != CON_STATE_ERROR) srv->con_written++;
1.1       misho     283: 
1.1.1.3 ! misho     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;
1.1       misho     289:        }
                    290: 
1.1.1.3 ! misho     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);
1.1       misho     298:        } else {
1.1.1.3 ! misho     299:                connection_handle_shutdown(srv, con);
1.1       misho     300:        }
1.1.1.3 ! misho     301: }
1.1       misho     302: 
1.1.1.3 ! misho     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);
1.1       misho     312:                }
                    313:        }
                    314: 
1.1.1.3 ! misho     315:        con->response.transfer_encoding = 0;
        !           316:        buffer_reset(con->physical.path);
        !           317:        array_reset(con->response.headers);
        !           318:        chunkqueue_reset(con->write_queue);
1.1       misho     319: 
1.1.1.3 ! misho     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:        }
1.1       misho     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:                         * */
1.1.1.3 ! misho     340:                        if ((!con->http_status || con->http_status == 200) && !buffer_string_is_empty(con->uri.path) &&
1.1       misho     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: 
1.1.1.3 ! misho     384:                connection_handle_errdoc_init(srv, con);
1.1       misho     385: 
                    386:                /* try to send static errorfile */
1.1.1.3 ! misho     387:                if (!buffer_string_is_empty(con->conf.errorfile_prefix)) {
1.1       misho     388:                        stat_cache_entry *sce = NULL;
                    389: 
1.1.1.3 ! misho     390:                        buffer_copy_buffer(con->physical.path, con->conf.errorfile_prefix);
        !           391:                        buffer_append_int(con->physical.path, con->http_status);
1.1       misho     392:                        buffer_append_string_len(con->physical.path, CONST_STR_LEN(".html"));
                    393: 
1.1.1.3 ! misho     394:                        if (0 == http_chunk_append_file(srv, con, con->physical.path)) {
1.1       misho     395:                                con->file_finished = 1;
1.1.1.3 ! misho     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:                                }
1.1       misho     399:                        }
                    400:                }
                    401: 
                    402:                if (!con->file_finished) {
                    403:                        buffer *b;
                    404: 
                    405:                        buffer_reset(con->physical.path);
                    406: 
                    407:                        con->file_finished = 1;
1.1.1.3 ! misho     408:                        b = buffer_init();
1.1       misho     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>"));
1.1.1.3 ! misho     418:                        buffer_append_int(b, con->http_status);
1.1       misho     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>"));
1.1.1.3 ! misho     427:                        buffer_append_int(b, con->http_status);
1.1       misho     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: 
1.1.1.3 ! misho     436:                        (void)http_chunk_append_buffer(srv, con, b);
        !           437:                        buffer_free(b);
        !           438: 
1.1       misho     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:                                 */
1.1.1.3 ! misho     471:                                buffer_copy_int(srv->tmp_buf, qlen);
1.1       misho     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)) {
1.1.1.3 ! misho     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:                        }
1.1       misho     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));
1.1.1.3 ! misho     572:        force_assert(NULL != con);
1.1       misho     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 *));
1.1.1.3 ! misho     623:        force_assert(NULL != con->plugin_ctx);
1.1       misho     624: 
                    625:        con->cond_cache = calloc(srv->config_context->used, sizeof(cond_cache_t));
1.1.1.3 ! misho     626:        force_assert(NULL != con->cond_cache);
1.1       misho     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;
1.1.1.3 ! misho     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)*/
1.1       misho     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 */
1.1.1.3 ! misho     807:        /* when in CON_STATE_READ: about to receive first byte for a request: */
        !           808:        int is_request_start = chunkqueue_is_empty(cq);
1.1       misho     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: 
1.1.1.3 ! misho     824:        chunkqueue_remove_finished_chunks(cq);
1.1       misho     825: 
                    826:        /* we might have got several packets at once
                    827:         */
                    828: 
1.1.1.3 ! misho     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: 
1.1       misho     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;
1.1.1.3 ! misho     850:                        size_t len = buffer_string_length(c->mem) - c->offset;
        !           851:                        const char *b = c->mem->ptr + c->offset;
1.1       misho     852: 
1.1.1.3 ! misho     853:                        for (i = 0; i < len; ++i) {
        !           854:                                char ch = b[i];
1.1       misho     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 ) {
1.1.1.3 ! misho     864:                                                size_t bblen = buffer_string_length(cc->mem) - cc->offset;
        !           865:                                                const char *bb = cc->mem->ptr + cc->offset;
1.1       misho     866: 
1.1.1.3 ! misho     867:                                                for ( ; j < bblen; j++) {
        !           868:                                                        ch = bb[j];
1.1       misho     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) {
1.1.1.3 ! misho     893:                                size_t len = buffer_string_length(c->mem) - c->offset;
1.1       misho     894: 
                    895:                                if (c == last_chunk) {
1.1.1.3 ! misho     896:                                        len = last_offset;
1.1       misho     897:                                }
                    898: 
1.1.1.3 ! misho     899:                                buffer_append_string_len(con->request.request, c->mem->ptr + c->offset, len);
        !           900:                                c->offset += len;
        !           901:                                cq->bytes_out += len;
1.1       misho     902: 
1.1.1.3 ! misho     903:                                if (c == last_chunk) break;
1.1       misho     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);
1.1.1.3 ! misho     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);
1.1       misho     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: 
1.1.1.3 ! misho     983:        if (con->state == CON_STATE_READ) {
1.1       misho     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 {
1.1.1.3 ! misho    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) {
1.1       misho    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;
1.1.1.3 ! misho    1083:                con->dst_addr = *cnt_addr;
1.1       misho    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: 
1.1.1.3 ! misho    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: 
1.1       misho    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;
1.1.1.3 ! misho    1138:                        if (con->conf.high_precision_timestamps)
        !          1139:                                log_clock_gettime_realtime(&con->request_start_hp);
1.1       misho    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;
1.1.1.3 ! misho    1164:                case CON_STATE_READ_POST:
1.1       misho    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)) {
1.1.1.3 ! misho    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 */
1.1       misho    1181:                        case HANDLER_FINISHED:
1.1.1.3 ! misho    1182:                                if (con->error_handler_saved_status > 0) {
        !          1183:                                        con->request.http_method = con->error_handler_saved_method;
        !          1184:                                }
1.1       misho    1185:                                if (con->mode == DIRECT) {
1.1.1.3 ! misho    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:                                                }
1.1       misho    1204: 
1.1.1.3 ! misho    1205:                                                if (error_handler) {
        !          1206:                                                        /* call error-handler */
1.1       misho    1207: 
1.1.1.3 ! misho    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();
1.1       misho    1214:                                                        }
1.1.1.3 ! misho    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:                                                                }
1.1       misho    1229: 
1.1.1.3 ! misho    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:                                                        }
1.1       misho    1246: 
1.1.1.3 ! misho    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())*/
1.1       misho    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 */
1.1.1.3 ! misho    1296:                case CON_STATE_ERROR:        /* transient */
        !          1297:                        connection_handle_response_end_state(srv, con);
1.1       misho    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:
1.1.1.3 ! misho    1306:                        connection_handle_close_state(srv, con);
1.1       misho    1307:                        break;
                   1308:                case CON_STATE_READ:
                   1309:                        connection_handle_read_state(srv, con);
                   1310:                        break;
                   1311:                case CON_STATE_WRITE:
1.1.1.3 ! misho    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;
1.1       misho    1328:                                }
                   1329: 
1.1.1.3 ! misho    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:
1.1       misho    1335:                                                break;
1.1.1.3 ! misho    1336:                                        case HANDLER_WAIT_FOR_FD:
        !          1337:                                                srv->want_fds++;
        !          1338:                                                fdwaitqueue_append(srv, con);
1.1       misho    1339:                                                break;
1.1.1.3 ! misho    1340:                                        case HANDLER_COMEBACK:
1.1       misho    1341:                                        default:
1.1.1.3 ! misho    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);
1.1       misho    1346:                                                break;
                   1347:                                        }
                   1348:                                }
1.1.1.3 ! misho    1349:                        } while (con->state == CON_STATE_WRITE && (!chunkqueue_is_empty(con->write_queue) ? con->is_writable : con->file_finished));
1.1       misho    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: 
1.1.1.3 ! misho    1373:        r = 0;
1.1       misho    1374:        switch(con->state) {
                   1375:        case CON_STATE_READ:
                   1376:        case CON_STATE_CLOSE:
1.1.1.3 ! misho    1377:                r = FDEVENT_IN;
1.1       misho    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)) {
1.1.1.3 ! misho    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;
1.1       misho    1393:                }
                   1394:                break;
                   1395:        default:
                   1396:                break;
1.1.1.3 ! misho    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:                }
1.1       misho    1418:        }
                   1419: 
                   1420:        return 0;
                   1421: }

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