michael@0: /* michael@0: * Copyright 2001-2007 Niels Provos michael@0: * Copyright 2007-2012 Niels Provos and Nick Mathewson michael@0: * michael@0: * This header file contains definitions for dealing with HTTP requests michael@0: * that are internal to libevent. As user of the library, you should not michael@0: * need to know about these. michael@0: */ michael@0: michael@0: #ifndef _HTTP_INTERNAL_H_ michael@0: #define _HTTP_INTERNAL_H_ michael@0: michael@0: #include "event2/event_struct.h" michael@0: #include "util-internal.h" michael@0: #include "defer-internal.h" michael@0: michael@0: #define HTTP_CONNECT_TIMEOUT 45 michael@0: #define HTTP_WRITE_TIMEOUT 50 michael@0: #define HTTP_READ_TIMEOUT 50 michael@0: michael@0: #define HTTP_PREFIX "http://" michael@0: #define HTTP_DEFAULTPORT 80 michael@0: michael@0: enum message_read_status { michael@0: ALL_DATA_READ = 1, michael@0: MORE_DATA_EXPECTED = 0, michael@0: DATA_CORRUPTED = -1, michael@0: REQUEST_CANCELED = -2, michael@0: DATA_TOO_LONG = -3 michael@0: }; michael@0: michael@0: enum evhttp_connection_error { michael@0: EVCON_HTTP_TIMEOUT, michael@0: EVCON_HTTP_EOF, michael@0: EVCON_HTTP_INVALID_HEADER, michael@0: EVCON_HTTP_BUFFER_ERROR, michael@0: EVCON_HTTP_REQUEST_CANCEL michael@0: }; michael@0: michael@0: struct evbuffer; michael@0: struct addrinfo; michael@0: struct evhttp_request; michael@0: michael@0: /* Indicates an unknown request method. */ michael@0: #define _EVHTTP_REQ_UNKNOWN (1<<15) michael@0: michael@0: enum evhttp_connection_state { michael@0: EVCON_DISCONNECTED, /**< not currently connected not trying either*/ michael@0: EVCON_CONNECTING, /**< tries to currently connect */ michael@0: EVCON_IDLE, /**< connection is established */ michael@0: EVCON_READING_FIRSTLINE,/**< reading Request-Line (incoming conn) or michael@0: **< Status-Line (outgoing conn) */ michael@0: EVCON_READING_HEADERS, /**< reading request/response headers */ michael@0: EVCON_READING_BODY, /**< reading request/response body */ michael@0: EVCON_READING_TRAILER, /**< reading request/response chunked trailer */ michael@0: EVCON_WRITING /**< writing request/response headers/body */ michael@0: }; michael@0: michael@0: struct event_base; michael@0: michael@0: /* A client or server connection. */ michael@0: struct evhttp_connection { michael@0: /* we use this tailq only if this connection was created for an http michael@0: * server */ michael@0: TAILQ_ENTRY(evhttp_connection) next; michael@0: michael@0: evutil_socket_t fd; michael@0: struct bufferevent *bufev; michael@0: michael@0: struct event retry_ev; /* for retrying connects */ michael@0: michael@0: char *bind_address; /* address to use for binding the src */ michael@0: u_short bind_port; /* local port for binding the src */ michael@0: michael@0: char *address; /* address to connect to */ michael@0: u_short port; michael@0: michael@0: size_t max_headers_size; michael@0: ev_uint64_t max_body_size; michael@0: michael@0: int flags; michael@0: #define EVHTTP_CON_INCOMING 0x0001 /* only one request on it ever */ michael@0: #define EVHTTP_CON_OUTGOING 0x0002 /* multiple requests possible */ michael@0: #define EVHTTP_CON_CLOSEDETECT 0x0004 /* detecting if persistent close */ michael@0: michael@0: int timeout; /* timeout in seconds for events */ michael@0: int retry_cnt; /* retry count */ michael@0: int retry_max; /* maximum number of retries */ michael@0: michael@0: enum evhttp_connection_state state; michael@0: michael@0: /* for server connections, the http server they are connected with */ michael@0: struct evhttp *http_server; michael@0: michael@0: TAILQ_HEAD(evcon_requestq, evhttp_request) requests; michael@0: michael@0: void (*cb)(struct evhttp_connection *, void *); michael@0: void *cb_arg; michael@0: michael@0: void (*closecb)(struct evhttp_connection *, void *); michael@0: void *closecb_arg; michael@0: michael@0: struct deferred_cb read_more_deferred_cb; michael@0: michael@0: struct event_base *base; michael@0: struct evdns_base *dns_base; michael@0: }; michael@0: michael@0: /* A callback for an http server */ michael@0: struct evhttp_cb { michael@0: TAILQ_ENTRY(evhttp_cb) next; michael@0: michael@0: char *what; michael@0: michael@0: void (*cb)(struct evhttp_request *req, void *); michael@0: void *cbarg; michael@0: }; michael@0: michael@0: /* both the http server as well as the rpc system need to queue connections */ michael@0: TAILQ_HEAD(evconq, evhttp_connection); michael@0: michael@0: /* each bound socket is stored in one of these */ michael@0: struct evhttp_bound_socket { michael@0: TAILQ_ENTRY(evhttp_bound_socket) next; michael@0: michael@0: struct evconnlistener *listener; michael@0: }; michael@0: michael@0: /* server alias list item. */ michael@0: struct evhttp_server_alias { michael@0: TAILQ_ENTRY(evhttp_server_alias) next; michael@0: michael@0: char *alias; /* the server alias. */ michael@0: }; michael@0: michael@0: struct evhttp { michael@0: /* Next vhost, if this is a vhost. */ michael@0: TAILQ_ENTRY(evhttp) next_vhost; michael@0: michael@0: /* All listeners for this host */ michael@0: TAILQ_HEAD(boundq, evhttp_bound_socket) sockets; michael@0: michael@0: TAILQ_HEAD(httpcbq, evhttp_cb) callbacks; michael@0: michael@0: /* All live connections on this host. */ michael@0: struct evconq connections; michael@0: michael@0: TAILQ_HEAD(vhostsq, evhttp) virtualhosts; michael@0: michael@0: TAILQ_HEAD(aliasq, evhttp_server_alias) aliases; michael@0: michael@0: /* NULL if this server is not a vhost */ michael@0: char *vhost_pattern; michael@0: michael@0: int timeout; michael@0: michael@0: size_t default_max_headers_size; michael@0: ev_uint64_t default_max_body_size; michael@0: michael@0: /* Bitmask of all HTTP methods that we accept and pass to user michael@0: * callbacks. */ michael@0: ev_uint16_t allowed_methods; michael@0: michael@0: /* Fallback callback if all the other callbacks for this connection michael@0: don't match. */ michael@0: void (*gencb)(struct evhttp_request *req, void *); michael@0: void *gencbarg; michael@0: michael@0: struct event_base *base; michael@0: }; michael@0: michael@0: /* XXX most of these functions could be static. */ michael@0: michael@0: /* resets the connection; can be reused for more requests */ michael@0: void evhttp_connection_reset(struct evhttp_connection *); michael@0: michael@0: /* connects if necessary */ michael@0: int evhttp_connection_connect(struct evhttp_connection *); michael@0: michael@0: /* notifies the current request that it failed; resets connection */ michael@0: void evhttp_connection_fail(struct evhttp_connection *, michael@0: enum evhttp_connection_error error); michael@0: michael@0: enum message_read_status; michael@0: michael@0: enum message_read_status evhttp_parse_firstline(struct evhttp_request *, struct evbuffer*); michael@0: enum message_read_status evhttp_parse_headers(struct evhttp_request *, struct evbuffer*); michael@0: michael@0: void evhttp_start_read(struct evhttp_connection *); michael@0: michael@0: /* response sending HTML the data in the buffer */ michael@0: void evhttp_response_code(struct evhttp_request *, int, const char *); michael@0: void evhttp_send_page(struct evhttp_request *, struct evbuffer *); michael@0: michael@0: #endif /* _HTTP_H */