diff options
Diffstat (limited to 'src/plugins')
-rw-r--r-- | src/plugins/hs_apps/http_server.c | 590 | ||||
-rw-r--r-- | src/plugins/http/http.c | 49 |
2 files changed, 188 insertions, 451 deletions
diff --git a/src/plugins/hs_apps/http_server.c b/src/plugins/hs_apps/http_server.c index a46e0a4ae13..e7d7ad34152 100644 --- a/src/plugins/hs_apps/http_server.c +++ b/src/plugins/hs_apps/http_server.c @@ -17,34 +17,23 @@ #include <vnet/session/application.h> #include <vnet/session/application_interface.h> #include <vnet/session/session.h> -#include <vppinfra/tw_timer_2t_1w_2048sl.h> - -typedef enum -{ - EVENT_WAKEUP = 1, -} http_process_event_t; +#include <http/http.h> typedef struct { u32 hs_index; u32 thread_index; u64 node_index; + u8 *buf; } http_server_args; -typedef enum -{ - HTTP_STATE_CLOSED, - HTTP_STATE_ESTABLISHED, - HTTP_STATE_OK_SENT, -} http_session_state_t; typedef struct { CLIB_CACHE_LINE_ALIGN_MARK (cacheline0); -#define _(type, name) type name; - foreach_app_session_field -#undef _ + u32 session_index; u32 thread_index; - u8 *rx_buf; + u8 *tx_buf; + u32 tx_offset; u32 vpp_session_index; u64 vpp_session_handle; u32 timer_handle; @@ -53,32 +42,12 @@ typedef struct typedef struct { http_session_t **sessions; - clib_rwlock_t sessions_lock; - u32 **session_to_http_session; - - svm_msg_q_t **vpp_queue; - - uword *handler_by_get_request; - u32 *free_http_cli_process_node_indices; - - /* Sever's event queue */ - svm_queue_t *vl_input_queue; - - /* API client handle */ - u32 my_client_index; - u32 app_index; - /* process node index for evnt scheduling */ - u32 node_index; - /* Cert key pair for tls */ u32 ckpair_index; - tw_timer_wheel_2t_1w_2048sl_t tw; - clib_spinlock_t tw_lock; - u32 prealloc_fifos; u32 private_segment_size; u32 fifo_size; @@ -89,29 +58,7 @@ typedef struct http_server_main_t http_server_main; -static void -http_server_sessions_reader_lock (void) -{ - clib_rwlock_reader_lock (&http_server_main.sessions_lock); -} - -static void -http_server_sessions_reader_unlock (void) -{ - clib_rwlock_reader_unlock (&http_server_main.sessions_lock); -} - -static void -http_server_sessions_writer_lock (void) -{ - clib_rwlock_writer_lock (&http_server_main.sessions_lock); -} - -static void -http_server_sessions_writer_unlock (void) -{ - clib_rwlock_writer_unlock (&http_server_main.sessions_lock); -} +static u8 *static_html; static http_session_t * http_server_session_alloc (u32 thread_index) @@ -146,66 +93,6 @@ http_server_session_free (http_session_t * hs) } static void -http_server_session_lookup_add (u32 thread_index, u32 s_index, u32 hs_index) -{ - http_server_main_t *hsm = &http_server_main; - vec_validate (hsm->session_to_http_session[thread_index], s_index); - hsm->session_to_http_session[thread_index][s_index] = hs_index; -} - -static void -http_server_session_lookup_del (u32 thread_index, u32 s_index) -{ - http_server_main_t *hsm = &http_server_main; - hsm->session_to_http_session[thread_index][s_index] = ~0; -} - -static http_session_t * -http_server_session_lookup (u32 thread_index, u32 s_index) -{ - http_server_main_t *hsm = &http_server_main; - u32 hs_index; - - if (s_index < vec_len (hsm->session_to_http_session[thread_index])) - { - hs_index = hsm->session_to_http_session[thread_index][s_index]; - return http_server_session_get (thread_index, hs_index); - } - return 0; -} - - -static void -http_server_session_timer_start (http_session_t * hs) -{ - u32 hs_handle; - hs_handle = hs->thread_index << 24 | hs->session_index; - clib_spinlock_lock (&http_server_main.tw_lock); - hs->timer_handle = tw_timer_start_2t_1w_2048sl (&http_server_main.tw, - hs_handle, 0, 60); - clib_spinlock_unlock (&http_server_main.tw_lock); -} - -static void -http_server_session_timer_stop (http_session_t * hs) -{ - if (hs->timer_handle == ~0) - return; - clib_spinlock_lock (&http_server_main.tw_lock); - tw_timer_stop_2t_1w_2048sl (&http_server_main.tw, hs->timer_handle); - clib_spinlock_unlock (&http_server_main.tw_lock); -} - -static void -http_server_session_disconnect (http_session_t * hs) -{ - vnet_disconnect_args_t _a = { 0 }, *a = &_a; - a->handle = hs->vpp_session_handle; - a->app_index = http_server_main.app_index; - vnet_disconnect_session (a); -} - -static void http_process_free (http_server_args * args) { vlib_node_runtime_t *rt; @@ -233,25 +120,6 @@ http_process_free (http_server_args * args) vec_add1 (hsm->free_http_cli_process_node_indices, node_index); } -/* *INDENT-OFF* */ -static const char *http_ok = - "HTTP/1.1 200 OK\r\n"; - -static const char *http_response = - "Content-Type: text/html\r\n" - "Expires: Mon, 11 Jan 1970 10:10:10 GMT\r\n" - "Connection: close \r\n" - "Pragma: no-cache\r\n" - "Content-Length: %d\r\n\r\n%v"; - -static const char *http_error_template = - "HTTP/1.1 %s\r\n" - "Content-Type: text/html\r\n" - "Expires: Mon, 11 Jan 1970 10:10:10 GMT\r\n" - "Connection: close\r\n" - "Pragma: no-cache\r\n" - "Content-Length: 0\r\n\r\n"; - /* Header, including incantation to suppress favicon.ico requests */ static const char *html_header_template = "<html><head><title>%v</title></head>" @@ -265,10 +133,6 @@ static const char *html_header_static = "<html><head><title>static reply</title></head>" "<link rel=\"icon\" href=\"data:,\">" "<body><pre>hello</pre></body></html>\r\n"; -/* *INDENT-ON* */ - -static u8 *static_http; -static u8 *static_ok; static void http_cli_output (uword arg, u8 * buffer, uword buffer_bytes) @@ -286,110 +150,79 @@ http_cli_output (uword arg, u8 * buffer, uword buffer_bytes) *output_vecp = output_vec; } -void -send_data (http_session_t * hs, u8 * data) +static void +start_send_data (http_session_t *hs, http_status_code_t status) { - http_server_main_t *hsm = &http_server_main; - vnet_disconnect_args_t _a = { 0 }, *a = &_a; - vlib_main_t *vm = vlib_get_main (); - f64 last_sent_timer = vlib_time_now (vm); - u32 offset, bytes_to_send; - f64 delay = 10e-3; + http_msg_t msg; + session_t *ts; + int rv; - bytes_to_send = vec_len (data); - offset = 0; + msg.type = HTTP_MSG_REPLY; + msg.code = status; + msg.data.content_type = HTTP_CONTENT_TEXT_HTML; + msg.data.len = vec_len (hs->tx_buf); - while (bytes_to_send > 0) - { - int actual_transfer; + ts = session_get (hs->vpp_session_index, hs->thread_index); + rv = svm_fifo_enqueue (ts->tx_fifo, sizeof (msg), (u8 *) &msg); + ASSERT (rv == sizeof (msg)); - actual_transfer = svm_fifo_enqueue - (hs->tx_fifo, bytes_to_send, data + offset); + if (!msg.data.len) + goto done; - /* Made any progress? */ - if (actual_transfer <= 0) - { - http_server_sessions_reader_unlock (); - vlib_process_suspend (vm, delay); - http_server_sessions_reader_lock (); + rv = svm_fifo_enqueue (ts->tx_fifo, vec_len (hs->tx_buf), hs->tx_buf); - /* 10s deadman timer */ - if (vlib_time_now (vm) > last_sent_timer + 10.0) - { - a->handle = hs->vpp_session_handle; - a->app_index = hsm->app_index; - vnet_disconnect_session (a); - break; - } - /* Exponential backoff, within reason */ - if (delay < 1.0) - delay = delay * 2.0; - } - else - { - last_sent_timer = vlib_time_now (vm); - offset += actual_transfer; - bytes_to_send -= actual_transfer; - - if (svm_fifo_set_event (hs->tx_fifo)) - session_send_io_evt_to_thread (hs->tx_fifo, - SESSION_IO_EVT_TX_FLUSH); - delay = 10e-3; - } + if (rv != vec_len (hs->tx_buf)) + { + hs->tx_offset = rv; + svm_fifo_add_want_deq_ntf (ts->tx_fifo, SVM_FIFO_WANT_DEQ_NOTIF); + } + else + { + vec_free (hs->tx_buf); } + +done: + + if (svm_fifo_set_event (ts->tx_fifo)) + session_send_io_evt_to_thread (ts->tx_fifo, SESSION_IO_EVT_TX); } static void -send_error (http_session_t * hs, char *str) +send_data_to_http (void *rpc_args) { - u8 *data; + http_server_args *args = (http_server_args *) rpc_args; + http_session_t *hs; + + hs = http_server_session_get (args->thread_index, args->hs_index); + if (!hs) + { + vec_free (args->buf); + goto cleanup; + } + + hs->tx_buf = args->buf; + start_send_data (hs, HTTP_STATUS_OK); + +cleanup: - data = format (0, http_error_template, str); - send_data (hs, data); - vec_free (data); + clib_mem_free (rpc_args); } static uword http_cli_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f) { - u8 *request = 0, *reply = 0, *http = 0, *html = 0; + u8 *request = 0, *reply = 0, *html = 0; http_server_main_t *hsm = &http_server_main; http_server_args **save_args; - http_server_args *args; + http_server_args *args, *rpc_args; unformat_input_t input; - http_session_t *hs; int i; save_args = vlib_node_get_runtime_data (hsm->vlib_main, rt->node_index); args = *save_args; - http_server_sessions_reader_lock (); - - hs = http_server_session_get (args->thread_index, args->hs_index); - ASSERT (hs); - - request = hs->rx_buf; - if (vec_len (request) < 7) - { - send_error (hs, "400 Bad Request"); - goto out; - } - - for (i = 0; i < vec_len (request) - 4; i++) - { - if (request[i] == 'G' && - request[i + 1] == 'E' && - request[i + 2] == 'T' && request[i + 3] == ' ') - goto found; - } -bad_request: - send_error (hs, "400 Bad Request"); - goto out; - -found: - /* Lose "GET " */ - vec_delete (request, i + 5, 0); + request = args->buf; /* Replace slashes with spaces, stop at the end of the path */ i = 0; @@ -406,7 +239,11 @@ found: i++; /* Should never happen */ if (i == vec_len (request)) - goto bad_request; + { + char *msg = "Bad CLI"; + vec_validate_init_c_string (html, msg, strlen (msg)); + goto send; + } } /* Generate the html header */ @@ -421,21 +258,21 @@ found: /* Generate the html page */ html = format (html, "%v", reply); html = format (html, html_footer); - /* And the http reply */ - http = format (0, http_ok); - http = format (http, http_response, vec_len (html), html); + +send: /* Send it */ - send_data (hs, http); + rpc_args = clib_mem_alloc (sizeof (*args)); + clib_memcpy_fast (rpc_args, args, sizeof (*args)); + rpc_args->buf = html; -out: - /* Cleanup */ - http_server_sessions_reader_unlock (); - vec_free (reply); - vec_free (html); - vec_free (http); + session_send_rpc_evt_to_thread_force (args->thread_index, send_data_to_http, + rpc_args); + vec_free (reply); + vec_free (args->buf); http_process_free (args); + return (0); } @@ -490,49 +327,34 @@ alloc_http_process_callback (void *cb_args) } static int -session_rx_request (http_session_t * hs) +http_server_rx_callback (session_t *ts) { - u32 max_dequeue, cursize; - int n_read; - - cursize = vec_len (hs->rx_buf); - max_dequeue = svm_fifo_max_dequeue_cons (hs->rx_fifo); - if (PREDICT_FALSE (max_dequeue == 0)) - return -1; - - vec_validate (hs->rx_buf, cursize + max_dequeue - 1); - n_read = app_recv_stream_raw (hs->rx_fifo, hs->rx_buf + cursize, - max_dequeue, 0, 0 /* peek */ ); - ASSERT (n_read == max_dequeue); - if (svm_fifo_is_empty_cons (hs->rx_fifo)) - svm_fifo_unset_event (hs->rx_fifo); - - _vec_len (hs->rx_buf) = cursize + n_read; - return 0; -} - -static int -http_server_rx_callback (session_t * s) -{ - http_server_args args; + http_server_args args = {}; http_session_t *hs; + http_msg_t msg; int rv; - http_server_sessions_reader_lock (); + hs = http_server_session_get (ts->thread_index, ts->opaque); - hs = http_server_session_lookup (s->thread_index, s->session_index); - if (!hs || hs->session_state != HTTP_STATE_ESTABLISHED) - return -1; + /* Read the http message header */ + rv = svm_fifo_dequeue (ts->rx_fifo, sizeof (msg), (u8 *) &msg); + ASSERT (rv == sizeof (msg)); - rv = session_rx_request (hs); - if (rv) - return rv; + if (msg.type != HTTP_MSG_REQUEST || msg.method_type != HTTP_REQ_GET) + { + hs->tx_buf = 0; + start_send_data (hs, HTTP_STATUS_METHOD_NOT_ALLOWED); + return 0; + } /* send the command to a new/recycled vlib process */ - args.hs_index = hs->session_index; - args.thread_index = hs->thread_index; + vec_validate (args.buf, msg.data.len - 1); + rv = svm_fifo_dequeue (ts->rx_fifo, msg.data.len, args.buf); + ASSERT (rv == msg.data.len); + vec_set_len (args.buf, rv); - http_server_sessions_reader_unlock (); + args.hs_index = hs->session_index; + args.thread_index = ts->thread_index; /* Send RPC request to main thread */ if (vlib_get_thread_index () != 0) @@ -544,97 +366,81 @@ http_server_rx_callback (session_t * s) } static int -http_server_rx_callback_static (session_t * s) +http_server_rx_callback_static (session_t *ts) { http_session_t *hs; - u32 request_len; - u8 *request = 0; - int i, rv; - - hs = http_server_session_lookup (s->thread_index, s->session_index); - if (!hs || hs->session_state == HTTP_STATE_CLOSED) - return 0; + http_msg_t msg; + int rv; - /* ok 200 was sent */ - if (hs->session_state == HTTP_STATE_OK_SENT) - goto send_data; + hs = http_server_session_get (ts->thread_index, ts->opaque); + rv = svm_fifo_dequeue (ts->rx_fifo, sizeof (msg), (u8 *) &msg); + ASSERT (rv == sizeof (msg)); - rv = session_rx_request (hs); - if (rv) - goto wait_for_data; + svm_fifo_dequeue_drop (ts->rx_fifo, msg.data.len); - request = hs->rx_buf; - request_len = vec_len (request); - if (vec_len (request) < 7) + if (msg.type != HTTP_MSG_REQUEST || msg.method_type != HTTP_REQ_GET) { - send_error (hs, "400 Bad Request"); - goto close_session; + hs->tx_buf = 0; + start_send_data (hs, HTTP_STATUS_METHOD_NOT_ALLOWED); + goto done; } - for (i = 0; i < request_len - 4; i++) - { - if (request[i] == 'G' && - request[i + 1] == 'E' && - request[i + 2] == 'T' && request[i + 3] == ' ') - goto find_end; - } - send_error (hs, "400 Bad Request"); - goto close_session; + hs->tx_buf = vec_dup (static_html); + start_send_data (hs, HTTP_STATUS_OK); + +done: -find_end: + return 0; +} + +static int +http_server_tx_callback (session_t *ts) +{ + http_session_t *hs; + u32 to_send; + int rv; - /* check for the end sequence: /r/n/r/n */ - if (request[request_len - 1] != 0xa || request[request_len - 3] != 0xa - || request[request_len - 2] != 0xd || request[request_len - 4] != 0xd) - goto wait_for_data; + hs = http_server_session_get (ts->thread_index, ts->opaque); + if (!hs || !hs->tx_buf) + return 0; - /* send 200 OK first */ - send_data (hs, static_ok); - hs->session_state = HTTP_STATE_OK_SENT; - goto postpone; + to_send = vec_len (hs->tx_buf) - hs->tx_offset; + rv = svm_fifo_enqueue (ts->tx_fifo, to_send, hs->tx_buf + hs->tx_offset); -send_data: - send_data (hs, static_http); + if (rv <= 0) + { + svm_fifo_add_want_deq_ntf (ts->tx_fifo, SVM_FIFO_WANT_DEQ_NOTIF); + return 0; + } -close_session: - http_server_session_disconnect (hs); - return 0; + if (rv < to_send) + { + hs->tx_offset += rv; + svm_fifo_add_want_deq_ntf (ts->tx_fifo, SVM_FIFO_WANT_DEQ_NOTIF); + } + else + { + vec_free (hs->tx_buf); + } -postpone: - (void) svm_fifo_set_event (hs->rx_fifo); - session_send_io_evt_to_thread (hs->rx_fifo, SESSION_IO_EVT_BUILTIN_RX); - return 0; + if (svm_fifo_set_event (ts->tx_fifo)) + session_send_io_evt_to_thread (ts->tx_fifo, SESSION_IO_EVT_TX); -wait_for_data: return 0; } static int -http_server_session_accept_callback (session_t * s) +http_server_session_accept_callback (session_t *ts) { - http_server_main_t *hsm = &http_server_main; http_session_t *hs; - hsm->vpp_queue[s->thread_index] = - session_main_get_vpp_event_queue (s->thread_index); + hs = http_server_session_alloc (ts->thread_index); + hs->vpp_session_index = ts->session_index; + hs->vpp_session_handle = session_handle (ts); - if (!hsm->is_static) - http_server_sessions_writer_lock (); + ts->opaque = hs->session_index; + ts->session_state = SESSION_STATE_READY; - hs = http_server_session_alloc (s->thread_index); - http_server_session_lookup_add (s->thread_index, s->session_index, - hs->session_index); - hs->rx_fifo = s->rx_fifo; - hs->tx_fifo = s->tx_fifo; - hs->vpp_session_index = s->session_index; - hs->vpp_session_handle = session_handle (s); - hs->session_state = HTTP_STATE_ESTABLISHED; - http_server_session_timer_start (hs); - - if (!hsm->is_static) - http_server_sessions_writer_unlock (); - - s->session_state = SESSION_STATE_READY; return 0; } @@ -677,28 +483,17 @@ http_server_add_segment_callback (u32 client_index, u64 segment_handle) static void http_server_cleanup_callback (session_t * s, session_cleanup_ntf_t ntf) { - http_server_main_t *hsm = &http_server_main; http_session_t *hs; if (ntf == SESSION_CLEANUP_TRANSPORT) return; - if (!hsm->is_static) - http_server_sessions_writer_lock (); - - hs = http_server_session_lookup (s->thread_index, s->session_index); + hs = http_server_session_get (s->thread_index, s->opaque); if (!hs) - goto done; + return; - http_server_session_lookup_del (hs->thread_index, hs->vpp_session_index); - vec_free (hs->rx_buf); - http_server_session_timer_stop (hs); + vec_free (hs->tx_buf); http_server_session_free (hs); - -done: - - if (!hsm->is_static) - http_server_sessions_writer_unlock (); } static session_cb_vft_t http_server_session_cb_vft = { @@ -707,6 +502,7 @@ static session_cb_vft_t http_server_session_cb_vft = { .session_connected_callback = http_server_session_connected_callback, .add_segment_callback = http_server_add_segment_callback, .builtin_app_rx_callback = http_server_rx_callback, + .builtin_app_tx_callback = http_server_tx_callback, .session_reset_callback = http_server_session_reset_callback, .session_cleanup_callback = http_server_cleanup_callback, }; @@ -773,6 +569,7 @@ http_server_listen () http_server_main_t *hsm = &http_server_main; vnet_listen_args_t _a, *a = &_a; char *uri = "tcp://0.0.0.0/80"; + u8 need_crypto; int rv; clib_memset (a, 0, sizeof (*a)); @@ -784,8 +581,12 @@ http_server_listen () if (parse_uri (uri, &sep)) return -1; + need_crypto = http_transport_needs_crypto (a->sep_ext.transport_proto); + + sep.transport_proto = TRANSPORT_PROTO_HTTP; clib_memcpy (&a->sep_ext, &sep, sizeof (sep)); - if (http_transport_needs_crypto (a->sep_ext.transport_proto)) + + if (need_crypto) { session_endpoint_alloc_ext_cfg (&a->sep_ext, TRANSPORT_ENDPT_EXT_CFG_CRYPTO); @@ -793,90 +594,22 @@ http_server_listen () } rv = vnet_listen (a); - if (a->sep_ext.ext_cfg) - clib_mem_free (a->sep_ext.ext_cfg); - return rv; -} - -static void -http_server_session_close_cb (void *hs_handlep) -{ - http_session_t *hs; - uword hs_handle; - hs_handle = pointer_to_uword (hs_handlep); - hs = http_server_session_get (hs_handle >> 24, hs_handle & 0x00FFFFFF); - if (!hs) - return; - hs->timer_handle = ~0; - http_server_session_disconnect (hs); -} -static void -http_expired_timers_dispatch (u32 * expired_timers) -{ - u32 hs_handle; - int i; - - for (i = 0; i < vec_len (expired_timers); i++) - { - /* Get session handle. The first bit is the timer id */ - hs_handle = expired_timers[i] & 0x7FFFFFFF; - session_send_rpc_evt_to_thread (hs_handle >> 24, - http_server_session_close_cb, - uword_to_pointer (hs_handle, void *)); - } -} - -static uword -http_server_process (vlib_main_t * vm, vlib_node_runtime_t * rt, - vlib_frame_t * f) -{ - http_server_main_t *hsm = &http_server_main; - f64 now, timeout = 1.0; - uword *event_data = 0; - uword __clib_unused event_type; - - while (1) - { - vlib_process_wait_for_event_or_clock (vm, timeout); - now = vlib_time_now (vm); - event_type = vlib_process_get_events (vm, (uword **) & event_data); - - /* expire timers */ - clib_spinlock_lock (&http_server_main.tw_lock); - tw_timer_expire_timers_2t_1w_2048sl (&hsm->tw, now); - clib_spinlock_unlock (&http_server_main.tw_lock); + if (need_crypto) + clib_mem_free (a->sep_ext.ext_cfg); - vec_reset_length (event_data); - } - return 0; + return rv; } -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (http_server_process_node) = -{ - .function = http_server_process, - .type = VLIB_NODE_TYPE_PROCESS, - .name = "http-server-process", - .state = VLIB_NODE_STATE_DISABLED, -}; -/* *INDENT-ON* */ - static int http_server_create (vlib_main_t * vm) { vlib_thread_main_t *vtm = vlib_get_thread_main (); http_server_main_t *hsm = &http_server_main; u32 num_threads; - vlib_node_t *n; num_threads = 1 /* main thread */ + vtm->n_threads; - vec_validate (hsm->vpp_queue, num_threads - 1); vec_validate (hsm->sessions, num_threads - 1); - vec_validate (hsm->session_to_http_session, num_threads - 1); - - clib_rwlock_init (&hsm->sessions_lock); - clib_spinlock_init (&hsm->tw_lock); if (http_server_attach ()) { @@ -889,14 +622,6 @@ http_server_create (vlib_main_t * vm) return -1; } - /* Init timer wheel and process */ - tw_timer_wheel_init_2t_1w_2048sl (&hsm->tw, http_expired_timers_dispatch, - 1 /* timer interval */ , ~0); - vlib_node_set_state (vm, http_server_process_node.index, - VLIB_NODE_STATE_POLLING); - n = vlib_get_node (vm, http_server_process_node.index); - vlib_start_process (vm, n->runtime_index); - return 0; } @@ -908,7 +633,6 @@ http_server_create_command_fn (vlib_main_t * vm, http_server_main_t *hsm = &http_server_main; unformat_input_t _line_input, *line_input = &_line_input; u64 seg_size; - u8 *html; int rv; hsm->prealloc_fifos = 0; @@ -950,7 +674,7 @@ http_server_create_command_fn (vlib_main_t * vm, start_server: - if (hsm->my_client_index != (u32) ~ 0) + if (hsm->app_index != (u32) ~0) return clib_error_return (0, "test http server is already running"); vnet_session_enable_disable (vm, 1 /* turn on TCP, etc. */ ); @@ -959,10 +683,10 @@ start_server: { http_server_session_cb_vft.builtin_app_rx_callback = http_server_rx_callback_static; - html = format (0, html_header_static); - static_http = format (0, http_response, vec_len (html), html); - static_ok = format (0, http_ok); + vec_free (static_html); + static_html = format (0, html_header_static); } + rv = http_server_create (vm); switch (rv) { @@ -974,21 +698,19 @@ start_server: return 0; } -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (http_server_create_command, static) = { .path = "test http server", .short_help = "test http server", .function = http_server_create_command_fn, }; -/* *INDENT-ON* */ static clib_error_t * http_server_main_init (vlib_main_t * vm) { http_server_main_t *hsm = &http_server_main; - hsm->my_client_index = ~0; + hsm->app_index = ~0; hsm->vlib_main = vm; return 0; } diff --git a/src/plugins/http/http.c b/src/plugins/http/http.c index 5cdbaa7df3e..6d08e1dd23e 100644 --- a/src/plugins/http/http.c +++ b/src/plugins/http/http.c @@ -360,9 +360,9 @@ read_request (http_conn_t *hc) } static int -v_find_index (u8 *vec, char *str) +v_find_index (u8 *vec, u32 offset, char *str) { - int start_index; + int start_index = offset; u32 slen = (u32) strnlen_s_inline (str, 8); u32 vlen = vec_len (vec); @@ -371,9 +371,9 @@ v_find_index (u8 *vec, char *str) if (vlen <= slen) return -1; - for (start_index = 0; start_index < (vlen - slen); start_index++) + for (; start_index < (vlen - slen); start_index++) { - if (!memcmp (vec, str, slen)) + if (!memcmp (vec + start_index, str, slen)) return start_index; } @@ -386,7 +386,7 @@ v_find_index (u8 *vec, char *str) static int state_wait_method (http_conn_t *hc, transport_send_params_t *sp) { - http_main_t *hm = &http_main; + http_status_code_t ec; app_worker_t *app_wrk; http_msg_t msg; session_t *as; @@ -402,35 +402,41 @@ state_wait_method (http_conn_t *hc, transport_send_params_t *sp) if (vec_len (hc->rx_buf) < 8) { - send_error (hc, HTTP_STATUS_BAD_REQUEST); - http_disconnect_transport (hc); - return -1; + ec = HTTP_STATUS_BAD_REQUEST; + goto error; } - if ((i = v_find_index (hc->rx_buf, "GET ")) >= 0) + if ((i = v_find_index (hc->rx_buf, 0, "GET ")) >= 0) { hc->method = HTTP_REQ_GET; hc->rx_buf_offset = i + 5; + + i = v_find_index (hc->rx_buf, hc->rx_buf_offset, "HTTP"); + if (i < 0) + { + ec = HTTP_STATUS_BAD_REQUEST; + goto error; + } + + len = i - hc->rx_buf_offset; } - else if ((i = v_find_index (hc->rx_buf, "POST ")) >= 0) + else if ((i = v_find_index (hc->rx_buf, 0, "POST ")) >= 0) { hc->method = HTTP_REQ_POST; hc->rx_buf_offset = i + 6; + len = vec_len (hc->rx_buf) - hc->rx_buf_offset; } else { - if (hm->debug_level > 1) - clib_warning ("Unknown http method"); - - send_error (hc, HTTP_STATUS_METHOD_NOT_ALLOWED); - http_disconnect_transport (hc); - return -1; + HTTP_DBG (0, "Unknown http method"); + ec = HTTP_STATUS_METHOD_NOT_ALLOWED; + goto error; } buf = &hc->rx_buf[hc->rx_buf_offset]; - len = vec_len (hc->rx_buf) - hc->rx_buf_offset; msg.type = HTTP_MSG_REQUEST; + msg.method_type = hc->method; msg.data.content_type = HTTP_CONTENT_TEXT_HTML; msg.data.len = len; msg.data.offset = 0; @@ -455,6 +461,14 @@ state_wait_method (http_conn_t *hc, transport_send_params_t *sp) app_worker_lock_and_send_event (app_wrk, as, SESSION_IO_EVT_RX); return 0; + +error: + + send_error (hc, ec); + session_transport_closing_notify (&hc->connection); + http_disconnect_transport (hc); + + return -1; } /** @@ -528,6 +542,7 @@ error: send_error (hc, ec); hc->req_state = HTTP_REQ_STATE_WAIT_METHOD; + session_transport_closing_notify (&hc->connection); http_disconnect_transport (hc); /* stop state machine processing */ |