aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/plugins/hs_apps/http_server.c590
-rw-r--r--src/plugins/http/http.c49
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 */