diff options
Diffstat (limited to 'src/plugins/http/http.h')
-rw-r--r-- | src/plugins/http/http.h | 359 |
1 files changed, 65 insertions, 294 deletions
diff --git a/src/plugins/http/http.h b/src/plugins/http/http.h index d61ac0b08c7..178bdd14881 100644 --- a/src/plugins/http/http.h +++ b/src/plugins/http/http.h @@ -17,15 +17,9 @@ #define SRC_PLUGINS_HTTP_HTTP_H_ #include <ctype.h> - #include <vnet/plugin/plugin.h> -#include <vpp/app/version.h> - -#include <vppinfra/time_range.h> - -#include <vnet/session/application_interface.h> -#include <vnet/session/application.h> -#include <http/http_buffer.h> +#include <vnet/ip/format.h> +#include <vnet/ip/ip46_address.h> #define HTTP_DEBUG 0 @@ -49,20 +43,6 @@ typedef struct transport_endpt_cfg_http http_udp_tunnel_mode_t udp_tunnel_mode; /**< connect-udp mode */ } transport_endpt_cfg_http_t; -typedef struct http_conn_id_ -{ - union - { - session_handle_t app_session_handle; - u32 parent_app_api_ctx; - }; - session_handle_t tc_session_handle; - u32 parent_app_wrk_index; -} http_conn_id_t; - -STATIC_ASSERT (sizeof (http_conn_id_t) <= TRANSPORT_CONN_ID_LEN, - "ctx id must be less than TRANSPORT_CONN_ID_LEN"); - typedef struct { char *base; @@ -71,40 +51,6 @@ typedef struct #define http_token_lit(s) (s), sizeof (s) - 1 -#define foreach_http_conn_state \ - _ (LISTEN, "listen") \ - _ (CONNECTING, "connecting") \ - _ (ESTABLISHED, "established") \ - _ (TRANSPORT_CLOSED, "transport-closed") \ - _ (APP_CLOSED, "app-closed") \ - _ (CLOSED, "closed") - -typedef enum http_conn_state_ -{ -#define _(s, str) HTTP_CONN_STATE_##s, - foreach_http_conn_state -#undef _ -} http_conn_state_t; - -#define foreach_http_req_state \ - _ (0, IDLE, "idle") \ - _ (1, WAIT_APP_METHOD, "wait app method") \ - _ (2, WAIT_TRANSPORT_REPLY, "wait transport reply") \ - _ (3, TRANSPORT_IO_MORE_DATA, "transport io more data") \ - _ (4, WAIT_TRANSPORT_METHOD, "wait transport method") \ - _ (5, WAIT_APP_REPLY, "wait app reply") \ - _ (6, APP_IO_MORE_DATA, "app io more data") \ - _ (7, TUNNEL, "tunnel") \ - _ (8, UDP_TUNNEL, "udp tunnel") - -typedef enum http_req_state_ -{ -#define _(n, s, str) HTTP_REQ_STATE_##s = n, - foreach_http_req_state -#undef _ - HTTP_REQ_N_STATES -} http_req_state_t; - typedef enum http_req_method_ { HTTP_REQ_GET = 0, @@ -118,14 +64,6 @@ typedef enum http_msg_type_ HTTP_MSG_REPLY } http_msg_type_t; -typedef enum http_target_form_ -{ - HTTP_TARGET_ORIGIN_FORM, - HTTP_TARGET_ABSOLUTE_FORM, - HTTP_TARGET_AUTHORITY_FORM, - HTTP_TARGET_ASTERISK_FORM -} http_target_form_t; - #define foreach_http_content_type \ _ (APP_7Z, ".7z", "application/x-7z-compressed") \ _ (APP_DOC, ".doc", "application/msword") \ @@ -432,118 +370,6 @@ typedef struct http_msg_ http_msg_data_t data; } http_msg_t; -typedef struct http_req_ -{ - http_req_state_t state; /* state-machine state */ - - http_buffer_t tx_buf; /* message body from app to be sent */ - - /* - * for parsing of incoming message from transport - */ - u8 *rx_buf; /* this should hold at least control data */ - u32 rx_buf_offset; /* current offset during parsing */ - u32 control_data_len; /* start line + headers + empty line */ - - union - { - u64 to_recv; /* remaining bytes of body to receive from transport */ - u64 to_skip; /* remaining bytes of capsule to skip */ - }; - - u8 is_tunnel; - - /* - * parsed metadata for app - */ - union - { - http_status_code_t status_code; - http_req_method_t method; - }; - - http_target_form_t target_form; - http_url_scheme_t scheme; - u32 target_authority_offset; - u32 target_authority_len; - u32 target_path_offset; - u32 target_path_len; - u32 target_query_offset; - u32 target_query_len; - - u32 headers_offset; - u32 headers_len; - - u32 body_offset; - u64 body_len; - - http_field_line_t *headers; - uword content_len_header_index; - uword connection_header_index; - uword upgrade_header_index; - uword host_header_index; - - http_upgrade_proto_t upgrade_proto; -} http_req_t; - -typedef struct http_tc_ -{ - union - { - transport_connection_t connection; - http_conn_id_t c_http_conn_id; - }; -#define h_tc_session_handle c_http_conn_id.tc_session_handle -#define h_pa_wrk_index c_http_conn_id.parent_app_wrk_index -#define h_pa_session_handle c_http_conn_id.app_session_handle -#define h_pa_app_api_ctx c_http_conn_id.parent_app_api_ctx -#define h_hc_index connection.c_index - - http_conn_state_t state; - u32 timer_handle; - u32 timeout; - u8 pending_timer; - u8 *app_name; - u8 *host; - u8 is_server; - http_udp_tunnel_mode_t udp_tunnel_mode; - - http_req_t req; -} http_conn_t; - -typedef struct http_worker_ -{ - http_conn_t *conn_pool; -} http_worker_t; - -typedef struct http_main_ -{ - http_worker_t *wrk; - http_conn_t *listener_pool; - http_conn_t *ho_conn_pool; - u32 app_index; - - u8 **rx_bufs; - u8 **tx_bufs; - u8 **app_header_lists; - - clib_timebase_t timebase; - - u16 *sc_by_u16; - /* - * Runtime config - */ - u8 debug_level; - u8 is_init; - - /* - * Config - */ - u64 first_seg_size; - u64 add_seg_size; - u32 fifo_size; -} http_main_t; - always_inline u8 * format_http_bytes (u8 *s, va_list *va) { @@ -736,124 +562,6 @@ http_path_remove_dot_segments (u8 *path) return new_path; } -always_inline int -_parse_field_name (u8 **pos, u8 *end, u8 **field_name_start, - u32 *field_name_len) -{ - u32 name_len = 0; - u8 *p; - - static uword tchar[4] = { - /* !#$%'*+-.0123456789 */ - 0x03ff6cba00000000, - /* ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz|~ */ - 0x57ffffffc7fffffe, - 0x0000000000000000, - 0x0000000000000000, - }; - - p = *pos; - - *field_name_start = p; - while (p != end) - { - if (clib_bitmap_get_no_check (tchar, *p)) - { - name_len++; - p++; - } - else if (*p == ':') - { - if (name_len == 0) - { - clib_warning ("empty field name"); - return -1; - } - *field_name_len = name_len; - p++; - *pos = p; - return 0; - } - else - { - clib_warning ("invalid character %d", *p); - return -1; - } - } - clib_warning ("field name end not found"); - return -1; -} - -always_inline int -_parse_field_value (u8 **pos, u8 *end, u8 **field_value_start, - u32 *field_value_len) -{ - u32 value_len = 0; - u8 *p; - - p = *pos; - - /* skip leading whitespace */ - while (1) - { - if (p == end) - { - clib_warning ("field value not found"); - return -1; - } - else if (*p != ' ' && *p != '\t') - { - break; - } - p++; - } - - *field_value_start = p; - while (p != end) - { - if (*p == '\r') - { - if ((end - p) < 1) - { - clib_warning ("incorrect field line end"); - return -1; - } - p++; - if (*p == '\n') - { - if (value_len == 0) - { - clib_warning ("empty field value"); - return -1; - } - p++; - *pos = p; - /* skip trailing whitespace */ - p = *field_value_start + value_len - 1; - while (*p == ' ' || *p == '\t') - { - p--; - value_len--; - } - *field_value_len = value_len; - return 0; - } - clib_warning ("CR without LF"); - return -1; - } - if (*p < ' ' && *p != '\t') - { - clib_warning ("invalid character %d", *p); - return -1; - } - p++; - value_len++; - } - - clib_warning ("field value end not found"); - return -1; -} - typedef struct { http_token_t name; @@ -873,6 +581,16 @@ typedef struct .values = 0, .value_by_name = 0, .buf = 0, .concatenated_values = 0, \ } +/** + * Case-sensitive comparison of two tokens. + * + * @param actual Pointer to the first token. + * @param actual_len Length of the first token. + * @param expected Pointer to the second token. + * @param expected_len Length of the second token. + * + * @return @c 1 if tokens are same, @c 0 otherwise. + */ always_inline u8 http_token_is (const char *actual, uword actual_len, const char *expected, uword expected_len) @@ -903,6 +621,16 @@ http_tolower_word (uword x) return (x | y); } +/** + * Case-insensitive comparison of two tokens. + * + * @param actual Pointer to the first token. + * @param actual_len Length of the first token. + * @param expected Pointer to the second token. + * @param expected_len Length of the second token. + * + * @return @c 1 if tokens are same, @c 0 otherwise. + */ always_inline u8 http_token_is_case (const char *actual, uword actual_len, const char *expected, uword expected_len) @@ -934,6 +662,16 @@ http_token_is_case (const char *actual, uword actual_len, const char *expected, return 1; } +/** + * Check if there is occurrence of token in another token. + * + * @param haystack Pointer to the token being searched. + * @param haystack_len Length of the token being searched. + * @param needle The token to search for. + * @param needle_len Length of the token to search for. + * + * @return @c 1 if in case of success, @c 0 otherwise. + */ always_inline u8 http_token_contains (const char *haystack, uword haystack_len, const char *needle, uword needle_len) @@ -1158,6 +896,13 @@ typedef struct /* Use high bit of header name length as custom header name bit. */ #define HTTP_CUSTOM_HEADER_NAME_BIT (1 << 31) +/** + * Initialize headers list context. + * + * @param ctx Headers list context. + * @param buf Buffer, which store headers list, provided by app. + * @param len Length of headers list buffer. + */ always_inline void http_init_headers_ctx (http_headers_ctx_t *ctx, u8 *buf, u32 len) { @@ -1166,6 +911,14 @@ http_init_headers_ctx (http_headers_ctx_t *ctx, u8 *buf, u32 len) ctx->buf = buf; } +/** + * Add header with predefined name to the headers list. + * + * @param ctx Headers list context. + * @param name Header name ID (see @ref http_header_name_t). + * @param value Header value pointer. + * @param value_len Header value length. + */ always_inline void http_add_header (http_headers_ctx_t *ctx, http_header_name_t name, const char *value, uword value_len) @@ -1182,6 +935,15 @@ http_add_header (http_headers_ctx_t *ctx, http_header_name_t name, ctx->tail_offset += sizeof (http_app_header_t) + value_len; } +/** + * Add header with custom name to the headers list. + * + * @param ctx Headers list context. + * @param name Header name pointer. + * @param name_len Header name length. + * @param value Header value pointer. + * @param value_len Header value length. + */ always_inline void http_add_custom_header (http_headers_ctx_t *ctx, const char *name, uword name_len, const char *value, uword value_len) @@ -1491,6 +1253,15 @@ http_parse_authority (u8 *authority, u32 authority_len, return token_start == end ? 0 : -1; } +/** + * Format given authority (RFC3986 section 3.2) + * + * @param authority Authority to format. + * + * @return New vector with formated authority. + * + * The caller is always responsible to free the returned vector. + */ always_inline u8 * http_serialize_authority (http_uri_authority_t *authority) { |