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

1.1     ! misho       1: #include "buffer.h"
        !             2: #include "server.h"
        !             3: #include "log.h"
        !             4: #include "connections.h"
        !             5: #include "fdevent.h"
        !             6: 
        !             7: #include "request.h"
        !             8: #include "response.h"
        !             9: #include "network.h"
        !            10: #include "http_chunk.h"
        !            11: #include "stat_cache.h"
        !            12: #include "joblist.h"
        !            13: 
        !            14: #include "plugin.h"
        !            15: 
        !            16: #include "inet_ntop_cache.h"
        !            17: 
        !            18: #include <sys/stat.h>
        !            19: 
        !            20: #include <stdlib.h>
        !            21: #include <stdio.h>
        !            22: #include <unistd.h>
        !            23: #include <errno.h>
        !            24: #include <string.h>
        !            25: #include <fcntl.h>
        !            26: #include <assert.h>
        !            27: 
        !            28: #ifdef USE_OPENSSL
        !            29: # include <openssl/ssl.h>
        !            30: # include <openssl/err.h>
        !            31: #endif
        !            32: 
        !            33: #ifdef HAVE_SYS_FILIO_H
        !            34: # include <sys/filio.h>
        !            35: #endif
        !            36: 
        !            37: #include "sys-socket.h"
        !            38: 
        !            39: typedef struct {
        !            40:                PLUGIN_DATA;
        !            41: } plugin_data;
        !            42: 
        !            43: static connection *connections_get_new_connection(server *srv) {
        !            44:        connections *conns = srv->conns;
        !            45:        size_t i;
        !            46: 
        !            47:        if (conns->size == 0) {
        !            48:                conns->size = 128;
        !            49:                conns->ptr = NULL;
        !            50:                conns->ptr = malloc(sizeof(*conns->ptr) * conns->size);
        !            51:                for (i = 0; i < conns->size; i++) {
        !            52:                        conns->ptr[i] = connection_init(srv);
        !            53:                }
        !            54:        } else if (conns->size == conns->used) {
        !            55:                conns->size += 128;
        !            56:                conns->ptr = realloc(conns->ptr, sizeof(*conns->ptr) * conns->size);
        !            57: 
        !            58:                for (i = conns->used; i < conns->size; i++) {
        !            59:                        conns->ptr[i] = connection_init(srv);
        !            60:                }
        !            61:        }
        !            62: 
        !            63:        connection_reset(srv, conns->ptr[conns->used]);
        !            64: #if 0
        !            65:        fprintf(stderr, "%s.%d: add: ", __FILE__, __LINE__);
        !            66:        for (i = 0; i < conns->used + 1; i++) {
        !            67:                fprintf(stderr, "%d ", conns->ptr[i]->fd);
        !            68:        }
        !            69:        fprintf(stderr, "\n");
        !            70: #endif
        !            71: 
        !            72:        conns->ptr[conns->used]->ndx = conns->used;
        !            73:        return conns->ptr[conns->used++];
        !            74: }
        !            75: 
        !            76: static int connection_del(server *srv, connection *con) {
        !            77:        size_t i;
        !            78:        connections *conns = srv->conns;
        !            79:        connection *temp;
        !            80: 
        !            81:        if (con == NULL) return -1;
        !            82: 
        !            83:        if (-1 == con->ndx) return -1;
        !            84: 
        !            85:        buffer_reset(con->uri.authority);
        !            86:        buffer_reset(con->uri.path);
        !            87:        buffer_reset(con->uri.query);
        !            88:        buffer_reset(con->request.orig_uri);
        !            89: 
        !            90:        i = con->ndx;
        !            91: 
        !            92:        /* not last element */
        !            93: 
        !            94:        if (i != conns->used - 1) {
        !            95:                temp = conns->ptr[i];
        !            96:                conns->ptr[i] = conns->ptr[conns->used - 1];
        !            97:                conns->ptr[conns->used - 1] = temp;
        !            98: 
        !            99:                conns->ptr[i]->ndx = i;
        !           100:                conns->ptr[conns->used - 1]->ndx = -1;
        !           101:        }
        !           102: 
        !           103:        conns->used--;
        !           104: 
        !           105:        con->ndx = -1;
        !           106: #if 0
        !           107:        fprintf(stderr, "%s.%d: del: (%d)", __FILE__, __LINE__, conns->used);
        !           108:        for (i = 0; i < conns->used; i++) {
        !           109:                fprintf(stderr, "%d ", conns->ptr[i]->fd);
        !           110:        }
        !           111:        fprintf(stderr, "\n");
        !           112: #endif
        !           113:        return 0;
        !           114: }
        !           115: 
        !           116: int connection_close(server *srv, connection *con) {
        !           117: #ifdef USE_OPENSSL
        !           118:        server_socket *srv_sock = con->srv_socket;
        !           119: #endif
        !           120: 
        !           121: #ifdef USE_OPENSSL
        !           122:        if (srv_sock->is_ssl) {
        !           123:                if (con->ssl) SSL_free(con->ssl);
        !           124:                con->ssl = NULL;
        !           125:        }
        !           126: #endif
        !           127: 
        !           128:        fdevent_event_del(srv->ev, &(con->fde_ndx), con->fd);
        !           129:        fdevent_unregister(srv->ev, con->fd);
        !           130: #ifdef __WIN32
        !           131:        if (closesocket(con->fd)) {
        !           132:                log_error_write(srv, __FILE__, __LINE__, "sds",
        !           133:                                "(warning) close:", con->fd, strerror(errno));
        !           134:        }
        !           135: #else
        !           136:        if (close(con->fd)) {
        !           137:                log_error_write(srv, __FILE__, __LINE__, "sds",
        !           138:                                "(warning) close:", con->fd, strerror(errno));
        !           139:        }
        !           140: #endif
        !           141: 
        !           142:        srv->cur_fds--;
        !           143: #if 0
        !           144:        log_error_write(srv, __FILE__, __LINE__, "sd",
        !           145:                        "closed()", con->fd);
        !           146: #endif
        !           147: 
        !           148:        connection_del(srv, con);
        !           149:        connection_set_state(srv, con, CON_STATE_CONNECT);
        !           150: 
        !           151:        return 0;
        !           152: }
        !           153: 
        !           154: #if 0
        !           155: static void dump_packet(const unsigned char *data, size_t len) {
        !           156:        size_t i, j;
        !           157: 
        !           158:        if (len == 0) return;
        !           159: 
        !           160:        for (i = 0; i < len; i++) {
        !           161:                if (i % 16 == 0) fprintf(stderr, "  ");
        !           162: 
        !           163:                fprintf(stderr, "%02x ", data[i]);
        !           164: 
        !           165:                if ((i + 1) % 16 == 0) {
        !           166:                        fprintf(stderr, "  ");
        !           167:                        for (j = 0; j <= i % 16; j++) {
        !           168:                                unsigned char c;
        !           169: 
        !           170:                                if (i-15+j >= len) break;
        !           171: 
        !           172:                                c = data[i-15+j];
        !           173: 
        !           174:                                fprintf(stderr, "%c", c > 32 && c < 128 ? c : '.');
        !           175:                        }
        !           176: 
        !           177:                        fprintf(stderr, "\n");
        !           178:                }
        !           179:        }
        !           180: 
        !           181:        if (len % 16 != 0) {
        !           182:                for (j = i % 16; j < 16; j++) {
        !           183:                        fprintf(stderr, "   ");
        !           184:                }
        !           185: 
        !           186:                fprintf(stderr, "  ");
        !           187:                for (j = i & ~0xf; j < len; j++) {
        !           188:                        unsigned char c;
        !           189: 
        !           190:                        c = data[j];
        !           191:                        fprintf(stderr, "%c", c > 32 && c < 128 ? c : '.');
        !           192:                }
        !           193:                fprintf(stderr, "\n");
        !           194:        }
        !           195: }
        !           196: #endif
        !           197: 
        !           198: static int connection_handle_read_ssl(server *srv, connection *con) {
        !           199: #ifdef USE_OPENSSL
        !           200:        int r, ssl_err, len, count = 0, read_offset, toread;
        !           201:        buffer *b = NULL;
        !           202: 
        !           203:        if (!con->srv_socket->is_ssl) return -1;
        !           204: 
        !           205:        ERR_clear_error();
        !           206:        do {
        !           207:                if (NULL != con->read_queue->last) {
        !           208:                        b = con->read_queue->last->mem;
        !           209:                }
        !           210: 
        !           211:                if (NULL == b || b->size - b->used < 1024) {
        !           212:                        b = chunkqueue_get_append_buffer(con->read_queue);
        !           213:                        len = SSL_pending(con->ssl);
        !           214:                        if (len < 4*1024) len = 4*1024; /* always alloc >= 4k buffer */
        !           215:                        buffer_prepare_copy(b, len + 1);
        !           216: 
        !           217:                        /* overwrite everything with 0 */
        !           218:                        memset(b->ptr, 0, b->size);
        !           219:                }
        !           220: 
        !           221:                read_offset = (b->used > 0) ? b->used - 1 : 0;
        !           222:                toread = b->size - 1 - read_offset;
        !           223: 
        !           224:                len = SSL_read(con->ssl, b->ptr + read_offset, toread);
        !           225: 
        !           226:                if (con->renegotiations > 1 && con->conf.ssl_disable_client_renegotiation) {
        !           227:                        log_error_write(srv, __FILE__, __LINE__, "s", "SSL: renegotiation initiated by client, killing connection");
        !           228:                        connection_set_state(srv, con, CON_STATE_ERROR);
        !           229:                        return -1;
        !           230:                }
        !           231: 
        !           232:                if (len > 0) {
        !           233:                        if (b->used > 0) b->used--;
        !           234:                        b->used += len;
        !           235:                        b->ptr[b->used++] = '\0';
        !           236: 
        !           237:                        con->bytes_read += len;
        !           238: 
        !           239:                        count += len;
        !           240:                }
        !           241:        } while (len == toread && count < MAX_READ_LIMIT);
        !           242: 
        !           243: 
        !           244:        if (len < 0) {
        !           245:                int oerrno = errno;
        !           246:                switch ((r = SSL_get_error(con->ssl, len))) {
        !           247:                case SSL_ERROR_WANT_READ:
        !           248:                case SSL_ERROR_WANT_WRITE:
        !           249:                        con->is_readable = 0;
        !           250: 
        !           251:                        /* the manual says we have to call SSL_read with the same arguments next time.
        !           252:                         * we ignore this restriction; no one has complained about it in 1.5 yet, so it probably works anyway.
        !           253:                         */
        !           254: 
        !           255:                        return 0;
        !           256:                case SSL_ERROR_SYSCALL:
        !           257:                        /**
        !           258:                         * man SSL_get_error()
        !           259:                         *
        !           260:                         * SSL_ERROR_SYSCALL
        !           261:                         *   Some I/O error occurred.  The OpenSSL error queue may contain more
        !           262:                         *   information on the error.  If the error queue is empty (i.e.
        !           263:                         *   ERR_get_error() returns 0), ret can be used to find out more about
        !           264:                         *   the error: If ret == 0, an EOF was observed that violates the
        !           265:                         *   protocol.  If ret == -1, the underlying BIO reported an I/O error
        !           266:                         *   (for socket I/O on Unix systems, consult errno for details).
        !           267:                         *
        !           268:                         */
        !           269:                        while((ssl_err = ERR_get_error())) {
        !           270:                                /* get all errors from the error-queue */
        !           271:                                log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
        !           272:                                                r, ERR_error_string(ssl_err, NULL));
        !           273:                        }
        !           274: 
        !           275:                        switch(oerrno) {
        !           276:                        default:
        !           277:                                log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
        !           278:                                                len, r, oerrno,
        !           279:                                                strerror(oerrno));
        !           280:                                break;
        !           281:                        }
        !           282: 
        !           283:                        break;
        !           284:                case SSL_ERROR_ZERO_RETURN:
        !           285:                        /* clean shutdown on the remote side */
        !           286: 
        !           287:                        if (r == 0) {
        !           288:                                /* FIXME: later */
        !           289:                        }
        !           290: 
        !           291:                        /* fall thourgh */
        !           292:                default:
        !           293:                        while((ssl_err = ERR_get_error())) {
        !           294:                                switch (ERR_GET_REASON(ssl_err)) {
        !           295:                                case SSL_R_SSL_HANDSHAKE_FAILURE:
        !           296:                                case SSL_R_TLSV1_ALERT_UNKNOWN_CA:
        !           297:                                case SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN:
        !           298:                                case SSL_R_SSLV3_ALERT_BAD_CERTIFICATE:
        !           299:                                        if (!con->conf.log_ssl_noise) continue;
        !           300:                                        break;
        !           301:                                default:
        !           302:                                        break;
        !           303:                                }
        !           304:                                /* get all errors from the error-queue */
        !           305:                                log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
        !           306:                                                r, ERR_error_string(ssl_err, NULL));
        !           307:                        }
        !           308:                        break;
        !           309:                }
        !           310: 
        !           311:                connection_set_state(srv, con, CON_STATE_ERROR);
        !           312: 
        !           313:                return -1;
        !           314:        } else if (len == 0) {
        !           315:                con->is_readable = 0;
        !           316:                /* the other end close the connection -> KEEP-ALIVE */
        !           317: 
        !           318:                return -2;
        !           319:        } else {
        !           320:                joblist_append(srv, con);
        !           321:        }
        !           322: 
        !           323:        return 0;
        !           324: #else
        !           325:        UNUSED(srv);
        !           326:        UNUSED(con);
        !           327:        return -1;
        !           328: #endif
        !           329: }
        !           330: 
        !           331: /* 0: everything ok, -1: error, -2: con closed */
        !           332: static int connection_handle_read(server *srv, connection *con) {
        !           333:        int len;
        !           334:        buffer *b;
        !           335:        int toread, read_offset;
        !           336: 
        !           337:        if (con->srv_socket->is_ssl) {
        !           338:                return connection_handle_read_ssl(srv, con);
        !           339:        }
        !           340: 
        !           341:        b = (NULL != con->read_queue->last) ? con->read_queue->last->mem : NULL;
        !           342: 
        !           343:        /* default size for chunks is 4kb; only use bigger chunks if FIONREAD tells
        !           344:         *  us more than 4kb is available
        !           345:         * if FIONREAD doesn't signal a big chunk we fill the previous buffer
        !           346:         *  if it has >= 1kb free
        !           347:         */
        !           348: #if defined(__WIN32)
        !           349:        if (NULL == b || b->size - b->used < 1024) {
        !           350:                b = chunkqueue_get_append_buffer(con->read_queue);
        !           351:                buffer_prepare_copy(b, 4 * 1024);
        !           352:        }
        !           353: 
        !           354:        read_offset = (b->used == 0) ? 0 : b->used - 1;
        !           355:        len = recv(con->fd, b->ptr + read_offset, b->size - 1 - read_offset, 0);
        !           356: #else
        !           357:        if (ioctl(con->fd, FIONREAD, &toread) || toread == 0 || toread <= 4*1024) {
        !           358:                if (NULL == b || b->size - b->used < 1024) {
        !           359:                        b = chunkqueue_get_append_buffer(con->read_queue);
        !           360:                        buffer_prepare_copy(b, 4 * 1024);
        !           361:                }
        !           362:        } else {
        !           363:                if (toread > MAX_READ_LIMIT) toread = MAX_READ_LIMIT;
        !           364:                b = chunkqueue_get_append_buffer(con->read_queue);
        !           365:                buffer_prepare_copy(b, toread + 1);
        !           366:        }
        !           367: 
        !           368:        read_offset = (b->used == 0) ? 0 : b->used - 1;
        !           369:        len = read(con->fd, b->ptr + read_offset, b->size - 1 - read_offset);
        !           370: #endif
        !           371: 
        !           372:        if (len < 0) {
        !           373:                con->is_readable = 0;
        !           374: 
        !           375:                if (errno == EAGAIN) return 0;
        !           376:                if (errno == EINTR) {
        !           377:                        /* we have been interrupted before we could read */
        !           378:                        con->is_readable = 1;
        !           379:                        return 0;
        !           380:                }
        !           381: 
        !           382:                if (errno != ECONNRESET) {
        !           383:                        /* expected for keep-alive */
        !           384:                        log_error_write(srv, __FILE__, __LINE__, "ssd", "connection closed - read failed: ", strerror(errno), errno);
        !           385:                }
        !           386: 
        !           387:                connection_set_state(srv, con, CON_STATE_ERROR);
        !           388: 
        !           389:                return -1;
        !           390:        } else if (len == 0) {
        !           391:                con->is_readable = 0;
        !           392:                /* the other end close the connection -> KEEP-ALIVE */
        !           393: 
        !           394:                /* pipelining */
        !           395: 
        !           396:                return -2;
        !           397:        } else if ((size_t)len < b->size - 1) {
        !           398:                /* we got less then expected, wait for the next fd-event */
        !           399: 
        !           400:                con->is_readable = 0;
        !           401:        }
        !           402: 
        !           403:        if (b->used > 0) b->used--;
        !           404:        b->used += len;
        !           405:        b->ptr[b->used++] = '\0';
        !           406: 
        !           407:        con->bytes_read += len;
        !           408: #if 0
        !           409:        dump_packet(b->ptr, len);
        !           410: #endif
        !           411: 
        !           412:        return 0;
        !           413: }
        !           414: 
        !           415: static int connection_handle_write_prepare(server *srv, connection *con) {
        !           416:        if (con->mode == DIRECT) {
        !           417:                /* static files */
        !           418:                switch(con->request.http_method) {
        !           419:                case HTTP_METHOD_GET:
        !           420:                case HTTP_METHOD_POST:
        !           421:                case HTTP_METHOD_HEAD:
        !           422:                        break;
        !           423:                case HTTP_METHOD_OPTIONS:
        !           424:                        /*
        !           425:                         * 400 is coming from the request-parser BEFORE uri.path is set
        !           426:                         * 403 is from the response handler when noone else catched it
        !           427:                         *
        !           428:                         * */
        !           429:                        if ((!con->http_status || con->http_status == 200) && con->uri.path->used &&
        !           430:                            con->uri.path->ptr[0] != '*') {
        !           431:                                response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("OPTIONS, GET, HEAD, POST"));
        !           432: 
        !           433:                                con->response.transfer_encoding &= ~HTTP_TRANSFER_ENCODING_CHUNKED;
        !           434:                                con->parsed_response &= ~HTTP_CONTENT_LENGTH;
        !           435: 
        !           436:                                con->http_status = 200;
        !           437:                                con->file_finished = 1;
        !           438: 
        !           439:                                chunkqueue_reset(con->write_queue);
        !           440:                        }
        !           441:                        break;
        !           442:                default:
        !           443:                        if (0 == con->http_status) {
        !           444:                                con->http_status = 501;
        !           445:                        }
        !           446:                        break;
        !           447:                }
        !           448:        }
        !           449: 
        !           450:        if (con->http_status == 0) {
        !           451:                con->http_status = 403;
        !           452:        }
        !           453: 
        !           454:        switch(con->http_status) {
        !           455:        case 204: /* class: header only */
        !           456:        case 205:
        !           457:        case 304:
        !           458:                /* disable chunked encoding again as we have no body */
        !           459:                con->response.transfer_encoding &= ~HTTP_TRANSFER_ENCODING_CHUNKED;
        !           460:                con->parsed_response &= ~HTTP_CONTENT_LENGTH;
        !           461:                chunkqueue_reset(con->write_queue);
        !           462: 
        !           463:                con->file_finished = 1;
        !           464:                break;
        !           465:        default: /* class: header + body */
        !           466:                if (con->mode != DIRECT) break;
        !           467: 
        !           468:                /* only custom body for 4xx and 5xx */
        !           469:                if (con->http_status < 400 || con->http_status >= 600) break;
        !           470: 
        !           471:                con->file_finished = 0;
        !           472: 
        !           473:                buffer_reset(con->physical.path);
        !           474: 
        !           475:                /* try to send static errorfile */
        !           476:                if (!buffer_is_empty(con->conf.errorfile_prefix)) {
        !           477:                        stat_cache_entry *sce = NULL;
        !           478: 
        !           479:                        buffer_copy_string_buffer(con->physical.path, con->conf.errorfile_prefix);
        !           480:                        buffer_append_long(con->physical.path, con->http_status);
        !           481:                        buffer_append_string_len(con->physical.path, CONST_STR_LEN(".html"));
        !           482: 
        !           483:                        if (HANDLER_ERROR != stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
        !           484:                                con->file_finished = 1;
        !           485: 
        !           486:                                http_chunk_append_file(srv, con, con->physical.path, 0, sce->st.st_size);
        !           487:                                response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type));
        !           488:                        }
        !           489:                }
        !           490: 
        !           491:                if (!con->file_finished) {
        !           492:                        buffer *b;
        !           493: 
        !           494:                        buffer_reset(con->physical.path);
        !           495: 
        !           496:                        con->file_finished = 1;
        !           497:                        b = chunkqueue_get_append_buffer(con->write_queue);
        !           498: 
        !           499:                        /* build default error-page */
        !           500:                        buffer_copy_string_len(b, CONST_STR_LEN(
        !           501:                                           "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"
        !           502:                                           "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n"
        !           503:                                           "         \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
        !           504:                                           "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n"
        !           505:                                           " <head>\n"
        !           506:                                           "  <title>"));
        !           507:                        buffer_append_long(b, con->http_status);
        !           508:                        buffer_append_string_len(b, CONST_STR_LEN(" - "));
        !           509:                        buffer_append_string(b, get_http_status_name(con->http_status));
        !           510: 
        !           511:                        buffer_append_string_len(b, CONST_STR_LEN(
        !           512:                                             "</title>\n"
        !           513:                                             " </head>\n"
        !           514:                                             " <body>\n"
        !           515:                                             "  <h1>"));
        !           516:                        buffer_append_long(b, con->http_status);
        !           517:                        buffer_append_string_len(b, CONST_STR_LEN(" - "));
        !           518:                        buffer_append_string(b, get_http_status_name(con->http_status));
        !           519: 
        !           520:                        buffer_append_string_len(b, CONST_STR_LEN("</h1>\n"
        !           521:                                             " </body>\n"
        !           522:                                             "</html>\n"
        !           523:                                             ));
        !           524: 
        !           525:                        response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
        !           526:                }
        !           527:                break;
        !           528:        }
        !           529: 
        !           530:        if (con->file_finished) {
        !           531:                /* we have all the content and chunked encoding is not used, set a content-length */
        !           532: 
        !           533:                if ((!(con->parsed_response & HTTP_CONTENT_LENGTH)) &&
        !           534:                    (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) == 0) {
        !           535:                        off_t qlen = chunkqueue_length(con->write_queue);
        !           536: 
        !           537:                        /**
        !           538:                         * The Content-Length header only can be sent if we have content:
        !           539:                         * - HEAD doesn't have a content-body (but have a content-length)
        !           540:                         * - 1xx, 204 and 304 don't have a content-body (RFC 2616 Section 4.3)
        !           541:                         *
        !           542:                         * Otherwise generate a Content-Length header as chunked encoding is not 
        !           543:                         * available
        !           544:                         */
        !           545:                        if ((con->http_status >= 100 && con->http_status < 200) ||
        !           546:                            con->http_status == 204 ||
        !           547:                            con->http_status == 304) {
        !           548:                                data_string *ds;
        !           549:                                /* no Content-Body, no Content-Length */
        !           550:                                if (NULL != (ds = (data_string*) array_get_element(con->response.headers, "Content-Length"))) {
        !           551:                                        buffer_reset(ds->value); /* Headers with empty values are ignored for output */
        !           552:                                }
        !           553:                        } else if (qlen > 0 || con->request.http_method != HTTP_METHOD_HEAD) {
        !           554:                                /* qlen = 0 is important for Redirects (301, ...) as they MAY have
        !           555:                                 * a content. Browsers are waiting for a Content otherwise
        !           556:                                 */
        !           557:                                buffer_copy_off_t(srv->tmp_buf, qlen);
        !           558: 
        !           559:                                response_header_overwrite(srv, con, CONST_STR_LEN("Content-Length"), CONST_BUF_LEN(srv->tmp_buf));
        !           560:                        }
        !           561:                }
        !           562:        } else {
        !           563:                /**
        !           564:                 * the file isn't finished yet, but we have all headers
        !           565:                 *
        !           566:                 * to get keep-alive we either need:
        !           567:                 * - Content-Length: ... (HTTP/1.0 and HTTP/1.0) or
        !           568:                 * - Transfer-Encoding: chunked (HTTP/1.1)
        !           569:                 */
        !           570: 
        !           571:                if (((con->parsed_response & HTTP_CONTENT_LENGTH) == 0) &&
        !           572:                    ((con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) == 0)) {
        !           573:                        con->keep_alive = 0;
        !           574:                }
        !           575: 
        !           576:                /**
        !           577:                 * if the backend sent a Connection: close, follow the wish
        !           578:                 *
        !           579:                 * NOTE: if the backend sent Connection: Keep-Alive, but no Content-Length, we
        !           580:                 * will close the connection. That's fine. We can always decide the close 
        !           581:                 * the connection
        !           582:                 *
        !           583:                 * FIXME: to be nice we should remove the Connection: ... 
        !           584:                 */
        !           585:                if (con->parsed_response & HTTP_CONNECTION) {
        !           586:                        /* a subrequest disable keep-alive although the client wanted it */
        !           587:                        if (con->keep_alive && !con->response.keep_alive) {
        !           588:                                con->keep_alive = 0;
        !           589:                        }
        !           590:                }
        !           591:        }
        !           592: 
        !           593:        if (con->request.http_method == HTTP_METHOD_HEAD) {
        !           594:                /**
        !           595:                 * a HEAD request has the same as a GET 
        !           596:                 * without the content
        !           597:                 */
        !           598:                con->file_finished = 1;
        !           599: 
        !           600:                chunkqueue_reset(con->write_queue);
        !           601:                con->response.transfer_encoding &= ~HTTP_TRANSFER_ENCODING_CHUNKED;
        !           602:        }
        !           603: 
        !           604:        http_response_write_header(srv, con);
        !           605: 
        !           606:        return 0;
        !           607: }
        !           608: 
        !           609: static int connection_handle_write(server *srv, connection *con) {
        !           610:        switch(network_write_chunkqueue(srv, con, con->write_queue, MAX_WRITE_LIMIT)) {
        !           611:        case 0:
        !           612:                con->write_request_ts = srv->cur_ts;
        !           613:                if (con->file_finished) {
        !           614:                        connection_set_state(srv, con, CON_STATE_RESPONSE_END);
        !           615:                        joblist_append(srv, con);
        !           616:                }
        !           617:                break;
        !           618:        case -1: /* error on our side */
        !           619:                log_error_write(srv, __FILE__, __LINE__, "sd",
        !           620:                                "connection closed: write failed on fd", con->fd);
        !           621:                connection_set_state(srv, con, CON_STATE_ERROR);
        !           622:                joblist_append(srv, con);
        !           623:                break;
        !           624:        case -2: /* remote close */
        !           625:                connection_set_state(srv, con, CON_STATE_ERROR);
        !           626:                joblist_append(srv, con);
        !           627:                break;
        !           628:        case 1:
        !           629:                con->write_request_ts = srv->cur_ts;
        !           630:                con->is_writable = 0;
        !           631: 
        !           632:                /* not finished yet -> WRITE */
        !           633:                break;
        !           634:        }
        !           635: 
        !           636:        return 0;
        !           637: }
        !           638: 
        !           639: 
        !           640: 
        !           641: connection *connection_init(server *srv) {
        !           642:        connection *con;
        !           643: 
        !           644:        UNUSED(srv);
        !           645: 
        !           646:        con = calloc(1, sizeof(*con));
        !           647: 
        !           648:        con->fd = 0;
        !           649:        con->ndx = -1;
        !           650:        con->fde_ndx = -1;
        !           651:        con->bytes_written = 0;
        !           652:        con->bytes_read = 0;
        !           653:        con->bytes_header = 0;
        !           654:        con->loops_per_request = 0;
        !           655: 
        !           656: #define CLEAN(x) \
        !           657:        con->x = buffer_init();
        !           658: 
        !           659:        CLEAN(request.uri);
        !           660:        CLEAN(request.request_line);
        !           661:        CLEAN(request.request);
        !           662:        CLEAN(request.pathinfo);
        !           663: 
        !           664:        CLEAN(request.orig_uri);
        !           665: 
        !           666:        CLEAN(uri.scheme);
        !           667:        CLEAN(uri.authority);
        !           668:        CLEAN(uri.path);
        !           669:        CLEAN(uri.path_raw);
        !           670:        CLEAN(uri.query);
        !           671: 
        !           672:        CLEAN(physical.doc_root);
        !           673:        CLEAN(physical.path);
        !           674:        CLEAN(physical.basedir);
        !           675:        CLEAN(physical.rel_path);
        !           676:        CLEAN(physical.etag);
        !           677:        CLEAN(parse_request);
        !           678: 
        !           679:        CLEAN(server_name);
        !           680:        CLEAN(error_handler);
        !           681:        CLEAN(dst_addr_buf);
        !           682: #if defined USE_OPENSSL && ! defined OPENSSL_NO_TLSEXT
        !           683:        CLEAN(tlsext_server_name);
        !           684: #endif
        !           685: 
        !           686: #undef CLEAN
        !           687:        con->write_queue = chunkqueue_init();
        !           688:        con->read_queue = chunkqueue_init();
        !           689:        con->request_content_queue = chunkqueue_init();
        !           690:        chunkqueue_set_tempdirs(con->request_content_queue, srv->srvconf.upload_tempdirs);
        !           691: 
        !           692:        con->request.headers      = array_init();
        !           693:        con->response.headers     = array_init();
        !           694:        con->environment     = array_init();
        !           695: 
        !           696:        /* init plugin specific connection structures */
        !           697: 
        !           698:        con->plugin_ctx = calloc(1, (srv->plugins.used + 1) * sizeof(void *));
        !           699: 
        !           700:        con->cond_cache = calloc(srv->config_context->used, sizeof(cond_cache_t));
        !           701:        config_setup_connection(srv, con);
        !           702: 
        !           703:        return con;
        !           704: }
        !           705: 
        !           706: void connections_free(server *srv) {
        !           707:        connections *conns = srv->conns;
        !           708:        size_t i;
        !           709: 
        !           710:        for (i = 0; i < conns->size; i++) {
        !           711:                connection *con = conns->ptr[i];
        !           712: 
        !           713:                connection_reset(srv, con);
        !           714: 
        !           715:                chunkqueue_free(con->write_queue);
        !           716:                chunkqueue_free(con->read_queue);
        !           717:                chunkqueue_free(con->request_content_queue);
        !           718:                array_free(con->request.headers);
        !           719:                array_free(con->response.headers);
        !           720:                array_free(con->environment);
        !           721: 
        !           722: #define CLEAN(x) \
        !           723:        buffer_free(con->x);
        !           724: 
        !           725:                CLEAN(request.uri);
        !           726:                CLEAN(request.request_line);
        !           727:                CLEAN(request.request);
        !           728:                CLEAN(request.pathinfo);
        !           729: 
        !           730:                CLEAN(request.orig_uri);
        !           731: 
        !           732:                CLEAN(uri.scheme);
        !           733:                CLEAN(uri.authority);
        !           734:                CLEAN(uri.path);
        !           735:                CLEAN(uri.path_raw);
        !           736:                CLEAN(uri.query);
        !           737: 
        !           738:                CLEAN(physical.doc_root);
        !           739:                CLEAN(physical.path);
        !           740:                CLEAN(physical.basedir);
        !           741:                CLEAN(physical.etag);
        !           742:                CLEAN(physical.rel_path);
        !           743:                CLEAN(parse_request);
        !           744: 
        !           745:                CLEAN(server_name);
        !           746:                CLEAN(error_handler);
        !           747:                CLEAN(dst_addr_buf);
        !           748: #if defined USE_OPENSSL && ! defined OPENSSL_NO_TLSEXT
        !           749:                CLEAN(tlsext_server_name);
        !           750: #endif
        !           751: #undef CLEAN
        !           752:                free(con->plugin_ctx);
        !           753:                free(con->cond_cache);
        !           754: 
        !           755:                free(con);
        !           756:        }
        !           757: 
        !           758:        free(conns->ptr);
        !           759: }
        !           760: 
        !           761: 
        !           762: int connection_reset(server *srv, connection *con) {
        !           763:        size_t i;
        !           764: 
        !           765:        plugins_call_connection_reset(srv, con);
        !           766: 
        !           767:        con->is_readable = 1;
        !           768:        con->is_writable = 1;
        !           769:        con->http_status = 0;
        !           770:        con->file_finished = 0;
        !           771:        con->file_started = 0;
        !           772:        con->got_response = 0;
        !           773: 
        !           774:        con->parsed_response = 0;
        !           775: 
        !           776:        con->bytes_written = 0;
        !           777:        con->bytes_written_cur_second = 0;
        !           778:        con->bytes_read = 0;
        !           779:        con->bytes_header = 0;
        !           780:        con->loops_per_request = 0;
        !           781: 
        !           782:        con->request.http_method = HTTP_METHOD_UNSET;
        !           783:        con->request.http_version = HTTP_VERSION_UNSET;
        !           784: 
        !           785:        con->request.http_if_modified_since = NULL;
        !           786:        con->request.http_if_none_match = NULL;
        !           787: 
        !           788:        con->response.keep_alive = 0;
        !           789:        con->response.content_length = -1;
        !           790:        con->response.transfer_encoding = 0;
        !           791: 
        !           792:        con->mode = DIRECT;
        !           793: 
        !           794: #define CLEAN(x) \
        !           795:        if (con->x) buffer_reset(con->x);
        !           796: 
        !           797:        CLEAN(request.uri);
        !           798:        CLEAN(request.request_line);
        !           799:        CLEAN(request.pathinfo);
        !           800:        CLEAN(request.request);
        !           801: 
        !           802:        /* CLEAN(request.orig_uri); */
        !           803: 
        !           804:        CLEAN(uri.scheme);
        !           805:        /* CLEAN(uri.authority); */
        !           806:        /* CLEAN(uri.path); */
        !           807:        CLEAN(uri.path_raw);
        !           808:        /* CLEAN(uri.query); */
        !           809: 
        !           810:        CLEAN(physical.doc_root);
        !           811:        CLEAN(physical.path);
        !           812:        CLEAN(physical.basedir);
        !           813:        CLEAN(physical.rel_path);
        !           814:        CLEAN(physical.etag);
        !           815: 
        !           816:        CLEAN(parse_request);
        !           817: 
        !           818:        CLEAN(server_name);
        !           819:        CLEAN(error_handler);
        !           820: #if defined USE_OPENSSL && ! defined OPENSSL_NO_TLSEXT
        !           821:        CLEAN(tlsext_server_name);
        !           822: #endif
        !           823: #undef CLEAN
        !           824: 
        !           825: #define CLEAN(x) \
        !           826:        if (con->x) con->x->used = 0;
        !           827: 
        !           828: #undef CLEAN
        !           829: 
        !           830: #define CLEAN(x) \
        !           831:                con->request.x = NULL;
        !           832: 
        !           833:        CLEAN(http_host);
        !           834:        CLEAN(http_range);
        !           835:        CLEAN(http_content_type);
        !           836: #undef CLEAN
        !           837:        con->request.content_length = 0;
        !           838: 
        !           839:        array_reset(con->request.headers);
        !           840:        array_reset(con->response.headers);
        !           841:        array_reset(con->environment);
        !           842: 
        !           843:        chunkqueue_reset(con->write_queue);
        !           844:        chunkqueue_reset(con->request_content_queue);
        !           845: 
        !           846:        /* the plugins should cleanup themself */
        !           847:        for (i = 0; i < srv->plugins.used; i++) {
        !           848:                plugin *p = ((plugin **)(srv->plugins.ptr))[i];
        !           849:                plugin_data *pd = p->data;
        !           850: 
        !           851:                if (!pd) continue;
        !           852: 
        !           853:                if (con->plugin_ctx[pd->id] != NULL) {
        !           854:                        log_error_write(srv, __FILE__, __LINE__, "sb", "missing cleanup in", p->name);
        !           855:                }
        !           856: 
        !           857:                con->plugin_ctx[pd->id] = NULL;
        !           858:        }
        !           859: 
        !           860:        /* The cond_cache gets reset in response.c */
        !           861:        /* config_cond_cache_reset(srv, con); */
        !           862: 
        !           863:        con->header_len = 0;
        !           864:        con->in_error_handler = 0;
        !           865: 
        !           866:        config_setup_connection(srv, con);
        !           867: 
        !           868:        return 0;
        !           869: }
        !           870: 
        !           871: /**
        !           872:  * handle all header and content read
        !           873:  *
        !           874:  * we get called by the state-engine and by the fdevent-handler
        !           875:  */
        !           876: static int connection_handle_read_state(server *srv, connection *con)  {
        !           877:        connection_state_t ostate = con->state;
        !           878:        chunk *c, *last_chunk;
        !           879:        off_t last_offset;
        !           880:        chunkqueue *cq = con->read_queue;
        !           881:        chunkqueue *dst_cq = con->request_content_queue;
        !           882:        int is_closed = 0; /* the connection got closed, if we don't have a complete header, -> error */
        !           883: 
        !           884:        if (con->is_readable) {
        !           885:                con->read_idle_ts = srv->cur_ts;
        !           886: 
        !           887:                switch(connection_handle_read(srv, con)) {
        !           888:                case -1:
        !           889:                        return -1;
        !           890:                case -2:
        !           891:                        is_closed = 1;
        !           892:                        break;
        !           893:                default:
        !           894:                        break;
        !           895:                }
        !           896:        }
        !           897: 
        !           898:        /* the last chunk might be empty */
        !           899:        for (c = cq->first; c;) {
        !           900:                if (cq->first == c && c->mem->used == 0) {
        !           901:                        /* the first node is empty */
        !           902:                        /* ... and it is empty, move it to unused */
        !           903: 
        !           904:                        cq->first = c->next;
        !           905:                        if (cq->first == NULL) cq->last = NULL;
        !           906: 
        !           907:                        c->next = cq->unused;
        !           908:                        cq->unused = c;
        !           909:                        cq->unused_chunks++;
        !           910: 
        !           911:                        c = cq->first;
        !           912:                } else if (c->next && c->next->mem->used == 0) {
        !           913:                        chunk *fc;
        !           914:                        /* next node is the last one */
        !           915:                        /* ... and it is empty, move it to unused */
        !           916: 
        !           917:                        fc = c->next;
        !           918:                        c->next = fc->next;
        !           919: 
        !           920:                        fc->next = cq->unused;
        !           921:                        cq->unused = fc;
        !           922:                        cq->unused_chunks++;
        !           923: 
        !           924:                        /* the last node was empty */
        !           925:                        if (c->next == NULL) {
        !           926:                                cq->last = c;
        !           927:                        }
        !           928: 
        !           929:                        c = c->next;
        !           930:                } else {
        !           931:                        c = c->next;
        !           932:                }
        !           933:        }
        !           934: 
        !           935:        /* we might have got several packets at once
        !           936:         */
        !           937: 
        !           938:        switch(ostate) {
        !           939:        case CON_STATE_READ:
        !           940:                /* if there is a \r\n\r\n in the chunkqueue
        !           941:                 *
        !           942:                 * scan the chunk-queue twice
        !           943:                 * 1. to find the \r\n\r\n
        !           944:                 * 2. to copy the header-packet
        !           945:                 *
        !           946:                 */
        !           947: 
        !           948:                last_chunk = NULL;
        !           949:                last_offset = 0;
        !           950: 
        !           951:                for (c = cq->first; c; c = c->next) {
        !           952:                        buffer b;
        !           953:                        size_t i;
        !           954: 
        !           955:                        b.ptr = c->mem->ptr + c->offset;
        !           956:                        b.used = c->mem->used - c->offset;
        !           957:                        if (b.used > 0) b.used--; /* buffer "used" includes terminating zero */
        !           958: 
        !           959:                        for (i = 0; i < b.used; i++) {
        !           960:                                char ch = b.ptr[i];
        !           961: 
        !           962:                                if ('\r' == ch) {
        !           963:                                        /* chec if \n\r\n follows */
        !           964:                                        size_t j = i+1;
        !           965:                                        chunk *cc = c;
        !           966:                                        const char header_end[] = "\r\n\r\n";
        !           967:                                        int header_end_match_pos = 1;
        !           968: 
        !           969:                                        for ( ; cc; cc = cc->next, j = 0 ) {
        !           970:                                                buffer bb;
        !           971:                                                bb.ptr = cc->mem->ptr + cc->offset;
        !           972:                                                bb.used = cc->mem->used - cc->offset;
        !           973:                                                if (bb.used > 0) bb.used--; /* buffer "used" includes terminating zero */
        !           974: 
        !           975:                                                for ( ; j < bb.used; j++) {
        !           976:                                                        ch = bb.ptr[j];
        !           977: 
        !           978:                                                        if (ch == header_end[header_end_match_pos]) {
        !           979:                                                                header_end_match_pos++;
        !           980:                                                                if (4 == header_end_match_pos) {
        !           981:                                                                        last_chunk = cc;
        !           982:                                                                        last_offset = j+1;
        !           983:                                                                        goto found_header_end;
        !           984:                                                                }
        !           985:                                                        } else {
        !           986:                                                                goto reset_search;
        !           987:                                                        }
        !           988:                                                }
        !           989:                                        }
        !           990:                                }
        !           991: reset_search: ;
        !           992:                        }
        !           993:                }
        !           994: found_header_end:
        !           995: 
        !           996:                /* found */
        !           997:                if (last_chunk) {
        !           998:                        buffer_reset(con->request.request);
        !           999: 
        !          1000:                        for (c = cq->first; c; c = c->next) {
        !          1001:                                buffer b;
        !          1002: 
        !          1003:                                b.ptr = c->mem->ptr + c->offset;
        !          1004:                                b.used = c->mem->used - c->offset;
        !          1005: 
        !          1006:                                if (c == last_chunk) {
        !          1007:                                        b.used = last_offset + 1;
        !          1008:                                }
        !          1009: 
        !          1010:                                buffer_append_string_buffer(con->request.request, &b);
        !          1011: 
        !          1012:                                if (c == last_chunk) {
        !          1013:                                        c->offset += last_offset;
        !          1014: 
        !          1015:                                        break;
        !          1016:                                } else {
        !          1017:                                        /* the whole packet was copied */
        !          1018:                                        c->offset = c->mem->used - 1;
        !          1019:                                }
        !          1020:                        }
        !          1021: 
        !          1022:                        connection_set_state(srv, con, CON_STATE_REQUEST_END);
        !          1023:                } else if (chunkqueue_length(cq) > 64 * 1024) {
        !          1024:                        log_error_write(srv, __FILE__, __LINE__, "s", "oversized request-header -> sending Status 414");
        !          1025: 
        !          1026:                        con->http_status = 414; /* Request-URI too large */
        !          1027:                        con->keep_alive = 0;
        !          1028:                        connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
        !          1029:                }
        !          1030:                break;
        !          1031:        case CON_STATE_READ_POST:
        !          1032:                for (c = cq->first; c && (dst_cq->bytes_in != (off_t)con->request.content_length); c = c->next) {
        !          1033:                        off_t weWant, weHave, toRead;
        !          1034: 
        !          1035:                        weWant = con->request.content_length - dst_cq->bytes_in;
        !          1036: 
        !          1037:                        assert(c->mem->used);
        !          1038: 
        !          1039:                        weHave = c->mem->used - c->offset - 1;
        !          1040: 
        !          1041:                        toRead = weHave > weWant ? weWant : weHave;
        !          1042: 
        !          1043:                        /* the new way, copy everything into a chunkqueue whcih might use tempfiles */
        !          1044:                        if (con->request.content_length > 64 * 1024) {
        !          1045:                                chunk *dst_c = NULL;
        !          1046:                                /* copy everything to max 1Mb sized tempfiles */
        !          1047: 
        !          1048:                                /*
        !          1049:                                 * if the last chunk is
        !          1050:                                 * - smaller than 1Mb (size < 1Mb)
        !          1051:                                 * - not read yet (offset == 0)
        !          1052:                                 * -> append to it
        !          1053:                                 * otherwise
        !          1054:                                 * -> create a new chunk
        !          1055:                                 *
        !          1056:                                 * */
        !          1057: 
        !          1058:                                if (dst_cq->last &&
        !          1059:                                    dst_cq->last->type == FILE_CHUNK &&
        !          1060:                                    dst_cq->last->file.is_temp &&
        !          1061:                                    dst_cq->last->offset == 0) {
        !          1062:                                        /* ok, take the last chunk for our job */
        !          1063: 
        !          1064:                                        if (dst_cq->last->file.length < 1 * 1024 * 1024) {
        !          1065:                                                dst_c = dst_cq->last;
        !          1066: 
        !          1067:                                                if (dst_c->file.fd == -1) {
        !          1068:                                                        /* this should not happen as we cache the fd, but you never know */
        !          1069:                                                        dst_c->file.fd = open(dst_c->file.name->ptr, O_WRONLY | O_APPEND);
        !          1070: #ifdef FD_CLOEXEC
        !          1071:                                                        fcntl(dst_c->file.fd, F_SETFD, FD_CLOEXEC);
        !          1072: #endif
        !          1073:                                                }
        !          1074:                                        } else {
        !          1075:                                                /* the chunk is too large now, close it */
        !          1076:                                                dst_c = dst_cq->last;
        !          1077: 
        !          1078:                                                if (dst_c->file.fd != -1) {
        !          1079:                                                        close(dst_c->file.fd);
        !          1080:                                                        dst_c->file.fd = -1;
        !          1081:                                                }
        !          1082:                                                dst_c = chunkqueue_get_append_tempfile(dst_cq);
        !          1083:                                        }
        !          1084:                                } else {
        !          1085:                                        dst_c = chunkqueue_get_append_tempfile(dst_cq);
        !          1086:                                }
        !          1087: 
        !          1088:                                /* we have a chunk, let's write to it */
        !          1089: 
        !          1090:                                if (dst_c->file.fd == -1) {
        !          1091:                                        /* we don't have file to write to,
        !          1092:                                         * EACCES might be one reason.
        !          1093:                                         *
        !          1094:                                         * Instead of sending 500 we send 413 and say the request is too large
        !          1095:                                         *  */
        !          1096: 
        !          1097:                                        log_error_write(srv, __FILE__, __LINE__, "sbs",
        !          1098:                                                        "denying upload as opening to temp-file for upload failed:",
        !          1099:                                                        dst_c->file.name, strerror(errno));
        !          1100: 
        !          1101:                                        con->http_status = 413; /* Request-Entity too large */
        !          1102:                                        con->keep_alive = 0;
        !          1103:                                        connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
        !          1104: 
        !          1105:                                        break;
        !          1106:                                }
        !          1107: 
        !          1108:                                if (toRead != write(dst_c->file.fd, c->mem->ptr + c->offset, toRead)) {
        !          1109:                                        /* write failed for some reason ... disk full ? */
        !          1110:                                        log_error_write(srv, __FILE__, __LINE__, "sbs",
        !          1111:                                                        "denying upload as writing to file failed:",
        !          1112:                                                        dst_c->file.name, strerror(errno));
        !          1113: 
        !          1114:                                        con->http_status = 413; /* Request-Entity too large */
        !          1115:                                        con->keep_alive = 0;
        !          1116:                                        connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
        !          1117: 
        !          1118:                                        close(dst_c->file.fd);
        !          1119:                                        dst_c->file.fd = -1;
        !          1120: 
        !          1121:                                        break;
        !          1122:                                }
        !          1123: 
        !          1124:                                dst_c->file.length += toRead;
        !          1125: 
        !          1126:                                if (dst_cq->bytes_in + toRead == (off_t)con->request.content_length) {
        !          1127:                                        /* we read everything, close the chunk */
        !          1128:                                        close(dst_c->file.fd);
        !          1129:                                        dst_c->file.fd = -1;
        !          1130:                                }
        !          1131:                        } else {
        !          1132:                                buffer *b;
        !          1133: 
        !          1134:                                if (dst_cq->last &&
        !          1135:                                    dst_cq->last->type == MEM_CHUNK) {
        !          1136:                                        b = dst_cq->last->mem;
        !          1137:                                } else {
        !          1138:                                        b = chunkqueue_get_append_buffer(dst_cq);
        !          1139:                                        /* prepare buffer size for remaining POST data; is < 64kb */
        !          1140:                                        buffer_prepare_copy(b, con->request.content_length - dst_cq->bytes_in + 1);
        !          1141:                                }
        !          1142:                                buffer_append_string_len(b, c->mem->ptr + c->offset, toRead);
        !          1143:                        }
        !          1144: 
        !          1145:                        c->offset += toRead;
        !          1146:                        dst_cq->bytes_in += toRead;
        !          1147:                }
        !          1148: 
        !          1149:                /* Content is ready */
        !          1150:                if (dst_cq->bytes_in == (off_t)con->request.content_length) {
        !          1151:                        connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
        !          1152:                }
        !          1153: 
        !          1154:                break;
        !          1155:        default: break;
        !          1156:        }
        !          1157: 
        !          1158:        /* the connection got closed and we didn't got enough data to leave one of the READ states
        !          1159:         * the only way is to leave here */
        !          1160:        if (is_closed && ostate == con->state) {
        !          1161:                connection_set_state(srv, con, CON_STATE_ERROR);
        !          1162:        }
        !          1163: 
        !          1164:        chunkqueue_remove_finished_chunks(cq);
        !          1165: 
        !          1166:        return 0;
        !          1167: }
        !          1168: 
        !          1169: static handler_t connection_handle_fdevent(server *srv, void *context, int revents) {
        !          1170:        connection *con = context;
        !          1171: 
        !          1172:        joblist_append(srv, con);
        !          1173: 
        !          1174:        if (con->srv_socket->is_ssl) {
        !          1175:                /* ssl may read and write for both reads and writes */
        !          1176:                if (revents & (FDEVENT_IN | FDEVENT_OUT)) {
        !          1177:                        con->is_readable = 1;
        !          1178:                        con->is_writable = 1;
        !          1179:                }
        !          1180:        } else {
        !          1181:                if (revents & FDEVENT_IN) {
        !          1182:                        con->is_readable = 1;
        !          1183:                }
        !          1184:                if (revents & FDEVENT_OUT) {
        !          1185:                        con->is_writable = 1;
        !          1186:                        /* we don't need the event twice */
        !          1187:                }
        !          1188:        }
        !          1189: 
        !          1190: 
        !          1191:        if (revents & ~(FDEVENT_IN | FDEVENT_OUT)) {
        !          1192:                /* looks like an error */
        !          1193: 
        !          1194:                /* FIXME: revents = 0x19 still means that we should read from the queue */
        !          1195:                if (revents & FDEVENT_HUP) {
        !          1196:                        if (con->state == CON_STATE_CLOSE) {
        !          1197:                                con->close_timeout_ts = srv->cur_ts - (HTTP_LINGER_TIMEOUT+1);
        !          1198:                        } else {
        !          1199:                                /* sigio reports the wrong event here
        !          1200:                                 *
        !          1201:                                 * there was no HUP at all
        !          1202:                                 */
        !          1203: #ifdef USE_LINUX_SIGIO
        !          1204:                                if (srv->ev->in_sigio == 1) {
        !          1205:                                        log_error_write(srv, __FILE__, __LINE__, "sd",
        !          1206:                                                "connection closed: poll() -> HUP", con->fd);
        !          1207:                                } else {
        !          1208:                                        connection_set_state(srv, con, CON_STATE_ERROR);
        !          1209:                                }
        !          1210: #else
        !          1211:                                connection_set_state(srv, con, CON_STATE_ERROR);
        !          1212: #endif
        !          1213: 
        !          1214:                        }
        !          1215:                } else if (revents & FDEVENT_ERR) {
        !          1216:                        /* error, connection reset, whatever... we don't want to spam the logfile */
        !          1217: #if 0
        !          1218:                        log_error_write(srv, __FILE__, __LINE__, "sd",
        !          1219:                                        "connection closed: poll() -> ERR", con->fd);
        !          1220: #endif
        !          1221:                        connection_set_state(srv, con, CON_STATE_ERROR);
        !          1222:                } else {
        !          1223:                        log_error_write(srv, __FILE__, __LINE__, "sd",
        !          1224:                                        "connection closed: poll() -> ???", revents);
        !          1225:                }
        !          1226:        }
        !          1227: 
        !          1228:        if (con->state == CON_STATE_READ ||
        !          1229:            con->state == CON_STATE_READ_POST) {
        !          1230:                connection_handle_read_state(srv, con);
        !          1231:        }
        !          1232: 
        !          1233:        if (con->state == CON_STATE_WRITE &&
        !          1234:            !chunkqueue_is_empty(con->write_queue) &&
        !          1235:            con->is_writable) {
        !          1236: 
        !          1237:                if (-1 == connection_handle_write(srv, con)) {
        !          1238:                        connection_set_state(srv, con, CON_STATE_ERROR);
        !          1239: 
        !          1240:                        log_error_write(srv, __FILE__, __LINE__, "ds",
        !          1241:                                        con->fd,
        !          1242:                                        "handle write failed.");
        !          1243:                }
        !          1244:        }
        !          1245: 
        !          1246:        if (con->state == CON_STATE_CLOSE) {
        !          1247:                /* flush the read buffers */
        !          1248:                int len;
        !          1249:                char buf[1024];
        !          1250: 
        !          1251:                len = read(con->fd, buf, sizeof(buf));
        !          1252:                if (len == 0 || (len < 0 && errno != EAGAIN && errno != EINTR) ) {
        !          1253:                        con->close_timeout_ts = srv->cur_ts - (HTTP_LINGER_TIMEOUT+1);
        !          1254:                }
        !          1255:        }
        !          1256: 
        !          1257:        return HANDLER_FINISHED;
        !          1258: }
        !          1259: 
        !          1260: 
        !          1261: connection *connection_accept(server *srv, server_socket *srv_socket) {
        !          1262:        /* accept everything */
        !          1263: 
        !          1264:        /* search an empty place */
        !          1265:        int cnt;
        !          1266:        sock_addr cnt_addr;
        !          1267:        socklen_t cnt_len;
        !          1268:        /* accept it and register the fd */
        !          1269: 
        !          1270:        /**
        !          1271:         * check if we can still open a new connections
        !          1272:         *
        !          1273:         * see #1216
        !          1274:         */
        !          1275: 
        !          1276:        if (srv->conns->used >= srv->max_conns) {
        !          1277:                return NULL;
        !          1278:        }
        !          1279: 
        !          1280:        cnt_len = sizeof(cnt_addr);
        !          1281: 
        !          1282:        if (-1 == (cnt = accept(srv_socket->fd, (struct sockaddr *) &cnt_addr, &cnt_len))) {
        !          1283:                switch (errno) {
        !          1284:                case EAGAIN:
        !          1285: #if EWOULDBLOCK != EAGAIN
        !          1286:                case EWOULDBLOCK:
        !          1287: #endif
        !          1288:                case EINTR:
        !          1289:                        /* we were stopped _before_ we had a connection */
        !          1290:                case ECONNABORTED: /* this is a FreeBSD thingy */
        !          1291:                        /* we were stopped _after_ we had a connection */
        !          1292:                        break;
        !          1293:                case EMFILE:
        !          1294:                        /* out of fds */
        !          1295:                        break;
        !          1296:                default:
        !          1297:                        log_error_write(srv, __FILE__, __LINE__, "ssd", "accept failed:", strerror(errno), errno);
        !          1298:                }
        !          1299:                return NULL;
        !          1300:        } else {
        !          1301:                connection *con;
        !          1302: 
        !          1303:                srv->cur_fds++;
        !          1304: 
        !          1305:                /* ok, we have the connection, register it */
        !          1306: #if 0
        !          1307:                log_error_write(srv, __FILE__, __LINE__, "sd",
        !          1308:                                "appected()", cnt);
        !          1309: #endif
        !          1310:                srv->con_opened++;
        !          1311: 
        !          1312:                con = connections_get_new_connection(srv);
        !          1313: 
        !          1314:                con->fd = cnt;
        !          1315:                con->fde_ndx = -1;
        !          1316: #if 0
        !          1317:                gettimeofday(&(con->start_tv), NULL);
        !          1318: #endif
        !          1319:                fdevent_register(srv->ev, con->fd, connection_handle_fdevent, con);
        !          1320: 
        !          1321:                connection_set_state(srv, con, CON_STATE_REQUEST_START);
        !          1322: 
        !          1323:                con->connection_start = srv->cur_ts;
        !          1324:                con->dst_addr = cnt_addr;
        !          1325:                buffer_copy_string(con->dst_addr_buf, inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
        !          1326:                con->srv_socket = srv_socket;
        !          1327: 
        !          1328:                if (-1 == (fdevent_fcntl_set(srv->ev, con->fd))) {
        !          1329:                        log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed: ", strerror(errno));
        !          1330:                        return NULL;
        !          1331:                }
        !          1332: #ifdef USE_OPENSSL
        !          1333:                /* connect FD to SSL */
        !          1334:                if (srv_socket->is_ssl) {
        !          1335:                        if (NULL == (con->ssl = SSL_new(srv_socket->ssl_ctx))) {
        !          1336:                                log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
        !          1337:                                                ERR_error_string(ERR_get_error(), NULL));
        !          1338: 
        !          1339:                                return NULL;
        !          1340:                        }
        !          1341: 
        !          1342:                        con->renegotiations = 0;
        !          1343:                        SSL_set_app_data(con->ssl, con);
        !          1344:                        SSL_set_accept_state(con->ssl);
        !          1345: 
        !          1346:                        if (1 != (SSL_set_fd(con->ssl, cnt))) {
        !          1347:                                log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
        !          1348:                                                ERR_error_string(ERR_get_error(), NULL));
        !          1349:                                return NULL;
        !          1350:                        }
        !          1351:                }
        !          1352: #endif
        !          1353:                return con;
        !          1354:        }
        !          1355: }
        !          1356: 
        !          1357: 
        !          1358: int connection_state_machine(server *srv, connection *con) {
        !          1359:        int done = 0, r;
        !          1360: #ifdef USE_OPENSSL
        !          1361:        server_socket *srv_sock = con->srv_socket;
        !          1362: #endif
        !          1363: 
        !          1364:        if (srv->srvconf.log_state_handling) {
        !          1365:                log_error_write(srv, __FILE__, __LINE__, "sds",
        !          1366:                                "state at start",
        !          1367:                                con->fd,
        !          1368:                                connection_get_state(con->state));
        !          1369:        }
        !          1370: 
        !          1371:        while (done == 0) {
        !          1372:                size_t ostate = con->state;
        !          1373: 
        !          1374:                switch (con->state) {
        !          1375:                case CON_STATE_REQUEST_START: /* transient */
        !          1376:                        if (srv->srvconf.log_state_handling) {
        !          1377:                                log_error_write(srv, __FILE__, __LINE__, "sds",
        !          1378:                                                "state for fd", con->fd, connection_get_state(con->state));
        !          1379:                        }
        !          1380: 
        !          1381:                        con->request_start = srv->cur_ts;
        !          1382:                        con->read_idle_ts = srv->cur_ts;
        !          1383: 
        !          1384:                        con->request_count++;
        !          1385:                        con->loops_per_request = 0;
        !          1386: 
        !          1387:                        connection_set_state(srv, con, CON_STATE_READ);
        !          1388: 
        !          1389:                        break;
        !          1390:                case CON_STATE_REQUEST_END: /* transient */
        !          1391:                        if (srv->srvconf.log_state_handling) {
        !          1392:                                log_error_write(srv, __FILE__, __LINE__, "sds",
        !          1393:                                                "state for fd", con->fd, connection_get_state(con->state));
        !          1394:                        }
        !          1395: 
        !          1396:                        buffer_reset(con->uri.authority);
        !          1397:                        buffer_reset(con->uri.path);
        !          1398:                        buffer_reset(con->uri.query);
        !          1399:                        buffer_reset(con->request.orig_uri);
        !          1400: 
        !          1401:                        if (http_request_parse(srv, con)) {
        !          1402:                                /* we have to read some data from the POST request */
        !          1403: 
        !          1404:                                connection_set_state(srv, con, CON_STATE_READ_POST);
        !          1405: 
        !          1406:                                break;
        !          1407:                        }
        !          1408: 
        !          1409:                        connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
        !          1410: 
        !          1411:                        break;
        !          1412:                case CON_STATE_HANDLE_REQUEST:
        !          1413:                        /*
        !          1414:                         * the request is parsed
        !          1415:                         *
        !          1416:                         * decided what to do with the request
        !          1417:                         * -
        !          1418:                         *
        !          1419:                         *
        !          1420:                         */
        !          1421: 
        !          1422:                        if (srv->srvconf.log_state_handling) {
        !          1423:                                log_error_write(srv, __FILE__, __LINE__, "sds",
        !          1424:                                                "state for fd", con->fd, connection_get_state(con->state));
        !          1425:                        }
        !          1426: 
        !          1427:                        switch (r = http_response_prepare(srv, con)) {
        !          1428:                        case HANDLER_FINISHED:
        !          1429:                                if (con->mode == DIRECT) {
        !          1430:                                        if (con->http_status == 404 ||
        !          1431:                                            con->http_status == 403) {
        !          1432:                                                /* 404 error-handler */
        !          1433: 
        !          1434:                                                if (con->in_error_handler == 0 &&
        !          1435:                                                    (!buffer_is_empty(con->conf.error_handler) ||
        !          1436:                                                     !buffer_is_empty(con->error_handler))) {
        !          1437:                                                        /* call error-handler */
        !          1438: 
        !          1439:                                                        con->error_handler_saved_status = con->http_status;
        !          1440:                                                        con->http_status = 0;
        !          1441: 
        !          1442:                                                        if (buffer_is_empty(con->error_handler)) {
        !          1443:                                                                buffer_copy_string_buffer(con->request.uri, con->conf.error_handler);
        !          1444:                                                        } else {
        !          1445:                                                                buffer_copy_string_buffer(con->request.uri, con->error_handler);
        !          1446:                                                        }
        !          1447:                                                        buffer_reset(con->physical.path);
        !          1448: 
        !          1449:                                                        con->in_error_handler = 1;
        !          1450: 
        !          1451:                                                        connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
        !          1452: 
        !          1453:                                                        done = -1;
        !          1454:                                                        break;
        !          1455:                                                } else if (con->in_error_handler) {
        !          1456:                                                        /* error-handler is a 404 */
        !          1457: 
        !          1458:                                                        con->http_status = con->error_handler_saved_status;
        !          1459:                                                }
        !          1460:                                        } else if (con->in_error_handler) {
        !          1461:                                                /* error-handler is back and has generated content */
        !          1462:                                                /* if Status: was set, take it otherwise use 200 */
        !          1463:                                        }
        !          1464:                                }
        !          1465:                                if (con->http_status == 0) con->http_status = 200;
        !          1466: 
        !          1467:                                /* we have something to send, go on */
        !          1468:                                connection_set_state(srv, con, CON_STATE_RESPONSE_START);
        !          1469:                                break;
        !          1470:                        case HANDLER_WAIT_FOR_FD:
        !          1471:                                srv->want_fds++;
        !          1472: 
        !          1473:                                fdwaitqueue_append(srv, con);
        !          1474: 
        !          1475:                                connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
        !          1476: 
        !          1477:                                break;
        !          1478:                        case HANDLER_COMEBACK:
        !          1479:                                done = -1;
        !          1480:                        case HANDLER_WAIT_FOR_EVENT:
        !          1481:                                /* come back here */
        !          1482:                                connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
        !          1483: 
        !          1484:                                break;
        !          1485:                        case HANDLER_ERROR:
        !          1486:                                /* something went wrong */
        !          1487:                                connection_set_state(srv, con, CON_STATE_ERROR);
        !          1488:                                break;
        !          1489:                        default:
        !          1490:                                log_error_write(srv, __FILE__, __LINE__, "sdd", "unknown ret-value: ", con->fd, r);
        !          1491:                                break;
        !          1492:                        }
        !          1493: 
        !          1494:                        break;
        !          1495:                case CON_STATE_RESPONSE_START:
        !          1496:                        /*
        !          1497:                         * the decision is done
        !          1498:                         * - create the HTTP-Response-Header
        !          1499:                         *
        !          1500:                         */
        !          1501: 
        !          1502:                        if (srv->srvconf.log_state_handling) {
        !          1503:                                log_error_write(srv, __FILE__, __LINE__, "sds",
        !          1504:                                                "state for fd", con->fd, connection_get_state(con->state));
        !          1505:                        }
        !          1506: 
        !          1507:                        if (-1 == connection_handle_write_prepare(srv, con)) {
        !          1508:                                connection_set_state(srv, con, CON_STATE_ERROR);
        !          1509: 
        !          1510:                                break;
        !          1511:                        }
        !          1512: 
        !          1513:                        connection_set_state(srv, con, CON_STATE_WRITE);
        !          1514:                        break;
        !          1515:                case CON_STATE_RESPONSE_END: /* transient */
        !          1516:                        /* log the request */
        !          1517: 
        !          1518:                        if (srv->srvconf.log_state_handling) {
        !          1519:                                log_error_write(srv, __FILE__, __LINE__, "sds",
        !          1520:                                                "state for fd", con->fd, connection_get_state(con->state));
        !          1521:                        }
        !          1522: 
        !          1523:                        plugins_call_handle_request_done(srv, con);
        !          1524: 
        !          1525:                        srv->con_written++;
        !          1526: 
        !          1527:                        if (con->keep_alive) {
        !          1528:                                connection_set_state(srv, con, CON_STATE_REQUEST_START);
        !          1529: 
        !          1530: #if 0
        !          1531:                                con->request_start = srv->cur_ts;
        !          1532:                                con->read_idle_ts = srv->cur_ts;
        !          1533: #endif
        !          1534:                        } else {
        !          1535:                                switch(r = plugins_call_handle_connection_close(srv, con)) {
        !          1536:                                case HANDLER_GO_ON:
        !          1537:                                case HANDLER_FINISHED:
        !          1538:                                        break;
        !          1539:                                default:
        !          1540:                                        log_error_write(srv, __FILE__, __LINE__, "sd", "unhandling return value", r);
        !          1541:                                        break;
        !          1542:                                }
        !          1543: 
        !          1544: #ifdef USE_OPENSSL
        !          1545:                                if (srv_sock->is_ssl) {
        !          1546:                                        switch (SSL_shutdown(con->ssl)) {
        !          1547:                                        case 1:
        !          1548:                                                /* done */
        !          1549:                                                break;
        !          1550:                                        case 0:
        !          1551:                                                /* wait for fd-event
        !          1552:                                                 *
        !          1553:                                                 * FIXME: wait for fdevent and call SSL_shutdown again
        !          1554:                                                 *
        !          1555:                                                 */
        !          1556: 
        !          1557:                                                break;
        !          1558:                                        default:
        !          1559:                                                log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
        !          1560:                                                                ERR_error_string(ERR_get_error(), NULL));
        !          1561:                                        }
        !          1562:                                }
        !          1563: #endif
        !          1564:                                if ((0 == shutdown(con->fd, SHUT_WR))) {
        !          1565:                                        con->close_timeout_ts = srv->cur_ts;
        !          1566:                                        connection_set_state(srv, con, CON_STATE_CLOSE);
        !          1567:                                } else {
        !          1568:                                        connection_close(srv, con);
        !          1569:                                }
        !          1570: 
        !          1571:                                srv->con_closed++;
        !          1572:                        }
        !          1573: 
        !          1574:                        connection_reset(srv, con);
        !          1575: 
        !          1576:                        break;
        !          1577:                case CON_STATE_CONNECT:
        !          1578:                        if (srv->srvconf.log_state_handling) {
        !          1579:                                log_error_write(srv, __FILE__, __LINE__, "sds",
        !          1580:                                                "state for fd", con->fd, connection_get_state(con->state));
        !          1581:                        }
        !          1582: 
        !          1583:                        chunkqueue_reset(con->read_queue);
        !          1584: 
        !          1585:                        con->request_count = 0;
        !          1586: 
        !          1587:                        break;
        !          1588:                case CON_STATE_CLOSE:
        !          1589:                        if (srv->srvconf.log_state_handling) {
        !          1590:                                log_error_write(srv, __FILE__, __LINE__, "sds",
        !          1591:                                                "state for fd", con->fd, connection_get_state(con->state));
        !          1592:                        }
        !          1593: 
        !          1594:                        /* we have to do the linger_on_close stuff regardless
        !          1595:                         * of con->keep_alive; even non-keepalive sockets may
        !          1596:                         * still have unread data, and closing before reading
        !          1597:                         * it will make the client not see all our output.
        !          1598:                         */
        !          1599:                        {
        !          1600:                                int len;
        !          1601:                                char buf[1024];
        !          1602: 
        !          1603:                                len = read(con->fd, buf, sizeof(buf));
        !          1604:                                if (len == 0 || (len < 0 && errno != EAGAIN && errno != EINTR) ) {
        !          1605:                                        con->close_timeout_ts = srv->cur_ts - (HTTP_LINGER_TIMEOUT+1);
        !          1606:                                }
        !          1607:                        }
        !          1608: 
        !          1609:                        if (srv->cur_ts - con->close_timeout_ts > HTTP_LINGER_TIMEOUT) {
        !          1610:                                connection_close(srv, con);
        !          1611: 
        !          1612:                                if (srv->srvconf.log_state_handling) {
        !          1613:                                        log_error_write(srv, __FILE__, __LINE__, "sd",
        !          1614:                                                        "connection closed for fd", con->fd);
        !          1615:                                }
        !          1616:                        }
        !          1617: 
        !          1618:                        break;
        !          1619:                case CON_STATE_READ_POST:
        !          1620:                case CON_STATE_READ:
        !          1621:                        if (srv->srvconf.log_state_handling) {
        !          1622:                                log_error_write(srv, __FILE__, __LINE__, "sds",
        !          1623:                                                "state for fd", con->fd, connection_get_state(con->state));
        !          1624:                        }
        !          1625: 
        !          1626:                        connection_handle_read_state(srv, con);
        !          1627:                        break;
        !          1628:                case CON_STATE_WRITE:
        !          1629:                        if (srv->srvconf.log_state_handling) {
        !          1630:                                log_error_write(srv, __FILE__, __LINE__, "sds",
        !          1631:                                                "state for fd", con->fd, connection_get_state(con->state));
        !          1632:                        }
        !          1633: 
        !          1634:                        /* only try to write if we have something in the queue */
        !          1635:                        if (!chunkqueue_is_empty(con->write_queue)) {
        !          1636: #if 0
        !          1637:                                log_error_write(srv, __FILE__, __LINE__, "dsd",
        !          1638:                                                con->fd,
        !          1639:                                                "packets to write:",
        !          1640:                                                con->write_queue->used);
        !          1641: #endif
        !          1642:                        }
        !          1643:                        if (!chunkqueue_is_empty(con->write_queue) && con->is_writable) {
        !          1644:                                if (-1 == connection_handle_write(srv, con)) {
        !          1645:                                        log_error_write(srv, __FILE__, __LINE__, "ds",
        !          1646:                                                        con->fd,
        !          1647:                                                        "handle write failed.");
        !          1648:                                        connection_set_state(srv, con, CON_STATE_ERROR);
        !          1649:                                }
        !          1650:                        }
        !          1651: 
        !          1652:                        break;
        !          1653:                case CON_STATE_ERROR: /* transient */
        !          1654: 
        !          1655:                        /* even if the connection was drop we still have to write it to the access log */
        !          1656:                        if (con->http_status) {
        !          1657:                                plugins_call_handle_request_done(srv, con);
        !          1658:                        }
        !          1659: #ifdef USE_OPENSSL
        !          1660:                        if (srv_sock->is_ssl) {
        !          1661:                                int ret, ssl_r;
        !          1662:                                unsigned long err;
        !          1663:                                ERR_clear_error();
        !          1664:                                switch ((ret = SSL_shutdown(con->ssl))) {
        !          1665:                                case 1:
        !          1666:                                        /* ok */
        !          1667:                                        break;
        !          1668:                                case 0:
        !          1669:                                        ERR_clear_error();
        !          1670:                                        if (-1 != (ret = SSL_shutdown(con->ssl))) break;
        !          1671: 
        !          1672:                                        /* fall through */
        !          1673:                                default:
        !          1674: 
        !          1675:                                        switch ((ssl_r = SSL_get_error(con->ssl, ret))) {
        !          1676:                                        case SSL_ERROR_WANT_WRITE:
        !          1677:                                        case SSL_ERROR_WANT_READ:
        !          1678:                                                break;
        !          1679:                                        case SSL_ERROR_SYSCALL:
        !          1680:                                                /* perhaps we have error waiting in our error-queue */
        !          1681:                                                if (0 != (err = ERR_get_error())) {
        !          1682:                                                        do {
        !          1683:                                                                log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
        !          1684:                                                                                ssl_r, ret,
        !          1685:                                                                                ERR_error_string(err, NULL));
        !          1686:                                                        } while((err = ERR_get_error()));
        !          1687:                                                } else if (errno != 0) { /* ssl bug (see lighttpd ticket #2213): sometimes errno == 0 */
        !          1688:                                                        switch(errno) {
        !          1689:                                                        case EPIPE:
        !          1690:                                                        case ECONNRESET:
        !          1691:                                                                break;
        !          1692:                                                        default:
        !          1693:                                                                log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):",
        !          1694:                                                                        ssl_r, ret, errno,
        !          1695:                                                                        strerror(errno));
        !          1696:                                                                break;
        !          1697:                                                        }
        !          1698:                                                }
        !          1699: 
        !          1700:                                                break;
        !          1701:                                        default:
        !          1702:                                                while((err = ERR_get_error())) {
        !          1703:                                                        log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
        !          1704:                                                                        ssl_r, ret,
        !          1705:                                                                        ERR_error_string(err, NULL));
        !          1706:                                                }
        !          1707: 
        !          1708:                                                break;
        !          1709:                                        }
        !          1710:                                }
        !          1711:                                ERR_clear_error();
        !          1712:                        }
        !          1713: #endif
        !          1714: 
        !          1715:                        switch(con->mode) {
        !          1716:                        case DIRECT:
        !          1717: #if 0
        !          1718:                                log_error_write(srv, __FILE__, __LINE__, "sd",
        !          1719:                                                "emergency exit: direct",
        !          1720:                                                con->fd);
        !          1721: #endif
        !          1722:                                break;
        !          1723:                        default:
        !          1724:                                switch(r = plugins_call_handle_connection_close(srv, con)) {
        !          1725:                                case HANDLER_GO_ON:
        !          1726:                                case HANDLER_FINISHED:
        !          1727:                                        break;
        !          1728:                                default:
        !          1729:                                        log_error_write(srv, __FILE__, __LINE__, "sd", "unhandling return value", r);
        !          1730:                                        break;
        !          1731:                                }
        !          1732:                                break;
        !          1733:                        }
        !          1734: 
        !          1735:                        connection_reset(srv, con);
        !          1736: 
        !          1737:                        /* close the connection */
        !          1738:                        if ((0 == shutdown(con->fd, SHUT_WR))) {
        !          1739:                                con->close_timeout_ts = srv->cur_ts;
        !          1740:                                connection_set_state(srv, con, CON_STATE_CLOSE);
        !          1741: 
        !          1742:                                if (srv->srvconf.log_state_handling) {
        !          1743:                                        log_error_write(srv, __FILE__, __LINE__, "sd",
        !          1744:                                                        "shutdown for fd", con->fd);
        !          1745:                                }
        !          1746:                        } else {
        !          1747:                                connection_close(srv, con);
        !          1748:                        }
        !          1749: 
        !          1750:                        con->keep_alive = 0;
        !          1751: 
        !          1752:                        srv->con_closed++;
        !          1753: 
        !          1754:                        break;
        !          1755:                default:
        !          1756:                        log_error_write(srv, __FILE__, __LINE__, "sdd",
        !          1757:                                        "unknown state:", con->fd, con->state);
        !          1758: 
        !          1759:                        break;
        !          1760:                }
        !          1761: 
        !          1762:                if (done == -1) {
        !          1763:                        done = 0;
        !          1764:                } else if (ostate == con->state) {
        !          1765:                        done = 1;
        !          1766:                }
        !          1767:        }
        !          1768: 
        !          1769:        if (srv->srvconf.log_state_handling) {
        !          1770:                log_error_write(srv, __FILE__, __LINE__, "sds",
        !          1771:                                "state at exit:",
        !          1772:                                con->fd,
        !          1773:                                connection_get_state(con->state));
        !          1774:        }
        !          1775: 
        !          1776:        switch(con->state) {
        !          1777:        case CON_STATE_READ_POST:
        !          1778:        case CON_STATE_READ:
        !          1779:        case CON_STATE_CLOSE:
        !          1780:                fdevent_event_set(srv->ev, &(con->fde_ndx), con->fd, FDEVENT_IN);
        !          1781:                break;
        !          1782:        case CON_STATE_WRITE:
        !          1783:                /* request write-fdevent only if we really need it
        !          1784:                 * - if we have data to write
        !          1785:                 * - if the socket is not writable yet
        !          1786:                 */
        !          1787:                if (!chunkqueue_is_empty(con->write_queue) &&
        !          1788:                    (con->is_writable == 0) &&
        !          1789:                    (con->traffic_limit_reached == 0)) {
        !          1790:                        fdevent_event_set(srv->ev, &(con->fde_ndx), con->fd, FDEVENT_OUT);
        !          1791:                } else {
        !          1792:                        fdevent_event_del(srv->ev, &(con->fde_ndx), con->fd);
        !          1793:                }
        !          1794:                break;
        !          1795:        default:
        !          1796:                fdevent_event_del(srv->ev, &(con->fde_ndx), con->fd);
        !          1797:                break;
        !          1798:        }
        !          1799: 
        !          1800:        return 0;
        !          1801: }

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