#pragma once #include #include #include #include #include #include #include #include /* Copy from http_parser.h */ #define __HTTP_METHOD_MAP(XX) \ XX(0, DELETE, DELETE) \ XX(1, GET, GET) \ XX(2, HEAD, HEAD) \ XX(3, POST, POST) \ XX(4, PUT, PUT) \ /* pathological */ \ XX(5, CONNECT, CONNECT) \ XX(6, OPTIONS, OPTIONS) \ XX(7, TRACE, TRACE) \ /* WebDAV */ \ XX(8, COPY, COPY) \ XX(9, LOCK, LOCK) \ XX(10, MKCOL, MKCOL) \ XX(11, MOVE, MOVE) \ XX(12, PROPFIND, PROPFIND) \ XX(13, PROPPATCH, PROPPATCH) \ XX(14, SEARCH, SEARCH) \ XX(15, UNLOCK, UNLOCK) \ XX(16, BIND, BIND) \ XX(17, REBIND, REBIND) \ XX(18, UNBIND, UNBIND) \ XX(19, ACL, ACL) \ /* subversion */ \ XX(20, REPORT, REPORT) \ XX(21, MKACTIVITY, MKACTIVITY) \ XX(22, CHECKOUT, CHECKOUT) \ XX(23, MERGE, MERGE) \ /* upnp */ \ XX(24, MSEARCH, M-SEARCH) \ XX(25, NOTIFY, NOTIFY) \ XX(26, SUBSCRIBE, SUBSCRIBE) \ XX(27, UNSUBSCRIBE, UNSUBSCRIBE) \ /* RFC-5789 */ \ XX(28, PATCH, PATCH) \ XX(29, PURGE, PURGE) \ /* CalDAV */ \ XX(30, MKCALENDAR, MKCALENDAR) \ /* RFC-2068, section 19.6.1.2 */ \ XX(31, LINK, LINK) \ XX(32, UNLINK, UNLINK) \ /* icecast */ \ XX(33, SOURCE, SOURCE) \ /* Status Codes */ #define __HTTP_STATUS_MAP(XX) \ XX(100, CONTINUE, Continue) \ XX(101, SWITCHING_PROTOCOLS, Switching Protocols) \ XX(102, PROCESSING, Processing) \ XX(200, OK, OK) \ XX(201, CREATED, Created) \ XX(202, ACCEPTED, Accepted) \ XX(203, NON_AUTHORITATIVE_INFORMATION, Non-Authoritative Information) \ XX(204, NO_CONTENT, No Content) \ XX(205, RESET_CONTENT, Reset Content) \ XX(206, PARTIAL_CONTENT, Partial Content) \ XX(207, MULTI_STATUS, Multi-Status) \ XX(208, ALREADY_REPORTED, Already Reported) \ XX(226, IM_USED, IM Used) \ XX(300, MULTIPLE_CHOICES, Multiple Choices) \ XX(301, MOVED_PERMANENTLY, Moved Permanently) \ XX(302, FOUND, Found) \ XX(303, SEE_OTHER, See Other) \ XX(304, NOT_MODIFIED, Not Modified) \ XX(305, USE_PROXY, Use Proxy) \ XX(307, TEMPORARY_REDIRECT, Temporary Redirect) \ XX(308, PERMANENT_REDIRECT, Permanent Redirect) \ XX(400, BAD_REQUEST, Bad Request) \ XX(401, UNAUTHORIZED, Unauthorized) \ XX(402, PAYMENT_REQUIRED, Payment Required) \ XX(403, FORBIDDEN, Forbidden) \ XX(404, NOT_FOUND, Not Found) \ XX(405, METHOD_NOT_ALLOWED, Method Not Allowed) \ XX(406, NOT_ACCEPTABLE, Not Acceptable) \ XX(407, PROXY_AUTHENTICATION_REQUIRED, Proxy Authentication Required) \ XX(408, REQUEST_TIMEOUT, Request Timeout) \ XX(409, CONFLICT, Conflict) \ XX(410, GONE, Gone) \ XX(411, LENGTH_REQUIRED, Length Required) \ XX(412, PRECONDITION_FAILED, Precondition Failed) \ XX(413, PAYLOAD_TOO_LARGE, Payload Too Large) \ XX(414, URI_TOO_LONG, URI Too Long) \ XX(415, UNSUPPORTED_MEDIA_TYPE, Unsupported Media Type) \ XX(416, RANGE_NOT_SATISFIABLE, Range Not Satisfiable) \ XX(417, EXPECTATION_FAILED, Expectation Failed) \ XX(421, MISDIRECTED_REQUEST, Misdirected Request) \ XX(422, UNPROCESSABLE_ENTITY, Unprocessable Entity) \ XX(423, LOCKED, Locked) \ XX(424, FAILED_DEPENDENCY, Failed Dependency) \ XX(426, UPGRADE_REQUIRED, Upgrade Required) \ XX(428, PRECONDITION_REQUIRED, Precondition Required) \ XX(429, TOO_MANY_REQUESTS, Too Many Requests) \ XX(431, REQUEST_HEADER_FIELDS_TOO_LARGE, Request Header Fields Too Large) \ XX(451, UNAVAILABLE_FOR_LEGAL_REASONS, Unavailable For Legal Reasons) \ XX(500, INTERNAL_SERVER_ERROR, Internal Server Error) \ XX(501, NOT_IMPLEMENTED, Not Implemented) \ XX(502, BAD_GATEWAY, Bad Gateway) \ XX(503, SERVICE_UNAVAILABLE, Service Unavailable) \ XX(504, GATEWAY_TIMEOUT, Gateway Timeout) \ XX(505, HTTP_VERSION_NOT_SUPPORTED, HTTP Version Not Supported) \ XX(506, VARIANT_ALSO_NEGOTIATES, Variant Also Negotiates) \ XX(507, INSUFFICIENT_STORAGE, Insufficient Storage) \ XX(508, LOOP_DETECTED, Loop Detected) \ XX(510, NOT_EXTENDED, Not Extended) \ XX(511, NETWORK_AUTHENTICATION_REQUIRED, Network Authentication Required) \ enum tfe_http_std_method { #define XX(num, name, string) TFE_HTTP_METHOD_##name = num, __HTTP_METHOD_MAP(XX) #undef XX }; enum tfe_http_std_status { #define XX(num, name, string) TFE_HTTP_STATUS_##name = num, __HTTP_STATUS_MAP(XX) #undef XX }; enum tfe_http_std_field { TFE_HTTP_UNKNOWN_FIELD = 0, TFE_HTTP_HOST, TFE_HTTP_REFERER, TFE_HTTP_USER_AGENT, TFE_HTTP_COOKIE, TFE_HTTP_SET_COOKIE, TFE_HTTP_PROXY_AUTHORIZATION, TFE_HTTP_AUTHORIZATION, TFE_HTTP_LOCATION, TFE_HTTP_SERVER, TFE_HTTP_ETAG, TFE_HTTP_DATE, TFE_HTTP_TRAILER, TFE_HTTP_TRANSFER_ENCODING, TFE_HTTP_VIA, TFE_HTTP_PRAGMA, TFE_HTTP_CONNECTION, TFE_HTTP_CONT_ENCODING, TFE_HTTP_CONT_LANGUAGE, TFE_HTTP_CONT_LOCATION, TFE_HTTP_CONT_RANGE, TFE_HTTP_CONT_LENGTH, TFE_HTTP_CONT_TYPE, TFE_HTTP_CONT_DISPOSITION, TFE_HTTP_EXPIRES, TFE_HTTP_ACCEPT_ENCODING, TFE_HTTP_CACHE_CONTROL, TFE_HTTP_IF_MATCH, TFE_HTTP_IF_NONE_MATCH, TFE_HTTP_IF_MODIFIED_SINCE, TFE_HTTP_IF_UNMODIFIED_SINCE, TFE_HTTP_LAST_MODIFIED }; extern const char * __str_std_header_field_map[]; extern const unsigned int __str_std_header_field_map_size; enum http_ev_bit_number { REQ_HDR_BITNUM = 0, REQ_BODY_BEGIN_BITNUM, REQ_BODY_CONT_BITNUM, REQ_BODY_END_BITNUM, REQ_END_BITNUM, RESP_HDR_BITNUM, RESP_BODY_BEGIN_BITNUM, RESP_BODY_CONT_BITNUM, RESP_BODY_END_BITNUM, RESP_END_BITNUM }; enum tfe_http_event { EV_HTTP_REQ_HDR = 1ULL << REQ_HDR_BITNUM, EV_HTTP_REQ_BODY_BEGIN = 1ULL << REQ_BODY_BEGIN_BITNUM, EV_HTTP_REQ_BODY_CONT = 1ULL << REQ_BODY_CONT_BITNUM, EV_HTTP_REQ_BODY_END = 1ULL << REQ_BODY_END_BITNUM, EV_HTTP_REQ_END = 1ULL << REQ_END_BITNUM, EV_HTTP_RESP_HDR = 1ULL << RESP_HDR_BITNUM, EV_HTTP_RESP_BODY_BEGIN = 1ULL << RESP_BODY_BEGIN_BITNUM, EV_HTTP_RESP_BODY_CONT = 1ULL << RESP_BODY_CONT_BITNUM, EV_HTTP_RESP_BODY_END = 1ULL << RESP_BODY_END_BITNUM, EV_HTTP_RESP_END = 1ULL << RESP_END_BITNUM, }; struct tfe_http_req_spec { enum tfe_http_std_method method; const char * uri; const char * host; const char * url; //uri+host }; struct tfe_http_resp_spec { int resp_code; const char * content_encoding; const char * content_type; const char * content_length; }; enum tfe_http_direction { TFE_HTTP_REQUEST = 1, TFE_HTTP_RESPONSE = 2 }; struct tfe_http_half_ops { const char * (* ops_http_field_read)(const struct tfe_http_half *, const struct http_field_name *); int (* ops_http_field_write)(struct tfe_http_half *, const struct http_field_name *, const char *); struct tfe_http_half * (* ops_http_allow_write)(const struct tfe_http_half *); const char * (* ops_http_field_iterate)(const struct tfe_http_half *, void **, struct http_field_name *); int (* ops_append_body)(struct tfe_http_half *, char *, size_t, int); int (* ops_body_begin)(struct tfe_http_half *, int by_stream); int (* ops_body_data)(struct tfe_http_half *, const unsigned char * data, size_t sz_data); int (* ops_body_end)(struct tfe_http_half *); void (* ops_free)(struct tfe_http_half * half); }; struct tfe_http_session_ops { struct tfe_http_session * (* ops_allow_write)(const struct tfe_http_session * session); void (* ops_detach)(const struct tfe_http_session * session); void (* ops_drop)(struct tfe_http_session * session); void (* ops_suspend)(struct tfe_http_session * session); void (* ops_resume)(struct tfe_http_session * session); void (* ops_kill)(struct tfe_http_session * session); void (* ops_request_set)(struct tfe_http_session * session, struct tfe_http_half * req); void (* ops_response_set)(struct tfe_http_session * session, struct tfe_http_half * resp); struct tfe_http_half * (* ops_request_create)(struct tfe_http_session * session, enum tfe_http_std_method method, const char * uri); struct tfe_http_half * (* ops_response_create)(struct tfe_http_session * session, int resp_code); }; struct tfe_http_half { enum tfe_http_direction direction; const struct tfe_http_half_ops * ops; short major_version; short minor_version; union { struct tfe_http_req_spec req_spec; struct tfe_http_resp_spec resp_spec; }; }; struct tfe_http_session { unsigned int session_id; short major_version; short minor_version; struct tfe_http_session_ops * ops; struct tfe_http_half * req; struct tfe_http_half * resp; }; struct http_field_name { /* Standard Field */ enum tfe_http_std_field field_id; /* Non-NULL when field_id is HTTP_UNKNOWN_FIELD */ const char * field_name; }; #define CALL_NEXT_PLUGIN 0 #define NO_CALL_NEXT_PLUGIN -1 typedef void (http_session_begin_cb)(const struct tfe_stream * stream, const struct tfe_http_session * session, unsigned int thread_id, void ** pme); typedef int (http_session_data_cb)(const struct tfe_stream * stream, const struct tfe_http_session * session, enum tfe_http_event event, const unsigned char * data, size_t datalen, unsigned int thread_id, void ** pme); typedef void (http_session_end_cb)(const struct tfe_stream * stream, const struct tfe_http_session * session, unsigned int thread_id, void ** pme); /* Tools functions for standard HTTP header field name */ struct http_field_name * http_field_name_duplicate(const struct http_field_name * orig); int http_field_name_compare(const struct http_field_name * lvalue, const struct http_field_name * rvalue); const char * http_field_name_to_string(const struct http_field_name * field); void http_field_name_destory(struct http_field_name *); /* Tools functions for standard HTTP method */ const char * http_std_method_to_string(enum tfe_http_std_method method); enum tfe_http_std_method http_std_method_construct(const char * str_method); /* Tools functions for standard HTTP status */ const char * http_std_status_to_string(enum tfe_http_std_status status); enum tfe_http_std_status http_std_status_construct(const char * str_status); static inline const char * tfe_http_field_read(const struct tfe_http_half * half, const struct http_field_name * name) { return half->ops->ops_http_field_read(half, name); } static inline const char * tfe_http_std_field_read(const struct tfe_http_half * half, enum tfe_http_std_field field_id) { struct http_field_name tmp_name; tmp_name.field_id=field_id; tmp_name.field_name=NULL; return tfe_http_field_read(half, &tmp_name); } static inline const char * tfe_http_nonstd_field_read(const struct tfe_http_half * half, const char* field) { struct http_field_name tmp_name; tmp_name.field_id=TFE_HTTP_UNKNOWN_FIELD; tmp_name.field_name=field; return tfe_http_field_read(half, &tmp_name); } static inline int tfe_http_field_write(struct tfe_http_half * half, const struct http_field_name * name, const char * value) { return half->ops->ops_http_field_write(half, name, value); } static inline int tfe_http_std_field_write(struct tfe_http_half * half, enum tfe_http_std_field field_id, const char * value) { struct http_field_name tmp_name; tmp_name.field_id=field_id; tmp_name.field_name=NULL; return tfe_http_field_write(half, &tmp_name, value); } static inline int tfe_http_nonstd_field_write(struct tfe_http_half * half, const char* field, const char * value) { struct http_field_name tmp_name; tmp_name.field_id=TFE_HTTP_UNKNOWN_FIELD; tmp_name.field_name=field; return tfe_http_field_write(half, &tmp_name, value); } static inline struct tfe_http_half * tfe_http_allow_write(const struct tfe_http_half * half) { return half->ops->ops_http_allow_write(half); } static inline const char * tfe_http_field_iterate(const struct tfe_http_half * half, void ** iterator, struct http_field_name * name) { return half->ops->ops_http_field_iterate(half, iterator, name); } static inline int tfe_http_half_append_body(struct tfe_http_half * half, char * buff, size_t size, int flag) { return half->ops->ops_append_body(half, buff, size, flag); } static inline void tfe_http_half_free(struct tfe_http_half * half) { return half->ops->ops_free(half); } static inline int tfe_http_half_write_body_begin(struct tfe_http_half * half, int by_stream) { return half->ops->ops_body_begin(half, by_stream); } static inline int tfe_http_half_write_body_data(struct tfe_http_half * half, const unsigned char * data, size_t sz_data) { return half->ops->ops_body_data(half, data, sz_data); } static inline int tfe_http_half_write_body_end(struct tfe_http_half * half) { return half->ops->ops_body_end(half); } static inline struct tfe_http_session * tfe_http_session_allow_write(const struct tfe_http_session * session) { return session->ops->ops_allow_write(session); } static inline void tfe_http_session_detach(const struct tfe_http_session * session) { return session->ops->ops_detach(session); } static inline void tfe_http_session_drop(struct tfe_http_session * session) { return session->ops->ops_drop(session); } static inline void tfe_http_session_kill(struct tfe_http_session * session) { return session->ops->ops_kill(session); } static inline void tfe_http_session_suspend(struct tfe_http_session * session) { return session->ops->ops_suspend(session); } static inline void tfe_http_session_resume(struct tfe_http_session * session) { return session->ops->ops_resume(session); } static inline void tfe_http_session_request_set(struct tfe_http_session * session, struct tfe_http_half * req) { return session->ops->ops_request_set(session, req); } static inline void tfe_http_session_response_set(struct tfe_http_session * session, struct tfe_http_half * resp) { return session->ops->ops_response_set(session, resp); } static inline struct tfe_http_half * tfe_http_session_request_create(struct tfe_http_session * session, enum tfe_http_std_method method, const char * uri) { return session->ops->ops_request_create(session, method, uri); } static inline struct tfe_http_half * tfe_http_session_response_create(struct tfe_http_session * session, int resp_code) { return session->ops->ops_response_create(session, resp_code); } static inline int tfe_http_in_request(enum tfe_http_event events) { if ((events & EV_HTTP_REQ_HDR) | (events & EV_HTTP_REQ_BODY_BEGIN) | (events & EV_HTTP_REQ_BODY_END) | (events & EV_HTTP_REQ_BODY_CONT)| (events & EV_HTTP_REQ_END)) { return 1; } else { return 0; } } static inline int tfe_http_in_response(enum tfe_http_event events) { return !(tfe_http_in_request(events)); } static inline int tfe_http_in_hdr(enum tfe_http_event events) { if ((events & EV_HTTP_REQ_HDR) | (events & EV_HTTP_REQ_END)) { return 1; } else { return 0; } } static inline struct tfe_http_half* tfe_http_session_request_duplicate(struct tfe_http_session * session) { struct http_field_name in_header_field{}; const char * in_header_value = NULL; void * iterator = NULL; struct tfe_http_half* dup_req=tfe_http_session_request_create(session, session->req->req_spec.method, session->req->req_spec.uri); while (true) { if ((in_header_value = tfe_http_field_iterate(session->req, &iterator, &in_header_field)) == NULL) { break; } tfe_http_field_write(dup_req, &in_header_field,in_header_value); } return dup_req; } //@flag EV_HTTP_RESP_BODY_END, EV_HTTP_RESP_BODY_FULL, //suspend stream on EV_HTTP_REQ_BODY_BEGIN, resume when EV_HTTP_REQ_BODY_END. /* handler_ { tfe_http_response_frag_create; tfe_http_session_set_half; } rpc_cb_ { tfe_http_set_field tfe_http_append_body tfe_http_write(); } rpc_finish_cb_ { tfe_http_write_finish(); }; */ /* TODO: transfer these declaration to ht_frame.h */ struct http_frame_plugin_status { void * pme; unsigned int detached; unsigned int is_preempted; unsigned int preempt_by; }; struct http_frame_session_ctx * http_frame_alloc(); int http_frame_raise_session_begin(struct http_frame_session_ctx * ht_frame, const tfe_stream * stream, struct tfe_http_session * ht_session, unsigned int thread_id); void http_frame_raise_session_end(struct http_frame_session_ctx * ht_frame, const tfe_stream * stream, struct tfe_http_session * ht_session, unsigned int thread_id); void http_frame_raise_event(struct http_frame_session_ctx * ht_frame, const struct tfe_stream * stream, struct tfe_http_session * ht_session, enum tfe_http_event event, const unsigned char * data, size_t datalen, unsigned int thread_id); void http_frame_currect_plugin_detach(struct http_frame_session_ctx * ht_frame); int http_frame_currect_plugin_preempt(struct http_frame_session_ctx * ht_frame);