http-server-private.h revision 0dffa25d211be541ee3c953b23566a1a990789df
10139N/A#ifndef HTTP_SERVER_PRIVATE_H
10139N/A#define HTTP_SERVER_PRIVATE_H
10139N/A
10139N/A#include "connection.h"
10139N/A
18970N/A#include "http-server.h"
18970N/A#include "llist.h"
10139N/A
10139N/A#define HTTP_SERVER_REQUEST_MAX_TARGET_LENGTH 4096
10139N/A
17185N/Astruct http_server_request;
10139N/Astruct http_server_connection;
17178N/A
18644N/Aenum http_server_request_state {
17178N/A /* New request; request header is still being parsed. */
10139N/A HTTP_SERVER_REQUEST_STATE_NEW = 0,
12132N/A /* Queued request; callback to request handler executing. */
12132N/A HTTP_SERVER_REQUEST_STATE_QUEUED,
17355N/A /* Reading request payload; request handler still needs to read more
10139N/A payload. */
10139N/A HTTP_SERVER_REQUEST_STATE_PAYLOAD_IN,
10139N/A /* This request is being processed; request payload is fully read, but no
18970N/A response is yet submitted */
18593N/A HTTP_SERVER_REQUEST_STATE_PROCESSING,
10139N/A /* A response is submitted for this request. If not all request payload
10139N/A was read by the handler, it is first skipped on the input.
10139N/A */
18908N/A HTTP_SERVER_REQUEST_STATE_SUBMITTED_RESPONSE,
10385N/A /* Request is ready for response; a response is submitted and the request
15760N/A payload is fully read */
15767N/A HTTP_SERVER_REQUEST_STATE_READY_TO_RESPOND,
15760N/A /* The response for the request is sent (apart from payload) */
15760N/A HTTP_SERVER_REQUEST_STATE_SENT_RESPONSE,
15760N/A /* Sending response payload to client */
15760N/A HTTP_SERVER_REQUEST_STATE_PAYLOAD_OUT,
15760N/A /* Request is finished; still lingering due to references */
10139N/A HTTP_SERVER_REQUEST_STATE_FINISHED,
12707N/A /* Request is aborted; still lingering due to references */
10139N/A HTTP_SERVER_REQUEST_STATE_ABORTED
10139N/A};
16401N/A
16401N/Astruct http_server_response {
10139N/A struct http_server_request *request;
10139N/A
10139N/A unsigned int status;
10139N/A const char *reason;
15760N/A
18688N/A string_t *headers;
18688N/A time_t date;
15762N/A ARRAY_TYPE(http_auth_challenge) auth_challenges;
16493N/A
16493N/A struct istream *payload_input;
16493N/A uoff_t payload_size, payload_offset;
16493N/A struct ostream *payload_output;
16493N/A
16493N/A struct ostream *blocking_output;
15762N/A
15760N/A http_server_tunnel_callback_t tunnel_callback;
16401N/A void *tunnel_context;
16401N/A
15760N/A bool have_hdr_connection:1;
15760N/A bool have_hdr_date:1;
15760N/A bool have_hdr_body_spec:1;
16224N/A
15760N/A bool payload_chunked:1;
10139N/A bool payload_blocking:1;
10139N/A bool payload_direct:1;
10139N/A bool payload_corked:1;
12754N/A bool close:1;
10139N/A bool submitted:1;
10139N/A};
10139N/A
10139N/Astruct http_server_request {
10139N/A struct http_request req;
10139N/A pool_t pool;
11149N/A unsigned int refcount;
12773N/A unsigned int id;
12773N/A
12773N/A enum http_server_request_state state;
12773N/A
12773N/A struct http_server_request *prev, *next;
10139N/A
10139N/A struct http_server *server;
10139N/A struct http_server_connection *conn;
10139N/A
10139N/A struct istream *payload_input;
10139N/A
10139N/A struct http_server_response *response;
10139N/A
11311N/A void (*destroy_callback)(void *);
11311N/A void *destroy_context;
11311N/A
11311N/A bool payload_halted:1;
10139N/A bool sent_100_continue:1;
11311N/A bool delay_destroy:1;
10139N/A bool destroy_pending:1;
11311N/A bool failed:1;
11311N/A};
11311N/A
11311N/Astruct http_server_connection {
11311N/A struct connection conn;
15824N/A struct http_server *server;
15824N/A unsigned int refcount;
15824N/A
11311N/A const struct http_server_callbacks *callbacks;
11311N/A void *context;
15760N/A
15760N/A unsigned int id; // DEBUG
15760N/A
15161N/A struct timeout *to_input, *to_idle;
15824N/A struct ssl_iostream *ssl_iostream;
15161N/A struct http_request_parser *http_parser;
15760N/A
15824N/A struct http_server_request *request_queue_head, *request_queue_tail;
15760N/A unsigned int request_queue_count;
15760N/A
15760N/A struct istream *incoming_payload;
15760N/A struct io *io_resp_payload;
15760N/A
15760N/A char *disconnect_reason;
15760N/A
15760N/A struct http_server_stats stats;
15824N/A
15760N/A bool ssl:1;
15824N/A bool closed:1;
15824N/A bool close_indicated:1;
15767N/A bool input_broken:1;
15760N/A bool output_locked:1;
15760N/A bool in_req_callback:1; /* performing request callback (busy) */
15824N/A bool switching_ioloop:1; /* in the middle of switching ioloop */
15760N/A};
15824N/A
15760N/Astruct http_server {
15161N/A pool_t pool;
15767N/A
15767N/A struct http_server_settings set;
10139N/A
10139N/A struct ioloop *ioloop;
10139N/A struct ssl_iostream_context *ssl_ctx;
10139N/A
10139N/A struct connection_list *conn_list;
15824N/A
10139N/A bool shutting_down:1; /* shutting down server */
10139N/A};
10139N/A
15824N/Astatic inline const char *
15760N/Ahttp_server_request_label(struct http_server_request *req)
16493N/A{
16493N/A if (req->req.method == NULL) {
16493N/A if (req->req.target_raw == NULL)
16493N/A return t_strdup_printf("[Req%u: <NEW>]", req->id);
16493N/A return t_strdup_printf("[Req%u: %s <INCOMPLETE>]",
16493N/A req->id, req->req.method);
16493N/A }
16493N/A return t_strdup_printf("[Req%u: %s %s]", req->id,
15760N/A req->req.method, req->req.target_raw);
15760N/A}
11311N/A
11311N/Astatic inline const char *
10139N/Ahttp_server_connection_label(struct http_server_connection *conn)
15161N/A{
10139N/A return conn->conn.name;
18974N/A}
18974N/A
18970N/Abool http_server_connection_pending_payload(struct http_server_connection *conn);
18970N/A
17418N/A
17418N/A/* response */
17355N/A
17355N/Avoid http_server_response_free(struct http_server_response *resp);
16224N/Aint http_server_response_send(struct http_server_response *resp,
16224N/A const char **error_r);
16224N/Aint http_server_response_send_more(struct http_server_response *resp,
16224N/A const char **error_r);
15767N/A
15767N/A/* request */
15760N/A
15760N/Astruct http_server_request *
15760N/Ahttp_server_request_new(struct http_server_connection *conn);
15161N/Avoid http_server_request_destroy(struct http_server_request **_req);
15161N/Avoid http_server_request_abort(struct http_server_request **_req,
15161N/A const char *reason) ATTR_NULL(2);
14435N/A
14435N/Avoid http_server_request_halt_payload(struct http_server_request *req);
14290N/Avoid http_server_request_continue_payload(struct http_server_request *req);
14290N/A
14071N/Avoid http_server_request_submit_response(struct http_server_request *req);
14071N/A
14071N/Avoid http_server_request_ready_to_respond(struct http_server_request *req);
14071N/Avoid http_server_request_finished(struct http_server_request *req);
14071N/A
14050N/Astatic inline bool
14050N/Ahttp_server_request_is_new(struct http_server_request *req)
13615N/A{
13615N/A return (req->state == HTTP_SERVER_REQUEST_STATE_NEW);
12733N/A}
12733N/A
12733N/Astatic inline bool
12460N/Ahttp_server_request_is_complete(struct http_server_request *req)
12460N/A{
12460N/A return (req->failed || req->conn->input_broken ||
12460N/A (req->next != NULL && !http_server_request_is_new(req->next)) ||
12460N/A !http_server_connection_pending_payload(req->conn));
12460N/A}
12460N/A
12460N/Astatic inline bool
12460N/Ahttp_server_request_version_equals(struct http_server_request *req,
12460N/A unsigned int major, unsigned int minor) {
12162N/A return (req->req.version_major == major && req->req.version_minor == minor);
12162N/A}
12047N/A
12047N/A/* connection */
11459N/A
11459N/Astruct connection_list *http_server_connection_list_init(void);
11459N/A
11311N/Abool http_server_connection_shut_down(struct http_server_connection *conn);
11311N/A
11311N/Avoid http_server_connection_switch_ioloop(struct http_server_connection *conn);
11311N/A
11311N/Avoid http_server_connection_write_failed(struct http_server_connection *conn,
11311N/A const char *error);
11218N/A
11218N/Avoid http_server_connection_trigger_responses(
11149N/A struct http_server_connection *conn);
11149N/Aint http_server_connection_flush(struct http_server_connection *conn);
10949N/Aint http_server_connection_output(struct http_server_connection *conn);
10949N/A
10949N/Avoid http_server_connection_tunnel(struct http_server_connection **_conn,
10726N/A http_server_tunnel_callback_t callback, void *context);
10726N/A
10385N/Aint http_server_connection_discard_payload(
10385N/A struct http_server_connection *conn);
10139N/Abool http_server_connection_pending_payload(struct http_server_connection *conn);
10139N/A
10139N/Astatic inline void http_server_connection_add_request(struct http_server_connection *conn,
10139N/A struct http_server_request *sreq)
10139N/A{
10139N/A DLLIST2_APPEND(&conn->request_queue_head, &conn->request_queue_tail, sreq);
10139N/A conn->request_queue_count++;
10139N/A}
10139N/Astatic inline void http_server_connection_remove_request(struct http_server_connection *conn,
10139N/A struct http_server_request *sreq)
10139N/A{
10139N/A DLLIST2_REMOVE(&conn->request_queue_head, &conn->request_queue_tail, sreq);
10139N/A conn->request_queue_count--;
10139N/A}
10139N/A
10139N/A#endif
10139N/A