<commit_before>/*
 * HTTP server implementation.
 *
 * author: <NAME> <<EMAIL>>
 */

#ifndef __BENG_HTTP_SERVER_INTERNAL_H
#define __BENG_HTTP_SERVER_INTERNAL_H

#include "http_server.hxx"
#include "http_body.hxx"
#include "async.hxx"
#include "filtered_socket.hxx"
#include "net/SocketAddress.hxx"
#include "istream/istream_pointer.hxx"

struct HttpServerConnection {
    struct RequestBodyReader : HttpBodyReader {
        HttpServerConnection &connection;

        RequestBodyReader(struct pool &_pool,
                          HttpServerConnection &_connection)
            :HttpBodyReader(_pool),
             connection(_connection) {}

        /* virtual methods from class Istream */

        off_t _GetAvailable(bool partial) override;
        void _Read() override;
        void _Close() override;
    };

    struct pool *pool;

    /* I/O */
    FilteredSocket socket;

    /**
     * Track the total time for idle periods plus receiving all
     * headers from the client.  Unlike the #filtered_socket read
     * timeout, it is not refreshed after receiving some header data.
     */
    struct event idle_timeout;

    enum http_server_score score = HTTP_SERVER_NEW;

    /* handler */
    const HttpServerConnectionHandler *handler;
    void *handler_ctx;

    /* info */

    SocketAddress local_address, remote_address;

    const char *local_host_and_port;
    const char *remote_host_and_port, *remote_host;

    /* request */
    struct Request {
        enum {
            /** there is no request (yet); waiting for the request
                line */
            START,

            /** parsing request headers; waiting for empty line */
            HEADERS,

            /** reading the request body */
            BODY,

            /** the request has been consumed, and we are going to send the response */
            END
        } read_state = START;

        /**
         * This flag is true if we are currently calling the HTTP
         * request handler.  During this period,
         * http_server_request_stream_read() does nothing, to prevent
         * recursion.
         */
        bool in_handler;

        /** has the client sent a HTTP/1.0 request? */
        bool http_1_0;

        /** did the client send an "Expect: 100-continue" header? */
        bool expect_100_continue;

        /** send a "417 Expectation Failed" response? */
        bool expect_failed;

        struct http_server_request *request = nullptr;

        struct async_operation_ref async_ref;

        uint64_t bytes_received = 0;
    } request;

    /** the request body reader; this variable is only valid if
        read_state==READ_BODY */
    RequestBodyReader *request_body_reader;

    /** the response; this struct is only valid if
        read_state==READ_BODY||read_state==READ_END */
    struct Response {
        bool want_write;

        /**
         * Are we currently waiting for all output buffers to be
         * drained, before we can close the socket?
         *
         * @see BufferedSocketHandler::drained
         * @see http_server_socket_drained()
         */
        bool pending_drained;

        http_status_t status;
        char status_buffer[64];
        char content_length_buffer[32];
        IstreamPointer istream;
        off_t length;

        uint64_t bytes_sent = 0;

        Response()
            :istream(nullptr) {}
    } response;

    bool date_header;

    /* connection settings */
    bool keep_alive;
<commit_msg>http_server: initialize "pending_drained"<commit_after>/*
 * HTTP server implementation.
 *
 * author: <NAME> <<EMAIL>>
 */

#ifndef __BENG_HTTP_SERVER_INTERNAL_H
#define __BENG_HTTP_SERVER_INTERNAL_H

#include "http_server.hxx"
#include "http_body.hxx"
#include "async.hxx"
#include "filtered_socket.hxx"
#include "net/SocketAddress.hxx"
#include "istream/istream_pointer.hxx"

struct HttpServerConnection {
    struct RequestBodyReader : HttpBodyReader {
        HttpServerConnection &connection;

        RequestBodyReader(struct pool &_pool,
                          HttpServerConnection &_connection)
            :HttpBodyReader(_pool),
             connection(_connection) {}

        /* virtual methods from class Istream */

        off_t _GetAvailable(bool partial) override;
        void _Read() override;
        void _Close() override;
    };

    struct pool *pool;

    /* I/O */
    FilteredSocket socket;

    /**
     * Track the total time for idle periods plus receiving all
     * headers from the client.  Unlike the #filtered_socket read
     * timeout, it is not refreshed after receiving some header data.
     */
    struct event idle_timeout;

    enum http_server_score score = HTTP_SERVER_NEW;

    /* handler */
    const HttpServerConnectionHandler *handler;
    void *handler_ctx;

    /* info */

    SocketAddress local_address, remote_address;

    const char *local_host_and_port;
    const char *remote_host_and_port, *remote_host;

    /* request */
    struct Request {
        enum {
            /** there is no request (yet); waiting for the request
                line */
            START,

            /** parsing request headers; waiting for empty line */
            HEADERS,

            /** reading the request body */
            BODY,

            /** the request has been consumed, and we are going to send the response */
            END
        } read_state = START;

        /**
         * This flag is true if we are currently calling the HTTP
         * request handler.  During this period,
         * http_server_request_stream_read() does nothing, to prevent
         * recursion.
         */
        bool in_handler;

        /** has the client sent a HTTP/1.0 request? */
        bool http_1_0;

        /** did the client send an "Expect: 100-continue" header? */
        bool expect_100_continue;

        /** send a "417 Expectation Failed" response? */
        bool expect_failed;

        struct http_server_request *request = nullptr;

        struct async_operation_ref async_ref;

        uint64_t bytes_received = 0;
    } request;

    /** the request body reader; this variable is only valid if
        read_state==READ_BODY */
    RequestBodyReader *request_body_reader;

    /** the response; this struct is only valid if
        read_state==READ_BODY||read_state==READ_END */
    struct Response {
        bool want_write;

        /**
         * Are we currently waiting for all output buffers to be
         * drained, before we can close the socket?
         *
         * @see BufferedSocketHandler::drained
         * @see http_server_socket_drained()
         */
        bool pending_drained = false;

        http_status_t status;
        char status_buffer[64];
        char content_length_buffer[32];
        IstreamPointer istream;
        off_t length;

        uint64_t bytes_sent = 0;

        Response()
            :istream(nullptr) {}
    } response;

    bool date_header;

    /* connection settings */
    bool keep_alive;

{'fraction_non_alphanumeric': 0.0808802515004287, 'fraction_numerical': 0.006573306659045442, 'mean_word_length': 2.1857077833409195, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2734530', 'n_tokens_mistral': 1977, 'n_tokens_neox': 1856, 'n_words': 577}